Skip to content
getnextpdf.com

Enterprise edition

Invoice — Deep Reference

The Invoice module has three independent surfaces: embedding, validation, and Schematron rule execution. ZugferdEmbedder and PeppolEmbedder attach caller-supplied invoice XML to a PDF/A-4f or PDF/A-3b carrier and return a structured result. InvoiceXmlValidator runs an EN 16931 structural pre-flight with selectable COMPAT or STRICT severity. SchematronValidator executes pre-compiled Schematron rule packs in process and parses SVRL findings. NextPDF does not generate invoice XML; the caller supplies and owns the payload.

This capability ships in NextPDF Enterprise (nextpdf/enterprise) and activates with an Enterprise-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.

Per-tier nuance: e-invoice detection and validation is the Pro-tier surface (Pro Compliance module). Hybrid-invoice embedding, the XRechnung CIUS profile, and the in-process Schematron engine are Enterprise-only. There is no separate per-feature capability code beyond the nextpdf/enterprise package boundary.

Terminal window
composer require nextpdf/enterprise:^3
SymbolParametersDefault behaviorReturnsThrows or fails withNotes
ZugferdEmbedder::basic()PdfAManager, FileAttachment, string $xmlDataEmbeds BASIC-profile CII XML: XmlGuard pass, structural validation, XMP schema injection, attachmentZugferdEmbedResultInvalidArgumentException, ZugferdEmbeddingExceptionQuick path; recommended starting point
ZugferdEmbedder::minimum()PdfAManager, FileAttachment, string $xmlDataSame pipeline at MINIMUM profileZugferdEmbedResultInvalidArgumentException, ZugferdEmbeddingExceptionQuick path
ZugferdEmbedder::create()ZugferdProfile, string $xmlDataBuilder entry; rejects empty XMLselfInvalidArgumentExceptionConfigure via withoutValidation(), withDescription()
ZugferdEmbedder::withAfRelationship() / PeppolEmbedder::withAfRelationship()AFRelationship|stringOverrides the default /Alternative relationship; gated by the associated-file rulebookselfInvalidArgumentExceptionSchema, EncryptedPayload, FormData rejected for invoices
ZugferdEmbedder::embed()PdfAManager, FileAttachmentTerminal builder call: XmlGuard, optional validation, carrier check, XMP, attachZugferdEmbedResultInvalidArgumentException, ZugferdEmbeddingExceptionValidation failure names the first error
ZugferdProfile (enum)Cases MINIMUM, BASIC_WL, BASIC, EN16931, EXTENDED, XRECHNUNGXRECHNUNG attaches xrechnung.xml; CII profiles attach factur-x.xml
ZugferdXmpSchema::apply()XmpMetadata, ZugferdProfileRegisters the Factur-X RDF description and PDF/A extension-schema entryXmpMetadataNoneCalled by embed(); also usable directly
PeppolEmbedder::invoice() / ::creditNote()PdfAManager, FileAttachment, string $ublXmlEmbeds Peppol BIS 3.0 UBL invoice or credit-note XMLPeppolEmbedResultInvalidArgumentException, PeppolEmbeddingExceptionDefault filenames invoice.xml / creditnote.xml
PeppolEmbedder::create()string $ublXml, string $filename = 'invoice.xml'Builder entry; rejects empty XML or filenameselfInvalidArgumentExceptionConfigure via withFilename(), withDescription(), withoutSanitization()
PeppolEmbedder::embed()PdfAManager, FileAttachmentXmlGuard pass, carrier check, rulebook gate, attachPeppolEmbedResultInvalidArgumentException, PeppolEmbeddingExceptionCarrier-aware rulebook re-check at embed time
InvoiceXmlValidator::validate()string $xmlData, ZugferdProfile, ?InvoiceValidatorModeEN 16931 structural pre-flight; COMPAT severity by defaultInvoiceValidationResultDoes not throw; failures surface as error findingsMode resolves argument, then environment, then COMPAT
InvoiceXmlValidator::isCrossIndustryInvoice()string $xmlDataRoot-element and namespace check for CII payloadsboolDoes not throw; returns falseCheap detection probe
InvoiceValidatorMode (enum)COMPAT (default) keeps BT-24 findings at warning; STRICT promotes them to errorfromEnvironment() falls back to COMPAT on unset or unrecognized values
InvoiceValidationResult / InvoiceValidationFindingImmutable aggregates: isValid, getErrors(), getWarnings(); level, code, message per findingInvoiceValidationResult::fail() wraps a single error
SchematronValidator::validate()string $xsltPath, string $xmlDataExecutes a pre-compiled Schematron XSLT; parses SVRL into findingsSchematronResultInvalidArgumentException for a missing or unreadable XSLT; engine failures return an error resultTiming captured in durationMs
SchematronValidator::runRules()string $xslPath, string $xmlPayloadCross-tier adapter; maps error findings to contract RuleViolation objectslist<RuleViolation>Same as validate()Info-level findings are skipped
SchematronResult / SchematronFindingVerdict, findings, duration; getFailedAssertions(), getSuccessfulReports()SchematronResult::error() marks engine failures invalid
SchematronCacheInterfaceTamper-detect cache contract: getVerified(), set(), computeKey()Fails closed on digest mismatch
AtomicRenameSchematronCachestring $cacheDir, bool $atomicRename = true, LoggerInterfaceSHA-256-verified file cache with atomic-rename writesInvalidArgumentException, SchematronCacheExceptionDirectory must exist or be creatable, and be writable
VersionPinRegistryarray $pins, ?string $sourcePathSHA-256-locked rule-pack pins: loadFromLockFile(), get(), verifyArtefact(), regenerateLockFile()VersionPinException, InvalidArgumentException, JsonException on malformed lock JSONBlank or malformed digests fail closed
InvoiceContractValidator?SemanticValidatorCross-tier ValidatorInterface adapter; structural pre-flight plus EN 16931 deep-semantic rulesContractResultFails closed; engine errors surface as error findingsBound on framework paths when nextpdf/premium is installed
ZugferdContractEmbedderFacturXContractEmbedderCross-tier EmbedderInterface adapter; byte-in / byte-out embedstring (PDF bytes)Propagates delegate failuresDelegates to the Pro-tier byte-rewrite engine
ZugferdEmbeddingException, PeppolEmbeddingException, SchematronCacheException, VersionPinExceptionModule failure taxonomyAll extend RuntimeException
public static function basic(
PdfAManager $pdfAManager,
FileAttachment $fileAttachment,
string $xmlData,
): ZugferdEmbedResult
public function embed(
PdfAManager $pdfAManager,
FileAttachment $fileAttachment,
): ZugferdEmbedResult
public static function invoice(
PdfAManager $pdfAManager,
FileAttachment $fileAttachment,
string $ublXml,
): PeppolEmbedResult
public static function validate(
string $xmlData,
ZugferdProfile $profile,
?InvoiceValidatorMode $mode = null,
): InvoiceValidationResult
public function validate(string $xsltPath, string $xmlData): SchematronResult

Embedding. ZugferdEmbedder attaches a caller-supplied ZUGFeRD 2.4 / Factur-X 1.08 UN/CEFACT CII XML payload to a PDF/A carrier. It supports two carriers: PDF/A-4f (ISO 19005-4:2020), the preferred modern carrier, and PDF/A-3b (ISO 19005-3:2012) for backward compatibility. embed() always runs an XmlGuard security pass first, then structural validation unless withoutValidation() was set, then verifies the carrier supports embedded files, injects the XMP extension-schema declaration via ZugferdXmpSchema, and attaches the XML as an associated file. The attachment relationship defaults to the rulebook recommendation /Alternative; overrides pass through the same rulebook, which enforces the ISO 32000-2:2020 §14.13 relationship set and the EN 16931 invoice subset. PeppolEmbedder performs the equivalent for caller-supplied Peppol BIS Billing 3.0 UBL 2.1 invoice or credit-note XML. Neither embedder generates invoice XML.

Validation. InvoiceXmlValidator checks CII XML against EN 16931 structural expectations: root element, required sections, header cardinality, line items where the profile requires them, and the BT-24 specification identifier mandated by business rule BR-1. InvoiceValidatorMode selects severity. COMPAT (default) reports a missing or mismatched BT-24 as a warning so a boolean validity gate does not regress. STRICT makes both a hard error and also asserts profile consistency against the declared ZugferdProfile, mirroring external KoSIT / Mustang validator semantics. The mode resolves in order: explicit argument, then the INVOICE_VALIDATOR_MODE environment override, then COMPAT. Results are structured InvoiceValidationResult / InvoiceValidationFinding objects; the validator returns findings rather than throwing.

Schematron. SchematronValidator executes pre-compiled Schematron rule sets — the CEN EN 16931 .sch rules compiled to XSLT at build time — using the in-process PHP XSLT processor. It parses the SVRL report into SchematronFinding / SchematronResult objects: failed assertions become error findings, successful reports become info findings. An optional cache (SchematronCacheInterface, with the atomic-rename file implementation) serves verified stylesheet bytes keyed by content digest plus compiler version. VersionPinRegistry pins every external rule pack to a SHA-256-locked version and fails closed on drift or malformed digests.

This module produces and checks structured invoice data. The validator checks the EN 16931 semantic model and the ZUGFeRD / Factur-X / UBL container only; it excludes national extensions (for example Italian SDI, French Chorus Pro, German XRechnung transport). As EN 16931-1 states, the invoice issuer is responsible for meeting the rules of relevant legislation.

  • Empty XML fails fast: builders throw InvalidArgumentException; InvoiceXmlValidator::validate() returns a failed result.
  • XmlGuard rejects DOCTYPE declarations, entity expansion, oversized payloads, and control characters. Embedders surface this as ZugferdEmbeddingException or PeppolEmbeddingException with the cause preserved.
  • withoutValidation() and withoutSanitization() never bypass the XmlGuard security pass. Only the structural business-term checks are skippable.
  • A carrier without embedded-file support (anything other than PDF/A-4f or PDF/A-3b) raises InvalidArgumentException naming the accepted versions.
  • A disallowed AFRelationship value is rejected at the builder boundary; a carrier-aware rulebook re-check runs again inside embed().
  • COMPAT keeps a missing BT-24 at warning severity; STRICT makes missing and profile-mismatched BT-24 values hard errors.
  • SchematronValidator throws only for a missing or unreadable XSLT path. Transform or SVRL-parse failures return SchematronResult::error() with isValid false.
  • A cache entry whose stored bytes fail digest verification is evicted and the stylesheet is re-read from disk; poisoned bytes are never returned.
  • The XSLT processor runs with file and network resource loading blocked and never registers PHP functions; document(), xsl:include, xsl:import, and result-document cannot load resources.
  • VersionPinRegistry rejects blank or malformed SHA-256 digests at ingest and on regeneration; verifyArtefact() returns false rather than passing an unverifiable pin.
  • This module performs no cryptographic signing; FIPS-mode behavior is out of scope here (see the Signature module).
BehaviorReferenceStatus
Core invoice semantic modelEN 16931-1:2026 §4Built against; issuer remains responsible
Specification identifier (BT-24)EN 16931-1:2026 BR-1Warning in COMPAT, error in STRICT
UN/CEFACT CII syntax bindingCEN/TS 16931-3-3:2020Embed supported
UBL 2.1 syntax bindingCEN/TS 16931-3-2:2020Embed supported
PDF/A-3 associated fileISO 19005-3:2012 §6.7.8Carrier supported
PDF/A-4f embedded fileISO 19005-4:2020 Annex ACarrier supported
Associated-file relationship valuesISO 32000-2:2020 §14.13Rulebook-gated
Schematron / SVRL report parsingISO/IEC 19757-3Built against

NextPDF produces structured invoices conforming to the EN 16931 data model and reports rule findings. Consult your tax and legal advisers.

  • The Schematron engine requires the ext-xsl PHP extension; provisioning and enabling it is the operator’s responsibility.
  • Processing is in-process and local. No outbound network calls occur during embedding or validation. National e-invoicing transport, clearance platforms, and archival systems are external to this module.
  • Rule packs are compiled from .sch to XSLT at build time; the runtime executes only pre-compiled stylesheets.
  • Cache keys fold in the compiler-version salt (currently nextpdf-schxslt-1.0); bumping it invalidates deployed caches without a purge step.
  • Rule-pack pins live in the lock file at enterprise/config/invoice-versions.lock (VersionPinRegistry::DEFAULT_LOCK_PATH); CI verifies deployed artifacts against the pinned digests.
  • Cross-tier callers use InvoiceContractValidator and ZugferdContractEmbedder; tier-native Enterprise callers use ZugferdEmbedder and InvoiceXmlValidator directly.

This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.