This commit is contained in:
Ga1maz 2026-02-01 03:21:09 +05:00
parent 5662425a23
commit 8c4056edcd
5 changed files with 104 additions and 4 deletions

View File

@ -4,6 +4,7 @@ PASSWORD=your_fns_password # Пароль от приложения «
# === Настройки приложения ===
APPNAME=Моя компания # Название, отображаемое в чеке ФНС
ADMIN_EMAIL=a@ga1maz.ru # Email администратора для уведомлений
# === SMTP настройки ===
SMTP_HOST=smtp.gmail.com # SMTP сервер

2
.gitignore vendored
View File

@ -37,8 +37,10 @@ build/
*
!error.json
!.gitignore
!.env.example
!package.json
!README.md
!server.js
!LICENSE

View File

@ -97,7 +97,7 @@ PASSWORD=your_fns_password
# === Приложение ===
APPNAME=Моя компания
ADMIN_EMAIL=admin@example.com
# === SMTP ===
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
@ -207,6 +207,9 @@ GET /health
* до **3 попыток**
* задержка **2 секунды** между попытками
* При окончательной ошибке:
* ошибка логируется в `error.json`
* администратору отправляется email с деталями ошибки
### 📤 Response (Success)
@ -242,6 +245,13 @@ GET /health
{ "error": "Не удалось создать чек" }
```
#### 500 — Internal Server Error
```json
{ "error": "Не удалось создать чек. Данные сохранены для повторной попытки. }
```
---
## 🧩 Переменные окружения (.env)
@ -252,6 +262,7 @@ GET /health
| `INN` | ИНН самозанятого |
| `PASSWORD` | Пароль «Мой налог» |
| `APPNAME` | Название в чеке ФНС |
| `ADMIN_EMAIL` | Email администратора |
| `SMTP_HOST` | SMTP сервер |
| `SMTP_PORT` | SMTP порт |
| `SMTP_USER` | SMTP логин |

0
error.json Normal file
View File

View File

@ -3,16 +3,24 @@ import bodyParser from "body-parser";
import nodemailer from "nodemailer";
import dotenv from "dotenv";
import pkg from "lknpd-nalog-api";
import fs from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
dotenv.config();
const { NalogApi } = pkg;
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
app.use(bodyParser.json());
const PORT = process.env.PORT || 4000;
const MAX_RETRIES = 3;
const ERROR_FILE = path.join(__dirname, "error.json");
const ADMIN_EMAIL = process.env.ADMIN_EMAIL;
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
@ -41,6 +49,68 @@ async function createReceiptWithRetry(income, retries = MAX_RETRIES) {
}
}
async function saveToErrorFile(errorData) {
try {
let errors = [];
try {
const data = await fs.readFile(ERROR_FILE, "utf8");
const parsedData = JSON.parse(data);
if (Array.isArray(parsedData)) {
errors = parsedData;
}
} catch (err) {
}
errors.push({
...errorData,
timestamp: new Date().toISOString(),
retryAttempt: 0
});
await fs.writeFile(ERROR_FILE, JSON.stringify(errors, null, 2));
console.log(`Ошибка сохранена в ${ERROR_FILE}`);
} catch (err) {
console.error("Не удалось сохранить ошибку в файл:", err);
}
}
async function notifyAdmin(errorData) {
try {
const html = `
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Ошибка создания чека</title>
</head>
<body>
<h2> Ошибка при создании чека</h2>
<p><b>Время:</b> ${new Date().toLocaleString()}</p>
<p><b>Email клиента:</b> ${errorData.email}</p>
<p><b>Сумма:</b> ${errorData.amount} </p>
<p><b>Ошибка:</b> ${errorData.error}</p>
<p><b>Данные заказа:</b></p>
<pre>${JSON.stringify(errorData.items, null, 2)}</pre>
<p>Ошибка сохранена в error.json для последующей обработки.</p>
<p>Пробейте чек вручную через приложение Мой налог и вручную отправте клиенту чек по email.</p>
</body>
</html>
`;
await transporter.sendMail({
from: process.env.SMTP_MAIL_FROM,
to: ADMIN_EMAIL,
subject: `Ошибка создания чека ${process.env.APPNAME}`,
html
});
console.log(`Администратор ${ADMIN_EMAIL} уведомлен об ошибке`);
} catch (err) {
console.error("Не удалось отправить уведомление администратору:", err);
}
}
app.get("/health", async (req, res) => {
const result = {
status: "ok",
@ -166,11 +236,27 @@ ${process.env.APPNAME}
});
} catch (err) {
console.error("Ошибка:", err);
res.status(500).json({ error: "Не удалось создать чек" });
console.error("Ошибка создания чека:", err);
const errorData = {
email: req.body.email,
items: req.body.items,
amount: req.body.items.reduce((sum, i) => sum + i.price * (i.quantity || 1), 0),
error: err.message || "Неизвестная ошибка",
api_pass: req.body.api_pass
};
await saveToErrorFile(errorData);
await notifyAdmin(errorData);
res.status(500).json({
error: "Не удалось создать чек. Данные сохранены для повторной попытки.",
saved_to_error_file: true
});
}
});
app.listen(PORT, () => {
console.log(`✅ Сервер запущен: http://localhost:${PORT}`);
});
console.log(`📁 Файл ошибок: ${ERROR_FILE}`);
});