電子發票 QR碼產生用程式碼 C# .NET
來源:財政部
註解:me
使用時注意 namespace
註解:me
使用時注意 namespace
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace tw.gov.nat.einvoice.qrutil
{
class QREncrypter
{
/// <summary>
/// 將發票資訊文字加密成驗證文字
/// </summary>
/// <param name="plainText">發票資訊</param>
/// <param name="AESKey">種子密碼(QRcode)</param>
/// <returns>加密後的HEX字串</returns>
public string AESEncrypt(string plainText, string AESKey)
{
byte[] bytes = Encoding.Default.GetBytes(plainText);
ICryptoTransform transform = new RijndaelManaged
{
KeySize = 0x80,
Key = this.convertHexToByte(AESKey),
BlockSize = 0x80,
IV = Convert.FromBase64String("Dt8lyToo17X/XkXaQvihuA==")
}.CreateEncryptor();
MemoryStream stream = new MemoryStream();
CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write);
stream2.Write(bytes, 0, bytes.Length);
stream2.FlushFinalBlock();
stream2.Close();
return Convert.ToBase64String(stream.ToArray());
}
/// <summary>
/// 轉換HEX值為 Binaries
/// </summary>
/// <param name="hexString">HEX字串</param>
/// <returns>Binaries值</returns>
private byte[] convertHexToByte(string hexString)
{
byte[] buffer = new byte[hexString.Length / 2];
int index = 0;
for (int i = 0; i < hexString.Length; i += 2)
{
int num3 = Convert.ToInt32(hexString.Substring(i, 2), 0x10);
buffer[index] = BitConverter.GetBytes(num3)[0];
index++;
}
return buffer;
}
/// <summary>
/// 檢查發票輸入資訊
/// </summary>
/// <param name="InvoiceNumber">發票字軌號碼共 10 碼</param>
/// <param name="InvoiceDate">發票開立年月日(中華民國年份月份日期)共 7 碼</param>
/// <param name="InvoiceTime">發票開立時間 (24 小時制) 共 6 碼</param>
/// <param name="RandomNumber">4碼隨機碼</param>
/// <param name="SalesAmount">以整數方式載入銷售額 (未稅),若無法分離稅項則記載為0</param>
/// <param name="TaxAmount">以整數方式載入稅額,若無法分離稅項則記載為0</param>
/// <param name="TotalAmount">整數方式載入總計金額(含稅)</param>
/// <param name="BuyerIdentifier">買受人統一編號,若買受人為一般消費者,請填入 00000000 8位字串</param>
/// <param name="RepresentIdentifier">代表店統一編號,電子發票證明聯二維條碼規格已不使用代表店,請填入00000000 8位字串</param>
/// <param name="SellerIdentifier">銷售店統一編號</param>
/// <param name="BusinessIdentifier">總機構統一編號,如無總機構請填入銷售店統一編號</param>
/// <param name="productArray">單項商品資訊</param>
/// <param name="AESKey">加解密金鑰(QR種子密碼)</param>
private void inputValidate(string InvoiceNumber,
string InvoiceDate,
string InvoiceTime,
string RandomNumber,
decimal SalesAmount,
decimal TaxAmount,
decimal TotalAmount,
string BuyerIdentifier,
string RepresentIdentifier,
string SellerIdentifier,
string BusinessIdentifier,
Array[] productArray,
string AESKey)
{
if (string.IsNullOrEmpty(InvoiceNumber) || (InvoiceNumber.Length != 10))
{
throw new Exception("Invaild InvoiceNumber: " + InvoiceNumber);
}
if (string.IsNullOrEmpty(InvoiceDate) || (InvoiceDate.Length != 7))
{
throw new Exception("Invaild InvoiceDate: " + InvoiceDate);
}
try
{
long num = long.Parse(InvoiceDate);
int num2 = int.Parse(InvoiceDate.Substring(3, 2));
int num3 = int.Parse(InvoiceDate.Substring(5));
if ((num2 < 1) || (num2 > 12))
{
throw new Exception();
}
if ((num3 < 1) || (num3 > 0x1f))
{
throw new Exception();
}
}
catch (Exception)
{
throw new Exception("Invaild InvoiceDate: " + InvoiceDate);
}
if (string.IsNullOrEmpty(InvoiceTime))
{
throw new Exception("Invaild InvoiceTime: " + InvoiceTime);
}
if (string.IsNullOrEmpty(RandomNumber) || (RandomNumber.Length != 4))
{
throw new Exception("Invaild RandomNumber: " + RandomNumber);
}
if (SalesAmount < 0M)
{
throw new Exception("Invaild SalesAmount: " + SalesAmount);
}
if (TotalAmount < 0M)
{
throw new Exception("Invaild TotalAmount: " + TotalAmount);
}
if (string.IsNullOrEmpty(BuyerIdentifier) || (BuyerIdentifier.Length != 8))
{
throw new Exception("Invaild BuyerIdentifier: " + BuyerIdentifier);
}
if (string.IsNullOrEmpty(RepresentIdentifier))
{
throw new Exception("Invaild RepresentIdentifier: " + RepresentIdentifier);
}
if (string.IsNullOrEmpty(SellerIdentifier) || (SellerIdentifier.Length != 8))
{
throw new Exception("Invaild SellerIdentifier: " + SellerIdentifier);
}
if (string.IsNullOrEmpty(BusinessIdentifier))
{
throw new Exception("Invaild BusinessIdentifier: " + BusinessIdentifier);
}
if ((productArray == null) || (productArray.Length == 0))
{
throw new Exception("Invaild ProductArray");
}
if (string.IsNullOrEmpty(AESKey))
{
throw new Exception("Invaild AESKey");
}
}
/// <summary>
/// 產生發票左邊QR碼
/// </summary>
/// <param name="InvoiceNumber">發票字軌號碼共 10 碼</param>
/// <param name="InvoiceDate">發票開立年月日(中華民國年份月份日期)共 7 碼</param>
/// <param name="InvoiceTime">發票開立時間 (24 小時制) 共 6 碼</param>
/// <param name="RandomNumber">4碼隨機碼</param>
/// <param name="SalesAmount">以整數方式載入銷售額 (未稅),若無法分離稅項則記載為0</param>
/// <param name="TaxAmount">以整數方式載入稅額,若無法分離稅項則記載為0</param>
/// <param name="TotalAmount">整數方式載入總計金額(含稅)</param>
/// <param name="BuyerIdentifier">買受人統一編號,若買受人為一般消費者,請填入 00000000 8位字串</param>
/// <param name="RepresentIdentifier">代表店統一編號,電子發票證明聯二維條碼規格已不使用代表店,請填入00000000 8位字串</param>
/// <param name="SellerIdentifier">銷售店統一編號</param>
/// <param name="BusinessIdentifier">總機構統一編號,如無總機構請填入銷售店統一編號</param>
/// <param name="productArray">單項商品資訊</param>
/// <param name="AESKey">加解密金鑰(QR種子密碼)</param>
/// <returns></returns>
public string QRCodeINV(string InvoiceNumber,
string InvoiceDate,
string InvoiceTime,
string RandomNumber,
decimal SalesAmount,
decimal TaxAmount,
decimal TotalAmount,
string BuyerIdentifier,
string RepresentIdentifier,
string SellerIdentifier,
string BusinessIdentifier,
string[][] productArray,
string AESKey)
{
try
{
this.inputValidate(InvoiceNumber,
InvoiceDate,
InvoiceTime,
RandomNumber,
SalesAmount,
TaxAmount,
TotalAmount,
BuyerIdentifier,
RepresentIdentifier,
SellerIdentifier,
BusinessIdentifier,
productArray,
AESKey);
}
catch (Exception exception)
{
throw exception;
}
return ((InvoiceNumber +
InvoiceDate +
RandomNumber +
Convert.ToInt32(SalesAmount).ToString("x8") +
Convert.ToInt32(TotalAmount).ToString("x8") +
BuyerIdentifier + SellerIdentifier) +
this.AESEncrypt(InvoiceNumber + RandomNumber, AESKey).PadRight(0x18));
}
}
}
留言
這個是固定寫死的嗎?
這是向財政部索取『加解密API』裡面有包含的 .NET 檔案,但是目前財政部網站好像看不到,您可以試著向財政部負責人員索取連結看看
是的,這是寫死的,這是AES加密用的vectory值(如果你自己要寫AES加密就要用到),建議直接引入『加解密API』裡面包含的DLL就有此加解密方法可用,省得自己寫
有沒有甚麼需要注意的地方?
其中傳入的第二個參數 AESKey是32碼金鑰 嗎?
IV = Convert.FromBase64String("Dt8lyToo17X/XkXaQvihuA==")
所以您貼的這段程式碼,我用在統一發票QR Code,是可以直接照copy使用嗎?
應該說整個dll可以正常用來電子發票的QR code加密使用,對吧?
不,自己包的話當然可以改,只是將來財政部如果有更新這段程式碼,下次你在包的時候就要記得改
這個是可以WORK的沒有問題,實際上使用時我不會自己打包這段程式碼,而是直接使用財政部提供的DLL檔,如果你使用財政部的DLL檔案,就必須使用它原本的namespace了(使用using引入)
是的,這個Key就是32碼金鑰,它的來源是拿你在財政部電子發票平台設定的金鑰(非32碼)丟給它提供的工具genkey.bat去產生32碼金鑰
這個IV值是固定的,當你做AES加密時會需要3個東西,分別是來源字串(Source)、金鑰(KEY)、向量(IV),但一般不會用到IV值的設定,因此財政部才把它固定寫死,當然就是全省統一了,這段程式碼片段是我用來學習使用的,為了避免將來財政部更新加密規則或IV值,所以我直接使用它的DLL,這樣以後有更新我只要更換DLL就好,不需要重寫程式碼或是重新編譯程式。
很容易的就能使用 TurnKey, 而且用戶端不用安裝 SQL, 並提供
"自行檢測V4.4"工具, 讓使用者很簡單的依照指示,就能完成檢測,
並取得上線通行碼, 正常情形15個工作天,即可完成.
此 .NET SDK DLL 並包含電子發票證明聯 5.7*9 熱感紙列印.
宜普科技 凌培軍 0927-217786