發票與電子發票
Spec: EN 16931-1:2026, BT-24 EN 16931-1:2026 BT-24 Spec: Factur-X 1.08 Factur-X 1.08 Spec: ISO 32000-2:2020, §14.13 ISO 32000-2:2020 §14.13 Evidence: Mixed evidence
一份現代發票,是同一個檔案裡的兩份文件:一頁給人閱讀,另一段是供稅務系統解析的機器可讀 XML 酬載。本頁從法規義務一路說到實際產出,說明混合式發票情境——ZUGFeRD 與 Factur-X 實際要求什麼、NextPDF 如何附加並檢查結構化酬載,以及合規何時不再是引擎的工作,而成為你的責任界線。
為何這很重要
標題為「為何這很重要」的區段如今已有多個司法管轄區,針對企業對企業或企業對政府開立發票,強制要求使用結構化發票。陷阱在於:一份混合式發票在畫面上可能看起來完美無缺,卻仍可能遭到退件。退件針對的是內嵌的 XML,而不是畫素。如果結構化酬載缺少規格識別碼、宣告了錯誤的設定檔,或以錯誤的關聯方式附加,接收平台就會將它判為失敗。從你這一端看,這種失敗往往沒有明顯訊號,而且要到數天之後才會浮現,背後還卡著一筆被擱置的款項。
在產生檔案的那一層就把這件事一次做對,遠比等發票進入清算流程後才逐張發現問題便宜得多。
簡短版
標題為「簡短版」的區段- 一份合規的混合式發票,是一個 PDF/A 載體,搭配一段 以關聯檔案形式內嵌的合規 XML 酬載。載體的中繼資料必須宣告該設定檔。
- 最常決定能否被接受的單一欄位,是 BT-24,也就是規格識別碼。EN 16931 商業規則 BR-1 要求每一張發票都必須帶有它。其值是一個 URN,用以指明確切的設定檔——例如 EN 16931(COMFORT)設定檔的
urn:cen.eu:en16931:2017。 - NextPDF 的工作,是對呼叫端提供的 XML 進行 內嵌與結構驗證。它不會撰寫發票內容,也 並非稅務機關的驗證器。
- 簽發者仍須對法律與財稅正確性負責。乾淨的驗證結果只是該決策的其中一項輸入,並不是一張證書。
NextPDF 採取的做法
標題為「NextPDF 採取的做法」的區段NextPDF 將結構化發票視為一份 跨層級契約,而不是單一功能。核心引擎定義介面——內嵌器、設定檔描述器、驗證器——由 Premium 層提供實作。這樣的分離是有意為之。公開介面在核心中凍結,因此無論背後是哪一層,呼叫端與測試都會以相同方式處理設定檔與結果。
此流程分為四個階段,順序很重要,因為每一個階段都依賴前一個階段。
- Author the invoice XML You (or your ERP) produce a UN/CEFACT CII or Peppol UBL payload. NextPDF never synthesizes invoice content.
- Produce the PDF/A carrier A PDF/A-3 or PDF/A-4f document is the human-readable face and the conformant container the standard requires.
- Embed the payload The embedder attaches the XML as an associated file with the correct AFRelationship, and injects the Factur-X XMP profile declaration.
- Validate, then ship A structural pass checks the root, the required sections, and BT-24 against the declared profile before the file leaves your system.
內嵌器契約採位元組進、位元組出:輸入一個 PDF/A 載體與一段 XML 酬載,輸出混合式 PDF 位元組。附加任何內容之前,XML 會先通過一道強化防護的解析程序;它會拒絕 DOCTYPE、限制輸入大小,並拒絕 XML 1.0 禁止的控制字元。這會從根本上消除 XML 外部實體(XXE)與 Billion-Laughs 攻擊,因為發票 XML 經常來自你的信任邊界之外。
設定檔描述器回答下游系統會問的四個問題:標準設定檔 URN、要主張的 BT-24 值、供記錄使用的穩定名稱,以及一個與層級無關的判別值,讓對等性測試能夠將結果分組。描述器也誠實呈現缺漏之處。ZUGFeRD MINIMUM 設定檔不帶有
BT-24 規格識別碼,描述器對它回傳 null
而不是捏造一個。 這也是為什麼 MINIMUM 與 BASIC WL 並非
EN 16931 合規。 引擎是把基數規定如實編入其中,而不是把它藏起來。
證據如何支持
標題為「證據如何支持」的區段上述行為有三個依據,而每一處承載的證據種類都不相同。
標準 定義義務。
Spec: EN 16931-1:2026, BR-1 EN 16931-1:2026 BR-1 讓規格識別碼成為每一張發票的強制項目。 Factur-X
技術附錄為每個設定檔固定了 URN 值,包括 EN 16931
設定檔的 urn:cen.eu:en16931:2017。 載體本身是一個 PDF 層面的問題: Spec: ISO 32000-2:2020, §9 ISO 32000-2:2020 §9 指出最可預測、最可靠的呈現,會在所有字型皆內嵌時發生——這與發票直接相關,因為一張十年後仍須能被閱讀的發票,不能依賴閱讀者的字型環境。
程式碼 承載著契約。 Evidence: Code-backed 核心的 EmbedderInterface、ProfileInterface 與 ValidatorInterface 是真實存在、且與層級無關的介面。 ProfileType::isEn16931Conformant() 在型別系統中編入 MINIMUM/BASIC WL 的排除規則。 ValidationResult 是一個不可變的 DTO,其 isValid 同時要求「無錯誤發現」與「無致命規則違反」成立。
行為 則以 Premium 層的能力描述記載: Evidence: Standard-backed 內嵌器會把呼叫端提供的 ZUGFeRD 2.4/Factur-X 1.08 CII 或 Peppol UBL XML,附加到 PDF/A-4f 或 PDF/A-3b 載體上,並設定正確的關聯檔案關係。 驗證器會檢查 EN 16931 語意模型,以及 BT-24 識別碼。 Schematron 階段會執行已編譯為 XSLT 的 CEN 規則集。 其中沒有任何部分會產生或修正發票內容。
實務範例
標題為「實務範例」的區段以下範例只是用來說明整合接點,並非可直接複製貼上的整合。載體的建構與內嵌器來自 Premium 層,而 XML 是你的。
<?php
declare(strict_types=1);
use NextPDF\Contracts\EInvoice\ProfileType;use NextPDF\Contracts\EInvoice\ValidatorContext;use NextPDF\Contracts\EInvoice\ValidatorInterface;use NextPDF\Contracts\EInvoice\EmbedderInterface;use NextPDF\Contracts\EInvoice\EmbedderOptions;use Psr\Log\LoggerInterface;
/** * Validate first, embed second, never ship an invalid payload. * * @param non-empty-string $carrierPdf PDF/A-3 or PDF/A-4f carrier bytes * @param non-empty-string $ciiXml Caller-authored UN/CEFACT CII XML * * @return non-empty-string Hybrid invoice bytes, ready to deliver */function buildHybridInvoice( ValidatorInterface $validator, EmbedderInterface $embedder, LoggerInterface $logger, string $carrierPdf, string $ciiXml,): string { // STRICT mode: a missing BT-24 is a hard error, not a warning. $context = new ValidatorContext( profile: ProfileType::EN16931, strictMode: true, );
$result = $validator->validate($ciiXml, $context);
if (!$result->isValid) { foreach ($result->getErrors() as $finding) { $logger->error('invoice.structural_finding', [ 'message' => $finding->message, ]); }
// A failed structural check is your signal to stop, not to ship. throw new \RuntimeException('Invoice XML failed structural validation.'); }
$options = new EmbedderOptions(profile: ProfileType::EN16931);
return $embedder->embed($carrierPdf, $ciiXml, $options);}重點正在於順序。相較於一張被退件的發票與一筆被延遲的款項,驗證的成本很低,因此它會在酬載被附加之前先行執行。
常見誤解
標題為「常見誤解」的區段最昂貴的誤解是 「NextPDF 讓我的發票變得合規。」 它不會,而且它也明確地這麼說。引擎只會內嵌並結構檢查你撰寫的 XML。一個通過的結構結果,意味著酬載具有 EN 16931 所預期的形狀,並宣告了你所要求的設定檔。它 並不 意味著該發票在法律上充分、經稅務機關核可,或保證會被任何清算平台接受。國家層級的擴充與清算傳輸,在引擎層級屬於範圍之外。正如 EN 16931-1 自身所說明,核心模型承載著支援合規所需的資訊。簽發者有責任滿足相關法律規定。
第二個更不醒目的陷阱是:支援某項標準,並不等於符合該標準。合規是最終檔案加上一個驗證器所構成的性質,而不是產生它的函式庫本身具備的性質。
限制與邊界
標題為「限制與邊界」的區段- NextPDF 不會撰寫或修正發票內容。 呼叫端必須提供有效的 XML,並且仍是發票的簽發者。一份空的發現清單,並不能讓一段不合規的酬載變得合規。
- 結構化內嵌與 Schematron 驗證屬於 Premium 層能力。 核心定義契約;實作則需要商業套件。請參閱下方的界線。
- 驗證器僅檢查 EN 16931 語意模型,以及 ZUGFeRD/Factur-X/UBL 容器。 它並非稅務機關的驗證器。SDI、Chorus Pro 與 XRechnung 的傳輸,在傳輸層級屬於範圍之外。
- MINIMUM 與 BASIC WL 設定檔並非 EN 16931 合規,且不帶有 BT-24 規格識別碼——這是刻意設計,反映的是標準的基數規定,而非引擎的限制。
- Schematron 引擎需要
ext-xsl。 規則集會在建置時編譯。執行階段只會執行預先編譯好的 XSLT,並停用網路與檔案系統的資源載入。 - 本頁所描述的是能力層級行為。它並未主張會獲得任何特定機關或平台接受。
| Edition | Availability |
|---|---|
| Core | 核心定義跨層級契約( |
| Pro | 可使用將 Factur-X 1.08 CII 內嵌到 PDF/A 載體,以及 EN 16931 設定檔描述器。 |
| Enterprise | 新增 Peppol BIS 3.0 UBL 內嵌、XRechnung B2G CIUS、COMPAT/STRICT XML 驗證,以及行程內的 Schematron 規則引擎。 |
相關文件
標題為「相關文件」的區段- 封存與 PDF/A——為什麼發票載體是一個 PDF/A 檔案,以及它對長期可讀性提供什麼保證。
- 整合決策指南——哪一個生態系套件適合你的開立發票管線(佇列化產生、框架橋接,或 Connect)。
- 在正式環境中運行 NextPDF——當發票大量流動時,如何觀測驗證發現與失敗。
詞彙表
標題為「詞彙表」的區段- 混合式發票——單一 PDF 檔案,同時包含人類可讀頁面與機器可讀的內嵌 XML 發票酬載。
- ZUGFeRD/Factur-X——同一種混合式發票做法的德文與法文名稱:一段內嵌於 PDF/A 載體中的 UN/CEFACT 跨產業發票(CII)XML 酬載。
- EN 16931——用來定義電子發票核心元素之語意資料模型的歐洲標準。
- BT-24(規格識別碼)——EN 16931 商業術語,其值是一個 URN,用以指明發票所遵循的確切設定檔。由商業規則 BR-1 要求。
- 設定檔——也稱為合規等級(MINIMUM、BASIC WL、BASIC、EN 16931、EXTENDED、XRECHNUNG)。決定一張發票必須帶有哪些商業術語。
- 關聯檔案——一個附加於 PDF 內部的檔案,帶有宣告好的關係(AFRelationship),描述它如何與可見文件相關聯;也就是承載發票 XML 的機制。
- Schematron——一種用來表達 EN 16931 商業規則的規則語言。NextPDF 會執行已編譯為 XSLT 的 CEN 規則集。