fix: 充值体验修复——回调写星尘流水(明细页有记录)+重推幂等+退款回调写流水+充值成功返回我的+我的页onShow刷新余额

This commit is contained in:
Hermes Agent
2026-09-14 15:21:24 +08:00
parent e6cb577305
commit c7d4158aca
3 changed files with 67 additions and 30 deletions
+49 -26
View File
@@ -48,7 +48,7 @@ module.exports = function registerWxMsgRoutes(app) {
const event = fields.Event || fields.event || ''
console.log('[wx-msg] 收到推送 Event=' + event, JSON.stringify(fields).slice(0, 500))
// 代币充值到账:改写用户星尘余额 + 订单状态
// 代币充值到账:改写用户星尘余额 + 订单状态 + 写星尘流水(明细页数据源)
if (event === 'xpay_coin_pay_notify') {
try {
const { User, Order, CoinLedger } = require('../models')
@@ -61,43 +61,66 @@ module.exports = function registerWxMsgRoutes(app) {
)
console.log(`[wx-msg] 充值回调解析: order=${outTradeNo} coins=${coins} coinInfo=${JSON.stringify(coinInfo)}`)
if (outTradeNo && coins > 0) {
// 先查订单,没有也直接给用户加币(Attach 里带了 uid)
const order = await Order.findOne({ orderNo: outTradeNo })
if (order && order.status === 'pending') {
await Order.updateOne({ _id: order._id }, { status: 'paid', paidAt: new Date() })
await User.updateOne({ _id: order.userId }, { $inc: { vpayCoins: coins } })
console.log(`[wx-msg] ✓ 星尘充值到账(有订单): ${outTradeNo} +${coins} → user=${order.userId}`)
// 幂等:微信会重推,同一订单只入账一次(以流水为准)
const dup = await CoinLedger.findOne({ orderNo: outTradeNo, type: 'recharge' })
if (dup) {
console.log(`[wx-msg] 重复推送已忽略: ${outTradeNo}`)
} else {
// 订单可能未落库或已处理——从 Attach 里拿 uid 直接加
try {
const attach = typeof coinInfo === 'object' ? coinInfo.Attach || '' : ''
const uid = attach ? JSON.parse(attach).uid : ''
if (uid) {
await User.updateOne({ _id: uid }, { $inc: { vpayCoins: coins } })
if (order) await Order.updateOne({ _id: order._id }, { status: 'paid', paidAt: new Date() })
console.log(`[wx-msg] ✓ 星尘充值到账(从Attach): ${outTradeNo} +${coins} → user=${uid}`)
} else if (order) {
await Order.updateOne({ _id: order._id }, { status: 'paid', paidAt: new Date() })
await User.updateOne({ _id: order.userId }, { $inc: { vpayCoins: coins } })
console.log(`[wx-msg] ✓ 星尘充值到账(订单补偿): ${outTradeNo} +${coins}`)
const order = await Order.findOne({ orderNo: outTradeNo })
if (order && order.status === 'refunded') {
console.log(`[wx-msg] 订单已退款,跳过重复入账: ${outTradeNo}`)
} else {
// userId 优先取订单,缺失时从 Attach 兜底解析
let uid = order ? String(order.userId) : ''
if (!uid) {
try {
const attach = typeof coinInfo === 'object' ? coinInfo.Attach || '' : ''
uid = attach ? JSON.parse(attach).uid || '' : ''
} catch (e2) { console.error('[wx-msg] Attach解析失败:', e2.message) }
}
if (uid) {
const u = await User.findOneAndUpdate({ _id: uid }, { $inc: { vpayCoins: coins } }, { new: true })
if (u) {
await CoinLedger.create({
openid: u.openid, userId: u._id, type: 'recharge', amount: coins,
balanceAfter: u.vpayCoins || 0, description: '星尘充值', orderNo: outTradeNo,
})
if (order && order.status === 'pending') {
await Order.updateOne({ _id: order._id }, { status: 'paid', paidAt: new Date() })
}
console.log(`[wx-msg] ✓ 星尘充值到账: ${outTradeNo} +${coins} → user=${uid} 余额=${u.vpayCoins}`)
}
} catch (e2) { console.error('[wx-msg] Attach解析失败:', e2.message) }
} else {
console.error(`[wx-msg] 充值到账失败: 找不到订单和Attach uid, order=${outTradeNo}`)
}
}
}
}
} catch (e) { console.error('[wx-msg] 充值到账失败:', e.message) }
}
// 退款:扣回星尘
// 退款:扣回星尘 + 写流水(仅处理管理后台之外直接发起的退款;后台退款时订单已标 refunded,此处自动跳过)
if (event === 'xpay_refund_notify') {
try {
const { User, Order, CoinLedger } = require('../models')
const outTradeNo = fields.OutTradeNo || ''
const dup = await CoinLedger.findOne({ orderNo: outTradeNo, type: 'refund' })
const order = await Order.findOne({ orderNo: outTradeNo, status: 'paid' })
if (order) {
await Order.updateOne({ _id: order._id }, { status: 'refunded' })
const coins = (order.metadata || {}).coins || 0
if (coins > 0) await User.updateOne({ _id: order.userId }, { $inc: { vpayCoins: -coins } })
console.log(`[wx-msg] 星尘退款: ${outTradeNo} -${coins}`)
if (order && !dup) {
const coins = (order.metadata || {}).coins || Math.round((order.amount || 0) * 100) || 0
if (coins > 0) {
const u = await User.findOneAndUpdate({ _id: order.userId }, { $inc: { vpayCoins: -coins } }, { new: true })
await Order.updateOne({ _id: order._id }, { status: 'refunded' })
if (u) {
await CoinLedger.create({
openid: u.openid, userId: u._id, type: 'refund', amount: -coins,
balanceAfter: u.vpayCoins || 0, description: '退款扣回', orderNo: outTradeNo,
})
}
console.log(`[wx-msg] 星尘退款: ${outTradeNo} -${coins}`)
} else {
await Order.updateOne({ _id: order._id }, { status: 'refunded' })
}
}
} catch (e) { console.error('[wx-msg] 退款处理失败:', e.message) }
}