Generate invoice assistant QR code

I heard about the invoice assistant before we had a meal. It can generate a two-dimensional code of the invoice header, and scan the code to make an invoice.
Official also has a small program of [tax invoice assistant], wechat search this name is OK.

I'm going to try it in my own small program. I thought it would be better if I spliced it to generate QR code. As a result, I found a lot of holes.
Refer to github for specific documents Convenient billing QR code application specification.pdf.

There's nothing wrong with splicing. The biggest problem is CRC-16. Found online CRC (cyclic redundancy check) online calculation It's always different from what the official program generates.
Several versions have been found on the Internet, most of which generate the same results as the above online calculation. Finally found a Java version of Calculation of CRC generated by QR code of invoice assistant of State Administration of Taxation After running, I found that the verification code was the same at last.

So it changed to C version, and added QRCode generation method (QRCoder package needs to be installed).

Version C code

public class ReceiptHelper
{
    private const int crc16 = 0x8005;

    private const string ReceiptQRCodePath = "Uploads\\Receipt\\";

    /// <summary>
    ///Generate QRCode image of invoice header
    /// </summary>
    ///< param name = "Id" > data ID < / param >
    ///< param name = "CompanyName" > Company Name < / param >
    ///< param name = "taxno" > taxpayer identification number < / param >
    ///< param name = "address" > address < / param >
    ///< param name = "phone" > phone < / param >
    ///< param name = "bankname" > opening bank < / param >
    ///< param name = "account" > account < / param >
    ///< returns > QRcode picture name < / 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>
    ///Generate QRCode content of invoice header
    /// </summary>
    ///< param name = "CompanyName" > Company Name < / param >
    ///< param name = "taxno" > taxpayer identification number < / param >
    ///< param name = "address" > address < / param >
    ///< param name = "phone" > phone < / param >
    ///< param name = "bankname" > opening bank < / param >
    ///< param name = "account" > account < / param >
    ///< returns > QRcode picture name < / 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 verification content
        string crcNo = CalcCRC16(crcInput); // Calculate CRC16 check code

        // Start symbol + version number + base64 (name < / > taxpayer identification number < / > address and telephone number < / > opening bank and account number < / > CRC) + end symbol 
        StringBuilder sbQRCode = new StringBuilder();
        sbQRCode.Append("$");
        sbQRCode.Append("01");
        sbQRCode.Append(Convert.ToBase64String(Encoding.UTF8.GetBytes(crcInput + crcNo)));
        sbQRCode.Append(" $");

        return sbQRCode.ToString();
    }

    /// <summary>
    ///Calculate CRC16 check code
    /// </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;
    }

}

Installation command of QRCoder

Install-Package QRCoder

You can also search for QRCoder installations through the NuGet tool.

Tags: C# QRCode encoding github Java

Posted on Sat, 02 May 2020 23:11:22 -0700 by pliant