跳轉到

ZUGFeRD 電子發票

ZUGFeRD(Zentraler User Guide des Forums elektronische Rechnung Deutschland)是歐洲主流的混合型電子發票標準,將人類可讀的 PDF 與機器可讀的 XML(EN 16931 格式)合併在同一份 PDF/A-4f 文件中。

NextPDF Enterprise 提供完整的 ZUGFeRD 2.x 生成管線,包含 XML 建構、Schema 驗證、PDF/A-4f 嵌入,以及 Factur-X 相容性。


支援 Profile

Profile 用途 XML 複雜度 強制欄位
MINIMUM 最小基礎資訊(Factur-X 相容) 極低 發票號、日期、金額、VAT
BASIC WL 基礎行次明細 + 行次說明
BASIC 完整 EN 16931 必要資訊 + 稅務分類、付款條件
COMFORT 推薦商業用途(EN 16931 全集) 中高 + 買賣方完整資訊、多稅率
EXTENDED 進階行次與物流資訊 + 交付資訊、允許自定義擴充
XRECHNUNG 德國政府 B2G 採購專用 中高 符合 XRechnung 2.3

核心 API

ZugferdBuilder

use NextPDF\Enterprise\Invoice\ZugferdBuilder;
use NextPDF\Enterprise\Invoice\ZugferdProfile;
use NextPDF\Enterprise\Invoice\InvoiceParty;
use NextPDF\Enterprise\Invoice\InvoiceLine;
use NextPDF\Enterprise\Invoice\TaxCategory;
use NextPDF\Enterprise\Invoice\MonetaryAmount;

$invoice = ZugferdBuilder::create(ZugferdProfile::Comfort)
    ->withInvoiceNumber('INV-2025-001234')
    ->withInvoiceDate(new DateTimeImmutable('2025-01-15'))
    ->withDueDate(new DateTimeImmutable('2025-02-14'))
    ->withCurrency('EUR')
    ->withSeller(
        InvoiceParty::create(
            name: 'ACME GmbH',
            vatId: 'DE123456789',
            address: InvoiceAddress::create(
                line1: 'Musterstraße 42',
                city: 'Berlin',
                postCode: '10115',
                countryCode: 'DE',
            ),
            contact: InvoiceContact::create(
                name: 'Hans Müller',
                email: '[email protected]',
                phone: '+49 30 12345678',
            ),
        )
    )
    ->withBuyer(
        InvoiceParty::create(
            name: 'Widget AG',
            vatId: 'CHE-123.456.789',
            address: InvoiceAddress::create(
                line1: 'Bahnhofstrasse 1',
                city: 'Zürich',
                postCode: '8001',
                countryCode: 'CH',
            ),
        )
    )
    ->addLine(
        InvoiceLine::create(
            id: '1',
            description: 'Professional Services — Q4 2024',
            quantity: MonetaryAmount::units(8.0),
            unitCode: 'HUR', // UN/ECE Rec 20: Hours
            unitPrice: MonetaryAmount::eur(125.00),
            taxCategory: TaxCategory::Standard,
            taxPercent: 19.0,
        )
    )
    ->addLine(
        InvoiceLine::create(
            id: '2',
            description: 'Software License — Annual',
            quantity: MonetaryAmount::units(1.0),
            unitCode: 'C62', // Each
            unitPrice: MonetaryAmount::eur(2400.00),
            taxCategory: TaxCategory::Standard,
            taxPercent: 19.0,
        )
    )
    ->withPaymentTerms('30 days net')
    ->withPaymentMeans(
        PaymentMeans::sepa(
            iban: 'DE89370400440532013000',
            bic: 'COBADEFFXXX',
        )
    );

// 產生 ZUGFeRD XML
$xml = $invoice->buildXml();

// 產生 PDF/A-4f 發票(XML 嵌入為關聯檔案)
$pdfInvoice = $invoice->buildPdf(
    visualTemplate: $invoicePdfTemplate,
);

PHP Compatibility

This example uses PHP 8.5 syntax. If your environment runs PHP 8.1 or 7.4, use NextPDF Backport for a backward-compatible build.

XML 驗證

use NextPDF\Enterprise\Invoice\ZugferdValidator;
use NextPDF\Enterprise\Invoice\ValidationLevel;

$validator = new ZugferdValidator();

// 多層次驗證
$result = $validator->validate(
    xmlContent: $xml,
    profile: ZugferdProfile::Comfort,
    level: ValidationLevel::Full, // Schema + Schematron + EN 16931 semantic rules
);

if (!$result->isValid()) {
    foreach ($result->errors() as $error) {
        echo sprintf(
            '[%s] %s (xpath: %s)',
            $error->severity()->name,   // ERROR | WARNING | INFO
            $error->message(),
            $error->xpath(),
        );
    }
}

PDF/A-4f 整合

ZUGFeRD 強制要求 PDF/A-4f 容器格式:

use NextPDF\Enterprise\Invoice\ZugferdPdfEmitter;
use NextPDF\Enterprise\Compliance\PdfA\PdfA4Builder;
use NextPDF\Enterprise\Compliance\PdfA\PdfA4Subset;

// ZugferdPdfEmitter 自動處理 PDF/A-4f 嵌入
$emitter = new ZugferdPdfEmitter(
    pdfBuilder: PdfA4Builder::forSubset(PdfA4Subset::PdfA4f),
);

$invoicePdf = $emitter->emit(
    invoiceXml: $xml,
    visualPdf: $renderedInvoicePdf,
    filename: 'factur-x.xml', // ZUGFeRD 標準要求此確切檔名
);

// 或直接從 ZugferdBuilder 一步完成
$invoicePdf = $invoice->buildPdf(visualTemplate: $template);

稅務計算

use NextPDF\Enterprise\Invoice\TaxCalculator;
use NextPDF\Enterprise\Invoice\VatRoundingMode;

$calculator = new TaxCalculator(
    roundingMode: VatRoundingMode::HalfUp,
    precision: 2,
);

// 自動計算行次小計、VAT、發票總計
$totals = $calculator->calculateTotals($invoiceLines);

echo $totals->netAmount();          // 未稅金額
echo $totals->taxAmount();          // 稅額
echo $totals->grossAmount();        // 含稅總計
echo $totals->taxBreakdown();       // 各稅率分項(多稅率支援)

Factur-X 相容性

ZUGFeRD 2.x 與法法共同定義的 Factur-X 1.0 完全相容:

use NextPDF\Enterprise\Invoice\FacturXBuilder;

// Factur-X 使用相同 API,僅 profile 命名不同
$invoice = FacturXBuilder::create(FacturXProfile::En16931)
    // ... 相同建構方法
    ->buildPdf(visualTemplate: $template);

延伸閱讀