This commit is contained in:
Clusy
2026-08-06 04:47:05 +00:00
parent 62bdd6291e
commit 2d4eee2950
81 changed files with 0 additions and 10766 deletions
-166
View File
@@ -1,166 +0,0 @@
# 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:
- Страница авторизации
- Страница проверки кодов
- Компонент загрузки УПД