UBL —— Universal Business Language —— 是 OASIS 标准,Peppol BIS、EN 16931、ZATCA Phase-2、阿联酋 PINT 子集、印度 IRP/e-invoice schema(带扩展)以及多个拉美制度都建立在它之上。如果你的电子发票战略不和 UBL 2.1 和解,你就会一遍又一遍地重复实现同一段 XML。
一份 UBL 发票长什么样
一份 UBL 发票是一个带三个主要命名空间的 XML 文档:cbc(Common Basic Components —— 像 ID 和 Amount 这样的基本类型)、cac(Common Aggregate Components —— 像 Party 和 TaxTotal 这样的复杂类型),以及文档自己的命名空间。每个 UBL 文档都遵循同样的结构:
<Invoice
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
<cbc:ID>INV-2026-0001</cbc:ID>
<cbc:IssueDate>2026-01-15</cbc:IssueDate>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cac:AccountingSupplierParty>...</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>...</cac:AccountingCustomerParty>
<cac:TaxTotal>...</cac:TaxTotal>
<cac:LegalMonetaryTotal>...</cac:LegalMonetaryTotal>
<cac:InvoiceLine>...</cac:InvoiceLine>
</Invoice>几乎总是被弄错的五个概念
- TaxTotal vs. LegalMonetaryTotal。前者按税率拆分税额,后者是合并后的应付总额。别混。
- AllowanceCharge 既可以是折扣也可以是附加费 —— 由 ChargeIndicator 控制(false = 折扣,true = 附加费)。指示器选错就总额错。
- Endpoint ID 需要 scheme 属性(如 schemeID="0088")。少了它,校验器会给出关于「缺失标识」的晦涩错误。
- 数量使用 UN/CEFACT 的单位代码(EA = 每件,KGM = 千克,HUR = 小时)。「piece」不是合法值。
- TaxCategory 使用 UNCL5305:S = 标准税率,Z = 零税率,E = 免税,AE = 反向征收。别自己造代码。
Invocie 的 EUStrategy 输出符合 BIS Billing 3.0 的 UBL 2.1 —— 同一份 XML 可用于 Peppol AP、阿联酋 PINT 子集,以及任何消费 EN 16931 的系统。