Если вы инженер, которому только что сказали «счета должны быть PDF/A-3 с Factur-X к следующему кварталу», и ваш единственный контекст в том, что кто-то из юридического отдела произнёс эти слова, этот пост для вас.
Срезаем тон документов стандартизации и объясняем, что эти профили реально ограничивают, почему правительства начали их обязывать, и наименьший практический pipeline для эмиссии compliant PDF из renderer-а структурированных данных.
PDF/A в двух абзацах
PDF — гибкий формат. Слишком гибкий — та же спецификация PDF позволяет встраивать JavaScript, ссылаться на внешние ресурсы, которые могут не существовать через 50 лет, шифровать содержимое обратимой криптографией, ссылаться на внешние шрифты, и сотню других вещей, делающих документ не-самодостаточным.
PDF/A («A» от Archival) — профиль PDF, запрещающий части, которые мешали бы документу рендериться идентично через 50 лет. Высокоуровневые правила:
- Все шрифты должны быть встроены.
- Никакого JavaScript, внешних ссылок, аудио/видео.
- Никакого шифрования.
- Вся прозрачность должна быть сплющена или поддерживаться версией профиля.
- Цвета должны быть аппаратно-независимыми (требуется ICC-профиль).
- Всё содержимое должно быть в файле — никаких ссылок, зависящих от сети.
Существует несколько версий, каждая добавляет толерантность к более новым функциям:
| Профиль | Год | Что добавляет |
|---|---|---|
| PDF/A-1b | 2005 | Изначальный baseline — самый строгий |
| PDF/A-2b | 2011 | Разрешает JPEG2000, прозрачность, слои |
| PDF/A-3b | 2012 | Разрешает произвольные вложения файлов (фундамент Factur-X) |
| PDF/A-4 | 2020 | База ISO 32000-2 (PDF 2.0), упрощённые уровни соответствия |
Суффикс «b» означает «basic» соответствие (визуальная верность). Также есть варианты «u» (Unicode-mapped) и «a» (accessibility-tagged) — для большинства workflow-ов счёт/чек, «b» — то, что вам нужно, потому что фискальное архивирование заботится о визуальной воспроизводимости, а не семантике для screen reader.
Практический вывод: если ваш renderer говорит, что поддерживает PDF/A-3b, это должен быть единственный config-флаг ({ profile: "PDF/A-3b" } или эквивалент). Если приходится запускать второй инструмент (Ghostscript, qpdf, Acrobat) для конвертации потом, это пробел в workflow для учёта в ваших ops.
Почему PDF/A-3 особенно важен: он носитель электронных счетов
PDF/A-3 добавил одну способность, которая оказалась мир-меняющей: произвольные вложения файлов внутри PDF.
Звучит скучно. Это не так. Это вся техническая основа мандатов электронных счетов, разворачивающихся по Европе прямо сейчас.
Архитектура: единственный файл PDF, который одновременно
- Человеко-читаемый счёт (визуальный layout, итоги, брендинг) — часть, которую читает человек.
- Машинно-читаемый XML-счёт — часть, которую парсит софт налоговой инстанции.
Оба внутри одного файла, оба представляют тот же счёт, и обёртка PDF/A-3 гарантирует, что файл будет parseable десятилетиями.
Два главных XML-формата:
- Factur-X (Франция) — XML-профиль на основе UN/CEFACT Cross Industry Invoice
- ZUGFeRD (Германия) — по сути идентичен Factur-X (две стандарта технически слились в 2018)
- EN 16931 — европейская норма, которой соответствуют обе реализации
Для большинства workflow-ов «Factur-X» и «ZUGFeRD» — взаимозаменяемые термины — делят схему, делят механизм встраивания, и единственный PDF, compliant с одним, обычно compliant с другим.
Что обязательно, где, когда
Неисчерпывающий снимок для инженеров, планирующих rollout-ы Q2/Q3 2026:
| Страна | Статус | Требуемый формат |
|---|---|---|
| Германия | B2B обязателен для приёма с 2025-01-01; эмиссия с 2027 | EN 16931 (ZUGFeRD / Factur-X / XRechnung) |
| Франция | Эмиссия обязательна для крупных предприятий 2026-09; МСП 2027-09 | Factur-X через Chorus Pro |
| Италия | B2B обязателен с 2019 | FatturaPA через SDI |
| Польша | Обязателен с 2024-07 | KSeF |
| Испания | Обязателен с 2026 (B2B) | Facturae через FACe |
| Бельгия | Обязателен с 2026-01 | Peppol BIS 3 |
| Россия | ЭДО для счёт-фактур (УПД) с 2014; маркированные товары с 2019 | XML УПД через операторов ЭДО |
Паттерн: каждое государство-член ЕС реализует какой-то вариант EN 16931-compliant электронного счёт-фактуры на timeline 2024–2027. Если ваши клиенты работают в любом из этих рынков, ваш PDF-генератор должен будет эмитировать прикреплённый XML рядом с визуальным счётом.
Для российских команд: российский ЭДО (электронный документооборот) управляется через операторов ЭДО (СКБ Контур, ТАКСКОМ, Тензор и др.) с XML УПД (Универсальный Передаточный Документ). Хотя схема российская и не EN 16931, концепция идентична Factur-X: структурированный XML + визуальное представление. Для интеграции с европейскими партнёрами тот же endpoint gPdf генерирует Factur-X согласно EU стандартам.
Наименьший практический pipeline
Забудьте, что предписывают документы стандартизации. Вот вид инженера:
┌─────────────────────┐
│ Данные счёта │ (уже JSON-объект где-то)
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Построить XML │ (детерминистичный mapping; проверенные libs существуют)
│ EN 16931 / УПД │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Рендерить PDF/A-3b │
│ + прикрепить XML │ (один API-вызов к gPdf — или два шага в других)
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Передать в │
│ ЭДО / Chorus Pro / │
│ SDI / Peppol / etc │
└─────────────────────┘
Два нетривиальных шага:
Шаг 1: построить XML
Это раздражает, но механически. Вы маппите данные счёта (строки, налоги, итоги, стороны) на имена полей XML EN 16931 (или УПД для России). Несколько Java/Node/Python библиотек делают это за вас — ищите «factur-x library» или «упд library» в вашем языке. Не пишите с нуля, если вы действительно не наслаждаетесь спецификациями XML-схем.
Шаг 2: рендерить PDF/A-3 и прикрепить XML
Здесь имеет значение выбор renderer-а.
Без встроенной поддержки: вы рендерите обычный PDF, затем post-обрабатываете инструментом, который конвертирует в PDF/A-3 и прикрепляет XML как встроенный файл. Распространённые стеки: Ghostscript + qpdf, или платный инструмент типа Aspose. Два дополнительных шага, две дополнительные точки отказа, и нужно убедиться, что post-обработка не сдвигает визуальный layout.
Со встроенной поддержкой (подход gPdf): один вызов.
curl -X POST https://gpdf.com/api/v1/e-invoice/render \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data '{
"document": {
"pages": [{ "size": "a4", "elements": [...] }]
},
"einvoice": {
"format": "factur-x",
"profile": "BASIC",
"xml": "<rsm:CrossIndustryInvoice>...</rsm:CrossIndustryInvoice>"
}
}' \
--output schet-s-factur-x.pdf
Это весь pipeline. Renderer эмитирует PDF/A-3b, прикрепляет ваш XML как factur-x.xml (или zugferd-invoice.xml, оба распознаются каждым потребителем) и возвращает байты.
Распространённые ловушки
Несколько вещей, которые люди узнают тяжёлым путём:
«PDF/A» и «со шрифтами compliant PDF/A» — не одно и то же
PDF/A-3 файл требует, чтобы все шрифты были встроены с полным покрытием используемых глифов. Если в счёте имя иностранного клиента, и renderer падает на шрифт, который не полностью встраиваемый, инструменты валидации отклонят его. Проверьте, встраивает ли ваш renderer CJK-шрифты в режиме PDF/A — многие не делают этого по умолчанию.
Визуальное + XML должны совпадать
XML-счёт и визуальный счёт должны представлять тот же счёт. Налоговые аудиторы будут diff их. Если ваш код эмитирует XML с total: 119,00, а визуальный PDF показывает Итого: 120,00 (из-за бага округления или устаревшего шаблона), у вас расхождение по налогам в файлах. Генерируйте оба из того же source-of-truth, идеально в том же code path.
Уровни «профиля» в EN 16931
Factur-X имеет профили: MINIMUM, BASIC, EN 16931, EXTENDED. Различаются по тому, сколько данных в XML. Используйте BASIC, если ваш клиент специально не требует больше — покрывает налоговые коды, строки, стороны, итоги, что достаточно для ~95% B2B-счёт-фактур.
Валидация перед отправкой
Всегда валидируйте сгенерированный PDF против PDF/A-валидатора (veraPDF — open-source стандарт) и валидируйте XML против схемы EN 16931 / УПД перед отправкой в налоговую инстанцию. Неудачные отправки в Chorus Pro / SDI / ЭДО считают против ваших метрик надёжности у регулятора.
TL;DR
PDF/A — профиль самосодержащегося документа. PDF/A-3 позволяет прикреплять файлы. Factur-X / ZUGFeRD — это «XML EN 16931, прикреплённый внутри PDF/A-3». Мандаты электронного счёт-фактуры по ЕС делают эту комбинацию де-факто B2B-форматом счёта 2025–2027.
Если ваш renderer обращается с PDF/A-3 + Factur-X как с единственным config-флагом, миграция механическая. Если нет, вы строите multi-step ops pipeline. /api/v1/e-invoice/render от gPdf — single-flag версия — API-справочник имеет полную схему, или попробуйте sample-render в Playground.