148 lines
4.3 KiB
JavaScript
148 lines
4.3 KiB
JavaScript
|
|
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;
|