2026-01-21 15:49:12 +08:00
|
|
|
/**
|
|
|
|
|
* 微信支付回调通知 API
|
|
|
|
|
* 基于 Universal_Payment_Module v4.0 设计
|
|
|
|
|
*
|
|
|
|
|
* POST /api/payment/wechat/notify
|
|
|
|
|
*/
|
|
|
|
|
|
2026-01-09 11:58:08 +08:00
|
|
|
import { type NextRequest, NextResponse } from "next/server"
|
2026-01-21 15:49:12 +08:00
|
|
|
import { PaymentFactory, SignatureError } from "@/lib/payment"
|
|
|
|
|
|
|
|
|
|
// 确保网关已注册
|
|
|
|
|
import "@/lib/payment/wechat"
|
2026-01-09 11:58:08 +08:00
|
|
|
|
|
|
|
|
export async function POST(request: NextRequest) {
|
|
|
|
|
try {
|
2026-01-21 15:49:12 +08:00
|
|
|
// 获取XML原始数据
|
2026-01-09 11:58:08 +08:00
|
|
|
const xmlData = await request.text()
|
|
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
console.log("[Wechat Notify] 收到回调:", xmlData.slice(0, 200))
|
2026-01-09 11:58:08 +08:00
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
// 创建微信支付网关
|
|
|
|
|
const gateway = PaymentFactory.create("wechat_native")
|
2026-01-09 11:58:08 +08:00
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
try {
|
|
|
|
|
// 解析并验证回调数据
|
|
|
|
|
const notifyResult = gateway.parseNotify(xmlData)
|
2026-01-09 11:58:08 +08:00
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
if (notifyResult.status === "paid") {
|
|
|
|
|
console.log("[Wechat Notify] 支付成功:", {
|
|
|
|
|
tradeSn: notifyResult.tradeSn,
|
|
|
|
|
platformSn: notifyResult.platformSn,
|
|
|
|
|
amount: notifyResult.payAmount / 100, // 转换为元
|
|
|
|
|
payTime: notifyResult.payTime,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// TODO: 更新订单状态
|
|
|
|
|
// await OrderService.updateStatus(notifyResult.tradeSn, 'paid')
|
2026-01-09 11:58:08 +08:00
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
// TODO: 解锁内容/开通权限
|
|
|
|
|
// await ContentService.unlockForUser(notifyResult.attach?.userId, notifyResult.attach?.productId)
|
2026-01-09 11:58:08 +08:00
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
// TODO: 分配佣金(如果有推荐人)
|
|
|
|
|
// if (notifyResult.attach?.referralCode) {
|
|
|
|
|
// await ReferralService.distributeCommission(notifyResult)
|
|
|
|
|
// }
|
|
|
|
|
} else {
|
|
|
|
|
console.log("[Wechat Notify] 支付失败:", notifyResult)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回成功响应
|
|
|
|
|
return new NextResponse(gateway.successResponse(), {
|
|
|
|
|
headers: { "Content-Type": "application/xml" },
|
2026-01-09 11:58:08 +08:00
|
|
|
})
|
|
|
|
|
|
2026-01-21 15:49:12 +08:00
|
|
|
} catch (error) {
|
|
|
|
|
if (error instanceof SignatureError) {
|
|
|
|
|
console.error("[Wechat Notify] 签名验证失败")
|
|
|
|
|
return new NextResponse(gateway.failResponse(), {
|
|
|
|
|
headers: { "Content-Type": "application/xml" },
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
throw error
|
2026-01-09 11:58:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
2026-01-21 15:49:12 +08:00
|
|
|
console.error("[Wechat Notify] 处理失败:", error)
|
|
|
|
|
|
|
|
|
|
// 返回失败响应
|
|
|
|
|
const failXml = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[系统错误]]></return_msg></xml>'
|
|
|
|
|
return new NextResponse(failXml, {
|
|
|
|
|
headers: { "Content-Type": "application/xml" },
|
|
|
|
|
})
|
2026-01-09 11:58:08 +08:00
|
|
|
}
|
|
|
|
|
}
|