如何在Flutter中解码符合ZATCA规范的QR码并提取对应字段?
Flutter 解析ZATCA规范二维码获取指定字段的实现方案
首先明确:ZATCA电子发票二维码采用TLV(标签-长度-值)二进制编码规则,你当前直接将base64解码后的字节转为UTF8字符串的操作无法直接拆分字段,需要直接对二进制字节数组做TLV结构解析。
1. 先定义存储发票信息的结构化类
class ZATCAInvoiceInfo { /// 卖家名称 final String sellerName; /// 卖家VAT注册编号 final String sellerVatNumber; /// 票据时间戳 final DateTime invoiceTime; /// VAT总金额 final double totalVat; /// 票据总金额 final double totalInvoiceAmount; ZATCAInvoiceInfo({ required this.sellerName, required this.sellerVatNumber, required this.invoiceTime, required this.totalVat, required this.totalInvoiceAmount, }); }
2. 编写TLV解析函数
不需要用到你之前生成的utf8data,直接处理base64解码得到的字节数组即可:
import 'dart:convert'; import 'dart:typed_data'; ZATCAInvoiceInfo parseZATCAQRCode(String qrBase64Content) { // 解码二维码得到的base64字符串为字节数组 Uint8List rawBytes = base64.decode(qrBase64Content); int currentOffset = 0; Map<int, String> tlvResult = {}; // 遍历解析TLV结构 while (currentOffset < rawBytes.length) { // 读取1字节标签 int tag = rawBytes[currentOffset]; currentOffset += 1; // 读取1字节值长度 int valueLength = rawBytes[currentOffset]; currentOffset += 1; // 读取对应长度的字节转成UTF8字符串 Uint8List valueBytes = rawBytes.sublist(currentOffset, currentOffset + valueLength); String value = utf8.decode(valueBytes); tlvResult[tag] = value; currentOffset += valueLength; } // 映射标签对应字段,ZATCA规范中前5个标签固定对应需求字段 return ZATCAInvoiceInfo( sellerName: tlvResult[1] ?? '', sellerVatNumber: tlvResult[2] ?? '', invoiceTime: DateTime.parse(tlvResult[3] ?? ''), totalVat: double.tryParse(tlvResult[4] ?? '0') ?? 0.0, totalInvoiceAmount: double.tryParse(tlvResult[5] ?? '0') ?? 0.0, ); }
3. 调用示例
// qrScanResult 为你扫描二维码得到的原始base64字符串 String qrScanResult = '你的二维码扫描结果'; ZATCAInvoiceInfo invoice = parseZATCAQRCode(qrScanResult); // 直接读取对应字段即可 debugPrint('卖家名称:${invoice.sellerName}'); debugPrint('票据总金额:${invoice.totalInvoiceAmount}');
注意事项
- 符合ZATCA规范的合规二维码前5个标签固定为1-5,和需求字段一一对应,无需额外适配
- 时间戳为ISO8601标准格式,可直接用
DateTime.parse解析 - 如果出现解析异常,优先检查扫描得到的base64字符串是否完整、是否为ZATCA合规发票二维码
内容的提问来源于stack exchange,提问作者mohamad kamel
相关产品推荐
相关产品推荐

