之前一起吃饭听说了发票助手这个东西,可以生成发票抬头的二维码,扫码就可以开票了。

官方也有个小程序的 【税务发票助手】,微信中搜这个名字就可以了。

我准备在自己的小程序中也尝试一下,本来觉得只要拼接一下生成二维码就好了,结果发现不少坑。

具体的文档参照github上的 便捷开票二维码应用规范.pdf

拼接倒是没什么,最坑的是CRC-16校验码那里。通过网上找到的CRC(循环冗余校验)在线计算计算的和官方程序生成的总是不一样。

在网上找到了好几个版本,大部分生成的和上面的在线计算结果一样。最终找到了一个Java版的国税总局发票助手二维码生成的CRC计算,跑起来之后发现终于验证码一样了。

于是改成了C#版,还加上了QRCode的生成方法(需要安装QRCoder包)。

C#版代码

public class ReceiptHelper
{
private const int crc16 = 0x8005; private const string ReceiptQRCodePath = "Uploads\\Receipt\\"; /// <summary>
/// 生成发票抬头QRCode图片
/// </summary>
/// <param name="id">数据ID</param>
/// <param name="companyName">公司名称</param>
/// <param name="taxNo">纳税人识别号</param>
/// <param name="address">地址</param>
/// <param name="phone">电话</param>
/// <param name="bankName">开户行</param>
/// <param name="account">账户</param>
/// <returns>QRCode图片名</returns>
public static string GenerateQRCodeImage(Guid id, string companyName, string taxNo, string address, string phone, string bankName, string account)
{
string strQRCode = GenerateQRCode(companyName, taxNo, address, phone, bankName, account);
string path = System.Web.Hosting.HostingEnvironment.MapPath("~/") + ReceiptQRCodePath + id.ToString() + ".png"; QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(strQRCode, QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
Bitmap qrCodeImage = qrCode.GetGraphic(15);
qrCodeImage.Save(path, System.Drawing.Imaging.ImageFormat.Png); return path;
} /// <summary>
/// 生成发票抬头QRCode内容
/// </summary>
/// <param name="companyName">公司名称</param>
/// <param name="taxNo">纳税人识别号</param>
/// <param name="address">地址</param>
/// <param name="phone">电话</param>
/// <param name="bankName">开户行</param>
/// <param name="account">账户</param>
/// <returns>QRCode图片名</returns>
public static string GenerateQRCode(string companyName, string taxNo, string address, string phone, string bankName, string account)
{
string crcInput = $"{companyName}</>{taxNo}</>{address}{phone}</>{bankName}{account}</>"; // CRC校验内容
string crcNo = CalcCRC16(crcInput); // 计算CRC16校验码 // 起始符 + 版本号 + base64(名称</>纳税人识别号</>地址电话</>开户行及账号</>CRC) + 结束符
StringBuilder sbQRCode = new StringBuilder();
sbQRCode.Append("$");
sbQRCode.Append("01");
sbQRCode.Append(Convert.ToBase64String(Encoding.UTF8.GetBytes(crcInput + crcNo)));
sbQRCode.Append(" $"); return sbQRCode.ToString();
} /// <summary>
/// 计算CRC16校验码
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string CalcCRC16(string input)
{
sbyte[] inputs = GetSBytesForEncoding("UTF-8", input); int a = 0;
for (int i = 0; i < inputs.Length; i++)
{
a = div(inputs[i], a);
} sbyte r = 0;
a = div(r, a);
a = div(r, a); return a.ToString("X4");
} private static int div(sbyte input, int a)
{
int temp;
int data = input;
for (int i = 0; i < 8; i++)
{
temp = a & 0x8000;
a = a << 1;
a = a & 0x0000ffff; int numIn = data & 0x80;
numIn = numIn >> 7; a = a ^ numIn; if (temp == 0x8000)
{
a = a ^ crc16;
} data = data << 1;
a = a & 0x0000ffff;
} return a;
} private static sbyte[] GetSBytesForEncoding(string encoding, string s)
{
return GetSBytesForEncoding(Encoding.GetEncoding(encoding), s);
} private static sbyte[] GetSBytesForEncoding(Encoding encoding, string s)
{
sbyte[] sbytes = new sbyte[encoding.GetByteCount(s)];
encoding.GetBytes(s, 0, s.Length, (byte[])(object)sbytes, 0);
return sbytes;
} }

QRCoder的安装命令

Install-Package QRCoder

也可以通过NuGet工具搜索QRCoder安装。

【C#】发票助手二维码生成的更多相关文章

  1. [开源]C#二维码生成解析工具,可添加自定义Logo

    二维码又称 QR Code,QR 全称 Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的 Bar Code 条形码能存更多的信息,也能表示更多的数据类型:比如:字 ...

  2. 聊聊 Web 项目二维码生成的最佳姿势

    在设计和实现的过程之后,你永远不知道部署上去的程序会已什么样的姿势运行. 本篇借一次生成二维码逻辑的不同实现,阐述 Web 项目中二维码生成的正确姿势. 文中如有批量,欢迎各位看客老爷拍砖.试运行前5 ...

  3. .NET 二维码生成(ThoughtWorks.QRCode)

    引用ThoughtWorks.QRCode.dll (源代码里有) 1.简单二维码生成及解码代码: //生成二维码方法一 private void CreateCode_Simple(string n ...

  4. iOS开发 二维码生成

    基于libqrencode的二维码生成 + (void)drawQRCode:(QRcode *)code context:(CGContextRef)ctx size:(CGFloat)size { ...

  5. PHP二维码生成的方法(google APi,PHP类库,libqrencode等)

    原文地址: http://blog.csdn.net/liuxinmingcode/article/details/7910975 ================================== ...

  6. Android 二维码 生成和识别(附Demo源码)

    今天讲一下目前移动领域很常用的技术——二维码.现在大街小巷.各大网站都有二维码的踪迹,不管是IOS. Android.WP都有相关支持的软件.之前我就想了解二维码是如何工作,最近因为工作需要使用相关技 ...

  7. Chrome浏览器二维码生成插件

      猛击就可以使用啦->>>猛击使用   源码如下: 源码打包   源码: jquery-2.1.3.min.js jquery.qrcode.min.js https://gith ...

  8. Android 二维码 生成和识别(转)

    原博客地址 :http://www.cnblogs.com/weixing/archive/2013/08/28/3287120.html 还有几个写的也可以参考一下:http://www.itnos ...

  9. wex5 实战 二维码生成,扫描,蓝牙打印

    给人设计了一个小模块,要求是,把一个单号生成二维码,实现扫描查询单号具体信息,并能通过蓝牙把二维码打印出来.功能实现并不复杂,今天一口气把它搞定.来看效果. 一   效果演示: 二.二维码生成 1 在 ...

随机推荐

  1. junit初探

    由于公司规模不大,所以测试方面一直不是很正规,都是做完一个功能,稍微测试一下,没有做单元测试,所以自然也没有接触过类似于junit这类测试的工具. 今天有空研究了一下junit,顾名思义,这是给jav ...

  2. JavaScript基础2——关于变量

    变量的声明                            变量的定义:使用var关键字来声明,区分大小写的.注意:不用var,会污染全局变量.        变量的命名规范是:字母,数字,$符 ...

  3. iOS 常用到的宏#define

    //AppDelegate #define APPDELEGATE [(AppDelegate*)[UIApplication sharedApplication] delegate] //----- ...

  4. SSH框架完全整合

    大三学期渐末,事情也挺多的,上周就开始着手整合SSH框架,到现在才真正的完成,过程中碰到了许多小问题(小问题大折腾,哭脸.jpg).本着善始善终的原则,最终把它给完成了. 本篇文章就在: win7 6 ...

  5. [array] leetcode - 41. First Missing Positive - Hard

    leetcode - 41. First Missing Positive - Hard descrition Given an unsorted integer array, find the fi ...

  6. C++ 头文件系列(iomanip)

    1. 简介 该头文件定义了一些参数化的操纵器(manipulatators),注意ios头文件也定义了一些. 2. maniapulators 2.1 C++98 resetiosflags : 重置 ...

  7. CubeSuit+ ( CS+ for ca )

    作为瑞萨单片机的初学者,最先接触的当属它的IDE了,接下来我将分享一些我使用这款单片机的心得,以供大家参考. 我使用的是RL78F13系列R5F10BGE,那如何建立一个能使用的工程呢?相信大家在网络 ...

  8. asp.net MVC分页

    .Net MVC  分页代码,分页的关键就是在于这几个参数pageIndex ,recordCount,pageSize ,下面是张林的网站做的一个简单的分页代码 效果如图 public class ...

  9. python 将文件夹内的图片转换成PDF

    import os import stringfrom PIL import Imagefrom reportlab.lib.pagesizes import A4, landscapefrom re ...

  10. rabbitmq 启动报错

    =============================================== 2017/10/24_第1次修改                       ccb_warlock = ...