Files
Rasadyar_Payment/index.js

2722 lines
92 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// app.js
const express = require("express");
const moment = require("moment");
const cors = require("cors");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");
const axios = require("axios");
const { toJalaali, toGregorian } = require("jalaali-js");
moment.locale("en");
const CryptoJS = require("crypto-js");
// app.options("*", cors);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const {
config,
encrypt,
decrypt,
encryptWS,
decryptWS,
} = require("./lib/asan-pardakht-config");
// Middleware to parse JSON requests
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",
// username: "7269507",
// password: "66506956",
// timeout: 10000,
// apiUrl: "https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl",
// });
// const apiUrl = "https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl";
// function _interopRequireDefault(obj) {
// return obj && obj.__esModule ? obj : { default: obj };
// }
// var _soap = require("soap");
// const soap = require("soap");
const { bpReversalRequest } = require("./lib/bp-reversal-request");
const { bpInquiryRequest } = require("./lib/bp-inquiry-request");
const { bpVerifyRequest } = require("./lib/bp-verify-request");
const { bpPayRequest } = require("./lib/bp-pay-request");
const { bpSettleRequest } = require("./lib/bp-settle-request");
const {
bpCumulativeDynamicPayRequest,
} = require("./lib/bp-cumulative-dynamic-pay-request");
const {
taavonSendData,
taavonSendDataZarinPal,
taavonSendDataZarinPalLink,
} = 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);
// var behpardakhtClient;
// _soap2.default.createClient(
// apiUrl,
// {
// overrideRootElement: {
// namespace: "ns1",
// },
// },
// function (error, client) {
// if (error) {
// // return callback(error);
// console.log("error", error);
// }
// console.log("Behpardakht Client Is Ready!");
// behpardakhtClient = client;
// // return callback(null);
// return null;
// }
// );
app.post("/cumulative-dynamic-pay-request", async (req, res) => {
// const orderId = moment().valueOf();
const orderId = req.body.orderId;
const amount = req.body.amount;
const additionalData = req.body.additionalData;
// let payRequestResult = await bpPayRequest(
// parseInt(orderId),
// 10000,
// "ok",
// "https://rasadyar.net/verify-payment"
// );
// additionalData: "9700383709,10000,0;1031990414,10000,0;",
let payRequestResult = await bpCumulativeDynamicPayRequest(
parseInt(orderId),
amount,
additionalData,
"https://rasadyar.net/verify-payment",
);
const payRequestRes = payRequestResult.return.split(",");
const responseCode = payRequestRes[0];
const refId = payRequestRes[1];
if (parseInt(responseCode) === 0) {
return res.json({ refId });
}
console.log("error: ", payRequestResult);
return res
.status(400)
.json({ error: desribtionStatusCode(parseInt(payRequestResult)) });
// var now = new Date();
// const bpPayRequestCallback = function (error, result) {
// console.log(result, "gggggg");
// if (error) {
// console.log("error", error);
// }
// var parsed = result.return.split(",");
// if (parsed.length < 2) {
// return {
// resCode: Number(parsed[0]),
// rawResCode: parsed[0],
// refId: null,
// };
// }
// var refId = parsed[1];
// // const redirectUrl = `https://bpm.shaparak.ir/pgwchannel/startpay.mellat?RefId=${refId}`;
// // // Redirect the user to the constructed URL
// // res.set('Referrer', 'https://rasadyar.net'); // Set the Referrer header
// // res.redirect(redirectUrl);
// return res.json({
// resCode: 0,
// rawResCode: "0",
// refId: refId,
// });
// };
// const localDate = moment().format("YYYYMMDD");
// const localTime = moment().format("HHmmss");
// const orderId = moment().valueOf();
// behpardakhtClient.bpPayRequest(
// {
// terminalId: 7269507,
// userName: "7269507",
// userPassword: "66506956",
// orderId: parseInt(orderId),
// amount: 10000,
// localDate: localDate,
// localTime: localTime,
// additionalData: "",
// payerId: 0,
// callBackUrl: "https://rasadyar.net/verify-payment", // Payment Callback URL
// },
// bpPayRequestCallback
// );
});
async function reversePay(orderId, saleOrderId, saleReferenceId) {
let resultReversePay = await bpReversalRequest(
orderId,
saleOrderId,
saleReferenceId,
);
resultReversePay = resultReversePay.return;
console.log(resultReversePay);
}
function desribtionStatusCode(statusCode) {
switch (statusCode) {
case 0:
return "ﺗﺮاﻛﻨﺶ_ﺑ_ﻣﻮﻓﻘﻴﺖ_اﻧﺠم_ﺷﺪ";
case 11:
return "ﺷﻤره_ﻛرت_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 12:
return "ﻣﻮﺟﻮدي_ﻛﻓﻲ_ﻧﻴﺴﺖ";
case 13:
return "رﻣﺰ_ﻧدرﺳﺖ_اﺳﺖ";
case 14:
return "ﺗﻌﺪاد_دﻓﻌت_وارد_ﻛﺮدن_رﻣﺰ_ﺑﻴﺶ_از_ﺣﺪ_ﻣﺠز_اﺳﺖ";
case 15:
return "ﻛرت_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 16:
return "دﻓﻌت_ﺑﺮداﺷﺖ_وﺟ_ﺑﻴﺶ_از_ﺣﺪ_ﻣﺠز_اﺳﺖ";
case 17:
return "ﻛرﺑﺮ_از_اﻧﺠم_ﺗﺮاﻛﻨﺶ_ﻣﻨﺼﺮف_ﺷﺪه_اﺳﺖ";
case 18:
return "ﺗرﻳﺦ_اﻧﻘﻀي_ﻛرت_ﮔﺬﺷﺘ_اﺳﺖ";
case 19:
return "ﻣﺒﻠﻎ_ﺑﺮداﺷﺖ_وﺟ_ﺑﻴﺶ_از_ﺣﺪ_ﻣﺠز_اﺳﺖ";
case 111:
return "ﺻدر_ﻛﻨﻨﺪه_ﻛرت_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 112:
return "ﺧﻄي_ﺳﻮﻳﻴﭻ_ﺻدر_ﻛﻨﻨﺪه_ﻛرت";
case 113:
return "ﭘﺳﺨﻲ_از_ﺻدر_ﻛﻨﻨﺪه_ﻛرت_درﻳﻓﺖ_ﻧﺸﺪ";
case 114:
return ارﻧﺪه_ﻛرت_ﻣﺠز_ﺑ_اﻧﺠم_اﻳﻦ_ﺗﺮاﻛﻨﺶ_ﻧﻴﺴﺖ";
case 21:
return "ﭘﺬﻳﺮﻧﺪه_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 23:
return "ﺧﻄي_اﻣﻨﻴﺘﻲ_رخ_داده_اﺳﺖ";
case 24:
return "اﻃﻼﻋت_ﻛرﺑﺮي_ﭘﺬﻳﺮﻧﺪه_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 25:
return "ﻣﺒﻠﻎ_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 31:
return "ﭘﺳﺦ_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 32:
return "ﻓﺮﻣﺖ_اﻃﻼﻋت_وارد_ﺷﺪه_ﺻﺤﻴﺢ_ﻧﻤﻲ_ﺑﺷﺪ";
case 33:
return "ﺣﺴب_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 34:
return "ﺧﻄي_ﺳﻴﺴﺘﻤﻲ";
case 35:
return "ﺗرﻳﺦ_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 41:
return "ﺷﻤره_درﺧﻮاﺳﺖ_ﺗﻜﺮاري_اﺳﺖ";
case 42:
return "ﺗﺮاﻛﻨﺶ_Sale_یافت_نشد_";
case 43:
return "ﻗﺒﻼ_Verify_درﺧﻮاﺳﺖ_داده_ﺷﺪه_اﺳﺖ";
case 44:
return "درخواست_verify_یافت_نشد";
case 45:
return "ﺗﺮاﻛﻨﺶ_Settle_ﺷﺪه_اﺳﺖ";
case 46:
return "ﺗﺮاﻛﻨﺶ_Settle_نشده_اﺳﺖ";
case 47:
return "ﺗﺮاﻛﻨﺶ_Settle_یافت_نشد";
case 48:
return "تراکنش_Reverse_شده_است";
case 49:
return "تراکنش_Refund_یافت_نشد";
case 412:
return "شناسه_قبض_نادرست_است";
case 413:
return "ﺷﻨ_ﭘﺮداﺧﺖ_ﻧدرﺳﺖ_اﺳﺖ";
case 414:
return ازﻣن_ﺻدر_ﻛﻨﻨﺪه_ﻗﺒﺾ_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 415:
return "زﻣن_ﺟﻠﺴ_ﻛري_ﺑ_ﭘن_رسیده_است";
case 416:
return "ﺧﻄ_در_ﺛﺒﺖ_اﻃﻼﻋت";
case 417:
return "ﺷﻨ_ﭘﺮداﺧﺖ_ﻛﻨﻨﺪه_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 418:
return "اﺷﻜل_در_ﺗﻌﺮﻳﻒ_اﻃﻼﻋت_ﻣﺸﺘﺮي";
case 419:
return "ﺗﻌﺪاد_دﻓﻌت_ورود_اﻃﻼﻋت_از_ﺣﺪ_ﻣﺠز_ﮔﺬﺷﺘ_اﺳﺖ";
case 421:
return "IP_نامعتبر_است";
case 51:
return "ﺗﺮاﻛﻨﺶ_ﺗﻜﺮاري_اﺳﺖ";
case 54:
return "ﺗﺮاﻛﻨﺶ_ﻣﺮﺟﻊ_ﻣﻮﺟﻮد_ﻧﻴﺴﺖ";
case 55:
return "ﺗﺮاﻛﻨﺶ_ﻧﻣﻌﺘﺒﺮ_اﺳﺖ";
case 61:
return "ﺧﻄ_در_واریز";
}
return "";
}
app.post("/verify-payment", async (req, res) => {
let Run_bpReversalRequest = false;
let saleReferenceId = -999;
let saleOrderId = -999;
let resultCode_bpPayRequest;
if (
req.body === null ||
req.body?.ResCode === null ||
req.body?.SaleOrderId === null ||
req.body?.SaleReferenceId === null ||
req.body?.CardHolderPan === null
) {
return res
.status(422)
.json({ error: "پارامترهای لازم از طرف بانک ارسال نشد." });
}
saleReferenceId = parseInt(req.body.SaleReferenceId, 10);
saleOrderId = parseInt(req.body.SaleOrderId, 10);
resultCode_bpPayRequest = parseInt(req.body.ResCode);
const finalAmount = req.body.FinalAmount;
const refId = req.body.RefId;
const cardHolderPan = req.body.CardHolderPan;
//Result Code
let resultCode_bpinquiryRequest = "-9999";
let resultCode_bpSettleRequest = "-9999";
let resultCode_bpVerifyRequest = "-9999";
let redirectUrlError = "";
const provinceCode = saleOrderId.toString().substring(0, 2);
if (provinceCode === "10") {
redirectUrlError = `https://check.rasadyar.net/payment?error=`;
} else if (provinceCode === "15") {
redirectUrlError = `https://sha.rasadyar.net/payment?error=`;
} else if (provinceCode === "18") {
redirectUrlError = `https://ha.rasadyar.net/payment?error=`;
} else if (provinceCode === "91") {
redirectUrlError = `https://ar.rasadyar.net/payment?error=`;
} else if (provinceCode === "47") {
redirectUrlError = `https://ma.rasadyar.net/payment?error=`;
}
if (parseInt(resultCode_bpPayRequest) === 17) {
const error = desribtionStatusCode(parseInt(resultCode_bpPayRequest));
console.log("uwuwuwuwuwuwu", error);
await taavonSendData(saleOrderId, { error, refId });
return res.redirect(redirectUrlError + "کاربر از انجام تراکنش منصرف شد!");
}
if (resultCode_bpPayRequest === 0) {
//verify request
resultCode_bpVerifyRequest = await bpVerifyRequest(
saleOrderId,
saleOrderId,
saleReferenceId,
);
resultCode_bpVerifyRequest = resultCode_bpVerifyRequest.return;
console.log("bpVerifyRequest:" + resultCode_bpVerifyRequest);
if (
resultCode_bpVerifyRequest === null ||
resultCode_bpVerifyRequest.length === 0
) {
//Inquiry Request
resultCode_bpinquiryRequest = await bpInquiryRequest(
saleOrderId,
saleOrderId,
saleReferenceId,
);
resultCode_bpinquiryRequest = parseInt(
resultCode_bpinquiryRequest.return,
);
console.log("bpinquiryRequest" + resultCode_bpinquiryRequest);
if (resultCode_bpinquiryRequest !== 0) {
reversePay(saleOrderId, saleOrderId, saleReferenceId);
const error = desribtionStatusCode(resultCode_bpinquiryRequest);
await taavonSendData(saleOrderId, { error, refId });
return res.json({ error });
}
}
if (
parseInt(resultCode_bpVerifyRequest) === 0 ||
resultCode_bpinquiryRequest === 0
) {
//SettleRequest
resultCode_bpSettleRequest = await bpSettleRequest(
saleOrderId,
saleOrderId,
saleReferenceId,
);
resultCode_bpSettleRequest = parseInt(resultCode_bpSettleRequest.return);
//ﺗﺮاﻛﻨﺶ_Settle_ﺷﺪه_اﺳﺖ
//ﺗﺮاﻛﻨﺶ_ﺑ_ﻣﻮﻓﻘﻴﺖ_اﻧﺠم_ﺷﺪ
if (
resultCode_bpSettleRequest === 0 ||
resultCode_bpSettleRequest === 45
) {
//success payment
const data = {
saleReferenceId,
saleOrderId,
cardHolderPan,
date: new Date(),
finalAmount,
refId,
};
let redirectUrl = "";
let subDomain = "test";
const provinceCode = saleOrderId.toString().substring(0, 2);
console.log({ data, provinceCode });
if (provinceCode === "10") {
subDomain = "test";
redirectUrl = `https://check.rasadyar.net/payment?finalAmount=${finalAmount}&saleOrderId=${saleOrderId}&cardHolderPan=${cardHolderPan}&date=${data.date}&saleReferenceId=${saleReferenceId}`;
} else if (provinceCode === "15") {
subDomain = "sha";
redirectUrl = `https://sha.rasadyar.net/payment?finalAmount=${finalAmount}&saleOrderId=${saleOrderId}&cardHolderPan=${cardHolderPan}&date=${data.date}&saleReferenceId=${saleReferenceId}`;
} else if (provinceCode === "18") {
subDomain = "ha";
redirectUrl = `https://ha.rasadyar.net/payment?finalAmount=${finalAmount}&saleOrderId=${saleOrderId}&cardHolderPan=${cardHolderPan}&date=${data.date}&saleReferenceId=${saleReferenceId}`;
} else if (provinceCode === "91") {
subDomain = "ar";
redirectUrl = `https://ar.rasadyar.net/payment?finalAmount=${finalAmount}&saleOrderId=${saleOrderId}&cardHolderPan=${cardHolderPan}&date=${data.date}&saleReferenceId=${saleReferenceId}`;
} else if (provinceCode === "47") {
subDomain = "ma";
redirectUrl = `https://ma.rasadyar.net/payment?finalAmount=${finalAmount}&saleOrderId=${saleOrderId}&cardHolderPan=${cardHolderPan}&date=${data.date}&saleReferenceId=${saleReferenceId}`;
}
//save success payment into db
const url = `https://${subDomain}backend.rasadyar.com/wage_payment_final_step/`;
const options = {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
};
try {
const r = await fetch(url, options);
} catch (error) {
return res.json({ error: "اطلاعات پرداخت ذخیره نشد!" });
}
return res.redirect(redirectUrl);
}
} else {
if (saleOrderId != -999 && saleReferenceId != -999) {
if (resultCode_bpPayRequest !== 17)
reversePay(saleOrderId, saleOrderId, saleReferenceId);
}
const error = desribtionStatusCode(resultCode_bpVerifyRequest);
try {
await taavonSendData(saleOrderId, { error, refId });
} catch (error) {
return res.json({ error: "اطلاعات پرداخت ذخیره نشد!" });
}
return res.json({ error });
}
} else {
if (saleOrderId != -999 && saleReferenceId != -999) {
if (resultCode_bpPayRequest !== 17)
reversePay(saleOrderId, saleOrderId, saleReferenceId);
const error = desribtionStatusCode(resultCode_bpPayRequest);
try {
taavonSendData(saleOrderId, { error, refId });
} catch (error) {
return res.json({ error: "اطلاعات پرداخت ذخیره نشد!" });
}
return res.json({ error });
}
}
});
//zarinpal ---------------------------------------------------------------------------------------------------
const MERCHANT_ID = "7ad4aa9d-a153-4b94-b850-552ecf690a4a";
const ZARINPAL_API = "https://api.zarinpal.com/pg/v4/payment/request.json";
const ZARINPAL_API_VERIFY =
"https://api.zarinpal.com/pg/v4/payment/verify.json";
app.post("/zarinpay", async (req, res) => {
const { amount, description, provincecode, wages, isLink } = req.body;
if (!amount || !description) {
return res.status(400).send("Invalid request parameters");
}
const parsedAmount = parseInt(amount);
if (isNaN(parsedAmount)) {
return res.status(400).send("Invalid amount");
}
try {
const response = await axios.post(
ZARINPAL_API,
{
merchant_id: MERCHANT_ID,
amount: parsedAmount,
description: description,
callback_url: `https://pay.rasadyar.com/zarinverify/?amount=${amount}&province=${provincecode}&isLink=${isLink}`,
wages: wages,
},
{
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
},
);
if (response.data.data.authority) {
return res.status(201).json(response.data.data);
} else {
return res
.status(500)
.json({ error: "Error Init Payment", data: response.data.errors });
}
console.log("Verification response: ", response.data);
} catch (error) {
return res
.status(500)
.json({ error: "Error in accessing ZarinPal", data: error });
}
});
app.get("/zarinverify", async (req, res) => {
const { Authority, Status, amount, province, isLink } = req.query;
if (!Authority || !Status || !amount || !province) {
return res.status(400).send("Invalid request parameters");
}
if (Status === "OK") {
try {
const response = await axios.post(
ZARINPAL_API_VERIFY,
{
merchant_id: MERCHANT_ID,
authority: Authority,
amount: amount,
},
{
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
},
);
console.log("Verification response in verify: ", response.data);
if (response.data.data.code === 100 || response.data.data.code === 101) {
let redirectUrl = `https://rasadyar.net/payment?finalAmount=${amount}&cardHolderPan=${
response.data.data.card_pan
}&date=${new Date()}&saleReferenceId=${response.data.data.ref_id}`;
let subDomain = "";
// if (province.substring(0, 2) === "10") {
// subDomain = "test";
// redirectUrl = `https://check.rasadyar.net/payment?finalAmount=${amount}&cardHolderPan=${
// response.data.data.card_pan
// }&date=${new Date()}&saleReferenceId=${response.data.data.ref_id}`;
// } else if (province.substring(0, 2) === "15") {
// subDomain = "sha";
// redirectUrl = `https://sha.rasadyar.net/payment?finalAmount=${amount}&cardHolderPan=${
// response.data.data.card_pan
// }&date=${new Date()}&saleReferenceId=${response.data.data.ref_id}`;
// } else if (province.substring(0, 2) === "18") {
// subDomain = "ha";
// redirectUrl = `https://ha.rasadyar.net/payment?finalAmount=${amount}&cardHolderPan=${
// response.data.data.card_pan
// }&date=${new Date()}&saleReferenceId=${response.data.data.ref_id}`;
// } else if (province.substring(0, 2) === "91") {
// subDomain = "ar";
// redirectUrl = `https://ar.rasadyar.net/payment?finalAmount=${amount}&cardHolderPan=${
// response.data.data.card_pan
// }&date=${new Date()}&saleReferenceId=${response.data.data.ref_id}`;
// } else if (province.substring(0, 2) === "47") {
// subDomain = "ma";
// redirectUrl = `https://ma.rasadyar.net/payment?finalAmount=${amount}&cardHolderPan=${
// response.data.data.card_pan
// }&date=${new Date()}&saleReferenceId=${response.data.data.ref_id}`;
// }
if (isLink) {
await taavonSendDataZarinPalLink(province, {
authority: Authority,
refId: response.data.data.ref_id,
cardHolderPan: response.data.data.card_pan,
});
} else {
await taavonSendDataZarinPal(province, {
authority: Authority,
refId: response.data.data.ref_id,
cardHolderPan: response.data.data.card_pan,
});
}
return res.redirect(redirectUrl);
}
} catch (error) {
res.status(400).send("Payment was not successful.");
}
} else {
let redirectUrlError = `https://rasadyar.net/payment?error=`;
// if (province.substring(0, 2) === "10") {
// redirectUrlError = `https://check.rasadyar.net/payment?error=`;
// } else if (province.substring(0, 2) === "15") {
// redirectUrlError = `https://sha.rasadyar.net/payment?error=`;
// } else if (province.substring(0, 2) === "18") {
// redirectUrlError = `https://ha.rasadyar.net/payment?error=`;
// } else if (province.substring(0, 2) === "91") {
// redirectUrlError = `https://ar.rasadyar.net/payment?error=`;
// } else if (province.substring(0, 2) === "47") {
// redirectUrlError = `https://ma.rasadyar.net/payment?error=`;
// }
await taavonSendDataZarinPal(province, {
error: "کاربر از انجام تراکنش منصرف شد!",
authority: Authority,
});
return res.redirect(redirectUrlError + "کاربر از انجام تراکنش منصرف شد!");
}
});
//sadad ---------------------------------------------------------------------------------------------------
const encrypt_pkcs7 = (data, key) => {
const keyHex = CryptoJS.enc.Base64.parse(key);
const encrypted = CryptoJS.TripleDES.encrypt(data, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return encrypted.toString();
};
app.post("/sadad-get-token", async (req, res) => {
const { data } = req.body;
try {
const response = await axios.post(
"https://sadad.shaparak.ir/api/v0/Request/PaymentRequest",
data,
{
headers: {
"Content-Type": "application/json",
Referer: "https://rasadyar.net/",
},
},
);
res.status(201).send(response.data);
} catch (error) {
res.status(500).send(error.message);
}
});
app.post("/sadad-request-payment", async (req, res) => {
const now = new Date();
const { OrderId, Amount, province } = req.body;
const month = String(now.getMonth() + 1).padStart(2, "0");
const day = String(now.getDate()).padStart(2, "0");
const year = now.getFullYear();
const hours = now.getHours();
const minutes = String(now.getMinutes()).padStart(2, "0");
const seconds = String(now.getSeconds()).padStart(2, "0");
const ampm = hours >= 12 ? "pm" : "am";
const formattedHours = hours % 12 || 12;
const key = "H8eOhSGAeKol46gNfb39dqbMFn0VJKbe";
const MerchantId = "000000140345422";
const TerminalId = "24107875";
const LocalDateTime = `${month}/${day}/${year} ${formattedHours}:${minutes}:${seconds} ${ampm}`;
const ReturnUrl = `https://rasadyar.net/sadad-verify?province=${province}&Amount=${Amount}`;
const dataToEncrypt = `${TerminalId};${OrderId};${Amount}`;
// Encrypt the data
const SignData = encrypt_pkcs7(dataToEncrypt, key);
const data = {
Amount: Amount,
OrderId: OrderId,
LocalDateTime: LocalDateTime,
ReturnUrl: ReturnUrl,
SignData: SignData,
TerminalId: TerminalId,
MerchantId: MerchantId,
};
console.log("Request Data:", data);
try {
const response = await axios.post(
"https://rasadyar.net/sadad-get-token",
{ data: data },
{
headers: {
"Content-Type": "application/json",
Referer: "https://rasadyar.net/",
},
},
);
const responseData = response.data;
if (responseData.ResCode === 0) {
res.status(201).send(responseData);
} else {
res.status(400).send(responseData);
}
} catch (error) {
res.status(500).send(error.message);
}
});
//asanpardakht ---------------------------------------------------------------------------------------------
app.post("/asanpay", async (req, res) => {
const { price } = req.body;
const orderId = Math.floor(Math.random() * 1000000);
const localDate = new Date()
.toISOString()
.replace(/T/, " ")
.replace(/\..+/, "");
const additionalData = "";
const callBackUrl = "https://rasadyar.net/asanverify";
const reqString = `1,${config.username},${config.password},${orderId},${price},${localDate},${additionalData},${callBackUrl},0`;
const encryptedRequest = await encryptWS(reqString);
const soapClient = await soap.createClientAsync(config.WebServiceUrl);
const args = {
merchantConfigurationID: config.merchantConfigurationID,
encryptedRequest: encryptedRequest,
};
soapClient.RequestOperation(args, (err, result) => {
if (err) {
res.status(500).send("خطا در فراخوانی وب‌سرویس.");
} else {
const response = result.RequestOperationResult;
if (response.startsWith("0,")) {
const refId = response.slice(2);
res.redirect(`https://asan.shaparak.ir/?RefId=${refId}`);
} else {
res.status(400).send(`خطای شماره: ${response}`);
}
}
});
});
app.post("/asanverify", async (req, res) => {
const { ReturningParams } = req.body;
const decryptedParams = await decryptWS(ReturningParams);
const params = decryptedParams.split(",");
if (params[3] !== "0" && params[3] !== "00") {
return res.status(400).send(`تراکنش ناموفق<br>خطای شماره: ${params[3]}`);
}
const encryptedCredintials = await encryptWS(
`${config.username},${config.password}`,
);
const soapClient = await soap.createClientAsync(config.WebServiceUrl);
const verifyArgs = {
merchantConfigurationID: config.merchantConfigurationID,
encryptedCredentials: encryptedCredintials,
payGateTranID: params[5],
};
soapClient.RequestVerification(verifyArgs, (err, verifyResult) => {
if (err || verifyResult.RequestVerificationResult !== "500") {
return res
.status(500)
.send(
`خطای شماره: ${verifyResult.RequestVerificationResult} در هنگام Verify`,
);
}
soapClient.RequestReconciliation(verifyArgs, (err, settlementResult) => {
if (err || settlementResult.RequestReconciliationResult !== "600") {
return res
.status(500)
.send(
`خطای شماره: ${settlementResult.RequestReconciliationResult} در هنگام Settlement`,
);
}
res.send(
'<div style="width:250px; margin:100px auto; direction:rtl; font:bold 14px Tahoma">تراکنش با موفقیت انجام پذیرفت.</div>',
);
});
});
});
//sep -------------------------------------------------------------------------------------------------
function generateRandomString() {
const numbers = "0123456789";
const lowerCase = "abcdefghijklmnopqrstuvwxyz";
const upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const specialChars = "!@#$%^&*()_+-=[]{}|;:,.<>?";
const getRandomChar = (chars) =>
chars[Math.floor(Math.random() * chars.length)];
const num = getRandomChar(numbers);
const lower = getRandomChar(lowerCase);
const upper = getRandomChar(upperCase);
const special = getRandomChar(specialChars);
const combined = [num, lower, special, upper].join("");
return combined
.split("")
.sort(() => Math.random() - 0.5)
.join("");
}
const SEP_TERMINAL_ID = 21608844;
const SEP_TERMINAL_PASS = 9238787;
const SEP_API = "https://sep.shaparak.ir/onlinepg/onlinepg";
const SEP_API_VERIFY =
"https://sep.shaparak.ir/verifyTxnRandomSessionkey/ipg/VerifyTransaction";
app.post("/sep-pay-request", async (req, res) => {
const { amount, phone, provincecode, isLink, wages } = req.body;
if (!amount) {
return res.status(400).send("Invalid request parameters");
}
const parsedAmount = parseInt(amount);
if (isNaN(parsedAmount)) {
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,
{
action: "token",
TerminalId: SEP_TERMINAL_ID,
Amount: parsedAmount,
ResNum: resNum,
RedirectUrl: redirectUrl,
CellNumber: phone,
SettlementIBANInfo: wages,
// TranType: "Government",
},
{
headers: {
"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
.status(500)
.json({ error: "Error in accessing SEP", data: error });
}
});
app.post("/sepverify", async (req, res) => {
const { State, Amount, RefNum, Token, TraceNo, SecurePan } = req.body;
const { province, isLink } = req.query;
if (!State || !Amount || !Token || !province || !isLink) {
return res.status(400).send("Missing required parameters");
}
if (State === "OK") {
try {
const response = await axios.post(
SEP_API_VERIFY,
{ RefNum: RefNum, TerminalNumber: SEP_TERMINAL_ID },
{
headers: {
"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}`;
if (isLink) {
await taavonSendDataZarinPalLink(province, {
authority: Token,
refId: TraceNo,
cardHolderPan: SecurePan,
});
} else {
await taavonSendDataZarinPal(province, {
authority: Token,
refId: TraceNo,
cardHolderPan: SecurePan,
});
}
return res.redirect(redirectUrl);
}
} catch (error) {
await taavonSendDataZarinPal(province, {
error: "تراکنش نامشخص!",
authority: Token,
});
return res.redirect(redirectUrlError + "تراکنش نامشخص!");
}
} else {
let redirectUrlError = `https://rasadyar.net/payment?error=`;
await taavonSendDataZarinPal(province, {
error: "کاربر از انجام تراکنش منصرف شد!",
authority: Token,
});
return res.redirect(redirectUrlError + "کاربر از انجام تراکنش منصرف شد!");
}
});
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: "شناسه الزامی است" });
}
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();
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 (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") },
];
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; }
h1 { font-size: 1.75rem; font-weight: 700; margin-bottom: 24px; letter-spacing: -0.02em; }
.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); }
.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">
<h1>همه پرداخت‌ها</h1>
<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">
<input type="text" id="search" placeholder="جستجو (مبلغ، موبایل، استان...) " />
</div>
<button type="button" class="btn btn-ghost" id="btn-apply">اعمال فیلتر</button>
</div>
<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 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: '' };
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.search) q += '&search=' + encodeURIComponent(state.search);
return q;
}
function renderRow(item) {
var createdAt = item.createdAt ? new Date(item.createdAt).toLocaleString('fa-IR') : '-';
var id = item._id;
return '<tr data-id="' + id + '"><td>' + (item.amountRaw || item.amount) + '</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></tr></thead><tbody>';
var rows = list.map(renderRow).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.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
const getPersianDate = (daysOffset = 0) => {
const currentDate = new Date();
currentDate.setDate(currentDate.getDate() + daysOffset);
const jalaaliDate = toJalaali(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
currentDate.getDate(),
);
const { jy, jm, jd } = jalaaliDate;
const formattedDate = `${jy}/${String(jm).padStart(2, "0")}/${String(
jd,
).padStart(2, "0")}`;
return formattedDate;
};
const getPersianDateForHatching = (daysOffset = 0) => {
const currentDate = new Date();
currentDate.setDate(currentDate.getDate() + daysOffset);
const jalaaliDate = toJalaali(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
currentDate.getDate(),
);
const { jy, jm, jd } = jalaaliDate;
const formattedDate = `${String(jd).padStart(2, "0")}/${String(jm).padStart(
2,
"0",
)}/${jy}`;
return formattedDate;
};
const removeDateMaxFrom = getPersianDate(-10);
const removeDateMaxFromForHatching = getPersianDateForHatching(-60);
const removeDateMaxTo = getPersianDate(0);
const removeDateMaxToForHatching = getPersianDateForHatching(0);
app.post("/transporting-chickens", async (req, res) => {
const { cookie, province } = req.body;
try {
const postData = querystring.stringify({
sort: "RemoveDateMax-desc~UnitName-asc",
page: 1,
pageSize: 1000,
group: "",
aggregate: "HatchingCount-sum~RemoveCount-sum",
filter: "",
"searchVm.ProvinceLocationId": parseInt(province),
"searchVm.UnitName": "",
"searchVm.PersonFullName": "",
"searchVm.PartIdCode": "",
"searchVm.PostalCode": "",
"searchVm.EpidemiologicCode": "",
"searchVm.CapacityFemale": "",
"searchVm.BfrCode": "",
"searchVm.SourceCertId": "",
"searchVm.HatchingCount": "",
"searchVm.RemoveCount": "",
"searchVm.HatchingDateFrom": "",
"searchVm.HatchingDateTo": "",
"searchVm.PercentRemoveTakhlieFromHatchingFrom": "",
"searchVm.PercentRemoveTakhlieFromHatchingTo": "",
"searchVm.RemoveDateMinFrom": "",
"searchVm.RemoveDateMinTo": "",
"searchVm.RemoveDateMaxFrom": removeDateMaxFrom,
"searchVm.RemoveDateMaxTo": removeDateMaxTo,
"searchVm.RemoveAgeAvgFrom": "",
"searchVm.RemoveAgeAvgTo": "",
"searchVm.RemoveAgeAvgSamasatFrom": "",
"searchVm.RemoveAgeAvgSamasatTo": "",
"searchVm.RemovePartyCountFrom": "",
"searchVm.RemovePartyCountTo": "",
});
const options = {
hostname: "www.samasat.ir",
path: "/Report/BroilerCarryChickenAccordingToCarriage/_AjaxBinding",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer:
"https://www.samasat.ir/Report/BroilerCarryChickenAccordingToCarriage",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(jsonData.Data);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error" });
}
});
app.post("/transporting-chickens-details", async (req, res) => {
const { cookie, certId } = req.body;
try {
const postData = querystring.stringify({
sort: "IssueDate-desc",
page: 1,
pageSize: 1000,
group: "",
filter: "",
certId: parseInt(certId),
});
const options = {
hostname: "www.samasat.ir",
path: "/WinBroilerFlockRequest/WinBroilerFlockRequestRemoveTrackingRep/_AjaxBindingWinBroilerFlockRequestRemoveTrackingRepVw",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer:
"https://www.samasat.ir/Report/BroilerOnFlowFlocksHealthPermitReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(jsonData.Data);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error" });
}
});
app.post("/hatchings", async (req, res) => {
const { cookie, province, tableName } = req.body;
try {
const postData = querystring.stringify({
sort: "HatchingDate-desc",
page: 1,
pageSize: 1000,
group: "",
aggregate:
"HatchingCount-sum~HatchingCountInBargiri-sum~HatchingCountInTakhlie-sum~TrackingBargiriCount-sum~DiffHamlThanTakhlieCount-sum~DiffTakhlieThanHamlCount-sum~HamlMorghTotalCount-sum~HamlMorghTakhlieCount-sum~EvacuationCount-sum",
filter: "",
"searchVm.ProvinceLocationId": parseInt(province),
"searchVm.FromDate": removeDateMaxFromForHatching + " 12:00:00 ق.ظ",
"searchVm.ToDate": removeDateMaxToForHatching + " 12:00:00 ق.ظ",
"searchVm.TableName":
tableName || "Z_002_ReportTempTable_9b95c4b1b4c6441c8c333258a51827da",
"searchVm.PartIdCode": "",
"searchVm.UnitName": "",
"searchVm.PostalCode": "",
"searchVm.EpidemiologicCode": "",
"searchVm.PersonFullName": "",
"searchVm.CapacityFemaleFrom": "",
"searchVm.CapacityFemaleTo": "",
"searchVm.RequestCode": "",
"searchVm.DesCertId": "",
"searchVm.FlockAgeDayFrom": 1,
"searchVm.FlockAgeDayTo": 60,
"searchVm.HatchingDateFromPersian": "",
"searchVm.HatchingDateToPersian": "",
"searchVm.MaxHatchingDateFromPersian": "",
"searchVm.MaxHatchingDateToPersian": "",
"searchVm.TrackingStatusId": "",
"searchVm.PercentMorghToJoojeTotalFrom": "",
"searchVm.PercentMorghToJoojeTotalTo": "",
"searchVm.PercentMorghToJoojeTakhlieFrom": "",
"searchVm.PercentMorghToJoojeTakhlieTo": "",
});
const options = {
hostname: "www.samasat.ir",
path: "/Report/BroilerOnFlowFlocksHealthPermitReport/_AjaxBinding",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer:
"https://www.samasat.ir/Report/BroilerOnFlowFlocksHealthPermitReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(jsonData.Data);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error" });
}
});
app.post("/samasat-users", async (req, res) => {
const { cookie, province } = req.body;
try {
const postData = querystring.stringify({
sort: "",
page: 1,
pageSize: 3000,
group: "",
filter: "",
"searchVm.HasUnit": "True",
"searchVm.IsOtherPoultry": "False",
"searchVm.ProvinceLocationId": parseInt(province),
"searchVm.UnitTypes[0]": "Broiler",
"searchVm.UserName": "",
"searchVm.FirstName": "",
"searchVm.LastName": "",
"searchVm.Mobile": "",
"searchVm.Email": "",
"searchVm.UserIsActive": "",
"searchVm.UnitName": "",
"searchVm.EpidemiologicCode": "",
"searchVm.PartIdCode": "",
"searchVm.SystemCode": "",
"searchVm.UnitPostalCode": "",
"searchVm.UnitIsActive": "",
});
const options = {
hostname: "www.samasat.ir",
path: "/BaseInformation/BroilerUserManagement/_AjaxBinding",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/BaseInformation/BroilerUserManagement",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
const transformedUsers = jsonData?.Data?.map(
({ Unit, Id, ...rest }) => {
let updatedUnit = Unit;
delete Unit.Id;
return {
...rest,
...updatedUnit,
PId: Id,
Province: getAllProvinces().find(
(p) => parseInt(p.id) === parseInt(province),
)?.name,
City: getAllCities().find(
(city) =>
parseInt(city.id) === parseInt(updatedUnit?.LocationIdCity),
)?.name,
};
},
);
res.json(transformedUsers);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error" });
}
});
app.post("/samasat-breeds", async (req, res) => {
const { cookie, province } = req.body;
try {
const postData = querystring.stringify({
sort: "SendDate-desc",
page: 1,
pageSize: 2000,
group: "",
aggregate: "RequestCountLong-sum~ChickCountLong-sum",
filter: "",
"searchVm.FlockRequestId": "",
"searchVm.Islegal": "True",
"searchVm.HatcheryId": "",
"searchVm.ProvinceLocationId": province,
"searchVm.PartIdCode": "",
"searchVm.UnitName": "",
"searchVm.BfrRequestCode": "",
"searchVm.CertId": "",
"searchVm.BroilerPedigreeTypeId": "",
"searchVm.SendDateFrom": removeDateMaxFrom,
"searchVm.SendDateTo": removeDateMaxTo,
"searchVm.ChickCountFrom": "",
"searchVm.ChickCountTo": "",
"searchVm.PedigreeType": "",
"searchVm.SenderUnitName": "",
"searchVm.StartDateFrom": "",
"searchVm.StartDateTo": "",
"searchVm.EndDateFrom": "",
"searchVm.EndDateTo": "",
"searchVm.RequestCountFrom": "",
"searchVm.RequestCountTo": "",
"searchVm.SystemCode": "",
"searchVm.EpidemiologicCode": "",
"searchVm.PostalCode": "",
"searchVm.CapacityFemaleFrom": "",
"searchVm.CapacityFemaleTo": "",
"searchVm.PersonNationalCodeOrId": "",
"searchVm.PersonName": "",
"searchVm.RegDateFrom": "",
"searchVm.RegDateTo": "",
});
const options = {
hostname: "www.samasat.ir",
path: "/Report/BroilerFlockRequestDetailReport/_AjaxBinding",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer:
"https://www.samasat.ir/Report/BroilerFlockRequestDetailReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(jsonData.Data);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error", error });
}
});
app.post("/samasat-license", async (req, res) => {
const { cookie, province, fromDate, toDate } = req.body;
try {
const postData = querystring.stringify({
sort: "InsertDate-desc",
page: 1,
pageSize: 100000,
group: "",
filter: "",
"searchVm.ProvinceLocationId": province,
"searchVm.Islegal": "True",
"searchVm.PartIdCode": "",
"searchVm.UnitName": "",
"searchVm.StatusIds[0]": 2,
"searchVm.StatusIds[1]": 3,
"searchVm.StatusIds[2]": 4,
"searchVm.StatusIds[3]": 5,
"searchVm.StatusIds[4]": 17,
"searchVm.UnionTypeFilter": "",
"searchVm.SystemCode": "",
"searchVm.EpidemiologicCode": "",
"searchVm.PostalCode": "",
"searchVm.CapacityFemaleFrom": "",
"searchVm.CapacityFemaleTo": "",
"searchVm.SendDateFrom": "",
"searchVm.SendDateTo": "",
"searchVm.RequestCode": "",
"searchVm.CertId": "",
"searchVm.GoodCountFrom": "",
"searchVm.GoodCountTo": "",
"searchVm.StartDateFromPersian": fromDate,
"searchVm.StartDateToPersian": toDate || "",
"searchVm.EndDateFromPersian": "",
"searchVm.EndDateToPersian": "",
"searchVm.RemindDaysFrom": "",
"searchVm.RemindDaysTo": "",
});
const options = {
hostname: "www.samasat.ir",
path: "/Report/BroilerIssuedLicensesReport/_AjaxBinding",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/Report/BroilerIssuedLicensesReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(jsonData.Data);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error", error });
}
});
app.post("/samasat-license-transports", async (req, res) => {
const { cookie, certId } = req.body;
try {
const postData = querystring.stringify({
sort: "IssueDate-desc",
page: 1,
pageSize: 100000,
group: "",
filter: "",
certId: certId,
});
const options = {
hostname: "www.samasat.ir",
path: "/WinBroilerFlockRequest/WinBroilerFlockRequestRemoveTrackingRep/_AjaxBindingWinBroilerFlockRequestRemoveTrackingRepVw",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/Report/BroilerIssuedLicensesReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
res.json(jsonData.Data);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error", error });
}
});
app.post("/samasat-good-sum", async (req, res) => {
const { cookie, certId } = req.body;
try {
const postData = querystring.stringify({
sort: "IssueDate-desc",
page: 1,
pageSize: 100000,
group: "",
filter: "",
certId: certId,
});
const options = {
hostname: "www.samasat.ir",
path: "/WinBroilerFlockRequest/WinBroilerFlockRequestHatchingTrackingRep/_AjaxBindingWinBroilerFlockRequestHatchingTrackingRepVw",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/Report/BroilerIssuedLicensesReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
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),
);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error", error });
}
});
app.post("/samasat-evacuation", async (req, res) => {
const { cookie, reqId } = req.body;
try {
const postData = querystring.stringify({
broilerFlockRequestId: reqId,
});
const options = {
hostname: "www.samasat.ir",
path: `/Report/BroilerCarryChickenAccordingToCarriage/_EvacuationDetailSum?broilerFlockRequestId=${reqId}`,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/Report/BroilerIssuedLicensesReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
if (
jsonData.SumEvacuation ||
jsonData.SumLosses ||
jsonData.SumIllness ||
jsonData.SumNaturalOccurrence ||
jsonData.SumFire
) {
if (jsonData.SumEvacuation > 0) {
res.json(jsonData.SumEvacuation);
} else {
res.json(
// jsonData.SumLosses +
jsonData.SumIllness +
jsonData.SumNaturalOccurrence +
jsonData.SumFire,
);
}
} else {
res.json(0);
}
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error", error });
}
});
app.post("/samasat-evacuation-detail", async (req, res) => {
const { cookie, certId } = req.body;
if (!cookie || !certId) {
return res
.status(400)
.json({ error: "Missing required fields: cookie or certId" });
}
try {
const postData = querystring.stringify({
sort: "ReportDate-desc",
page: 1,
pageSize: 25,
group: "",
filter: "",
certId,
});
const options = {
hostname: "www.samasat.ir",
path: "/WinBroilerFlockRequest/WinBroilerFlockRequestHatchingTrackingRep/_AjaxBindingWinBroilerFlockRequestHatchingTrackingRepVwEvacuation",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/Report/BroilerIssuedLicensesReport",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const contentType = response.headers["content-type"] || "";
if (!contentType.toLowerCase().includes("application/json")) {
return res
.status(502)
.json({ error: "Upstream response is not JSON", body: data });
}
const jsonData = JSON.parse(data);
res.json(jsonData.Data ?? jsonData);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Request Error:", error);
res.status(500).json({ error: "Failed to fetch data" });
});
request.write(postData);
request.end();
} catch (error) {
console.error("Server Error:", error);
res.status(500).json({ error: "Internal server error", error });
}
});
app.post("/samasat-cities", async (req, res) => {
const { cookie, province } = req.body;
if (!cookie || !province) {
return res
.status(400)
.json({ error: "Missing required fields: cookie or province" });
}
const options = {
hostname: "www.samasat.ir",
path:
"/Location/_GetCities?locationIdProvince[]=" +
encodeURIComponent(province),
method: "GET",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
Accept: "*/*",
Referer: "https://www.samasat.ir/BaseInformation/BroilerUserManagement",
"X-Requested-With": "XMLHttpRequest",
Cookie: cookie,
Origin: "https://www.samasat.ir",
},
};
const request = https.request(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
const transformedData = jsonData.map((city) => ({
name: city.Text,
id: city.Value,
province: province,
}));
res.json(transformedData);
} catch (error) {
console.error("Error parsing JSON:", error.message);
res
.status(500)
.json({ error: "Invalid JSON response from external API" });
}
});
});
request.on("error", (error) => {
console.error("Error with the request:", error.message);
res.status(500).json({ error: "Failed to make request to external API" });
});
request.end();
});
app.post("/loginsamasat", async (req, res) => {
const url = "https://www.samasat.ir/Account/Login";
const payload = {
Key: "9c74474d883848248eae926cdabd25d4",
UsernameOrMobile: "03029",
Password: "at50205020",
CaptchaCode: "3334",
remember: 1,
};
const headers = {
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "application/json",
};
try {
const response = await axios.post(url, payload, { headers: headers });
res.json(response.data);
} catch (error) {
res.status(500).json({
message: "Error making request to external API",
error: error.message,
});
}
});
function getRandomElement(array) {
const randomIndex = Math.floor(Math.random() * array.length);
return array[randomIndex];
}
async function performLogin() {
const getOptions = {
hostname: "ba124.ir",
path: "/Account/Login",
method: "GET",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7",
Connection: "keep-alive",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
},
};
const loginPageCookies = await new Promise((resolve, reject) => {
const request = https.request(getOptions, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
const csrfMatch = data.match(
/<input name="__RequestVerificationToken" type="hidden" value="([^"]+)"/,
);
const csrfToken = csrfMatch ? csrfMatch[1] : null;
if (!csrfToken) {
reject(new Error("Could not extract CSRF token"));
return;
}
const cookies = response.headers["set-cookie"] || [];
const cookieString = cookies
.map((cookie) => cookie.split(";")[0])
.join("; ");
resolve({ csrfToken, cookieString });
});
});
request.on("error", (error) => {
reject(error);
});
request.end();
});
const randomUser = getRandomElement([
4072893341, 4072452238, 4070413170, 4189617652, 4071417919, 4172069355,
]);
const postData = querystring.stringify({
NationalId: randomUser,
Password: randomUser,
__RequestVerificationToken: loginPageCookies.csrfToken,
});
const postOptions = {
hostname: "ba124.ir",
path: "/Account/Login",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Content-Length": Buffer.byteLength(postData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7",
Connection: "keep-alive",
Cookie: loginPageCookies.cookieString,
Host: "ba124.ir",
Origin: "https://ba124.ir",
Referer: "https://ba124.ir/Account/Login",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
},
};
const finalCookie = await new Promise((resolve, reject) => {
const request = https.request(postOptions, (response) => {
response.on("data", () => {});
response.on("end", () => {
const cookies = response.headers["set-cookie"] || [];
const cookieString = cookies
.map((cookie) => cookie.split(";")[0])
.join("; ");
const combinedCookie = loginPageCookies.cookieString
? `${loginPageCookies.cookieString}; ${cookieString}`
: cookieString;
resolve(combinedCookie);
});
});
request.on("error", (error) => {
reject(error);
});
request.write(postData);
request.end();
});
return finalCookie;
}
async function makeInquiryRequest(info, type, cookie) {
const payloadData =
type === "person"
? querystring.stringify({
nationalCode: info,
birthDateString: "1404/08/12",
})
: type === "unit"
? querystring.stringify({
NationalCode: info,
})
: JSON.stringify({
NationaId: info,
});
const requestOptions = {
hostname: "ba124.ir",
path:
type === "person"
? "/Inquiries/PersonInfo"
: type === "unit"
? "/Inquiries/CallGetLegalPersonInfoByNationalCode"
: "/Inquiries/AsnafGWLicenseInquiry",
method: "POST",
headers: {
"Content-Type":
type === "person" || type === "unit"
? "application/x-www-form-urlencoded; charset=UTF-8"
: "application/json; charset=UTF-8",
"Content-Length": Buffer.byteLength(payloadData),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
Accept: "application/json, text/javascript, */*; q=0.01",
Accept_Encoding: "gzip, deflate, br, zstd",
Accept_Language: "en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7",
Connection: "keep-alive",
Cookie: cookie,
Host: "ba124.ir",
Origin: "https://ba124.ir",
Referer:
type === "person"
? "https://ba124.ir/Inquiries/PersonInfo"
: type === "unit"
? "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",
"Sec-Ch-Ua-Platform": '"Windows"',
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"X-Requested-With": "XMLHttpRequest",
},
};
const finalInfo = await new Promise((resolve, reject) => {
const request = https.request(requestOptions, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
try {
const jsonData = JSON.parse(data);
resolve(jsonData);
} catch (error) {
reject(new Error(`Invalid JSON response: ${error.message}`));
}
});
});
request.on("error", (error) => {
reject(error);
});
request.write(payloadData);
request.end();
});
return finalInfo;
}
app.get("/national-documents", async (req, res) => {
const { info, type } = req.query;
if (!info) {
return res.status(400).json({
error: "Missing required field: info",
});
}
try {
let finalCookie = await performLogin();
let finalInfo = await makeInquiryRequest(info, type, finalCookie);
while (finalInfo && finalInfo.error) {
console.log("Session expired, retrying login and request...");
finalCookie = await performLogin();
finalInfo = await makeInquiryRequest(info, type, finalCookie);
}
res.json(finalInfo);
} catch (error) {
res.status(500).json({
error: "Failed to fetch person info",
message: error.message,
});
}
});
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}`);
});