修复虚拟支付
This commit is contained in:
@@ -167,7 +167,7 @@ func (s *OrderService) XPayNotify(ctx context.Context, raw []byte) []byte {
|
||||
}
|
||||
|
||||
// verifyXPayOrderPaid 反查微信侧订单真实性:消息推送无签名,发货前必须通过
|
||||
// query_order(带 HMAC 签名的服务端 API)确认订单已真实支付、金额与道具一致,
|
||||
// query_order(带 HMAC 签名的服务端 API)确认订单已真实支付、实付金额一致,
|
||||
// 防止伪造发货推送零成本获取权益。任一校验不通过返回错误(fail-closed,触发微信重试)。
|
||||
func (s *OrderService) verifyXPayOrderPaid(ctx context.Context, order *mysqlmodel.Order, deliver *wechat.XPayGoodsDeliverNotify) *errcode.Error {
|
||||
if deliver.OpenID == "" {
|
||||
@@ -183,22 +183,19 @@ func (s *OrderService) verifyXPayOrderPaid(ctx context.Context, order *mysqlmode
|
||||
}
|
||||
|
||||
// 微信侧无支付记录/未支付:伪造推送或数据异常,拒绝发放。
|
||||
if !wechat.IsOrderPaidStatus(info.Status) {
|
||||
if !wechat.IsOrderPaidStatus(info.Order.Status) {
|
||||
slog.ErrorContext(ctx, "xpay deliver: order not paid in wechat side",
|
||||
"order_no", order.OrderNo, "query_status", info.Status)
|
||||
"order_no", order.OrderNo, "query_status", info.Order.Status)
|
||||
return errcode.OrderRealityCheckFailed
|
||||
}
|
||||
// 反查金额与道具必须与下单快照一致(资损防线)。
|
||||
if info.PayFee != order.PayAmount {
|
||||
// 反查金额必须与下单快照一致(资损防线)。
|
||||
if info.Order.PaidFee != order.PayAmount {
|
||||
slog.ErrorContext(ctx, "xpay deliver: query amount mismatch",
|
||||
"order_no", order.OrderNo, "query_amount", info.PayFee, "order_amount", order.PayAmount)
|
||||
return errcode.OrderRealityCheckFailed
|
||||
}
|
||||
if info.ProductID != order.XPayProductID {
|
||||
slog.ErrorContext(ctx, "xpay deliver: query product mismatch",
|
||||
"order_no", order.OrderNo, "query_product", info.ProductID, "order_product", order.XPayProductID)
|
||||
"order_no", order.OrderNo, "query_amount", info.Order.PaidFee, "order_amount", order.PayAmount)
|
||||
return errcode.OrderRealityCheckFailed
|
||||
}
|
||||
// 道具一致性由推送报文层校验(deliver.GoodsInfo.ProductID 对订单快照);
|
||||
// query_order 不回传 product_id,无法在此二次核对,故不再重复校验。
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -219,15 +216,20 @@ func (s *OrderService) verifyXPayRefund(ctx context.Context, order *mysqlmodel.O
|
||||
}
|
||||
|
||||
// 微信侧无退款记录/未退款:伪造推送或数据异常,拒绝回退权益。
|
||||
if !wechat.IsOrderRefundedStatus(info.RefundStatus) {
|
||||
if !wechat.IsOrderRefundedStatus(info.Order.Status) {
|
||||
slog.ErrorContext(ctx, "xpay refund: order not refunded in wechat side",
|
||||
"order_no", order.OrderNo, "refund_status", info.RefundStatus)
|
||||
"order_no", order.OrderNo, "query_status", info.Order.Status)
|
||||
return errcode.OrderRealityCheckFailed
|
||||
}
|
||||
// 反查退款金额必须与推送一致(资损防线)。
|
||||
if info.RefundFee != refund.RefundFee {
|
||||
// 退款单用 refund_fee;支付单退款后用 paid_fee - left_fee 推算累计已退金额。
|
||||
refundedFee := info.Order.RefundFee
|
||||
if refundedFee <= 0 {
|
||||
refundedFee = info.Order.PaidFee - info.Order.LeftFee
|
||||
}
|
||||
if refundedFee != refund.RefundFee {
|
||||
slog.ErrorContext(ctx, "xpay refund: refund amount mismatch",
|
||||
"order_no", order.OrderNo, "query_refund_fee", info.RefundFee, "notify_refund_fee", refund.RefundFee)
|
||||
"order_no", order.OrderNo, "query_refunded_fee", refundedFee, "notify_refund_fee", refund.RefundFee)
|
||||
return errcode.OrderRealityCheckFailed
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user