Nếu bạn gửi e-invoices cho khách hàng B2B ở Đức trong năm 2026, file đó hoặc ZUGFeRD-compliant, hoặc sẽ bị bounce khi nhận. Ở Pháp với Factur-X cũng vậy. Format là một PDF/A-3 wrapper kèm EN 16931 CII XML attached; generate từ đầu không đơn giản, và validate cần reference engine.
Trong thực tế engine đó là Mustang (mustangproject.org): một open-source Java project trích xuất embedded XML từ PDF/A-3 và validate theo EN 16931 Schematron. Mustang có support sâu nhất cho ZUGFeRD và Factur-X trong nhóm open-source tools, và nhiều independent verifiers cũng chạy nó.
Bài này đi qua các failure modes Mustang flag và cách chạy nhanh hơn.
Mustang thực sự check gì
Khi đưa Factur-X hoặc ZUGFeRD PDF vào Mustang, nó thường làm:
- Extract embedded file. PDF/A-3 lưu attachments trong name tree
/EmbeddedFiles. Mustang tìm canonical filename (factur-x.xmlcho Factur-X,zugferd-invoice.xmlcho ZUGFeRD 2.x) rồi đọc bytes. - Check AFRelationship. Attached file phải khai báo
AFRelationship="Alternative"theo baseline Factur-X / ZUGFeRD. Giá trị khác (Source,Data,Supplement) sẽ fail. - Check XMP namespace và version. Factur-X 1.0 dùng
urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#. ZUGFeRD 2.x dùngurn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#. Sai namespace hoặc version string sẽ fail. - Parse XML như Cross-Industry Invoice (CII). XML phải well-formed và bắt đầu với CII root element đúng (
rsm:CrossIndustryInvoice). - Run EN 16931 Schematron. Đây là phần chính: khoảng 200 business rules về field semantics, mandatory codes, totals math, VAT logic, party identifiers, v.v.
Pass nghĩa là invoice chấp nhận được với mọi EN 16931-conformant AP system trong EU. Fail nghĩa là AP automation của khách hàng sẽ reject invoice khi nhận và AR team phải xử lý manual exception.
Năm failure mode thường gặp nhất
Chúng xuất hiện nhiều ở cột Mustang của validator khi team test những e-invoices đầu tiên.
1. Wrong AFRelationship
ERROR: Embedded file factur-x.xml uses AFRelationship="Source",
expected "Alternative".
PDF spec cho phép nhiều relationship types cho attached files. Factur-X / ZUGFeRD yêu cầu Alternative, nghĩa là attached XML là alternative representation của visible PDF content. Nếu PDF generator dùng Data (default trong nhiều libraries), Mustang fail ngay. PDF nhìn vẫn render đúng, nhưng structured payload không hợp lệ với AP system.
2. Wrong / missing XMP namespace
ERROR: XMP metadata missing fx:DocumentType or fx:DocumentFileName under
namespace urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#.
XMP packet của PDF phải khai báo đây là Factur-X profile nào (MINIMUM, BASIC, EN 16931, EXTENDED) và filename nào cần tìm. Khi viết PDF/A-3 wrapper thủ công, chi tiết này rất dễ bị bỏ sót; endpoint /api/v1/e-invoice/render của gPdf auto-emit các trường đó.
3. CII XML well-formed nhưng EN 16931 Schematron fail
ERROR: BR-CO-25 — In an invoice (BR-01) the
ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime is required when
ram:DocumentTypeCode is 380.
Đây là phần lớn failure thực tế. XML valid về syntax; business rules fail. EN 16931 Schematron rules có stable IDs (BR-01, BR-CO-25, v.v.) có thể tra trong specification. Những lỗi thường gặp:
- BR-01: invoice phải có unique invoice number.
- BR-04: invoice phải có issue date.
- BR-05: invoice phải có invoice type code.
- BR-CO-25: payment terms required khi document type là “Commercial invoice”.
- BR-Z-01: VAT category codes phải là một trong
S,Z,E,AE,K,G,O,L,M.
Sửa source data, rebuild, rồi re-validate.
4. PDF/A wrapper không validate
INFO: CII XML extracted and validates against EN 16931.
ERROR: PDF/A-3b conformance check failed: missing Output Intent.
Trong case này XML check của Mustang pass, nhưng underlying PDF/A-3 wrapper fail. Nguyên nhân phổ biến: XML đúng, nhưng output là PDF thường chứ không phải PDF/A-3. Embedded file có mặt, nhưng archival wrapper rules không thỏa. Validator ở gpdf.com/validator/ bắt được bằng cách chạy veraPDF song song: PDF/A-3 fail hiện ở cột veraPDF, còn Mustang báo XML pass.
5. Encoding / declaration mismatch
ERROR: XML declares <?xml version="1.0" encoding="UTF-8"?> but the
embedded byte stream is UTF-8 with BOM. Mustang strict mode rejects BOM.
Khá thường gặp khi XML tool emit UTF-8 BOM rồi bytes đó được embed raw. Cách sửa: strip BOM trước khi embedding. Endpoint e-invoice của gPdf normalise bước này.
Cách chạy Mustang không cần cài Java
Cài Java + Mustang CLI vẫn ổn cho one-off check. Nhưng với ongoing verification — mỗi invoice generate, mỗi CI run assert e-invoice compliance — đó là friction không cần thiết.
gpdf.com/validator/ chạy Mustang trong browser:
- Drag Factur-X / ZUGFeRD PDF vào upload zone.
- Validator extract embedded XML và chạy Schematron engine của Mustang (compiled sang JavaScript / WebAssembly, run trong Cloudflare Worker).
- Mustang report trả về side-by-side với veraPDF PDF/A-3 report, vì cả hai layer đều phải pass.
- Download JSON report làm QA evidence.
Không login. Không quota. Cùng kiểu Mustang bạn cài qua Maven, nhưng được phục vụ như free public service.
TL;DR
Mustang flag 5 common failure modes; đa số quy về “file được generate bằng tool không emit fully-conformant Factur-X / ZUGFeRD PDF/A-3”. E-invoice API của gPdf emit file đó trong một call. validator verify kết quả bằng Mustang + veraPDF song song.
Phần lớn bug Mustang bắt được nằm ở wrapper hoặc AFRelationship, không chỉ XML semantics. Generate file đúng đã giải quyết phần lớn trận chiến; validator là receipt chứng minh điều đó.