ZUGFeRD / Factur-X e-Invoice
Tạo hóa đơn điện tử ZUGFeRD / Factur-X — PDF hybrid mà con người có thể đọc và máy có thể phân tích tự động.
ZUGFeRD / Factur-X là gì?
ZUGFeRD (Đức) và Factur-X (Pháp / EU) là cùng một chuẩn dưới hai tên. Hóa đơn tuân thủ chứa:
- PDF trực quan — hóa đơn người đọc được render dạng PDF/A-3 (hoặc PDF/A-4f)
- XML nhúng — dữ liệu hóa đơn máy đọc được theo định dạng UN/CEFACT Cross Industry Invoice (CII), đính kèm bên trong PDF
Điều này cho phép xử lý tự động hoàn toàn trong khi giữ document trực quan quen thuộc cho kế toán và kiểm toán.
Profile
| Profile | Sử dụng thông thường |
|---|---|
| Minimum | Số hóa đơn, ngày, tổng cộng, thuế |
| Basic WL | + Mục hàng, điều khoản thanh toán |
| Basic | + Mục hàng chi tiết |
| EN 16931 (Comfort) | Tuân thủ mua sắm công EU |
| Extended | Hóa đơn đa thuế phức tạp |
| XRechnung | Hóa đơn khu vực công Đức |
Yêu cầu PDF/A
ZUGFeRD yêu cầu PDF chủ phải là PDF/A-3 hoặc PDF/A-4f (ISO 19005). Biến thể "f" cho phép file nhúng. TCPDF-Next xử lý metadata tuân thủ, output intent và cờ đính kèm file tự động.
Ví dụ code đầy đủ
php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use TcpdfNext\Document;
use TcpdfNext\Enums\PdfALevel;
use TcpdfNext\Archive\OutputIntent;
use TcpdfNext\Archive\EmbeddedFile;
use TcpdfNext\Archive\AFRelationship;
// ── 1. Tạo document PDF/A-4f ──────────────────────────────────────
$pdf = Document::create()
->setPdfALevel(PdfALevel::A4F)
->setOutputIntent(OutputIntent::sRGB())
->setTitle('Invoice INV-2026-0042')
->setAuthor('Acme GmbH')
->setSubject('Invoice for Order PO-2026-0815');
// ── 2. Render hóa đơn trực quan ───────────────────────────────────
$invoiceHtml = <<<'HTML'
<h1 style="color:#1a2634;">INVOICE</h1>
<table style="width:100%; margin-bottom:20px;">
<tr>
<td><strong>Acme GmbH</strong><br>Friedrichstr. 123<br>10117 Berlin, DE</td>
<td style="text-align:right;"><strong>INV-2026-0042</strong><br>Date: 2026-02-15<br>Due: 2026-03-17</td>
</tr>
</table>
<table border="1" cellpadding="6" style="width:100%; border-collapse:collapse;">
<thead>
<tr style="background:#1a2634; color:#fff;">
<th>#</th><th>Description</th><th style="text-align:right;">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Professional Services -- February 2026</td>
<td style="text-align:right;">EUR 1,000.00</td>
</tr>
</tbody>
<tfoot>
<tr><td colspan="2" style="text-align:right;">Net</td><td style="text-align:right;">EUR 1,000.00</td></tr>
<tr><td colspan="2" style="text-align:right;">VAT 19%</td><td style="text-align:right;">EUR 190.00</td></tr>
<tr style="font-weight:bold;">
<td colspan="2" style="text-align:right;">Total</td>
<td style="text-align:right;">EUR 1,190.00</td>
</tr>
</tfoot>
</table>
HTML;
$pdf->addPage()
->setFont('helvetica', size: 10)
->writeHtml($invoiceHtml);
// ── 3. Xây dựng Factur-X XML (profile EN 16931) ───────────────────
$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
<rsm:ExchangedDocumentContext>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:factur-x.eu:1p0:en16931</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>INV-2026-0042</ram:ID>
<ram:TypeCode>380</ram:TypeCode>
<ram:IssueDateTime>
<udt:DateTimeString format="102">20260215</udt:DateTimeString>
</ram:IssueDateTime>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<ram:ApplicableHeaderTradeAgreement>
<ram:SellerTradeParty>
<ram:Name>Acme GmbH</ram:Name>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">DE123456789</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:SellerTradeParty>
<ram:BuyerTradeParty>
<ram:Name>Customer Corp</ram:Name>
</ram:BuyerTradeParty>
</ram:ApplicableHeaderTradeAgreement>
<ram:ApplicableHeaderTradeSettlement>
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:LineTotalAmount>1000.00</ram:LineTotalAmount>
<ram:TaxBasisTotalAmount>1000.00</ram:TaxBasisTotalAmount>
<ram:TaxTotalAmount currencyID="EUR">190.00</ram:TaxTotalAmount>
<ram:GrandTotalAmount>1190.00</ram:GrandTotalAmount>
<ram:DuePayableAmount>1190.00</ram:DuePayableAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>
XML;
// ── 4. Nhúng XML dạng file liên kết ─────────────────────────────
$pdf->addEmbeddedFile(
EmbeddedFile::create()
->setFilename('factur-x.xml')
->setMimeType('text/xml')
->setContent($xml)
->setRelationship(AFRelationship::Alternative)
->setDescription('Factur-X EN 16931 invoice data')
);
// ── 5. Thiết lập ZUGFeRD XMP metadata ────────────────────────────
$pdf->getMetadata()
->setXmpProperty('fx:DocumentType', 'INVOICE')
->setXmpProperty('fx:DocumentFileName', 'factur-x.xml')
->setXmpProperty('fx:Version', '1.0')
->setXmpProperty('fx:ConformanceLevel', 'EN 16931');
// ── 6. Lưu ──────────────────────────────────────────────────────
$pdf->save(__DIR__ . '/INV-2026-0042.pdf');
echo 'ZUGFeRD invoice created.' . PHP_EOL;Validation
bash
# Tuân thủ PDF/A
verapdf --flavour 4f INV-2026-0042.pdf
# Schema Factur-X XML
java -jar Mustang-CLI.jar --action validate --source INV-2026-0042.pdfTIP
Mustangproject là công cụ validation miễn phí mã nguồn mở cho hóa đơn ZUGFeRD/Factur-X.
Sơ đồ workflow
Dữ liệu ERP / hóa đơn
|
v
TCPDF-Next generate
|
v
PDF/A-4f + nhúng factur-x.xml
|
v
(tùy chọn) Chữ ký số PAdES
|
+-------+-------+-------+
| | | |
Email Portal PEPPOL Lưu trữĐọc thêm
- PDF/A-4 lưu trữ -- Chi tiết tuân thủ ISO 19005-4
- Workflow PAdES B-LTA -- Ký số hóa đơn