跳轉到

ZUGFeRD 電子發票範例(Enterprise)

需求套件nextpdf/enterprise 難度:進階

先決條件

composer require nextpdf/enterprise

ZUGFeRD 設定檔說明

設定檔 適用場景 XML 欄位數量
MINIMUM 最基本(僅供 B2C)
BASIC 標準 B2B 中等
EN-16931 歐盟標準(推薦) 完整
XRECHNUNG 德國政府採購 完整(特定格式)

完整程式碼

<?php

declare(strict_types=1);

use NextPDF\Enterprise\EInvoice\ZugferdBuilder;
use NextPDF\Enterprise\EInvoice\ValueObjects\ZugferdProfile;
use NextPDF\Enterprise\EInvoice\ValueObjects\TradeParty;
use NextPDF\Enterprise\EInvoice\ValueObjects\Address;
use NextPDF\Enterprise\EInvoice\ValueObjects\TaxRegistration;
use NextPDF\Enterprise\EInvoice\ValueObjects\LineItem;
use NextPDF\Enterprise\EInvoice\ValueObjects\Tax;
use NextPDF\Enterprise\EInvoice\ValueObjects\PaymentTerms;
use NextPDF\Enterprise\EInvoice\ValueObjects\BankAccount;
use NextPDF\Core\Document;
use NextPDF\Core\ValueObjects\PageSize;
use NextPDF\Core\ValueObjects\Margin;

// ─── 發票資料 ─────────────────────────────────────────────────
$invoiceNumber = 'INV-2024-DE-001';
$issueDate     = new DateTimeImmutable('2024-03-15');
$dueDate       = new DateTimeImmutable('2024-04-14');

// ─── 賣方資訊 ─────────────────────────────────────────────────
$seller = TradeParty::create(
    name:    'NextPDF Technology GmbH',
    address: Address::create(
        street:     'Musterstraße 42',
        city:       'Berlin',
        postalCode: '10115',
        country:    'DE',
    ),
    taxId:          TaxRegistration::vatId('DE123456789'),
    globalId:       '4012345678901',  // GLN(可選)
    contactEmail:   '[email protected]',
    contactPhone:   '+49 30 12345678',
);

// ─── 買方資訊 ─────────────────────────────────────────────────
$buyer = TradeParty::create(
    name:    'Musterkunde AG',
    address: Address::create(
        street:     'Hauptstraße 100',
        city:       'München',
        postalCode: '80331',
        country:    'DE',
    ),
    taxId:   TaxRegistration::vatId('DE987654321'),
    buyerReference: 'PO-2024-0042',  // Leitweg-ID(德國政府採購必填)
);

// ─── 發票明細 ─────────────────────────────────────────────────
$lineItems = [
    LineItem::create(
        id:          '1',
        name:        'NextPDF Enterprise Annual License',
        description: 'Full year enterprise PDF generation license (PDF 2.0, PAdES B-LTA, PDF/A-4)',
        quantity:    1.0,
        unitCode:    'C62',  // UN/ECE Unit Code: piece
        unitPrice:   4_990.00,
        tax:         Tax::create(rate: 19.0, categoryCode: 'S'),  // Standard rate
    ),
    LineItem::create(
        id:          '2',
        name:        'Technical Support Package (10h)',
        description: 'Premium technical support, 10 hours, valid 12 months',
        quantity:    10.0,
        unitCode:    'HUR',  // Hours
        unitPrice:   150.00,
        tax:         Tax::create(rate: 19.0, categoryCode: 'S'),
    ),
    LineItem::create(
        id:          '3',
        name:        'CJK Font Bundle License',
        description: 'Commercial license for CJK font package (TC, SC, JP, KR)',
        quantity:    1.0,
        unitCode:    'C62',
        unitPrice:   299.00,
        tax:         Tax::create(rate: 19.0, categoryCode: 'S'),
    ),
];

// ─── 建立 ZUGFeRD 文件 ────────────────────────────────────────
$builder = ZugferdBuilder::create(
    profile: ZugferdProfile::EN16931,  // EN 16931(COMFORT)設定檔
);

$zugferd = $builder->build(
    invoiceNumber:  $invoiceNumber,
    issueDate:      $issueDate,
    dueDate:        $dueDate,
    seller:         $seller,
    buyer:          $buyer,
    lineItems:      $lineItems,
    paymentTerms:   PaymentTerms::create(
        description: 'Zahlbar innerhalb von 30 Tagen netto.',
        bankAccount: BankAccount::create(
            iban: 'DE89370400440532013000',
            bic:  'COBADEFFXXX',
        ),
    ),
    note:           'Vielen Dank für Ihr Vertrauen in NextPDF!',
    currency:       'EUR',
    buyerOrderReference: 'PO-2024-0042',
);

// ─── 生成 PDF/A-3 視覺 PDF(可視為發票外觀)───────────────────
$pdfDocument = Document::createStandalone(
    pageSize: PageSize::A4,
    margin:   Margin::symmetric(vertical: 20.0, horizontal: 25.0),
);

$page = $pdfDocument->pages()->add();

// 渲染視覺發票(使用 Core API)
// ... (與 invoice.zh-TW.md 範例相同的視覺渲染程式碼)...

// ─── 嵌入 ZUGFeRD XML 並轉換為 PDF/A-3 ──────────────────────
$finalDocument = $zugferd->embedInto(
    document:     $pdfDocument,
    conformance:  'PDF/A-3B',  // ZUGFeRD 要求 PDF/A-3B 或更高
    xmlFilename:  'factur-x.xml',
);

$finalDocument->save('/output/invoice-zugferd-' . $invoiceNumber . '.pdf');

// ─── 驗證輸出 ─────────────────────────────────────────────────
$validator = $zugferd->validator();
$result    = $validator->validateFile('/output/invoice-zugferd-' . $invoiceNumber . '.pdf');

if (!$result->isValid()) {
    foreach ($result->errors() as $error) {
        error_log("ZUGFeRD Validation Error: {$error->code()}{$error->message()}");
    }
    throw new RuntimeException('ZUGFeRD validation failed: ' . $result->errorSummary());
}

echo "ZUGFeRD invoice generated successfully.\n";
echo "Profile: {$result->profile()}\n";
echo "Conformance: {$result->conformance()}\n";

程式碼說明

驗證工具

延伸閱讀