310 lines
9.2 KiB
Markdown
310 lines
9.2 KiB
Markdown
# 🧾 FNS Receipt Service
|
||
|
||
> Автоматизированный сервис для создания чеков самозанятого через ФНС (Мой налог) с отправкой детализированных чеков клиентам по email
|
||
|
||
---
|
||
|
||
## 📋 Содержание
|
||
|
||
* [Описание](#-описание)
|
||
* [Возможности](#-возможности)
|
||
* [Установка](#-установка)
|
||
* [Настройка](#️-настройка)
|
||
* [Использование](#-использование)
|
||
* [API Reference](#-api-reference)
|
||
* [Переменные окружения](#-переменные-окружения-env)
|
||
* [Ограничения и особенности](#-ограничения-и-особенности)
|
||
* [FAQ](#-faq)
|
||
* [Лицензия](#-лицензия)
|
||
|
||
---
|
||
|
||
## 🎯 Описание
|
||
|
||
**FNS Receipt Service** — Node.js сервис для автоматического создания чеков самозанятого через API ФНС («Мой налог») и отправки клиентам детализированных чеков по email.
|
||
|
||
Сервис учитывает ограничения официального API ФНС и использует практику, применяемую платёжными системами.
|
||
|
||
### Ключевая особенность
|
||
|
||
⚠️ **Ограничение API ФНС**: официальный API самозанятых **не поддерживает несколько позиций в одном чеке**.
|
||
|
||
Используется гибридный подход:
|
||
|
||
* **В ФНС** → отправляется **одна агрегированная позиция** с общей суммой дохода
|
||
* **Клиенту по email** → отправляется **детализированный HTML‑чек** со всеми товарами/услугами
|
||
|
||
Это полностью соответствует требованиям ФНС: налоговый учёт ведётся по сумме дохода, а не по товарным позициям.
|
||
|
||
Если вы обнаружили баг или есть идея для улучшения сервиса, пожалуйста, создайте [Issue](https://github.com/ga1maz/fns-receipt-service/issues) в репозитории.
|
||
|
||
---
|
||
|
||
## ✨ Возможности
|
||
|
||
* ✅ Создание чеков самозанятого через официальный API ФНС
|
||
* ✅ Retry‑механизм при временных ошибках ФНС (до 3 попыток)
|
||
* ✅ Детализированные HTML‑чеки для клиентов
|
||
* ✅ Отправка официальной ссылки на чек ФНС
|
||
* ✅ Защита API паролем
|
||
* ✅ Простая HTTP‑интеграция с любыми сервисами
|
||
|
||
---
|
||
|
||
## 🚀 Установка
|
||
|
||
### Требования
|
||
|
||
* Node.js **16.x+**
|
||
* npm или yarn
|
||
* Активный статус самозанятого в «Мой налог»
|
||
|
||
### Установка
|
||
|
||
```bash
|
||
git clone https://github.com/ga1maz/fns-receipt-service.git
|
||
cd fns-receipt-service
|
||
npm install
|
||
```
|
||
|
||
### Основные зависимости
|
||
|
||
```json
|
||
{
|
||
"express": "^4.18.0",
|
||
"lknpd-nalog-api": "^1.0.0",
|
||
"nodemailer": "^6.9.0",
|
||
"dotenv": "^16.0.0"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ⚙️ Настройка
|
||
|
||
### 1. Создание `.env`
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
### 2. Переменные окружения
|
||
|
||
```env
|
||
# === ФНС (Мой налог) ===
|
||
INN=123456789012
|
||
PASSWORD=your_fns_password
|
||
|
||
# === Приложение ===
|
||
APPNAME=Моя компания
|
||
ADMIN_EMAIL=admin@example.com
|
||
# === SMTP ===
|
||
SMTP_HOST=smtp.gmail.com
|
||
SMTP_PORT=587
|
||
SMTP_USER=noreply@example.com
|
||
SMTP_PASS=app_password
|
||
SMTP_MAIL_FROM=noreply@example.com
|
||
|
||
# === Безопасность ===
|
||
API_PASS=your_secure_password_here
|
||
PORT=4000
|
||
```
|
||
|
||
> Поддерживаются любые SMTP‑провайдеры (Gmail, Яндекс, Mail.ru и др.). Для Gmail рекомендуется использовать **пароль приложения**.
|
||
|
||
---
|
||
|
||
## 🎮 Использование
|
||
|
||
### Запуск сервера
|
||
|
||
```bash
|
||
node index.js
|
||
```
|
||
|
||
Сервер запускается на:
|
||
|
||
```
|
||
http://localhost:4000
|
||
```
|
||
|
||
### Проверка состояния сервиса
|
||
|
||
```bash
|
||
GET /health
|
||
```
|
||
|
||
Сервис возвращает состояние подключения и возможные ошибки:
|
||
|
||
```json
|
||
{
|
||
"status": "ok", // общий статус сервера (ok, degraded, error)
|
||
"connect_to_fns": "ok", // соединение с API ФНС
|
||
"smtp": "ok" // статус SMTP
|
||
}
|
||
```
|
||
|
||
Примеры возможных ошибок `health`:
|
||
|
||
* `connect_to_fns: error` — проблемы с авторизацией или доступностью API ФНС
|
||
* `smtp: error` — проблемы с подключением к SMTP серверу (неверный логин/пароль, блокировка сервера)
|
||
* `status: degraded` — сервис работает, но есть неполадки с одним из сервисов
|
||
|
||
Если вы что-то не заметили или есть идеи для доработки, создайте [Issue](https://github.com/ga1maz/fns-receipt-service/issues) в репозитории.
|
||
|
||
---
|
||
|
||
## 📡 API Reference
|
||
|
||
### POST `/api/v1/create-receipt`
|
||
|
||
Создаёт **один чек дохода в ФНС** на общую сумму всех позиций и отправляет клиенту **детализированный HTML‑чек по email**.
|
||
|
||
### 🔐 Авторизация
|
||
|
||
Пароль передаётся **в теле запроса**:
|
||
|
||
```json
|
||
{
|
||
"api_pass": "..."
|
||
}
|
||
```
|
||
|
||
Значение сравнивается с `API_PASS` из `.env`.
|
||
|
||
### 📥 Request Body
|
||
|
||
```json
|
||
{
|
||
"api_pass": "your_secure_password_here",
|
||
"email": "client@example.com",
|
||
"items": [
|
||
{
|
||
"id": "sku-001",
|
||
"name": "Консультация по налогам",
|
||
"price": 5000,
|
||
"quantity": 1
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### ⚙️ Логика обработки
|
||
|
||
* Общая сумма:
|
||
|
||
```
|
||
Σ (price × quantity)
|
||
```
|
||
|
||
* В ФНС отправляется:
|
||
|
||
* `name` → `APPNAME`
|
||
* `amount` → общая сумма
|
||
* `quantity` → `1`
|
||
|
||
* При ошибке ФНС:
|
||
|
||
* до **3 попыток**
|
||
* задержка **2 секунды** между попытками
|
||
* При окончательной ошибке:
|
||
* ошибка логируется в `error.json`
|
||
* администратору отправляется email с деталями ошибки
|
||
|
||
### 📤 Response (Success)
|
||
|
||
**HTTP 200 OK**
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"receiptId": "200uhagtun",
|
||
"printLink": "https://lknpd.nalog.ru/api/v1/receipt/INN/receiptId/print"
|
||
}
|
||
```
|
||
|
||
> Поля `totalAmount` и `email` **не возвращаются** в ответе.
|
||
|
||
### ❌ Ошибки
|
||
|
||
#### 400 — Неверные данные
|
||
|
||
```json
|
||
{ "error": "Неверные данные" }
|
||
```
|
||
|
||
#### 401 — Unauthorized
|
||
|
||
```json
|
||
{ "error": "Unauthorized" }
|
||
```
|
||
|
||
#### 500 — Internal Server Error
|
||
|
||
```json
|
||
{ "error": "Не удалось создать чек" }
|
||
```
|
||
|
||
#### 500 — Internal Server Error
|
||
|
||
```json
|
||
{ "error": "Не удалось создать чек. Данные сохранены для повторной попытки. }
|
||
```
|
||
|
||
|
||
---
|
||
|
||
## 🧩 Переменные окружения (.env)
|
||
|
||
| Переменная | Назначение |
|
||
| ---------------- | -------------------- |
|
||
| `API_PASS` | Пароль доступа к API |
|
||
| `INN` | ИНН самозанятого |
|
||
| `PASSWORD` | Пароль «Мой налог» |
|
||
| `APPNAME` | Название в чеке ФНС |
|
||
| `ADMIN_EMAIL` | Email администратора |
|
||
| `SMTP_HOST` | SMTP сервер |
|
||
| `SMTP_PORT` | SMTP порт |
|
||
| `SMTP_USER` | SMTP логин |
|
||
| `SMTP_PASS` | SMTP пароль |
|
||
| `SMTP_MAIL_FROM` | Email отправителя |
|
||
| `PORT` | Порт сервера |
|
||
|
||
---
|
||
|
||
## 📝 Ограничения и особенности
|
||
|
||
* ❗ Один запрос = **один чек дохода**
|
||
* ❗ Детализация **не передаётся в ФНС**, только в email
|
||
* ✔️ Поддержка дробных количеств
|
||
* ✔️ HTML‑чек с таблицей позиций
|
||
* ✔️ Официальная ссылка ФНС
|
||
|
||
---
|
||
|
||
## ❓ FAQ
|
||
|
||
**Это законно?**
|
||
Да. ФНС учитывает доход суммарно, детализация — дополнительный сервис.
|
||
|
||
**Можно ли создать несколько чеков на один платёж?**
|
||
Нет. Один платёж = один чек.
|
||
|
||
**Нужно ли хранить `receiptId`?**
|
||
Рекомендуется для поддержки клиентов и учёта.
|
||
|
||
**Где получить пароль?**
|
||
На сайте: https://lkfl2.nalog.ru/lkfl/profile-settings/common/security
|
||
|
||
**Нужен ли IP РФ?**
|
||
Да, API ФНС работает только с IP РФ.
|
||
|
||
---
|
||
|
||
## 📄 Лицензия
|
||
|
||
MIT License © 2026
|
||
|
||
---
|
||
|
||
**Сделано с ❤️ для самозанятых** |