import express from "express"; import bodyParser from "body-parser"; import nodemailer from "nodemailer"; import dotenv from "dotenv"; import pkg from "lknpd-nalog-api"; dotenv.config(); const { NalogApi } = pkg; const app = express(); app.use(bodyParser.json()); const PORT = process.env.PORT || 4000; const MAX_RETRIES = 3; const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT), secure: false, auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS } }); const nalogApi = new NalogApi({ inn: process.env.INN, password: process.env.PASSWORD }); async function createReceiptWithRetry(income, retries = MAX_RETRIES) { for (let attempt = 1; attempt <= retries; attempt++) { try { return await nalogApi.addIncome(income); } catch (err) { console.error(`Попытка ${attempt} не удалась`, err.message || err); if (attempt === retries) throw err; await new Promise(r => setTimeout(r, 2000)); } } } app.get("/health", async (req, res) => { const result = { status: "ok", connect_to_fns: "ok", smtp: "ok", }; try { await transporter.verify(); } catch (err) { result.smtp = "error"; result.status = "degraded"; } try { await nalogApi.getUserInfo(); } catch (err) { console.error("FNS health error:", err.message || err); result.connect_to_fns = "error"; result.status = "degraded"; } res.json(result); }); app.post("/api/v1/create-receipt", async (req, res) => { try { const { api_pass, email, items } = req.body; if (api_pass !== process.env.API_PASS) { return res.status(401).json({ error: "Unauthorized" }); } if (!email || !Array.isArray(items) || items.length === 0) { return res.status(400).json({ error: "Неверные данные" }); } const total = items.reduce( (sum, i) => sum + i.price * (i.quantity || 1), 0 ); const income = { name: `${process.env.APPNAME}`, amount: Number(total.toFixed(2)), quantity: 1 }; const receiptId = await createReceiptWithRetry(income); const printLink = `https://lknpd.nalog.ru/api/v1/receipt/${process.env.INN}/${receiptId}/print`; const rows = items.map(i => { const qty = i.quantity || 1; return ` ${i.id} ${i.name} ${i.price.toFixed(2)} ${qty} ${(i.price * qty).toFixed(2)} `; }).join(""); const html = ` Чек

Ваш чек

Чек сформирован в ФНС (Мой налог)

${rows}
IDНазваниеЦенаКол-воСумма

Итого: ${total.toFixed(2)} ₽

Посмотреть чек

${process.env.APPNAME}

`; await transporter.sendMail({ from: process.env.SMTP_MAIL_FROM, to: email, subject: `Чек ${process.env.APPNAME}`, html }); res.json({ success: true, receiptId, printLink }); } catch (err) { console.error("Ошибка:", err); res.status(500).json({ error: "Не удалось создать чек" }); } }); app.listen(PORT, () => { console.log(`✅ Сервер запущен: http://localhost:${PORT}`); });