Files
jurong_circle_black/routes/payment.js
2025-10-21 17:29:58 +08:00

404 lines
10 KiB
JavaScript
Raw Permalink 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 WechatPayService = require('../services/wechatPayService');
const AlipayService = require('../services/alipayservice');
const { getDB } = require('../database');
const { auth, paymentAuth } = require('../middleware/auth');
// 创建支付服务实例
const wechatPayService = new WechatPayService();
const alipayService = new AlipayService();
/**
* 获取支持的支付方式
* GET /api/payment/methods
*/
router.get('/methods', (req, res) => {
res.json({
success: true,
data: {
methods: [
{
code: 'wechat_h5',
name: '微信支付',
description: '微信H5支付',
icon: 'wechat',
enabled: true
},
{
code: 'alipay_wap',
name: '支付宝支付',
description: '支付宝手机网站支付',
icon: 'alipay',
enabled: true
}
]
}
});
});
/**
* 创建统一支付订单
* POST /api/payment/create-order
*/
router.post('/create-order', paymentAuth, async (req, res) => {
try {
const { paymentMethod } = req.body;
const userId = req.user.id;
const username = req.user.username;
const phone = req.user.phone;
// 验证支付方式
if (!paymentMethod || !['wechat_h5', 'alipay_wap'].includes(paymentMethod)) {
return res.status(400).json({
success: false,
message: '不支持的支付方式'
});
}
// 检查用户是否已经支付过
const db = getDB();
const [existingOrders] = await db.execute(
'SELECT id FROM payment_orders WHERE user_id = ? AND status = "paid"',
[userId]
);
if (existingOrders.length > 0) {
return res.status(400).json({
success: false,
message: '用户已完成支付,无需重复支付'
});
}
let result;
// 获取客户端IP
const clientIp = req.headers['x-forwarded-for'] ||
req.headers['x-real-ip'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
(req.connection.socket ? req.connection.socket.remoteAddress : null) ||
'127.0.0.1';
// 根据支付方式创建订单
if (paymentMethod === 'wechat_h5') {
// 创建微信支付订单
result = await wechatPayService.createRegistrationPayOrder({
userId,
username,
phone,
clientIp
});
} else if (paymentMethod === 'alipay_wap') {
// 创建支付宝支付订单
result = await alipayService.createRegistrationPayOrder({
userId,
username,
phone,
clientIp
});
}
if (result && result.success) {
res.json({
success: true,
data: {
outTradeNo: result.data.outTradeNo,
payUrl: result.data.h5Url || result.data.payUrl,
paymentType: result.data.paymentType,
paymentMethod
}
});
} else {
res.status(500).json({
success: false,
message: '创建支付订单失败'
});
}
} catch (error) {
console.error('创建统一支付订单异常:', error);
res.status(500).json({
success: false,
message: error.message || '服务器内部错误'
});
}
});
/**
* 查询支付状态
* GET /api/payment/query-status/:outTradeNo
*/
router.get('/query-status/:outTradeNo', paymentAuth, async (req, res) => {
try {
const { outTradeNo } = req.params;
const userId = req.user.id;
// 验证订单是否属于当前用户
const db = getDB();
const [orders] = await db.execute(
'SELECT id FROM payment_orders WHERE out_trade_no = ? AND user_id = ?',
[outTradeNo, userId]
);
if (orders.length === 0) {
return res.status(404).json({
success: false,
message: '订单不存在或无权限访问'
});
}
// 获取订单详细信息包括trade_type
const [orderDetails] = await db.execute(
'SELECT id, trade_type FROM payment_orders WHERE id = ?',
[orders[0].id]
);
if (orderDetails.length === 0) {
return res.status(404).json({
success: false,
message: '订单详情不存在'
});
}
let result;
const tradeType = orderDetails[0].trade_type;
// 根据交易类型查询支付状态
if (tradeType === 'WECHAT_H5') {
// 查询微信支付状态
result = await wechatPayService.queryPaymentStatus(outTradeNo);
} else if (tradeType === 'ALIPAY_WAP') {
// 查询支付宝支付状态
result = await alipayService.queryPaymentStatus(outTradeNo);
} else {
return res.status(400).json({
success: false,
message: '不支持的支付方式'
});
}
res.json(result);
} catch (error) {
console.error('查询支付状态失败:', error);
res.status(500).json({
success: false,
message: error.message || '查询支付状态失败'
});
}
});
router.get('/pay-product/test', async (req, res) => {
console.log(123)
})
/**
* 获取用户支付记录
* GET /api/payment/orders
*/
router.get('/orders', paymentAuth, async (req, res) => {
try {
const userId = req.user.id;
const { page = 1, limit = 10, status } = req.query;
const offset = (page - 1) * limit;
const db = getDB();
let whereClause = 'WHERE user_id = ?';
let params = [userId];
if (status) {
whereClause += ' AND status = ?';
params.push(status);
}
// 查询订单列表
const [orders] = await db.execute(
`SELECT id, out_trade_no, transaction_id, total_fee, body, trade_type,
status, paid_at, created_at
FROM payment_orders
${whereClause}
ORDER BY created_at DESC
LIMIT ? OFFSET ?`,
[...params, parseInt(limit), parseInt(offset)]
);
// 查询总数
const [countResult] = await db.execute(
`SELECT COUNT(*) as total FROM payment_orders ${whereClause}`,
params
);
const total = countResult[0].total;
res.json({
success: true,
data: {
orders: orders.map(order => ({
...order,
total_fee: order.total_fee / 100, // 转换为元
payment_method_name: order.trade_type && order.trade_type.startsWith('ALIPAY') ? '支付宝支付' : '微信支付'
})),
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / limit)
}
}
});
} catch (error) {
console.error('获取支付记录失败:', error);
res.status(500).json({
success: false,
message: '获取支付记录失败'
});
}
});
/**
* 检查用户支付状态
* GET /api/payment/check-status
*/
router.get('/check-status', auth, async (req, res) => {
try {
const userId = req.user.id;
const db = getDB();
// 查询用户支付状态
const [users] = await db.execute(
'SELECT payment_status FROM users WHERE id = ?',
[userId]
);
if (users.length === 0) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
const paymentStatus = users[0].payment_status;
// 查询最近的支付订单
const [recentOrders] = await db.execute(
`SELECT out_trade_no, trade_type, status, total_fee, paid_at
FROM payment_orders
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT 1`,
[userId]
);
res.json({
success: true,
data: {
paymentStatus,
isPaid: paymentStatus === 'paid',
recentOrder: recentOrders.length > 0 ? {
...recentOrders[0],
total_fee: recentOrders[0].total_fee / 100,
payment_method_name: recentOrders[0].trade_type.startsWith('ALIPAY') ? '支付宝支付' : '微信支付'
} : null
}
});
} catch (error) {
console.error('检查用户支付状态失败:', error);
res.status(500).json({
success: false,
message: '检查支付状态失败'
});
}
});
/**
* 支付宝支付回调通知
* POST /api/payment/alipay/notify
*/
router.post('/alipay/notify', async (req, res) => {
try {
console.log('收到支付宝支付回调:', req.body);
// 验证签名
const isValid = alipayService.verifyNotifySign(req.body);
if (!isValid) {
console.error('支付宝回调签名验证失败');
return res.status(400).send('FAIL');
}
const {
out_trade_no: outTradeNo,
trade_no: transactionId,
trade_status: tradeStatus,
total_amount: totalAmount
} = req.body;
// 只处理支付成功的回调
if (tradeStatus === 'TRADE_SUCCESS') {
const db = getDB();
// 检查订单是否存在
const [orders] = await db.execute(
'SELECT id, user_id, status FROM payment_orders WHERE out_trade_no = ?',
[outTradeNo]
);
if (orders.length === 0) {
console.error('支付宝回调:订单不存在', outTradeNo);
return res.status(400).send('FAIL');
}
const order = orders[0];
// 如果订单已经处理过,直接返回成功
if (order.status === 'paid') {
console.log('支付宝回调:订单已处理', outTradeNo);
return res.send('SUCCESS');
}
// 更新订单状态
await alipayService.updatePaymentStatus(outTradeNo, {
status: 'paid',
transactionId,
paidAt: new Date()
});
console.log('支付宝支付成功处理完成:', {
outTradeNo,
transactionId,
userId: order.user_id
});
}
res.send('SUCCESS');
} catch (error) {
console.error('处理支付宝支付回调失败:', error);
res.status(500).send('FAIL');
}
});
/**
* 支付宝支付返回页面处理
* GET /api/payment/alipay/return
*/
router.get('/alipay/return', async (req, res) => {
try {
console.log('支付宝支付返回:', req.query);
// 验证签名
const isValid = alipayService.verifyNotifySign(req.query);
if (!isValid) {
console.error('支付宝返回签名验证失败');
return res.redirect('/payment/failed');
}
const { out_trade_no: outTradeNo } = req.query;
// 重定向到支付成功页面
res.redirect(`/payment/success?outTradeNo=${outTradeNo}`);
} catch (error) {
console.error('处理支付宝支付返回失败:', error);
res.redirect('/payment/failed');
}
});
module.exports = router;