docs: 更新项目文档,完善需求和技术细节
This commit is contained in:
148
backend/routes/payments.js
Normal file
148
backend/routes/payments.js
Normal file
@@ -0,0 +1,148 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user