fns-receipt-service/README.MD
romantarkin ab50066400 fix
2026-06-12 22:58:09 +05:00

206 lines
7.0 KiB
Markdown
Raw Permalink 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.

# FNS Receipt Service
Express-сервис на Node.js 22 для создания чеков через ФНС и отправки ссылки на чек по email.
## Локальный запуск
```bash
npm install
cp .env.example .env
npm start
```
Сервис запустится на порту из `PORT` или на `4000` по умолчанию.
Админ-интерфейс доступен по адресу:
```http
GET /admin
```
Для входа используется значение `API_PASS`. Через интерфейс можно смотреть локальный журнал чеков, синхронизировать последние чеки из кабинета ФНС, создавать чек вручную, проверять ФНС/SMTP и менять параметры сервиса без отдельного фронтенд-фреймворка.
Swagger UI доступен по адресу:
```http
GET /swagger
```
OpenAPI JSON доступен по адресу:
```http
GET /openapi.json
```
## Docker
Сборка образа:
```bash
docker build -t fns-receipt-service .
```
Запуск контейнера:
```bash
docker run --env-file .env -p 3000:3000 fns-receipt-service
```
## Переменные окружения
Заполните эти переменные в Timeweb Cloud в разделе переменных окружения:
```env
INN=123456789012
PASSWORD=your_fns_password
APPNAME=Название проекта
ADMIN_EMAIL=admin@example.com
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=noreply@example.com
SMTP_PASS=email_app_password
SMTP_MAIL_FROM=noreply@example.com
API_PASS=strong_api_password
JWT_SECRET=long_random_jwt_secret
ADMIN_SESSION_HOURS=12
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_USER=default
REDIS_PASS=redis_password
REDIS_DB=0
REDIS_KEY_PREFIX=fns-receipt-service
REDIS_TIMEOUT_MS=5000
PORT=3000
HOST=0.0.0.0
FNS_TIMEOUT_MS=30000
SMTP_TIMEOUT_MS=15000
```
`API_PASS` используется как пароль входа в админ-панель и должен совпадать с `api_pass` в старых запросах к `POST /api/v1/create-receipt`. После входа UI получает JWT и дальше отправляет запросы с `Authorization: Bearer <token>`.
`JWT_SECRET` лучше задавать отдельно от `API_PASS`. Если `JWT_SECRET` не задан, сервис подпишет JWT через `API_PASS`, но для продакшена это менее удобно при ротации пароля.
Настройки, измененные через UI, сохраняются в `data/config.json` и перекрывают значения из `.env`. Сетевые параметры `PORT` и `HOST` применятся после перезапуска процесса.
Чеки сохраняются в Redis, если задан `REDIS_URL` или `REDIS_HOST`. Основной ключ:
```text
fns-receipt-service:receipts
```
Префикс можно изменить через `REDIS_KEY_PREFIX`. Если Redis не настроен или временно недоступен, сервис использует локальный fallback `data/receipts.json`.
## Timeweb Cloud
Что заполнить при Docker-деплое:
| Поле | Значение |
| --- | --- |
| Dockerfile | `Dockerfile` |
| Порт | `3000` |
| Путь до директории проекта | `/fns-receipt-service` |
| Путь проверки состояния | `/health` |
Команду запуска для Docker-деплоя отдельно указывать не нужно: она уже задана в `Dockerfile` как `CMD ["node", "/app/server.js"]`.
## API
Документация доступна в Swagger UI:
```http
GET /swagger
```
Авторизация API поддерживает два способа:
- `Authorization: Bearer <token>` после логина через `POST /api/v1/auth/login`
- `x-api-key: <API_PASS>` для серверных интеграций
Для совместимости `POST /api/v1/create-receipt` также принимает `api_pass` в JSON body.
Проверка состояния:
```http
GET /health
```
Получить JWT:
```http
POST /api/v1/auth/login
Content-Type: application/json
{
"password": "strong_api_password"
}
```
Создание чека:
```http
POST /api/v1/create-receipt
Content-Type: application/json
X-Api-Key: strong_api_password
{
"email": "client@example.com",
"items": [
{
"id": "order-1",
"name": "Услуга",
"price": 1000,
"quantity": 1
}
]
}
```
Поле `email` обязательно: на этот адрес сервис отправит письмо со ссылкой на чек после успешного создания чека в ФНС.
Получить журнал чеков:
```http
GET /api/v1/receipts?limit=50&offset=0&status=created&clientType=individual&search=client@example.com
X-Api-Key: strong_api_password
```
Журнал можно фильтровать по периоду через `dateFrom` и `dateTo`:
```http
GET /api/v1/receipts?dateFrom=2026-06-01&dateTo=2026-06-30
X-Api-Key: strong_api_password
```
Экспортировать все чеки за период в CSV без пагинации:
```http
GET /api/v1/receipts/export?dateFrom=2026-06-01&dateTo=2026-06-30
X-Api-Key: strong_api_password
```
Получить один чек:
```http
GET /api/v1/receipts/{receiptId}
X-Api-Key: strong_api_password
```
Синхронизировать чеки из ФНС за месяц:
```http
POST /api/v1/receipts/sync
Content-Type: application/json
X-Api-Key: strong_api_password
{
"month": "2026-06"
}
```
Если чек создан в ФНС, но письмо клиенту не отправилось, API вернет `success: true`, `receiptCreated: true`, `emailSent: false`, `receiptId`, `printLink` и `technicalError`. Ошибка отправки сохранится в `error.json`.
Все успешно созданные чеки сохраняются в Redis, чтобы в UI была связь между чеком, email пользователя и позициями заказа. Синхронизация с ФНС выполняется за выбранный месяц, подтягивает страницы по 50 записей до конца месяца и помечает аннулированные чеки как `cancelled`. Аннулированные чеки показываются в списке, но не учитываются в количестве действующих чеков и итоговой сумме.
В UI и API по каждому чеку рассчитываются суммы `grossAmount` (грязными), `taxAmount` (налог) и `netAmount` (чистыми). Для физлиц используется ставка 4%, для юрлиц 6%.