Files
aijianhua/backend/routes/payments.js

148 lines
4.3 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.

const express = require('express');
const router = express.Router();
const dbConnector = require('../utils/dbConnector');
// 发起支付
router.post('/orders/:order_no', async (req, res) => {
try {
const { order_no } = req.params;
const userId = req.user.id;
// 查询订单信息
const order = await dbConnector.query(`
SELECT o.*, u.openid
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.order_no = ? AND o.user_id = ?
`, [order_no, userId]);
if (order.length === 0) {
return res.status(404).json({
code: 404,
message: '订单不存在'
});
}
// 检查订单状态
if (order[0].payment_status !== 0) {
return res.status(400).json({
code: 400,
message: '订单已支付或已取消'
});
}
// 模拟微信支付参数生成实际项目中需要调用微信支付API
const paymentParams = {
timeStamp: Math.floor(Date.now() / 1000).toString(),
nonceStr: generateNonceStr(),
package: `prepay_id=wx${generateNonceStr(28)}`,
signType: 'MD5',
paySign: generateNonceStr(32)
};
// 记录支付请求
await dbConnector.query(
`INSERT INTO payments
(order_id, payment_method, amount, status, created_at, updated_at)
VALUES (?, 'wechat', ?, 'pending', NOW(), NOW())`,
[order[0].id, order[0].total_amount]
);
res.json({
code: 200,
message: '支付参数生成成功',
data: {
payment_params: paymentParams
}
});
} catch (error) {
console.error('发起支付失败:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误',
error: error.message
});
}
});
// 查询支付结果
router.get('/orders/:order_no/status', async (req, res) => {
try {
const { order_no } = req.params;
const userId = req.user.id;
// 查询订单和支付信息
const result = await dbConnector.query(`
SELECT o.order_no, o.payment_status, p.amount as paid_amount, p.paid_at
FROM orders o
LEFT JOIN payments p ON o.id = p.order_id
WHERE o.order_no = ? AND o.user_id = ?
ORDER BY p.created_at DESC LIMIT 1
`, [order_no, userId]);
if (result.length === 0) {
return res.status(404).json({
code: 404,
message: '订单不存在'
});
}
const paymentStatus = result[0].payment_status === 1 ? 'paid' : 'pending';
res.json({
code: 200,
message: '查询成功',
data: {
order_no: result[0].order_no,
payment_status: paymentStatus,
paid_amount: result[0].paid_amount || 0,
paid_at: result[0].paid_at
}
});
} catch (error) {
console.error('查询支付状态失败:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误',
error: error.message
});
}
});
// 支付回调(微信支付回调接口)
router.post('/notify/wechat', async (req, res) => {
try {
// 这里应该验证微信支付回调的签名
const { out_trade_no, transaction_id, total_fee, time_end } = req.body;
// 更新订单支付状态
await dbConnector.query(`
UPDATE orders SET payment_status = 1, updated_at = NOW()
WHERE order_no = ? AND payment_status = 0
`, [out_trade_no]);
// 更新支付记录
await dbConnector.query(`
UPDATE payments SET status = 'paid', transaction_id = ?, paid_at = NOW()
WHERE order_id = (SELECT id FROM orders WHERE order_no = ?)
`, [transaction_id, out_trade_no]);
// 返回成功响应给微信
res.send('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
} catch (error) {
console.error('支付回调处理失败:', error);
res.status(500).send('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml>');
}
});
// 生成随机字符串
function generateNonceStr(length = 16) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let nonceStr = '';
for (let i = 0; i < length; i++) {
nonceStr += chars.charAt(Math.floor(Math.random() * chars.length));
}
return nonceStr;
}
module.exports = router;