博客

PDF/A-3 解释:以及如何确认文件真的合规

PDF/A-3 是唯一常见、可合法携带附件的 PDF/A profile,也是 Factur-X / ZUGFeRD 电子发票的基础。本文讲差异、检查点和双引擎校验。

PDF/A 是 PDF 的归档版本:它承诺一份文档在 2050 年的显示效果,和 2026 年生成时保持一致。PDF/A 有几个主要 profile(PDF/A-1、2、3、4),每个 profile 又有不同的符合性等级。其中,PDF/A-3 是支撑欧盟电子发票的那一个,也是目前广泛使用的 PDF/A profile 里唯一允许在归档外壳内嵌任意附件的版本。

如果你的流程涉及发票、监管申报,或者任何“PDF + 结构化数据”的组合,PDF/A-3 基本绕不开。下面把它是什么、和其他 profile 的差异,以及如何验证文件是否真正合规讲清楚。

一段话看懂 PDF/A 家族

ProfileISO part年份核心特性
PDF/A-119005-12005第一代归档 profile。禁止透明度和 JavaScript,字体必须嵌入。
PDF/A-219005-22011增加 JPEG2000、透明度和图层支持,打印保真度更好。
PDF/A-319005-32012增加嵌入文件附件能力,是 Factur-X / ZUGFeRD 的外壳。
PDF/A-419005-42020现代化修订;符合性模型更干净,不再拆 ba

每个 profile 还有子等级:

  • b (basic):保证视觉保真。人能读,但不承诺语义结构。
  • a (accessible):包含结构标签和 Unicode 映射,屏幕阅读器能按正确顺序提取文本。
  • u (Unicode):有 Unicode 映射,但没有完整结构标签,介于两者之间。
  • e / f(仅 PDF/A-4):支持工程 3D 内容和完整表单。

所以 “PDF/A-3b” 的意思是:第 3 代归档 profile(允许附件)+ basic 等级(不要求可访问性标签)。这是发票场景里最常见的组合。

PDF/A-3 的特殊之处

PDF/A-1 和 PDF/A-2 禁止任意嵌入文件。原因很直接:归档 PDF 应该自包含;如果里面挂了一个 data.xlsx,这个附件可能独立腐化,破坏归档承诺。

PDF/A-3 在一个严格条件下放宽了这条规则:每个嵌入文件都必须声明 AFRelationship,说明附件和可见 PDF 内容之间是什么关系。有效值包括 SourceDataAlternativeSupplementUnspecified。PDF 本身还必须在 /AF 数组中列出附件,并通过 XMP metadata 描述该附件。

换句话说,PDF/A-3 的规则是:“可以附带文件,但你必须明确说明它是什么,以及它和人眼看到的 PDF 有什么关系。”这个声明正是电子发票的技术基础:人类可读发票放在 PDF 里,机器可读的 EN 16931 CII XML 放在附件里,AFRelationship="Alternative" 表明两者是同一张发票的两种表示。

PDF/A-3 在生产里的位置

  • Factur-X(法国,2026 起 B2B 逐步强制):PDF/A-3 + CII XML,并使用 urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0# XMP namespace。
  • ZUGFeRD 2.x(德国,2025 起强制接收):PDF/A-3 + CII XML,并使用 urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0# XMP namespace。
  • 工程 CAD 归档:PDF/A-3 内附原生 CAD 文件。PDF 是渲染结果,CAD 是源文件。
  • 监管申报:PDF/A-3 内附 XML payload,例如 FDA 提交、欧盟上市公司的 ESEF 财报。

这些场景里,PDF 外壳不只是容器,而是一份合同:这份 PDF 和这个附件代表同一份文档,并且两层都必须通过验证。

如何验证文件符合 PDF/A-3

官方符合性检查器是 veraPDFverapdf.org),由 PDF Association 维护。它实现 ISO 19005-3 规则集;如果 veraPDF 报 “Pass — PDF/A-3b”,这是单一引擎能给出的最强信号。

但单引擎 “Pass” 还不是审计级标准(Why two PDF/A validators are better than one 解释了原因)。审计级做法是运行两个独立引擎,只有两边都通过,才把文件视为合规。

如果是电子发票,还需要第二层检查:Mustangmustangproject.org)。它是事实上的 Factur-X / ZUGFeRD 检查器,会把嵌入的 CII XML 按 EN 16931 Schematron 规则验证。只有 PDF/A-3 外壳合规还不够;附件 XML 也必须是有效的 EN 16931,否则接收方的 AP 系统仍会拒收。

很多团队会安装 Java、配置 veraPDF CLI、安装 Mustang,再写 shell 脚本把输出串起来。能用,但摩擦很高。

validator 在浏览器里同时跑三层:

  1. veraPDF:官方参考实现,检查 PDF/A-3 符合性。
  2. gPdf 的 Rust+WASM edge engine:独立实现,提供第二意见。
  3. Mustang:针对嵌入式电子发票 payload 的 EN 16931 CII XML Schematron。

拖入文件,三个引擎并行运行,报告并排展示。JSON 可下载作为 QA 证据。不需要登录,也没有 quota。

报告里真正要看什么

验证失败通常集中在几个地方:

  • 嵌入文件 metadata 缺失:没有 /AF 数组,或者附件没有列在里面。
  • AFRelationship 缺失或错误:电子发票应为 Alternative;许多 PDF 库默认给 SourceData
  • XMP namespace 缺失或错误:Factur-X 和 ZUGFeRD 有固定 namespace URI,一个字符错也会失败。
  • 字体未子集化或未嵌入:PDF/A 要求文档用到的所有 glyph 都随字体嵌入。边界情况:声明了但实际没用的字体引用也可能导致失败。
  • Output intent 缺失:即使文档只有黑白文本,PDF/A 也要求声明颜色意图(sRGB 或其他 ICC profile)。
  • 文档 metadata 不完整:document info dictionary 里必须有 /Title/Producer/CreationDate

这些错误在报告里通常会指向具体规范条款。你应该从生成源头修复;如果用 gPdf 生成,API 会自动处理这些要求,validator 则是公开可复核的收据。

TL;DR

PDF/A-3 = PDF/A-2 + 合法嵌入任意文件的能力。正是这个能力让欧盟电子发票可落地:一份人类可读发票,加一份结构化 EN 16931 CII XML,封在同一个归档外壳里。合规要求 PDF/A-3 外壳和附件 XML 两层都通过;两边都过了,才可以交付。

POST /api/v1/e-invoice/render 生成。到 validator 验证。三个引擎(veraPDF + gPdf edge + Mustang),一次上传,免费。