2025-12-21 19:28:31 +08:00

230 lines
6.0 KiB
TypeScript
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.

import { NextRequest, NextResponse } from 'next/server'
import { db } from '@/lib/db'
import crypto from 'crypto'
// 验证易支付回调签名
function verifySign(params: Record<string, any>, key: string): boolean {
const sign = params.sign
if (!sign) return false
// 移除sign和sign_type参数
const filtered: Record<string, any> = {}
Object.keys(params)
.sort()
.forEach((k) => {
if (k !== 'sign' && k !== 'sign_type' && params[k] !== '' && params[k] !== null && params[k] !== undefined) {
filtered[k] = params[k]
}
})
// 拼接字符串
const signStr = Object.keys(filtered)
.map((k) => `${k}=${filtered[k]}`)
.join('&')
const signStrWithKey = `${signStr}&key=${key}`
// MD5加密并转大写
const calculatedSign = crypto.createHash('md5').update(signStrWithKey).digest('hex').toUpperCase()
return calculatedSign === sign.toUpperCase()
}
export async function POST(request: NextRequest) {
try {
const formData = await request.formData()
const params: Record<string, any> = {}
// 将FormData转换为对象
formData.forEach((value, key) => {
params[key] = value.toString()
})
// 也支持JSON格式
if (Object.keys(params).length === 0) {
try {
const json = await request.json()
Object.assign(params, json)
} catch {
// 忽略JSON解析错误
}
}
console.log('📥 收到支付回调:', params)
const epayKey = process.env.EPAY_KEY
if (!epayKey) {
console.error('❌ 易支付密钥未配置')
return NextResponse.text('FAIL', { status: 500 })
}
// 验证签名
if (!verifySign(params, epayKey)) {
console.error('❌ 签名验证失败:', params)
return NextResponse.text('FAIL', { status: 400 })
}
// 获取订单信息
const orderNo = params.out_trade_no
const tradeNo = params.trade_no
const tradeStatus = params.trade_status
const paymentMethod = params.type || params.payment_method
if (!orderNo) {
console.error('❌ 订单号缺失')
return NextResponse.text('FAIL', { status: 400 })
}
// 查找订单
const order = await db.findOrderByOrderNo(orderNo)
if (!order) {
console.error('❌ 订单不存在:', orderNo)
return NextResponse.text('FAIL', { status: 404 })
}
// 检查订单状态
if (order.status === 'paid') {
console.log('✅ 订单已支付,跳过处理:', orderNo)
return NextResponse.text('SUCCESS')
}
// 验证支付状态
// 易支付通常 trade_status = 'TRADE_SUCCESS' 表示支付成功
if (tradeStatus === 'TRADE_SUCCESS' || params.status === 'success' || params.code === '1') {
// 更新订单状态
await db.updateOrderStatus(
orderNo,
'paid',
tradeNo,
paymentMethod,
JSON.stringify(params)
)
console.log('✅ 订单支付成功:', {
orderNo,
tradeNo,
amount: order.amount,
paymentMethod,
})
// TODO: 这里可以添加其他业务逻辑,比如:
// - 发送邮件通知
// - 更新用户权限
// - 记录日志等
return NextResponse.text('SUCCESS')
} else {
// 支付失败
await db.updateOrderStatus(
orderNo,
'failed',
tradeNo,
paymentMethod,
JSON.stringify(params)
)
console.log('❌ 订单支付失败:', {
orderNo,
tradeStatus,
params,
})
return NextResponse.text('SUCCESS') // 即使失败也要返回SUCCESS,避免重复通知
}
} catch (error) {
console.error('处理支付回调错误:', error)
return NextResponse.text('FAIL', { status: 500 })
}
}
// 也支持GET请求(某些支付平台可能使用GET)
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
const params: Record<string, any> = {}
searchParams.forEach((value, key) => {
params[key] = value
})
console.log('📥 收到支付回调(GET):', params)
const epayKey = process.env.EPAY_KEY
if (!epayKey) {
console.error('❌ 易支付密钥未配置')
return NextResponse.text('FAIL', { status: 500 })
}
// 验证签名
if (!verifySign(params, epayKey)) {
console.error('❌ 签名验证失败:', params)
return NextResponse.text('FAIL', { status: 400 })
}
// 获取订单信息
const orderNo = params.out_trade_no
const tradeNo = params.trade_no
const tradeStatus = params.trade_status
const paymentMethod = params.type || params.payment_method
if (!orderNo) {
console.error('❌ 订单号缺失')
return NextResponse.text('FAIL', { status: 400 })
}
// 查找订单
const order = await db.findOrderByOrderNo(orderNo)
if (!order) {
console.error('❌ 订单不存在:', orderNo)
return NextResponse.text('FAIL', { status: 404 })
}
// 检查订单状态
if (order.status === 'paid') {
console.log('✅ 订单已支付,跳过处理:', orderNo)
return NextResponse.text('SUCCESS')
}
// 验证支付状态
if (tradeStatus === 'TRADE_SUCCESS' || params.status === 'success' || params.code === '1') {
// 更新订单状态
await db.updateOrderStatus(
orderNo,
'paid',
tradeNo,
paymentMethod,
JSON.stringify(params)
)
console.log('✅ 订单支付成功:', {
orderNo,
tradeNo,
amount: order.amount,
paymentMethod,
})
return NextResponse.text('SUCCESS')
} else {
// 支付失败
await db.updateOrderStatus(
orderNo,
'failed',
tradeNo,
paymentMethod,
JSON.stringify(params)
)
console.log('❌ 订单支付失败:', {
orderNo,
tradeStatus,
params,
})
return NextResponse.text('SUCCESS')
}
} catch (error) {
console.error('处理支付回调错误:', error)
return NextResponse.text('FAIL', { status: 500 })
}
}