Честный знак — Интеграция в ERP
Обзор
Честный знак (ГИС МТ) — государственная система маркировки и прослеживания товаров, оператор — ЦРПТ. Каждая единица маркированного товара получает уникальный DataMatrix-код, который отслеживается от производителя до конечного покупателя.
Для нашей франшизы общепита это обязательное требование MVP — кафе/фастфуд принимает, использует и продаёт маркированные товары (молоко, вода, напитки, пиво).
Статус на апрель 2026
Все основные категории уже обязательны. Штрафы: 50 000–300 000 руб. для ЮЛ, до 500 000 руб. для пива/алкоголя. Конфискация товара при серьёзных нарушениях.
Какие категории товаров затрагивают общепит
Уже обязательны (апрель 2026)
| Категория | Релевантность для франшизы | Поэкземплярный учёт (ПЭУ) |
|---|---|---|
| Молочная продукция | ВЫСОКАЯ — молоко, сливки, сыр, йогурт, масло | С июня 2025 |
| Упакованная вода | ВЫСОКАЯ — бутилированная, минеральная | С марта 2025 |
| Пиво и слабоалкогольные | СРЕДНЕ-ВЫСОКАЯ — если продаётся | С сентября 2025 (упаковка), марта 2025 (кеги) |
| Безалкогольные напитки | ВЫСОКАЯ — соки, лимонады, энергетики | С марта 2026 |
| Табак | НЕТ — продажа в общепите запрещена (15-ФЗ) | N/A |
Скоро обязательны
| Категория | Регистрация | Маркировка | Сканирование на кассе |
|---|---|---|---|
| Чай | Апрель 2026 | Июнь 2026 | — |
| Кофе | Июнь 2026 | — | — |
| Растительные масла | Уже | С ноября 2025 | С ноября 2025 |
| Консервы | — | — | С октября 2026 |
| Мясо и колбасы | Март 2026 | Август 2026 (производители) | — |
| Кондитерские изделия | Декабрь 2025 | Март–май 2026 | Июль 2027 |
Терминал и физическая архитектура
POS-терминал: Unitodi K10
Терминал Unitodi K10 — Android-устройство со встроенным ККТ-модулем.
| Параметр | Значение |
|---|---|
| ОС | Android 13 |
| Процессор | 8-ядер, 2.0 ГГц |
| Экран | 6.67”, 720x1600 |
| Память | 16 ГБ ROM / 2 ГБ RAM (опция 32/4) |
| Камера | Задняя 5 Мп (опционально — 2D сканер штрих-кодов) |
| NFC | Да (бесконтактная оплата) |
| Картридер | Магнитный, EMV, NFC |
| Связь | 2G/3G/4G, Wi-Fi, Bluetooth |
| Док-станция | USB-C, Ethernet, RS232, 2xUSB-A |
Что внутри K10 — два независимых модуля
┌──────────────────── K10 (одна железка) ────────────────────┐
│ │
│ Android 13 ККТ-модуль (ФЯ) │
│ ───────────── ────────────────── │
│ Обычный Android. Отдельный │
│ Тут наше POS-приложение. сертифицированный модуль.│
│ Мы его пишем Мы его НЕ пишем. │
│ и контролируем. Содержит ФН (фис. нак.) │
│ │
│ Наше приложение ◄── HTTP :8088 ──► ФЯ (API012) │
│ localhost │
└─────────────────────────────────────────────────────────────┘
- Наше POS-приложение — Android-приложение, которое мы разрабатываем. Показывает UI кассиру, управляет заказами, общается с бэкендом
- ФЯ (Фискальное Ядро) — программно-аппаратный модуль ККТ. Запускается при старте K10 как HTTP-сервер на порту 8088. Ждёт команд от нашего приложения. Сертифицирован государством, мы не можем менять его логику
Словарь терминов
| Термин | Расшифровка | Что это |
|---|---|---|
| ККТ | Контрольно-кассовая техника | Фискальный модуль, записывает продажи, печатает чеки, отправляет в ОФД |
| ФЯ | Фискальное Ядро | Софт ККТ — HTTP-сервер API012 на порту 8088 внутри K10 |
| ФН | Фискальный накопитель | Защищённый чип внутри ККТ, хранит все чеки. Версия 1.2 обязательна |
| ОФД | Оператор фискальных данных | Облачный посредник (Контур, Такском), пересылает чеки из ККТ в ФНС и ЧЗ |
| ФНС | Федеральная налоговая служба | Получает данные обо всех продажах (54-ФЗ) |
| ОИСМ | Оператор информационной системы маркировки | Честный знак / ЦРПТ — проверяет и отслеживает коды маркировки |
| ФФД | Формат фискальных документов | Стандарт структуры чеков. Версия 1.2 обязательна для маркировки |
| УКЭП | Усиленная квалифицированная электронная подпись | Юридически значимая подпись для API Честного знака |
| ПИОТ | Проверка и Отслеживание | Новый протокол — проверка марок переезжает от ФЯ к кассовому приложению |
| ЕСП | Единая Система Проверки | Модуль проверки марок от ЧЗ (для ПИОТ) |
Протокол API012 — взаимодействие с ФЯ (ККТ)
Взаимодействие нашего POS-приложения с ФЯ осуществляется по HTTP. Это прямо описано в документации API012.
| Параметр | Значение |
|---|---|
| Протокол | HTTP |
| Порт | 8088 (по умолчанию) |
| Базовый путь | /api012/v1/ |
| Авторизация | BasicAuth (логин/пароль кассира) |
| Формат | JSON |
Валидный ответ: result = 0. Если result != 0 — код ошибки + поле message.
Ключевые эндпоинты API012
Авторизация и кассиры:
| Метод | Эндпоинт | Описание |
|---|---|---|
| GET | login.json | Авторизация кассира, получение прав |
| GET | loadcashiers.json | Список кассиров |
| POST | savecashier.json | Создание/изменение кассира |
Смены:
| Метод | Эндпоинт | Описание |
|---|---|---|
| GET/POST | cycleopen.json | Открытие смены |
| GET/POST | cycleclose.json | Закрытие смены |
Чеки и маркировка:
| Метод | Эндпоинт | Описание |
|---|---|---|
| GET | startlabelschecksession.json | Очистить таблицу проверки марок в ФН (перед чеком) |
| POST | labelcheck.json | Проверить код маркировки в ФН + ОИСМ |
| POST | receipt.json | Сформировать и фискализировать чек |
| POST | correction.json | Чек коррекции |
Статус и отчёты:
| Метод | Эндпоинт | Описание |
|---|---|---|
| GET | cashboxstatus.json | Полный статус ККТ |
| GET | fscounters.json | Счётчики ФН |
| GET | xreport.json | X-отчёт (статистика за смену, нефискальный) |
| GET | fsreport.json | Статистика ФН |
Прочее:
| Метод | Эндпоинт | Описание |
|---|---|---|
| GET | introduction.json | Внесение наличных (в копейках) |
| GET | payout.json | Изъятие наличных (в копейках) |
| GET/POST | saveofdcfg.json | Настройки связи с ОФД |
| GET | offlineNotifications.bin | Выгрузка сообщений ОИСМ для офлайн-режима |
Три потока работы с маркировкой
Поток 1: Продажа маркированного товара на кассе
Бутылка воды, банка сока — покупатель берёт маркированный товар целиком. Наше приложение НЕ ходит в Честный знак. Всё делает ФЯ (ККТ).
sequenceDiagram participant Кассир participant POS as POS App (наше) participant ФЯ as ФЯ (API012 :8088) participant ОИСМ as Честный знак (ОИСМ) participant ОФД participant ФНС Кассир->>POS: Сканирует DataMatrix камерой K10 POS->>POS: Парсит rawLabel Note over POS,ФЯ: Шаг 1: очистка сессии POS->>ФЯ: GET startlabelschecksession.json ФЯ-->>POS: { result: 0 } Note over POS,ОИСМ: Шаг 2: проверка каждой марки POS->>ФЯ: POST labelcheck.json { rawLabel, checkFlags, expectedStatus } ФЯ->>ОИСМ: Проверка кода (ФЯ сама ходит в ОИСМ) ОИСМ-->>ФЯ: Статус кода ФЯ-->>POS: { st2109: 1, reqResult: 5, ... } Note over POS,ФЯ: Шаг 3: чек с результатами проверок POS->>ФЯ: POST receipt.json { labledOperations: [{ labelCheckResult }] } ФЯ->>ФЯ: Запись в ФН ФЯ->>ОФД: Фискальный документ ОФД->>ФНС: Данные о продаже (54-ФЗ) ОФД->>ОИСМ: Автоматический вывод из оборота ФЯ-->>POS: { result: 0, document: { fiscalCode, docNumber, ... } } POS->>Кассир: Чек напечатан
При продаже на кассе наше приложение НЕ обращается в Честный знак напрямую и НЕ обращается в наш Marking Service. Всю проверку и вывод из оборота делает ФЯ (ККТ) → ОФД → Честный знак автоматически.
Последовательность запросов к API012 (из документации)
1. GET startlabelschecksession.json ← очистить таблицу проверок в ФН
2. POST labelcheck.json ← для каждого маркированного товара
POST labelcheck.json ← (повторить N раз, макс 128 на чек)
3. POST receipt.json ← чек с результатами проверок
Структура POST receipt.json — два списка позиций
В чеке позиции разделяются на два массива:
operations— обычные товары (БЕЗ маркировки): капучино, круассан, бургерlabledOperations— маркированные товары: бутылка воды, пачка молока
{
"document": {
"cashier": "Иванов И.И.",
"tax": 1,
"paymentAttr": 1,
"operations": [
{
"name": "Капучино",
"price": "250.00",
"quantity": "1.000",
"type": 1,
"vatRate": 1
}
],
"labledOperations": [
{
"name": "Вода Святой источник 0.5л",
"price": "89.00",
"quantity": "1.000",
"type": 33,
"vatRate": 1,
"productCode": {
"type": 1304,
"data": "0104600000000013..."
},
"checkLabelFlags": 3,
"labelCheckResult": { ... }
}
],
"cash": "339.00"
}
}Ключевые поля маркированной позиции (labledOperations)
| Поле | Тег ФФД | Описание |
|---|---|---|
productCode | 1163 | Объект { type, data }. Тип 1304 = GS1 DataMatrix (КТ GS1.0) |
checkLabelFlags | 2106 | Результат проверки сведений о товаре |
labelCheckResult | — | Целиком ответ от labelcheck.json. Не записывается в ФН целиком, используется при оформлении |
fraction | 1291 | Дробное количество { nominator, denominator } — только для мерных маркированных товаров |
POST labelcheck.json — проверка марки
Входные данные:
{
"document": {
"rawLabel": "010123456789012321M,7aL0JDGbJCWa...",
"checkFlags": 0,
"excpectedStatus": 2,
"quantity": "1.000",
"unit": 0,
"fraction": { "nominator": 2, "denominator": 10 }
}
}| Поле | Описание |
|---|---|
rawLabel | Сырая строка DataMatrix как есть (UTF-8) |
checkFlags | Битовая маска: флаги согласия покупателя продолжить при ошибке. 0 = не продолжать, 255 = решение на стороне нашего приложения |
excpectedStatus | 1=штучный, 2=мерный, 3=возврат штучного, 4=возврат мерного, 5=штучный на стадии реализации, 6=мерный реализован, 255=не менять |
quantity | Количество товара |
unit | Единица измерения: 0=шт, 10=грамм, 11=кг, 40=мл, 41=литр |
Выходные данные:
| Поле | Описание |
|---|---|
st2109 | Ответ ОИСМ: 1=статус корректен, 2=некорректен, 3=оборот приостановлен |
reqCode2105 | 0=формат корректный, 1=некорректный формат, 2=код не распознан |
reqResult | Битовая маска результата: бит 1 = проверка КП КМ, бит 3 = статус товара |
clFlags | Битовая маска — то же что передано в checkFlags |
Лимит: не более 128 маркированных позиций на один чек (ограничение таблицы проверки в ФН).
Поток 2: Использование для приготовления
Молоко для капучино, сыр для пиццы — маркированный товар используется как ингредиент. Чека нет, ФЯ не участвует. Тут нужен наш Marking Service → Честный знак API.
sequenceDiagram participant Сотрудник participant POS as POS App (наше) participant BFF as POS BFF :3022 participant MS as Marking Service :3013 participant ЧЗ as Честный знак API Сотрудник->>POS: Сканирует код при вскрытии упаковки POS->>BFF: POST /marking/withdrawal { rawLabel, reason } BFF->>MS: Проксирует запрос MS->>ЧЗ: POST /lk/documents/create?pg=milk { type: WITHDRAWAL } Note right of ЧЗ: reason: "собственные нужды"<br/>или "производственные цели" ЧЗ-->>MS: Документ принят MS-->>POS: OK Note over POS: Дедлайн: 3 рабочих дня<br/>с момента вскрытия
Коды причин вывода:
- Код 1: “Использование для собственных нужд” — вода для персонала
- Код 3: “Производственные цели, не связанные с реализацией” — молоко для латте
Поток 3: Приёмка товара от поставщика
ФЯ не участвует. Наш Marking Service.
sequenceDiagram participant Поставщик participant ЭДО participant MS as Marking Service :3013 participant Сотрудник participant POS as POS App (наше) Поставщик->>ЭДО: Отправляет УПД с кодами маркировки ЭДО->>MS: Входящий УПД Сотрудник->>POS: Сканирует коды товаров POS->>MS: Отправляет отсканированные коды MS->>MS: Сверяет коды с УПД alt Совпадают MS->>ЭДО: Подтверждение приёмки (подпись УКЭП) Note over MS: Право собственности<br/>переходит в ЧЗ else Расхождение MS->>POS: Ошибка — несовпадение кодов POS->>Сотрудник: Показать расхождения end
Кто с кем разговаривает — общая схема
ИНТЕРНЕТ
┌────────────┬─────────────────────┐
│ │ │
▼ ▼ ▼
Наш сервер ОФД Честный знак
(POS BFF, (Контур, (ЦРПТ)
Marking Такском)
Service) ▲ ▲
▲ │ │
│ │ ФЯ сама ходит │
│ │ в ОФД и ОИСМ │
│ │ (мы не контролируем)
┌─────────────┼────────────┼─────────────────────┼────────┐
│ K10 │ │ │ │
│ │ │ │ │
│ Наше POS ──┘ ФЯ (API012 :8088) ───────┘ │
│ приложение HTTP ▲ │
│ │ localhost │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Простая формула:
| Сценарий | Путь данных | Через Marking Service? |
|---|---|---|
| Продажа | POS App → ФЯ (localhost:8088) → ОФД → ЧЗ | НЕТ |
| Готовка | POS App → POS BFF → Marking Service → ЧЗ API | ДА |
| Приёмка | POS App → POS BFF → Marking Service → ЧЗ API + ЭДО | ДА |
Где нужен УКЭП
УКЭП (усиленная квалифицированная электронная подпись) нужен только на сервере в Marking Service. На кассе K10 его нет.
| Операция | Где выполняется | УКЭП нужен? | Почему |
|---|---|---|---|
| Сканирование DataMatrix | K10 (камера) | Нет | Просто чтение штрих-кода |
| Проверка кода перед продажей | ФЯ (API012) → ОИСМ | Нет | ФЯ авторизуется сама |
| Формирование чека | ФЯ (API012) → ФН | Нет | ФН подписывает своим ключом |
| Отправка чека в ОФД | ФЯ → ОФД | Нет | ОФД авторизован сам |
| Вывод через продажу | ОФД → ЧЗ | Нет | ОФД делает автоматически |
| Вывод для готовки | Marking Service → ЧЗ API | ДА | Auth токен + подпись документа |
| Приёмка (подпись УПД) | Marking Service → ЭДО | ДА | Подпись УПД |
| Списание просрочки | Marking Service → ЧЗ API | ДА | Auth токен + подпись документа |
Как УКЭП работает на сервере
Один УКЭП-сертификат на ЮЛ, установлен в CryptoPro на сервере Marking Service:
1. Marking Service стартует, загружает УКЭП из CryptoPro keystore
2. GET /auth/key → { uuid, data: "случайная_строка" }
3. CryptoPro JCP подписывает "случайная_строка" → Base64
4. POST /auth/simpleSignIn { uuid, data: "подпись" }
→ { token: "abc...", life_time: 36000 }
5. Токен кэшируется в Redis (TTL 10 часов, idle 30 мин)
6. Все запросы от всех касс используют этот один токен
GS1 DataMatrix — формат кода
Структура
[FNC1] 01 [GTIN, 14 цифр] 21 [Серийный номер, до 13 символов] [GS] 93 [Код проверки, 4 символа]
| AI (идентификатор) | Название | Длина | Тип |
|---|---|---|---|
| (01) | GTIN (код товара) | 14 цифр | Фиксированная |
| (21) | Серийный номер | До 13 символов | Переменная (GS после) |
| (91) | Ключ проверки | 4 символа | Переменная |
| (92) | Криптоподпись (крипто-хвост) | 44 символа | Переменная |
| (93) | Код проверки (краткая форма) | 4 символа | Переменная |
Спец-символы:
- FNC1 (ASCII 232) — маркер GS1 DataMatrix (первая позиция)
- GS (ASCII 29 / 0x1D) — разделитель полей переменной длины
Скобки вокруг AI — только для человека, в DataMatrix их НЕТ. Сканер возвращает сырые байты.
Полная длина кода: 31 символ (короткая часть GTIN + серийный) / 83–88 символов (с крипто-хвостом).
Агрегационные коды vs индивидуальные
| Тип | Формат | Где | Для чего |
|---|---|---|---|
| КИ (SGTIN) | GTIN + серийный | На каждой единице товара | Сканирование на кассе, вывод из оборота |
| КИТУ (SSCC) | 18-значный SSCC | На транспортной упаковке (коробка, паллет) | Упрощение приёмки — сканируешь коробку = принимаешь все единицы внутри |
Фискальные требования (ФФД 1.2)
ФФД 1.2 обязательна для продажи маркированных товаров. ФН (фискальный накопитель) внутри K10 должен быть версии 1.2.
Ключевые теги в чеке
Чек
└── Тег 1059 (Предмет расчёта / позиция)
└── Тег 1163 (Код товара) — новый в ФФД 1.2
├── Тег 2100 (Тип кода маркировки)
├── Тег 2000 (Код маркировки)
└── Тег 2106 (Результат проверки)
| Тег | Название | Описание |
|---|---|---|
| 1162 | Код товара (legacy) | Контейнер ФФД 1.05, первые 2 байта: 0x44 0x4D (“DM”), далее 31 байт кода |
| 1163 | Код товара (new) | ФФД 1.2, содержит вложенные теги по типу кода |
| 2000 | Код маркировки | Сам код маркировки |
| 2003 | Планируемый статус | Статус товара (штучный/мерный) |
| 2100 | Тип кода маркировки | Идентификатор типа кода |
| 2106 | Результат проверки | Корректен / некорректен |
| 2107 | Результаты проверки маркированных товаров | Общий результат проверки в чеке (тег уровня чека) |
Типы кодов товаров (productCode.type)
| Тип | Название | Код ФФД |
|---|---|---|
| 1300 | Нераспознанный | КТ Н |
| 1301 | EAN-8 | КТ EAN-8 |
| 1302 | EAN-13 | КТ EAN-13 |
| 1303 | ITF-14 | КТ ITF-14 |
| 1304 | GS1 DataMatrix | КТ GS1.0 — основной для маркировки |
| 1305 | GS1.M | КТ GS1.M |
| 1306 | КМК (короткий код) | КТ КМК |
Разрешительный режим
С марта 2026 — обязательная онлайн-проверка кода перед продажей. Если код невалиден — продажа блокируется.
Текущая схема (ФФД 1.2): ФЯ сама проверяет коды в ОИСМ через labelcheck.json.
Офлайн-фолбек: Локальный модуль Честного знака на кассе, синхронизируется каждые 3 дня. Если не синхронизирован — модуль блокируется.
Исключение для HoReCa
Заведения общепита (без розничной торговли) могут:
- Не устанавливать Локальный модуль
- Использовать агрегированные коды (GTIN) вместо индивидуальных в чеке
- Использовать тег
mode=horecaв фискальных документах
ПИОТ — будущий протокол (следить)
ПИОТ (Проверка и Отслеживание) — новый протокол, который меняет схему работы с маркировкой. Пока не обязателен, но нужно учитывать.
Текущая схема (ФФД 1.2): ФЯ делает всё сама
POS App ──► ФЯ ──► ОИСМ (Честный знак)
ФЯ сама проверяет марку
Наше приложение не знает про Честный знак при продаже. Мы просто шлём rawLabel в labelcheck.json и получаем ответ.
ПИОТ (новая схема): ответственность переезжает к кассовому приложению
POS App ──► модуль ЕСП ──► Честный знак (проверка марки)
│ │
│ результат проверки
│ │
▼ ▼
POS App ──► ФЯ (только фискализация, без проверки марок)
Изменения:
- ФЯ перестаёт сама проверять марки в Честном знаке
- Наше приложение должно само проверять марки через модуль ЕСП (Единая Система Проверки)
- Результат проверки мы передаём обратно в ФЯ для записи в чек
- Нужен Локальный Модуль для офлайн-проверки (кэш кодов на устройстве, синхронизация каждые 3 дня)
Влияние на нашу архитектуру
| Аспект | Сейчас (ФФД 1.2) | ПИОТ (будущее) |
|---|---|---|
| Кто проверяет марки при продаже | ФЯ (через API012 labelcheck.json) | Наше приложение (через ЕСП) |
| Нужен ли Marking Service для продажи | Нет | Возможно — как backend для ЕСП |
| Локальный Модуль | Не обязателен для HoReCa | Потребуется |
| Сложность интеграции | Низкая | Высокая |
Для MVP делаем на текущей схеме (ФФД 1.2, API012). ФЯ проверяет марки, мы просто шлём запросы. Когда ПИОТ станет обязательным — переделаем проверку на нашу сторону.
API Честного знака (True API)
Используется только нашим Marking Service для потоков готовки и приёмки. При продаже на кассе НЕ используется.
Среды
| Среда | URL |
|---|---|
| Production | https://markirovka.crpt.ru/api/v4/true-api/ |
| Sandbox | https://markirovka.sandbox.crptech.ru/api/v4/true-api/ |
Rate limit: 50 запросов/сек на участника. Sandbox бесплатный.
Аутентификация
Требуется УКЭП + CryptoPro CSP. См. секцию Где нужен УКЭП.
Ключевые эндпоинты
Проверка кодов:
| Метод | Путь | Описание |
|---|---|---|
| POST | /cises/info | Публичная информация о кодах |
| POST | /cises/search | Поиск кодов по фильтрам (100/стр) |
Документы (вывод из оборота, приёмка):
| Метод | Путь | Описание |
|---|---|---|
| POST | /lk/documents/create?pg={group} | Создание документа (withdrawal, acceptance) |
| GET | /lk/documents/{docId} | Получение документа по ID |
| GET | /lk/receipts | Квитанции обработки документов |
Товарные группы (параметр pg): milk, water, beer, ncp (безалкогольные), tobacco
Типы документов:
WITHDRAWAL— вывод из оборота (стандартный)WITHDRAWAL_OSU— вывод для собственных нужд / производства (для общепита)
Библиотеки / SDK
| Язык | Библиотека | Примечание |
|---|---|---|
| Java | borkli/CrptApi | Java 11+, thread-safe, rate limiting |
| .NET | FairMark/FairMarkClient | True API + OMS + EDO Lite |
| PHP | kilylabs/true-api-cli | CLI для True API + СУЗ |
| Node.js | — | Нет готовых SDK, прямые HTTP-вызовы |
CryptoPro — главная сложность
Для Node.js нет нативной поддержки CryptoPro. Варианты: (1) Java-сервис с JCP, (2) sidecar-контейнер с CryptoPro, (3) отдельный signing-микросервис.
Архитектурное решение для нашей ERP
Общая схема
graph TB subgraph "K10 (терминал)" POS_APP["POS App (Android)"] FY["ФЯ (API012 :8088)"] POS_APP -->|"HTTP localhost"| FY end subgraph "Backend (наш сервер)" POS_BFF["POS BFF :3022"] MARKING["Marking Service :3013"] CATALOG["Catalog Service :3004"] WAREHOUSE["Warehouse Service :3008"] end subgraph "External" CRPT["Честный знак API"] OFD["ОФД"] EDO["ЭДО оператор"] FNS["ФНС"] end POS_APP -->|"HTTPS (готовка, приёмка)"| POS_BFF POS_BFF --> MARKING MARKING -->|"True API + УКЭП"| CRPT MARKING -->|"подпись УПД"| EDO FY -->|"чеки"| OFD OFD -->|"54-ФЗ"| FNS OFD -->|"авто-вывод при продаже"| CRPT FY -.->|"labelcheck"| CRPT MARKING -.->|"Kafka"| WAREHOUSE MARKING -.->|"Kafka"| CATALOG style MARKING fill:#e94560,stroke:#1a1a2e,color:#fff style FY fill:#0f3460,stroke:#1a1a2e,color:#fff style CRPT fill:#533483,stroke:#1a1a2e,color:#fff style OFD fill:#533483,stroke:#1a1a2e,color:#fff
Marking Service — зона ответственности
Marking Service НЕ участвует при продаже на кассе. Нужен только для готовки, приёмки и учёта.
| Функция | Описание |
|---|---|
| Аутентификация ЦРПТ | Получение и кэширование токенов (УКЭП + CryptoPro) |
| Вывод из оборота | Документы WITHDRAWAL / WITHDRAWAL_OSU для приготовления |
| Приёмка | Сверка кодов с УПД, подтверждение в ЭДО |
| Учёт кодов | Статусы кодов в БД, дедлайны вывода (3 дня) |
| Синхронизация | Периодическая синхронизация с ЧЗ |
Tech Stack
| Технология | Назначение |
|---|---|
| Java 21 + Spring Boot | Основной сервис (нативная поддержка CryptoPro через JCP) |
| PostgreSQL | Хранение кодов, документов, истории |
| Redis | Кэш токенов, результатов проверки |
| CryptoPro JCP | Подпись УКЭП для аутентификации в True API |
| Kafka | События жизненного цикла кодов |
Модель данных
erDiagram marking_codes { uuid id PK uuid franchise_id FK uuid store_id FK varchar code "полный DataMatrix код" varchar gtin "14 цифр" varchar serial "до 13 символов" varchar product_group "milk, water, beer, ncp" varchar status "received, in_stock, withdrawn, sold" varchar withdrawal_reason "sale, own_needs, production, expired, damaged" uuid supplier_document_id FK timestamp received_at timestamp withdrawn_at timestamp withdrawal_deadline "received_at + 3 рабочих дня" } marking_documents { uuid id PK uuid franchise_id FK varchar doc_type "WITHDRAWAL, WITHDRAWAL_OSU, ACCEPTANCE" varchar product_group "milk, water, beer, ncp" varchar status "pending, submitted, accepted, rejected" varchar crpt_doc_id "ID в системе ЦРПТ" jsonb payload "тело документа" varchar error_message timestamp submitted_at timestamp processed_at } marking_products { uuid id PK varchar gtin UK "14 цифр" varchar product_name varchar product_group boolean requires_marking jsonb crpt_product_info "кэш из True API" timestamp synced_at } supplier_documents { uuid id PK uuid franchise_id FK uuid store_id FK varchar upd_number "номер УПД" varchar supplier_inn varchar status "pending, accepted, rejected, partial" integer total_codes integer scanned_codes timestamp received_at timestamp confirmed_at } marking_codes ||--o| supplier_documents : "принят по" marking_codes ||--o| marking_documents : "выведен через" marking_codes }o--|| marking_products : "GTIN"
Kafka-события
| Топик | Publisher | Consumer | Payload |
|---|---|---|---|
marking.code.received | Marking | Warehouse | { code, gtin, store_id, supplier_document_id } |
marking.code.withdrawn | Marking | Warehouse, Catalog | { code, gtin, store_id, reason, document_id } |
marking.code.sold | Marking | Warehouse | { code, gtin, store_id, receipt_id } |
marking.document.submitted | Marking | — | { document_id, type, status } |
marking.document.processed | Marking | — | { document_id, type, status, crpt_doc_id } |
API Marking Service (внутренний, для POS BFF)
Base: /api/v1
| Метод | Путь | Описание | Auth |
|---|---|---|---|
| POST | /marking/withdrawal | Вывести коды из оборота (приготовление) | franchise, franchisee, manager |
| POST | /marking/codes/accept | Принять коды из УПД (приёмка) | franchise, franchisee, manager |
| GET | /marking/codes/{code} | Статус конкретного кода | franchise, franchisee, manager |
| GET | /marking/codes | Список кодов (фильтры: store, status, product_group) | franchise, franchisee, manager |
| GET | /marking/products/{gtin} | Требует ли товар маркировки | all |
| GET | /marking/documents | Список документов | franchise, franchisee, manager |
| GET | /marking/documents/{id} | Детали документа | franchise, franchisee, manager |
| POST | /marking/supplier-documents | Создать приёмку по УПД | franchise, franchisee, manager |
| PATCH | /marking/supplier-documents/{id} | Подтвердить/отклонить приёмку | franchise, franchisee, manager |
Что меняется в существующих сервисах
| Сервис | Изменение |
|---|---|
| Catalog Service | Флаг requires_marking + product_group (milk/water/beer/ncp) на товарах. Уже есть alcohol, tobacco, sugary_drink — расширяем |
| Store Service | Добавить participant_id (ID участника ЧЗ) и kkt_settings на ТТ |
| Warehouse Service | Слушать marking.code.received/withdrawn/sold для связи с остатками |
| POS BFF | Роутинг к Marking Service для готовки/приёмки |
| POS App | Интеграция с API012 (ФЯ), UI для сканирования, работа с labledOperations |
Что нужно закупить / настроить
На каждую ТТ
| Что | Зачем | Примечание |
|---|---|---|
| Unitodi K10 | Терминал с Android + встроенной ККТ | Уже выбран |
| ФН версии 1.2 | Фискальный накопитель | Должен быть внутри K10 |
| 2D сканер (опция) | Быстрое чтение DataMatrix | Камера K10 тоже работает, но медленнее |
Сервисы и подписки
| Что | Зачем |
|---|---|
| УКЭП (КЭП) | Электронная подпись для API (устанавливается на сервере Marking Service) |
| CryptoPro CSP 5+ | Криптопровайдер для подписи (на сервере) |
| ЭДО оператор | Обмен УПД с поставщиками (Контур.Диадок, СБИС, Такском) |
| ОФД с поддержкой маркировки | Передача чеков в ФНС + ЧЗ |
| Регистрация в ЧЗ | Личный кабинет markirovka.crpt.ru, роль “Розница и Иное” |
Приоритет реализации для MVP
Phase 1 (минимум для запуска POS)
- POS App — интеграция с API012:
startlabelschecksession→labelcheck→receiptсlabledOperations - Catalog Service — флаги
requires_marking+product_groupна товарах - Marking Service (базовый) — вывод из оборота для готовки (УКЭП + True API)
Phase 2 (расширение)
- Приёмка — полная сверка с УПД через ЭДО
- Warehouse интеграция — автоматический учёт маркированных остатков
- Массовый вывод — batch-операции для кухни (списание ингредиентов)
- Дашборд — мониторинг просроченных дедлайнов вывода (3 дня)
Phase 3 (ПИОТ — когда станет обязательным)
- Интеграция модуля ЕСП в POS App
- Локальный Модуль для офлайн-проверки
- Перенос проверки марок с ФЯ на нашу сторону
Sandbox для разработки
| Параметр | Значение |
|---|---|
| URL | https://markirovka.sandbox.crptech.ru/ |
| API | https://markirovka.sandbox.crptech.ru/api/v4/true-api/ |
| Login | https://markirovka.sandbox.crptech.ru/login-kep |
| Стоимость | Бесплатно |
| Ограничение | Тестовые коды невалидны в продакшене |
Ссылки
Внешние источники
- True API документация
- Честный знак — кабинет
- Sandbox
- Unitodi K10
- Календарь маркировки для общепита
- Маркировка в общепите 2025-2026
- Вывод из оборота — способы
- GS1 DataMatrix формат
- ФФД 1.2 теги 1162/1163/2106
- Java CrptApi
Документация API012
Файл: _assets/API012 (1).pdf — полная спецификация протокола взаимодействия с ККТ (версия V1).