Node.js应用AAPanel部署后UPI支付接口500错误排查求助
Node.js部署到AAPanel VPS后/wallet/paynow/upi接口POST 500错误排查与修复
问题场景
本地运行Node.js应用完全正常,但部署到AAPanel管理的VPS服务器后,调用/wallet/paynow/upi接口时出现POST 500(Internal Server Error),无法完成钱包充值。
前端recharge.ejs代码
const handleUPIGatewayPaymentRequest = async (moneyAmount) => { const response = await axios.post("/wallet/paynow/upi", { money: moneyAmount }) const data = response?.data if (data === undefined || data === null) { alertMessage("Something went wrong!") return } if (data?.status === false) { alertMessage(data?.message) return } window.location.href = data?.urls?.web_url }
后端paymentcontroller.js代码
const initiateUPIPayment = async (req, res) => { const type = PaymentMethodsMap.UPI_GATEWAY let auth = req.cookies.auth; let money = parseInt(req.body.money); const minimumMoneyAllowed = parseInt(process.env.MINIMUM_MONEY) if (!money || !(money >= minimumMoneyAllowed)) { return res.status(400).json({ message: `Money is Required and it should be ₹${minimumMoneyAllowed} or above!`, status: false, timeStamp: timeNow, }) } try { const user = await getUserDataByAuthToken(auth) const pendingRechargeList = await rechargeTable.getRecordByPhoneAndStatus({ phone: user.phone, status: PaymentStatusMap.PENDING, type: PaymentMethodsMap.UPI_GATEWAY }) if (pendingRechargeList.length !== 0) { const deleteRechargeQueries = pendingRechargeList.map(recharge => { return rechargeTable.cancelById(recharge.id) }); await Promise.all(deleteRechargeQueries) } const orderId = getRechargeOrderId() const ekqrResponse = await axios.post('https://api.ekqr.in/api/create_order', { key: process.env.UPI_GATEWAY_PAYMENT_KEY, client_txn_id: orderId, amount: String(money), p_info: process.env.PAYMENT_INFO, customer_name: user.username, customer_email: process.env.PAYMENT_EMAIL, customer_mobile: user.phone, redirect_url: `${process.env.APP_BASE_URL}/wallet/verify/upi`, udf1: process.env.APP_NAME, }) const ekqrData = ekqrResponse?.data if (ekqrData === undefined || ekqrData.status === false) { throw Error("Gateway er!#ror from ekqr!") } const newRecharge = { orderId: orderId, transactionId: 'NULL', utr: null, phone: user.phone, money: money, type: type, status: 0, today: rechargeTable.getCurrentTimeForTodayField(), url: ekqrData.data.payment_url, time: timeNow, } const recharge = await rechargeTable.create(newRecharge) console.log(ekqrData) return res.status(200).json({ message: 'Payment Initiated successfully', recharge: recharge, urls: { web_url: ekqrData.data.payment_url, bhim_link: ekqrData.data?.upi_intent?.bhim_link || "", phonepe_link: ekqrData.data?.upi_intent?.phonepe_link || "", paytm_link: ekqrData.data?.upi_intent?.paytm_link || "", gpay_link: ekqrData.data?.upi_intent?.gpay_link || "", }, status: true, timeStamp: timeNow, }); } catch (error) { console.log(error) res.status(500).json({ status: false, message: "Something went wrong!", timestamp: timeNow }) } }
排查与修复步骤
1. 查看服务器端具体错误日志
500错误的核心是后端抛出未捕获异常,必须先看具体错误信息:
- 登录AAPanel,找到你的Node.js应用,查看应用日志或项目目录下的日志文件
- 如果用PM2管理进程,执行
pm2 logs查看实时日志,能获取错误堆栈、变量缺失等关键信息
2. 检查环境变量配置
本地正常但部署出错,大概率是环境变量没配全:
- 确认AAPanel中Node.js应用的环境变量是否完整:
MINIMUM_MONEY、UPI_GATEWAY_PAYMENT_KEY、PAYMENT_INFO、PAYMENT_EMAIL、APP_BASE_URL、APP_NAME必须和本地一致 APP_BASE_URL要配置成VPS的公网域名/IP,不能用localhost,否则第三方支付网关无法回调
3. 验证第三方API请求权限
调用https://api.ekqr.in/api/create_order失败是常见诱因:
- 确认
UPI_GATEWAY_PAYMENT_KEY是生产环境密钥,而非测试环境密钥 - 检查VPS防火墙/安全组是否允许出站请求到
api.ekqr.in,AAPanel防火墙可能默认限制外部请求,需放行该域名或443端口 - 在VPS上执行curl命令测试第三方接口连通性:
curl -X POST https://api.ekqr.in/api/create_order -d '{"key":"你的密钥","client_txn_id":"test123","amount":"100","p_info":"test","customer_name":"test","customer_email":"test@test.com","customer_mobile":"1234567890","redirect_url":"https://你的域名/wallet/verify/upi","udf1":"test"}'
4. 检查数据库连接与权限
代码中涉及rechargeTable操作,需确认:
- VPS上的数据库服务(MySQL/MongoDB等)是否正常运行
- 数据库账号是否有读写权限,连接字符串是否正确
- 验证
rechargeTable的几个方法是否能正常执行,排查SQL语法错误、集合/表不存在等问题
5. 验证Cookie与用户认证
req.cookies.auth可能在部署环境无法获取:
- 打开浏览器开发者工具的Network面板,查看POST请求的Cookie字段是否携带
auth - 若前后端域名不同,需配置CORS允许携带Cookie:后端设置
credentials: true,前端axios添加withCredentials: true
6. 代码细节优化
- 把catch块中的
console.log(error)改成console.error(error),错误信息会包含完整堆栈,更易排查 - 给第三方API请求添加超时配置,避免请求挂起:
const ekqrResponse = await axios.post('https://api.ekqr.in/api/create_order', { // ...参数 }, { timeout: 10000 // 10秒超时 }) - 检查
timeNow变量是否定义,代码中直接使用了该变量,若未全局定义/导入会导致ReferenceError
内容的提问来源于stack exchange,提问作者Baba Tournament
相关产品推荐
相关产品推荐

