Skip to content

ZUGFeRD / Factur-X 전자 인보이스

사람이 읽을 수 있고 기계가 자동으로 파싱할 수 있는 하이브리드 PDF인 ZUGFeRD / Factur-X 전자 인보이스를 생성합니다.

ZUGFeRD / Factur-X란?

ZUGFeRD(독일)와 Factur-X(프랑스 / EU)는 두 이름으로 된 동일한 표준입니다. 규정 준수 인보이스는 다음을 포함합니다:

  1. 시각적 PDF -- PDF/A-3(또는 PDF/A-4f)로 렌더링된 사람이 읽을 수 있는 인보이스
  2. 임베디드 XML -- PDF 내에 첨부된 UN/CEFACT Cross Industry Invoice(CII) 형식의 기계 판독 가능한 인보이스 데이터

이를 통해 회계사와 감사관을 위한 익숙한 시각적 문서를 유지하면서 완전 자동화된 처리가 가능합니다.

프로파일

프로파일일반적 사용
Minimum인보이스 번호, 날짜, 합계, 세금
Basic WL+ 라인 항목, 결제 조건
Basic+ 상세 라인 항목
EN 16931 (Comfort)EU 공공 조달 규정 준수
Extended복잡한 다중 세금 인보이스
XRechnung독일 공공 부문 인보이스

PDF/A 요구사항

ZUGFeRD는 호스트 PDF가 PDF/A-3 또는 PDF/A-4f(ISO 19005)여야 합니다. "f" 변형은 임베디드 파일을 허용합니다. TCPDF-Next는 적합성 메타데이터, 출력 인텐트, 파일 첨부 플래그를 자동으로 처리합니다.

전체 코드 예제

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. 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. 시각적 인보이스 렌더링 ───────────────────────────────────────
$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. Factur-X XML 구성 (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. XML을 관련 파일로 임베딩 ─────────────────────────────
$pdf->addEmbeddedFile(
    EmbeddedFile::create()
        ->setFilename('factur-x.xml')
        ->setMimeType('text/xml')
        ->setContent($xml)
        ->setRelationship(AFRelationship::Alternative)
        ->setDescription('Factur-X EN 16931 invoice data')
);

// ── 5. ZUGFeRD XMP 메타데이터 설정 ────────────────────────────────
$pdf->getMetadata()
    ->setXmpProperty('fx:DocumentType', 'INVOICE')
    ->setXmpProperty('fx:DocumentFileName', 'factur-x.xml')
    ->setXmpProperty('fx:Version', '1.0')
    ->setXmpProperty('fx:ConformanceLevel', 'EN 16931');

// ── 6. 저장 ────────────────────────────────────────────────────────
$pdf->save(__DIR__ . '/INV-2026-0042.pdf');

echo 'ZUGFeRD invoice created.' . PHP_EOL;

검증

bash
# PDF/A 적합성
verapdf --flavour 4f INV-2026-0042.pdf

# Factur-X XML 스키마
java -jar Mustang-CLI.jar --action validate --source INV-2026-0042.pdf

TIP

Mustangproject는 ZUGFeRD/Factur-X 인보이스를 위한 무료 오픈소스 검증기입니다.

워크플로 다이어그램

ERP / 청구 데이터
        |
        v
  TCPDF-Next 생성
        |
        v
  PDF/A-4f + 임베디드 factur-x.xml
        |
        v
  (선택사항) PAdES 디지털 서명
        |
        +-------+-------+-------+
        |       |       |       |
      이메일   포털  PEPPOL  아카이브

더 읽을거리

LGPL-3.0-or-later 라이선스로 배포됩니다.