diff --git a/index.js b/index.js index 89d8c97..d1c961f 100644 --- a/index.js +++ b/index.js @@ -25,6 +25,10 @@ app.use(express.json()); app.use(cors()); const querystring = require("querystring"); const https = require("https"); +const cookieParser = require("cookie-parser"); +const crypto = require("crypto"); + +app.use(cookieParser()); // const mellat = new mellatCheckout({ // terminalId: "7269507", @@ -59,7 +63,6 @@ const { getAllCities } = require("./lib/getAllCities"); const { getAllProvinces } = require("./lib/getAllProvinces"); const { MongoClient, ObjectId } = require("mongodb"); -// MongoDB for SEP pay requests (use MONGODB_URI env to override) const MONGODB_URI = process.env.MONGODB_URI || "mongodb://root:2pCCFs4wrsLDsO1pjQVA9jORT2WCjLNO5uauS6FUUaGLXCcfjw28IJmAO8RxlEJN@31.7.78.133:14365/?authSource=admin"; @@ -869,7 +872,6 @@ app.post("/sep-pay-request", async (req, res) => { }, ); - // Save to MongoDB before returning try { const coll = await getSepPayCollection(); const token = response.data?.Token ?? response.data?.token ?? null; @@ -961,11 +963,48 @@ app.post("/sepverify", async (req, res) => { } }); -// all-payments/send: send one payment to Taavon (like sepverify) -app.post("/all-payments/send", async (req, res) => { +const ALL_PAYMENTS_USER = "09011110919"; +const ALL_PAYMENTS_PASS = "666666"; +const ALL_PAYMENTS_SECRET = + process.env.ALL_PAYMENTS_SECRET || "rasadyar_all_payments_secret_2026"; +const ALL_PAYMENTS_AUTH_TOKEN = crypto + .createHmac("sha256", ALL_PAYMENTS_SECRET) + .update(ALL_PAYMENTS_USER + ":" + ALL_PAYMENTS_PASS) + .digest("hex"); + +function requireAllPaymentsAuth(req, res, next) { + const token = req.cookies && req.cookies.all_payments_auth; + if (token === ALL_PAYMENTS_AUTH_TOKEN) return next(); + res.status(401).json({ error: "Unauthorized" }); +} + +app.post("/all-payments/login", (req, res) => { + const { username, password } = req.body || {}; + if ( + String(username).trim() === ALL_PAYMENTS_USER && + String(password) === ALL_PAYMENTS_PASS + ) { + res + .cookie("all_payments_auth", ALL_PAYMENTS_AUTH_TOKEN, { + httpOnly: true, + path: "/", + maxAge: 24 * 60 * 60 * 1000, + sameSite: "lax", + }) + .json({ ok: true }); + } else { + res.status(401).json({ error: "نام کاربری یا رمز عبور اشتباه است" }); + } +}); + +app.post("/all-payments/logout", (req, res) => { + res.clearCookie("all_payments_auth", { path: "/" }).json({ ok: true }); +}); + +app.post("/all-payments/send", requireAllPaymentsAuth, async (req, res) => { const { id } = req.body; if (!id) { - return res.status(400).json({ error: "id is required" }); + return res.status(400).json({ error: "شناسه الزامی است" }); } try { const coll = await getSepPayCollection(); @@ -994,8 +1033,7 @@ app.post("/all-payments/send", async (req, res) => { } }); -// all-payments/remove: remove one payment from MongoDB -app.post("/all-payments/remove", async (req, res) => { +app.post("/all-payments/remove", requireAllPaymentsAuth, async (req, res) => { const { id } = req.body; if (!id) { return res.status(400).json({ error: "id is required" }); @@ -1013,23 +1051,25 @@ app.post("/all-payments/remove", async (req, res) => { } }); -// all-payments/remove-all: remove all payments from MongoDB -app.post("/all-payments/remove-all", async (req, res) => { - try { - const coll = await getSepPayCollection(); - const result = await coll.deleteMany({}); - return res.json({ - ok: true, - message: "همه حذف شد", - deletedCount: result.deletedCount, - }); - } catch (err) { - console.error("all-payments remove-all error", err); - return res.status(500).json({ error: err.message }); - } -}); +app.post( + "/all-payments/remove-all", + requireAllPaymentsAuth, + async (req, res) => { + try { + const coll = await getSepPayCollection(); + const result = await coll.deleteMany({}); + return res.json({ + ok: true, + message: "همه حذف شد", + deletedCount: result.deletedCount, + }); + } catch (err) { + console.error("all-payments remove-all error", err); + return res.status(500).json({ error: err.message }); + } + }, +); -// Province code (first 2 digits) -> name for all-payments const PROVINCE_NAMES = { 10: "تست", 18: "همدان", @@ -1037,8 +1077,7 @@ const PROVINCE_NAMES = { 51: "کردستان", }; -// all-payments/data: paginated + filtered list (JSON API) -app.get("/all-payments/data", async (req, res) => { +app.get("/all-payments/data", requireAllPaymentsAuth, async (req, res) => { const page = Math.max(1, parseInt(req.query.page, 10) || 1); const limit = Math.min(100, Math.max(5, parseInt(req.query.limit, 10) || 20)); let dateFrom = (req.query.dateFrom || "").trim(); // YYYY-MM-DD @@ -1054,7 +1093,6 @@ app.get("/all-payments/data", async (req, res) => { const coll = await getSepPayCollection(); const filter = {}; - // Iran timezone UTC+3:30 - treat selected date as full calendar day in Iran const IRAN_OFFSET_MS = 3.5 * 60 * 60 * 1000; if (dateFrom || dateTo) { filter.createdAt = {}; @@ -1115,8 +1153,76 @@ function escapeRegex(s) { return String(s).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } -// all-payments: modern UI with pagination, date filter, search +const allPaymentsLoginHtml = ` + +
+ + +