Files
chestno-api/plans/chestny-znak-web-app-2026-07-08.md
T
2026-07-08 15:10:29 +00:00

167 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# chestny-znak-web-app — План реализации тестового web-приложения для API Честного знака
**Статус:** Активен
## Описание задачи
Проанализировать API «Честный знак» (ГИС МТ, True API) и создать план реализации тестового web-приложения, которое позволяет:
1. Авторизоваться в системе (подписать тестовый набор данных УКЭП)
2. Получить информацию о QR-кодах (КМ) из УПД — актуальны или нет
## Результаты анализа API
### Документация True API
| Параметр | Значение |
|----------|----------|
| Официальная документация | https://docs.crpt.ru/gismt/True_API/ |
| Тестовый контур (sandbox) | `https://markirovka.sandbox.crptech.ru/api/v3/true-api` |
| Промышленный контур | `https://markirovka.crpt.ru/api/v3/true-api` |
| Версия API | v3/v4 |
| Формат | REST, JSON |
| Аутентификация | УКЭП (ГОСТ, CAdES-BES) → Bearer token |
### Процесс аутентификации (Единая аутентификация)
```
Шаг 1: GET /auth/key → { uuid, data }
(получаем UUID и случайную строку для подписи)
Шаг 2: Подписать data УКЭП (CAdES-BES, присоединённая подпись, base64)
(требуется КриптоПро или совместимое СКЗИ)
Шаг 3: POST /auth/simpleSignIn → { token, uuidToken?, expireDate? }
Body: { uuid: "<uuid>", data: "<base64 signature>" }
```
- Срок действия токена: **не более 10 часов**
- Форматы токена: JWT (по умолчанию) или UUID (параметр `unitedToken: true`)
- Поддержка JWT — до марта 2026 года, UUID — основной формат
### Ключевые методы для задачи
| Метод | Endpoint | Описание |
|-------|----------|----------|
| Получение информации о КМ | `POST /api/v3/true-api/cises/info` | Статус, производитель, собственник, GTIN |
| Проверка кодов (розница) | `POST /api/v4/true-api/codes/check` | Проверка перед продажей |
| Публичная проверка | `GET https://mobile.api.crpt.ru/mobile/check?code=<код>` | Без авторизации (недокументированный эндпоинт моб. приложения) |
| Поиск КМ | `POST /api/v4/true-api/cises/search` | Поиск по фильтрам |
### Пример публичного API (без авторизации)
Запрос:
```
GET https://mobile.api.crpt.ru/mobile/check?code=0104640507713421215TxdVFoOB.zFF
```
Ответ (JSON):
```json
{
"code": "0104640507713421215TxdVFoOB.zFF",
"found": true,
"valid": true,
"status": "INTRODUCED"
}
```
**Ограничения публичного API:**
- Не требует аутентификации — можно использовать для быстрой проверки единичных кодов
- Возвращает минимум данных: только статус и флаг валидности
- Не подходит для пакетной проверки (по одному коду за запрос)
- Не документирован официально (эндпоинт мобильного приложения)
**Для полноценной проверки КМ из УПД рекомендуется использовать авторизованный метод** `POST /api/v3/true-api/cises/info`, который возвращает полную информацию: GTIN, наименование товара, производителя, владельца, дату ввода в оборот и т.д.
### Структура ответа /cises/info
```json
{
"cisInfo": [{
"requestedCis": "0104600702028445...",
"cis": "0104600702028445...",
"gtin": "04600702028445",
"status": "INTRODUCED",
"productName": "Молоко 3.2%",
"productGroup": "Молочная продукция",
"producerName": "АО \"Данон Россия\"",
"ownerName": "ООО Магнит",
"ownerBin": "2309085638",
"producedDate": "2025-01-15T10:00:00.000Z",
"packageType": "UNIT"
}]
}
```
**Статусы КМ:** `EMITTED` (эмитирован), `APPLIED` (нанесён), `INTRODUCED` (в обороте), `RETIRED` (выбыл), `WRITTEN_OFF` (списан), `DISAGGREGATION` (расформирован), `CANCELLED` (аннулирован)
### Работа с УПД
- Коды маркировки в XML УПД (формат Приказа №970 ФНС) находятся в элементе `Документ/ТаблСчФакт/СведТов/ДопСведТов/НомСредИдентТов`
- При проверке QR-кодов из УПД необходимо:
1. Загрузить XML УПД (формат 970 приказа)
2. Распарсить XML по XPath: `//Документ/ТаблСчФакт/СведТов/ДопСведТов/НомСредИдентТов`
3. Извлечь все коды маркировки
4. Отправить запрос в `/cises/info` (с авторизацией)
5. Отобразить статус каждого кода
---
## Шаги
- [ ] 1. **Инициализация проекта** — создать Fastify/Express backend + React frontend. Оба сервиса запускаются через `docker-compose`
- [ ] 2. **Backend: модуль аутентификации**
- 2.1. Реализовать `GET /auth/key` — получение UUID + data от True API
- 2.2. Реализовать подпись data через КриптоПро с помощью `@vgoma/crypto-pro` (Node.js binding для КриптоПро CSP)
- 2.3. Реализовать `POST /auth/simpleSignIn` — получение токена
- 2.4. Кеширование и auto-refresh токена (раз в 10 часов)
- [ ] 3. **Backend: модуль проверки КМ**
- 3.1. Реализовать `POST /api/check-codes` — принимает массив кодов маркировки
- 3.2. Вызов `POST /api/v3/true-api/cises/info` для каждого кода (батчами до 1000)
- 3.3. Возврат статуса: актуален / неактуален / не найден / ошибка
- [ ] 4. **Backend: модуль обработки УПД**
- 4.1. Приём XML-файла УПД через `POST /api/upload-upd`
- 4.2. Парсинг XML, извлечение кодов маркировки из `НомСредИдентТов`
- 4.3. Передача кодов в модуль проверки КМ (шаг 3)
- [ ] 5. **Frontend: страница авторизации**
- 5.1. Форма ввода/загрузки сертификата УКЭП
- 5.2. Отображение статуса авторизации и срока действия токена
- [ ] 6. **Frontend: страница проверки QR-кодов**
- 6.1. **Проверка одного кода** — поле ввода + две кнопки:
- «Проверить без авторизации» — через публичный API (`mobile.api.crpt.ru/mobile/check`), минимум данных
- «Проверить с авторизацией» — через `POST /cises/info`, полная информация: GTIN, наименование, производитель, владелец, статус
- 6.2. **Загрузка XML УПД (формат 970 приказа)** — drag & drop / file picker, парсинг на backend, пакетная проверка через `/cises/info`
- 6.3. Таблица результатов: код, GTIN, наименование, статус, производитель, владелец
- 6.4. Цветовая индикация: зелёный (актуален / в обороте), красный (выбыл / списан), жёлтый (предупреждение)
- [ ] 7. **Тестирование на sandbox**
- 7.1. Получение тестового УКЭП через testca2012.cryptopro.ru
- 7.2. Регистрация в sandbox (markirovka.sandbox.crptech.ru)
- 7.3. Интеграционные тесты: авторизация → проверка кодов
- [ ] 8. **Docker-сборка**
- 8.1. `Dockerfile.backend` — backend-образ с Node.js + установленным КриптоПро CSP (`crypto-pro`)
- 8.2. `Dockerfile.frontend` — nginx-образ со статикой React-приложения
- 8.3. `docker-compose.yml` — сервисы `backend`, `frontend`, общая сеть
- 8.4. README с инструкцией по запуску (`docker-compose up --build`)
- [x] 9. **Переключение контура (sandbox/prod) из UI**
- 9.1. Backend: два набора URL (`envUrls`) в `config.ts`, per-env кеш токенов
- 9.2. Backend: все сервисы и роуты принимают `?env=sandbox|prod`
- 9.3. Frontend: `<select>` в хедере, `getEnv()`/`setEnv()` в модуле API
- 9.4. QA-доработки:
- `onUnauthorized` передаёт env — логаут правильного контура при 401
- `window.confirm` при переключении на промышленный контур
- `setPage('auth')` при смене env
- `getAuthStatus` при переключении — восстановление `authenticated` если токен жив
- `uploadUpd` через общий `request()` (устранено дублирование)
## Затрагиваемые сервисы
- `backend/` — Fastify/Express backend с модулями:
- `auth-service` — получение и менеджмент токена True API
- `crypto-service` — подпись данных через `@vgoma/crypto-pro` (КриптоПро CSP)
- `cises-service` — проверка статусов кодов маркировки через `/cises/info`
- `upd-parser` — парсинг XML УПД и извлечение кодов
- `frontend/` — React (Next.js) SPA:
- Страница авторизации
- Страница проверки кодов
- Компонент загрузки УПД