Compare commits

..

12 Commits

Author SHA1 Message Date
957d5407c7 update: samasat good sum 2026-02-03 16:42:17 +03:30
226cfae959 ad: transactions province filter 2026-02-01 10:59:40 +03:30
6f7d04829d ad: transactions province filter 2026-02-01 10:47:38 +03:30
d1c0112b43 add: all payments page authentication 2026-02-01 10:26:22 +03:30
f7818a57c0 add: gui sep requests 2026-02-01 10:19:02 +03:30
f3cc7e6957 add: gui sep requests 2026-02-01 10:02:52 +03:30
ef50e04a4c add: gui sep requests 2026-02-01 09:49:46 +03:30
18d3f17ce3 add: gui sep requests 2026-02-01 09:43:51 +03:30
1406e4bd24 add: gui sep requests 2026-02-01 08:41:16 +03:30
c5aad8deca add: gui sep requests 2026-02-01 08:32:36 +03:30
2898086499 add: server health endpoint 2026-01-27 12:41:56 +03:30
6d80230613 update: dockerfile 2026-01-27 12:36:10 +03:30
4 changed files with 1001 additions and 50 deletions

View File

@@ -4,7 +4,7 @@ WORKDIR /app
COPY . .
npm install --force
RUN npm install --force
ENV PORT=3000
EXPOSE 3000

776
index.js
View File

@@ -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",
@@ -57,6 +61,26 @@ const {
} = require("./lib/taavon-send-data");
const { getAllCities } = require("./lib/getAllCities");
const { getAllProvinces } = require("./lib/getAllProvinces");
const { MongoClient, ObjectId } = require("mongodb");
const MONGODB_URI =
process.env.MONGODB_URI ||
"mongodb://root:2pCCFs4wrsLDsO1pjQVA9jORT2WCjLNO5uauS6FUUaGLXCcfjw28IJmAO8RxlEJN@31.7.78.133:14365/?authSource=admin";
const SEP_DB_NAME = "rasadyar";
const SEP_COLLECTION = "sepPayRequests";
let mongoClient = null;
async function getMongoClient() {
if (!mongoClient) {
mongoClient = new MongoClient(MONGODB_URI);
await mongoClient.connect();
}
return mongoClient;
}
async function getSepPayCollection() {
const client = await getMongoClient();
return client.db(SEP_DB_NAME).collection(SEP_COLLECTION);
}
// var _soap2 = _interopRequireDefault(_soap);
@@ -98,7 +122,7 @@ app.post("/cumulative-dynamic-pay-request", async (req, res) => {
parseInt(orderId),
amount,
additionalData,
"https://rasadyar.net/verify-payment"
"https://rasadyar.net/verify-payment",
);
const payRequestRes = payRequestResult.return.split(",");
const responseCode = payRequestRes[0];
@@ -168,7 +192,7 @@ async function reversePay(orderId, saleOrderId, saleReferenceId) {
let resultReversePay = await bpReversalRequest(
orderId,
saleOrderId,
saleReferenceId
saleReferenceId,
);
resultReversePay = resultReversePay.return;
console.log(resultReversePay);
@@ -329,7 +353,7 @@ app.post("/verify-payment", async (req, res) => {
resultCode_bpVerifyRequest = await bpVerifyRequest(
saleOrderId,
saleOrderId,
saleReferenceId
saleReferenceId,
);
resultCode_bpVerifyRequest = resultCode_bpVerifyRequest.return;
console.log("bpVerifyRequest:" + resultCode_bpVerifyRequest);
@@ -342,10 +366,10 @@ app.post("/verify-payment", async (req, res) => {
resultCode_bpinquiryRequest = await bpInquiryRequest(
saleOrderId,
saleOrderId,
saleReferenceId
saleReferenceId,
);
resultCode_bpinquiryRequest = parseInt(
resultCode_bpinquiryRequest.return
resultCode_bpinquiryRequest.return,
);
console.log("bpinquiryRequest" + resultCode_bpinquiryRequest);
@@ -366,7 +390,7 @@ app.post("/verify-payment", async (req, res) => {
resultCode_bpSettleRequest = await bpSettleRequest(
saleOrderId,
saleOrderId,
saleReferenceId
saleReferenceId,
);
resultCode_bpSettleRequest = parseInt(resultCode_bpSettleRequest.return);
@@ -492,7 +516,7 @@ app.post("/zarinpay", async (req, res) => {
"Content-Type": "application/json",
accept: "application/json",
},
}
},
);
if (response.data.data.authority) {
return res.status(201).json(response.data.data);
@@ -530,7 +554,7 @@ app.get("/zarinverify", async (req, res) => {
"Content-Type": "application/json",
accept: "application/json",
},
}
},
);
console.log("Verification response in verify: ", response.data);
@@ -634,7 +658,7 @@ app.post("/sadad-get-token", async (req, res) => {
"Content-Type": "application/json",
Referer: "https://rasadyar.net/",
},
}
},
);
res.status(201).send(response.data);
@@ -691,7 +715,7 @@ app.post("/sadad-request-payment", async (req, res) => {
"Content-Type": "application/json",
Referer: "https://rasadyar.net/",
},
}
},
);
const responseData = response.data;
@@ -750,7 +774,7 @@ app.post("/asanverify", async (req, res) => {
}
const encryptedCredintials = await encryptWS(
`${config.username},${config.password}`
`${config.username},${config.password}`,
);
const soapClient = await soap.createClientAsync(config.WebServiceUrl);
const verifyArgs = {
@@ -764,7 +788,7 @@ app.post("/asanverify", async (req, res) => {
return res
.status(500)
.send(
`خطای شماره: ${verifyResult.RequestVerificationResult} در هنگام Verify`
`خطای شماره: ${verifyResult.RequestVerificationResult} در هنگام Verify`,
);
}
@@ -773,11 +797,11 @@ app.post("/asanverify", async (req, res) => {
return res
.status(500)
.send(
`خطای شماره: ${settlementResult.RequestReconciliationResult} در هنگام Settlement`
`خطای شماره: ${settlementResult.RequestReconciliationResult} در هنگام Settlement`,
);
}
res.send(
'<div style="width:250px; margin:100px auto; direction:rtl; font:bold 14px Tahoma">تراکنش با موفقیت انجام پذیرفت.</div>'
'<div style="width:250px; margin:100px auto; direction:rtl; font:bold 14px Tahoma">تراکنش با موفقیت انجام پذیرفت.</div>',
);
});
});
@@ -824,6 +848,9 @@ app.post("/sep-pay-request", async (req, res) => {
return res.status(400).send("Invalid amount");
}
const resNum = generateRandomString();
const redirectUrl = `https://pay.rasadyar.net/sepverify/?Amount=${amount}&province=${provincecode}&isLink=${isLink}`;
try {
const response = await axios.post(
SEP_API,
@@ -831,8 +858,8 @@ app.post("/sep-pay-request", async (req, res) => {
action: "token",
TerminalId: SEP_TERMINAL_ID,
Amount: parsedAmount,
ResNum: generateRandomString(),
RedirectUrl: `https://pay.rasadyar.net/sepverify/?Amount=${amount}&province=${provincecode}&isLink=${isLink}`,
ResNum: resNum,
RedirectUrl: redirectUrl,
CellNumber: phone,
SettlementIBANInfo: wages,
// TranType: "Government",
@@ -842,8 +869,34 @@ app.post("/sep-pay-request", async (req, res) => {
"Content-Type": "application/json",
accept: "application/json",
},
}
},
);
try {
const coll = await getSepPayCollection();
const token = response.data?.Token ?? response.data?.token ?? null;
await coll.insertOne({
amount: parsedAmount,
amountRaw: amount,
phone: phone || null,
provincecode: provincecode || null,
isLink: isLink || null,
wages: wages || null,
resNum,
redirectUrl,
token,
rawResponse: response.data,
verified: false,
refNum: null,
traceNo: null,
securePan: null,
createdAt: new Date(),
updatedAt: new Date(),
});
} catch (dbErr) {
console.error("SEP pay request: failed to save to DB", dbErr);
}
return res.status(201).json(response.data);
} catch (error) {
return res
@@ -870,12 +923,11 @@ app.post("/sepverify", async (req, res) => {
"Content-Type": "application/json",
accept: "application/json",
},
}
},
);
if (response.data.ResultCode === 0) {
let redirectUrl = `https://rasadyar.net/payment?finalAmount=${Amount}&cardHolderPan=${SecurePan}&date=${new Date()}&saleReferenceId=${TraceNo}`;
let subDomain = "";
if (isLink) {
await taavonSendDataZarinPalLink(province, {
@@ -911,6 +963,635 @@ app.post("/sepverify", async (req, res) => {
}
});
const ALL_PAYMENTS_USER = "09011110919";
const ALL_PAYMENTS_PASS = "1110919";
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: "شناسه الزامی است" });
}
try {
const coll = await getSepPayCollection();
const doc = await coll.findOne({ _id: new ObjectId(id) });
if (!doc) {
return res.status(404).json({ error: "Record not found" });
}
const province = (doc.provincecode || "").toString().substring(0, 2);
const isLink =
doc.isLink === true || doc.isLink === "true" || doc.isLink === "1";
const data = {
authority: doc.token,
refId: doc.traceNo,
cardHolderPan: doc.securePan,
};
if (isLink) {
await taavonSendDataZarinPalLink(province, data);
} else {
await taavonSendDataZarinPal(province, data);
}
await coll.deleteOne({ _id: new ObjectId(id) });
return res.json({ ok: true, message: "ارسال شد" });
} catch (err) {
console.error("all-payments send error", err);
return res.status(500).json({ error: err.message });
}
});
app.post("/all-payments/remove", requireAllPaymentsAuth, async (req, res) => {
const { id } = req.body;
if (!id) {
return res.status(400).json({ error: "id is required" });
}
try {
const coll = await getSepPayCollection();
const result = await coll.deleteOne({ _id: new ObjectId(id) });
if (result.deletedCount === 0) {
return res.status(404).json({ error: "Record not found" });
}
return res.json({ ok: true, message: "حذف شد" });
} catch (err) {
console.error("all-payments remove 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 });
}
},
);
const PROVINCE_NAMES = {
10: "تست",
18: "همدان",
47: "مرکزی",
51: "کردستان",
};
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
let dateTo = (req.query.dateTo || "").trim();
if (dateFrom && !dateTo) dateTo = dateFrom;
const search = (req.query.search || "").trim();
const province = (req.query.province || "").trim();
if (dateFrom || dateTo) {
console.log("all-payments/data date filter:", { dateFrom, dateTo });
}
try {
const coll = await getSepPayCollection();
const filter = {};
const IRAN_OFFSET_MS = 3.5 * 60 * 60 * 1000;
if (dateFrom || dateTo) {
filter.createdAt = {};
if (dateFrom) {
const utcStart = new Date(dateFrom + "T00:00:00.000Z").getTime();
filter.createdAt.$gte = new Date(utcStart - IRAN_OFFSET_MS);
}
if (dateTo) {
const utcEnd = new Date(dateTo + "T23:59:59.999Z").getTime();
filter.createdAt.$lte = new Date(utcEnd - IRAN_OFFSET_MS);
}
}
if (province) {
const code = String(province).trim();
const prefixRegex = new RegExp("^" + escapeRegex(code));
filter.$and = filter.$and || [];
filter.$and.push({
$or: [
{ provincecode: prefixRegex },
{
$expr: {
$regexMatch: {
input: { $toString: "$provincecode" },
regex: "^" + escapeRegex(code),
},
},
},
],
});
}
if (search) {
filter.$or = [
{ amountRaw: new RegExp(escapeRegex(search), "i") },
{ phone: new RegExp(escapeRegex(search), "i") },
{ provincecode: new RegExp(escapeRegex(search), "i") },
{ resNum: new RegExp(escapeRegex(search), "i") },
];
// Province name filter: match search text against province names (e.g. همدان, تست)
Object.keys(PROVINCE_NAMES).forEach((code) => {
if (PROVINCE_NAMES[code].indexOf(search) !== -1) {
filter.$or.push({ provincecode: code });
filter.$or.push({ provincecode: parseInt(code, 10) });
}
});
if (!isNaN(parseInt(search, 10))) {
filter.$or.push({ amount: parseInt(search, 10) });
}
}
const total = await coll.countDocuments(filter);
const raw = await coll
.find(filter)
.sort({ createdAt: -1 })
.skip((page - 1) * limit)
.limit(limit)
.toArray();
const list = raw.map((doc) => {
const code = (doc.provincecode || "").toString().substring(0, 2);
const provinceName = PROVINCE_NAMES[code] || doc.provincecode || "-";
return {
...doc,
_id: doc._id ? doc._id.toString() : doc._id,
provinceName,
};
});
return res.json({
list,
total,
page,
limit,
totalPages: Math.ceil(total / limit) || 1,
});
} catch (err) {
console.error("all-payments data error", err);
return res.status(500).json({ error: err.message });
}
});
function escapeRegex(s) {
return String(s).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
const allPaymentsLoginHtml = `<!DOCTYPE html>
<html dir="rtl" lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ورود - همه پرداخت‌ها</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root { --bg: #0f0f14; --surface: #18181f; --surface-hover: #1e1e28; --border: #2a2a36; --text: #e4e4e7; --text-muted: #a1a1aa; --primary: #6366f1; --primary-hover: #818cf8; --danger: #ef4444; --radius: 12px; --radius-sm: 8px; }
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Inter', -apple-system, sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; }
.login-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 32px; width: 100%; max-width: 360px; }
.login-card h1 { font-size: 1.25rem; margin-bottom: 24px; text-align: center; }
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 0.8125rem; color: var(--text-muted); margin-bottom: 6px; }
.form-group input { width: 100%; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); padding: 10px 14px; font-size: 0.875rem; }
.form-group input:focus { outline: none; border-color: var(--primary); }
.btn { width: 100%; border: none; border-radius: var(--radius-sm); padding: 12px; font-size: 0.875rem; font-weight: 500; cursor: pointer; background: var(--primary); color: #fff; margin-top: 8px; }
.btn:hover:not(:disabled) { background: #818cf8; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
.err-msg { color: var(--danger); font-size: 0.8125rem; margin-top: 12px; text-align: center; }
</style>
</head>
<body>
<div class="login-card">
<h1>ورود به بخش پرداخت‌ها</h1>
<form id="login-form">
<div class="form-group">
<label for="username">نام کاربری</label>
<input type="text" id="username" name="username" autocomplete="username" required />
</div>
<div class="form-group">
<label for="password">رمز عبور</label>
<input type="password" id="password" name="password" autocomplete="current-password" required />
</div>
<button type="submit" class="btn" id="btn-login">ورود</button>
<div class="err-msg" id="err-msg"></div>
</form>
</div>
<script>
(function() {
var form = document.getElementById('login-form');
var btn = document.getElementById('btn-login');
var errEl = document.getElementById('err-msg');
form.onsubmit = function(e) {
e.preventDefault();
errEl.textContent = '';
var username = (document.getElementById('username').value || '').trim();
var password = (document.getElementById('password').value || '');
btn.disabled = true;
fetch('/all-payments/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: username, password: password }) })
.then(function(r) { return r.json(); })
.then(function(j) {
if (j.ok) { window.location.href = '/all-payments'; return; }
errEl.textContent = j.error || 'نام کاربری یا رمز عبور اشتباه است';
})
.catch(function(e) { errEl.textContent = e.message || 'خطا در ارتباط'; })
.finally(function() { btn.disabled = false; });
};
})();
</script>
</body>
</html>`;
app.get("/all-payments", async (req, res) => {
const token = req.cookies && req.cookies.all_payments_auth;
if (token !== ALL_PAYMENTS_AUTH_TOKEN) {
res.setHeader("Content-Type", "text/html; charset=utf-8");
return res.send(allPaymentsLoginHtml);
}
const html = `<!DOCTYPE html>
<html dir="rtl" lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>همه پرداخت‌ها</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/persian-datepicker@1.2.0/dist/css/persian-datepicker.min.css">
<style>
:root {
--bg: #0f0f14;
--surface: #18181f;
--surface-hover: #1e1e28;
--border: #2a2a36;
--text: #e4e4e7;
--text-muted: #a1a1aa;
--primary: #6366f1;
--primary-hover: #818cf8;
--danger: #ef4444;
--danger-hover: #dc2626;
--success: #22c55e;
--radius: 12px;
--radius-sm: 8px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Inter', -apple-system, sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; padding: 24px; line-height: 1.5; }
.page { max-width: 1200px; margin: 0 auto; }
.page-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 24px; }
.page-header h1 { font-size: 1.75rem; font-weight: 700; margin: 0; letter-spacing: -0.02em; }
.header-actions { display: flex; gap: 10px; align-items: center; }
.toolbar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 20px; }
.filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; flex: 1; }
.filter-group { display: flex; align-items: center; gap: 8px; }
.filter-group label { font-size: 0.8125rem; color: var(--text-muted); font-weight: 500; }
input[type="text"], input[type="date"] {
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
color: var(--text); padding: 10px 14px; font-size: 0.875rem; min-width: 140px;
}
input[type="text"]:focus, input[type="date"]:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(99,102,241,0.2); }
input[type="text"]::placeholder { color: var(--text-muted); }
select {
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
color: var(--text); padding: 10px 14px; font-size: 0.875rem; min-width: 140px; cursor: pointer;
}
select:focus { outline: none; border-color: var(--primary); }
.btn { border: none; border-radius: var(--radius-sm); padding: 10px 18px; font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: background 0.15s, opacity 0.15s; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--primary-hover); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover:not(:disabled) { background: var(--danger-hover); }
.btn-ghost { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-hover); }
.btn-sm { padding: 6px 12px; font-size: 0.8125rem; }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 14px 16px; text-align: right; border-bottom: 1px solid var(--border); }
th { font-size: 0.75rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; background: rgba(0,0,0,0.2); }
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--surface-hover); }
td { font-size: 0.875rem; }
.cell-msg { font-size: 0.75rem; margin-top: 4px; }
.cell-msg.ok { color: var(--success); }
.cell-msg.err { color: var(--danger); }
.actions-cell { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pagination { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 16px; border-top: 1px solid var(--border); }
.pagination-info { font-size: 0.8125rem; color: var(--text-muted); }
.pagination-btns { display: flex; gap: 6px; align-items: center; }
.pagination-btns button { min-width: 36px; }
.pagination-btns .page-num { min-width: 32px; padding: 8px; }
.empty { text-align: center; padding: 48px 24px; color: var(--text-muted); font-size: 0.9375rem; }
.loading { text-align: center; padding: 48px; color: var(--text-muted); }
.pwt-btn-today { font-family: inherit !important; }
.datepicker-input { cursor: pointer; }
</style>
</head>
<body>
<div class="page">
<div class="page-header">
<h1>همه پرداخت‌ها</h1>
<div class="header-actions">
<button type="button" class="btn btn-danger" id="btn-remove-all">حذف همه</button>
<button type="button" class="btn btn-ghost" id="btn-logout">خروج</button>
</div>
</div>
<div class="toolbar">
<div class="filters">
<div class="filter-group">
<label>از تاریخ</label>
<input type="text" id="dateFrom" class="datepicker-input" readonly placeholder="انتخاب تاریخ" autocomplete="off" />
<input type="hidden" id="dateFromGregorian" />
</div>
<div class="filter-group">
<label>تا تاریخ</label>
<input type="text" id="dateTo" class="datepicker-input" readonly placeholder="انتخاب تاریخ" autocomplete="off" />
<input type="hidden" id="dateToGregorian" />
</div>
<div class="filter-group">
<label>استان</label>
<select id="province">
<option value="">همه استان‌ها</option>
${Object.keys(PROVINCE_NAMES)
.map((c) => `<option value="${c}">${PROVINCE_NAMES[c]}</option>`)
.join("")}
</select>
</div>
<div class="filter-group">
<input type="text" id="search" placeholder="جستجو" />
</div>
<button type="button" class="btn btn-ghost" id="btn-apply">اعمال فیلتر</button>
</div>
</div>
<div class="card">
<div class="table-wrap">
<div id="table-content"></div>
</div>
<div id="pagination" class="pagination" style="display:none;"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/persian-date@1.1.0/dist/persian-date.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/persian-datepicker@1.2.0/dist/js/persian-datepicker.min.js"></script>
<script>
(function() {
var state = { page: 1, limit: 20, dateFrom: '', dateTo: '', search: '', province: '' };
var contentEl = document.getElementById('table-content');
var paginationEl = document.getElementById('pagination');
function persianDigitsToAscii(s) {
var p = '۰۱۲۳۴۵۶۷۸۹';
var a = '0123456789';
var out = '';
for (var i = 0; i < s.length; i++) {
var idx = p.indexOf(s[i]);
out += idx !== -1 ? a[idx] : s[i];
}
return out;
}
function persianToGregorianStr(pStr) {
if (!pStr || typeof pStr !== 'string' || !pStr.trim()) return '';
if (typeof persianDate === 'undefined') return '';
try {
var normalized = persianDigitsToAscii(pStr.trim());
var d = new persianDate(normalized).toDate();
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
} catch (e) { return ''; }
}
function buildQuery() {
var q = 'page=' + state.page + '&limit=' + state.limit;
if (state.dateFrom) q += '&dateFrom=' + encodeURIComponent(state.dateFrom);
if (state.dateTo) q += '&dateTo=' + encodeURIComponent(state.dateTo);
if (state.province) q += '&province=' + encodeURIComponent(state.province);
if (state.search) q += '&search=' + encodeURIComponent(state.search);
return q;
}
function renderRow(item, index) {
var createdAt = item.createdAt ? new Date(item.createdAt).toLocaleString('fa-IR') : '-';
var id = item._id;
var rowNum = (state.page - 1) * state.limit + (index + 1);
var amountVal = item.amountRaw != null ? item.amountRaw : item.amount;
var amountStr = amountVal != null ? Number(amountVal).toLocaleString('fa-IR') : '-';
return '<tr data-id="' + id + '"><td>' + rowNum + '</td><td>' + amountStr + '</td><td>' + (item.provinceName || '-') + '</td><td>' + (item.isLink ? 'بله' : 'خیر') + '</td><td>' + (item.phone || '-') + '</td><td>' + createdAt + '</td><td><div class="actions-cell"><button type="button" class="btn btn-primary btn-sm btn-send" data-id="' + id + '">ارسال به سرور</button><button type="button" class="btn btn-danger btn-sm btn-remove" data-id="' + id + '">حذف</button><div class="cell-msg" id="msg-' + id + '"></div></div></td></tr>';
}
function bindRowEvents(fragment) {
if (!fragment || !fragment.querySelectorAll) return;
fragment.querySelectorAll('.btn-send').forEach(function(btn) {
btn.onclick = function() {
if (!confirm('آیا مطمئن هستید؟')) return;
var id = btn.getAttribute('data-id');
var msgEl = document.getElementById('msg-' + id);
if (msgEl) { msgEl.textContent = ''; msgEl.className = 'cell-msg'; }
btn.disabled = true;
fetch('/all-payments/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
.then(function(r) { return r.json(); })
.then(function(j) {
if (j.error && msgEl) { msgEl.textContent = j.error; msgEl.className = 'cell-msg err'; }
else { var row = document.querySelector('tr[data-id="' + id + '"]'); if (row) { row.remove(); if (!contentEl.querySelector('tbody tr')) load(); } }
})
.catch(function(e) { if (msgEl) msgEl.textContent = e.message; msgEl.className = 'cell-msg err'; })
.finally(function() { btn.disabled = false; });
};
});
fragment.querySelectorAll('.btn-remove').forEach(function(btn) {
btn.onclick = function() {
if (!confirm('آیا از حذف این مورد مطمئن هستید؟')) return;
var id = btn.getAttribute('data-id');
var msgEl = document.getElementById('msg-' + id);
if (msgEl) { msgEl.textContent = ''; msgEl.className = 'cell-msg'; }
btn.disabled = true;
fetch('/all-payments/remove', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
.then(function(r) { return r.json(); })
.then(function(j) {
if (j.error && msgEl) { msgEl.textContent = j.error; msgEl.className = 'cell-msg err'; }
else { var row = document.querySelector('tr[data-id="' + id + '"]'); if (row) { row.remove(); if (!contentEl.querySelector('tbody tr')) load(); } }
})
.catch(function(e) { if (msgEl) msgEl.textContent = e.message; msgEl.className = 'cell-msg err'; })
.finally(function() { btn.disabled = false; });
};
});
}
function renderPagination(data) {
var totalPages = data.totalPages;
var page = data.page;
var total = data.total;
var start = (page - 1) * data.limit + 1;
var end = Math.min(page * data.limit, total);
if (total === 0) { paginationEl.style.display = 'none'; return; }
paginationEl.style.display = 'flex';
var info = 'نمایش ' + start + ' تا ' + end + ' از ' + total + ' مورد';
var btns = '';
btns += '<button type="button" class="btn btn-ghost btn-sm" data-page="' + (page - 1) + '" ' + (page <= 1 ? 'disabled' : '') + '>قبلی</button>';
var from = Math.max(1, page - 2);
var to = Math.min(totalPages, page + 2);
for (var i = from; i <= to; i++) {
btns += '<button type="button" class="btn btn-sm page-num ' + (i === page ? 'btn-primary' : 'btn-ghost') + '" data-page="' + i + '">' + i + '</button>';
}
btns += '<button type="button" class="btn btn-ghost btn-sm" data-page="' + (page + 1) + '" ' + (page >= totalPages ? 'disabled' : '') + '>بعدی</button>';
paginationEl.innerHTML = '<span class="pagination-info">' + info + '</span><div class="pagination-btns">' + btns + '</div>';
paginationEl.querySelectorAll('[data-page]').forEach(function(b) {
b.onclick = function() {
var p = parseInt(b.getAttribute('data-page'), 10);
if (p >= 1 && p <= totalPages) { state.page = p; load(); }
};
});
}
function load() {
contentEl.innerHTML = '<div class="loading">در حال بارگذاری...</div>';
fetch('/all-payments/data?' + buildQuery())
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.error) { contentEl.innerHTML = '<div class="empty">' + data.error + '</div>'; return; }
var list = data.list || [];
if (list.length === 0) {
contentEl.innerHTML = '<div class="empty">موردی یافت نشد.</div>';
paginationEl.style.display = 'none';
return;
}
var thead = '<table><thead><tr><th>ردیف</th><th>مبلغ</th><th>استان</th><th>لینک</th><th>موبایل</th><th>تاریخ</th><th>عملیات</th></tr></thead><tbody>';
var rows = list.map(function(item, i) { return renderRow(item, i); }).join('');
contentEl.innerHTML = thead + rows + '</tbody></table>';
bindRowEvents(contentEl);
renderPagination(data);
})
.catch(function(e) {
contentEl.innerHTML = '<div class="empty">خطا: ' + e.message + '</div>';
});
}
function unixToGregorianYMD(unix) {
var d = new Date(unix);
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}
function initDatepickers() {
if (typeof jQuery === 'undefined' || !jQuery.fn.pDatepicker) return;
jQuery('#dateFrom').pDatepicker({
format: 'YYYY/MM/DD',
initialValue: false,
observer: true,
calendar: { persian: { locale: 'fa' } },
autoClose: true,
onSelect: function(unix) {
if (unix) {
var g = unixToGregorianYMD(unix);
document.getElementById('dateFromGregorian').value = g;
if (typeof persianDate !== 'undefined') {
var pd = new persianDate(unix);
document.getElementById('dateFrom').value = pd.format('YYYY/MM/DD');
}
}
}
});
jQuery('#dateTo').pDatepicker({
format: 'YYYY/MM/DD',
initialValue: false,
observer: true,
calendar: { persian: { locale: 'fa' } },
autoClose: true,
onSelect: function(unix) {
if (unix) {
var g = unixToGregorianYMD(unix);
document.getElementById('dateToGregorian').value = g;
if (typeof persianDate !== 'undefined') {
var pd = new persianDate(unix);
document.getElementById('dateTo').value = pd.format('YYYY/MM/DD');
}
}
}
});
}
document.getElementById('btn-apply').onclick = function() {
document.getElementById('dateFrom').blur();
document.getElementById('dateTo').blur();
state.dateFrom = (document.getElementById('dateFromGregorian').value || '').trim();
state.dateTo = (document.getElementById('dateToGregorian').value || '').trim();
if (state.dateFrom && !state.dateTo) state.dateTo = state.dateFrom;
state.province = (document.getElementById('province').value || '').trim();
state.search = document.getElementById('search').value.trim();
state.page = 1;
load();
};
document.getElementById('search').onkeydown = function(e) { if (e.key === 'Enter') document.getElementById('btn-apply').click(); };
document.getElementById('btn-remove-all').onclick = function() {
if (!confirm('آیا از حذف همه موارد مطمئن هستید؟')) return;
var btn = this;
btn.disabled = true;
fetch('/all-payments/remove-all', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' })
.then(function(r) { return r.json(); })
.then(function(j) {
if (j.error) alert(j.error);
else { state.page = 1; load(); }
})
.catch(function(e) { alert(e.message); })
.finally(function() { btn.disabled = false; });
};
document.getElementById('btn-logout').onclick = function() {
fetch('/all-payments/logout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' })
.then(function() { window.location.href = '/all-payments'; });
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() { initDatepickers(); load(); });
} else {
initDatepickers();
load();
}
})();
</script>
</body>
</html>`;
res.setHeader("Content-Type", "text/html; charset=utf-8");
res.send(html);
});
//end sep ---------------------------------------------------------------------------------------------
// samasat crack
@@ -922,12 +1603,12 @@ const getPersianDate = (daysOffset = 0) => {
const jalaaliDate = toJalaali(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
currentDate.getDate()
currentDate.getDate(),
);
const { jy, jm, jd } = jalaaliDate;
const formattedDate = `${jy}/${String(jm).padStart(2, "0")}/${String(
jd
jd,
).padStart(2, "0")}`;
return formattedDate;
@@ -940,13 +1621,13 @@ const getPersianDateForHatching = (daysOffset = 0) => {
const jalaaliDate = toJalaali(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
currentDate.getDate()
currentDate.getDate(),
);
const { jy, jm, jd } = jalaaliDate;
const formattedDate = `${String(jd).padStart(2, "0")}/${String(jm).padStart(
2,
"0"
"0",
)}/${jy}`;
return formattedDate;
@@ -1265,14 +1946,14 @@ app.post("/samasat-users", async (req, res) => {
...updatedUnit,
PId: Id,
Province: getAllProvinces().find(
(p) => parseInt(p.id) === parseInt(province)
(p) => parseInt(p.id) === parseInt(province),
)?.name,
City: getAllCities().find(
(city) =>
parseInt(city.id) === parseInt(updatedUnit?.LocationIdCity)
parseInt(city.id) === parseInt(updatedUnit?.LocationIdCity),
)?.name,
};
}
},
);
res.json(transformedUsers);
@@ -1584,11 +2265,16 @@ app.post("/samasat-good-sum", async (req, res) => {
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(
jsonData.Data?.filter(
(option) => option?.TrackingStatus === 2
)?.reduce((acc, item) => acc + Number(item?.GoodAmount || 0), 0)
);
const goodSum = jsonData.Data?.filter(
(option) => option?.TrackingStatus === 2,
)?.reduce((acc, item) => acc + Number(item?.GoodAmount || 0), 0);
const loadingSum = jsonData.Data?.filter(
(option) => option?.TrackingStatus === 1,
)?.reduce((acc, item) => acc + Number(item?.GoodAmount || 0), 0);
res.json({ goodSum, loadingSum });
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
@@ -1660,7 +2346,7 @@ app.post("/samasat-evacuation", async (req, res) => {
// jsonData.SumLosses +
jsonData.SumIllness +
jsonData.SumNaturalOccurrence +
jsonData.SumFire
jsonData.SumFire,
);
}
} else {
@@ -1877,7 +2563,7 @@ async function performLogin() {
response.on("end", () => {
const csrfMatch = data.match(
/<input name="__RequestVerificationToken" type="hidden" value="([^"]+)"/
/<input name="__RequestVerificationToken" type="hidden" value="([^"]+)"/,
);
const csrfToken = csrfMatch ? csrfMatch[1] : null;
@@ -1973,12 +2659,12 @@ async function makeInquiryRequest(info, type, cookie) {
birthDateString: "1404/08/12",
})
: type === "unit"
? querystring.stringify({
NationalCode: info,
})
: JSON.stringify({
NationaId: info,
});
? querystring.stringify({
NationalCode: info,
})
: JSON.stringify({
NationaId: info,
});
const requestOptions = {
hostname: "ba124.ir",
@@ -1986,8 +2672,8 @@ async function makeInquiryRequest(info, type, cookie) {
type === "person"
? "/Inquiries/PersonInfo"
: type === "unit"
? "/Inquiries/CallGetLegalPersonInfoByNationalCode"
: "/Inquiries/AsnafGWLicenseInquiry",
? "/Inquiries/CallGetLegalPersonInfoByNationalCode"
: "/Inquiries/AsnafGWLicenseInquiry",
method: "POST",
headers: {
"Content-Type":
@@ -2008,8 +2694,8 @@ async function makeInquiryRequest(info, type, cookie) {
type === "person"
? "https://ba124.ir/Inquiries/PersonInfo"
: type === "unit"
? "https://ba124.ir/Inquiries/GetLegalPersonInfoByNationalCode"
: "https://ba124.ir/Inquiries/AsnafGWLicenseInquiry",
? "https://ba124.ir/Inquiries/GetLegalPersonInfoByNationalCode"
: "https://ba124.ir/Inquiries/AsnafGWLicenseInquiry",
"Sec-Ch-Ua":
'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
"Sec-Ch-Ua-Mobile": "?0",
@@ -2082,6 +2768,10 @@ app.get("/", async (req, res) => {
return res.redirect("https://rasadyar.com");
});
app.get("/health", async (req, res) => {
return res.json({ status: "server is working..." });
});
// Start the server
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);

271
package-lock.json generated
View File

@@ -11,14 +11,40 @@
"dependencies": {
"axios": "^1.7.2",
"body-parser": "^1.20.2",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"crypto-js": "^4.2.0",
"express": "^4.18.2",
"jalaali-js": "^1.2.7",
"moment": "^2.29.4",
"mongodb": "^6.10.0",
"soap": "^0.16.0"
}
},
"node_modules/@mongodb-js/saslprep": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.5.tgz",
"integrity": "sha512-k64Lbyb7ycCSXHSLzxVdb2xsKGPMvYZfCICXvDsI8Z65CeWQzTEKS4YmGbnqw+U9RBvLPTsB6UCmwkgsDTGWIw==",
"license": "MIT",
"dependencies": {
"sparse-bitfield": "^3.0.3"
}
},
"node_modules/@types/webidl-conversions": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
"license": "MIT"
},
"node_modules/@types/whatwg-url": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
"license": "MIT",
"dependencies": {
"@types/webidl-conversions": "*"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -162,6 +188,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/bson": {
"version": "6.10.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz",
"integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==",
"license": "Apache-2.0",
"engines": {
"node": ">=16.20.1"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -250,6 +285,28 @@
"node": ">= 0.6"
}
},
"node_modules/cookie-parser": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
"license": "MIT",
"dependencies": {
"cookie": "0.7.2",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -821,6 +878,12 @@
"node": ">= 0.6"
}
},
"node_modules/memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"license": "MIT"
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -872,6 +935,62 @@
"node": "*"
}
},
"node_modules/mongodb": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.21.0.tgz",
"integrity": "sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==",
"license": "Apache-2.0",
"dependencies": {
"@mongodb-js/saslprep": "^1.3.0",
"bson": "^6.10.4",
"mongodb-connection-string-url": "^3.0.2"
},
"engines": {
"node": ">=16.20.1"
},
"peerDependencies": {
"@aws-sdk/credential-providers": "^3.188.0",
"@mongodb-js/zstd": "^1.1.0 || ^2.0.0",
"gcp-metadata": "^5.2.0",
"kerberos": "^2.0.1",
"mongodb-client-encryption": ">=6.0.0 <7",
"snappy": "^7.3.2",
"socks": "^2.7.1"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-providers": {
"optional": true
},
"@mongodb-js/zstd": {
"optional": true
},
"gcp-metadata": {
"optional": true
},
"kerberos": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"snappy": {
"optional": true
},
"socks": {
"optional": true
}
}
},
"node_modules/mongodb-connection-string-url": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz",
"integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==",
"license": "Apache-2.0",
"dependencies": {
"@types/whatwg-url": "^11.0.2",
"whatwg-url": "^14.1.0 || ^13.0.0"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -981,9 +1100,10 @@
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
},
"node_modules/punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
@@ -1175,6 +1295,15 @@
"node": "*"
}
},
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"license": "MIT",
"dependencies": {
"memory-pager": "^1.0.2"
}
},
"node_modules/sshpk": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -1242,6 +1371,18 @@
"node": ">=0.8"
}
},
"node_modules/tr46": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
"license": "MIT",
"dependencies": {
"punycode": "^2.3.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -1343,6 +1484,28 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
}
},
"node_modules/whatwg-url": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
"license": "MIT",
"dependencies": {
"tr46": "^5.1.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/xml-crypto": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-0.8.5.tgz",
@@ -1374,6 +1537,27 @@
}
},
"dependencies": {
"@mongodb-js/saslprep": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.5.tgz",
"integrity": "sha512-k64Lbyb7ycCSXHSLzxVdb2xsKGPMvYZfCICXvDsI8Z65CeWQzTEKS4YmGbnqw+U9RBvLPTsB6UCmwkgsDTGWIw==",
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"@types/webidl-conversions": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
},
"@types/whatwg-url": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
"requires": {
"@types/webidl-conversions": "*"
}
},
"accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -1495,6 +1679,11 @@
}
}
},
"bson": {
"version": "6.10.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz",
"integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng=="
},
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -1553,6 +1742,22 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
},
"cookie-parser": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
"requires": {
"cookie": "0.7.2",
"cookie-signature": "1.0.6"
},
"dependencies": {
"cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="
}
}
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -1978,6 +2183,11 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
},
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -2011,6 +2221,25 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"mongodb": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.21.0.tgz",
"integrity": "sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==",
"requires": {
"@mongodb-js/saslprep": "^1.3.0",
"bson": "^6.10.4",
"mongodb-connection-string-url": "^3.0.2"
}
},
"mongodb-connection-string-url": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz",
"integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==",
"requires": {
"@types/whatwg-url": "^11.0.2",
"whatwg-url": "^14.1.0 || ^13.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -2095,9 +2324,9 @@
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
},
"punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
},
"qs": {
"version": "6.5.3",
@@ -2257,6 +2486,14 @@
}
}
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"requires": {
"memory-pager": "^1.0.2"
}
},
"sshpk": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -2301,6 +2538,14 @@
"punycode": "^2.1.1"
}
},
"tr46": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
"requires": {
"punycode": "^2.3.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -2378,6 +2623,20 @@
}
}
},
"webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
},
"whatwg-url": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
"requires": {
"tr46": "^5.1.0",
"webidl-conversions": "^7.0.0"
}
},
"xml-crypto": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-0.8.5.tgz",

View File

@@ -12,6 +12,8 @@
"license": "ISC",
"dependencies": {
"axios": "^1.7.2",
"cookie-parser": "^1.4.6",
"mongodb": "^6.10.0",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"crypto-js": "^4.2.0",