fix(v2): P4 终审波——歧义渠道错误留 processing(ErrRefundRejected 哨兵)/ 拒绝fixture签名 / 错误映射测试 / GetRefund 日志
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -3,6 +3,7 @@ package gateway
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/wangjia/pay/internal/model"
|
||||
@@ -93,9 +94,20 @@ func (g *Gateway) Refund(ctx context.Context, in RefundInput) (*RefundResult, er
|
||||
// 渠道退款:refundID 作渠道幂等键。
|
||||
refundRef, pstatus, rerr := rp.Refund(ctx, att.ProviderRef, refundID, in.AmountMinor, in.Reason)
|
||||
if rerr != nil {
|
||||
_, _ = g.refunds.MarkRefundStatus(refundID, model.RefundProcessing, model.RefundFailed, "", time.Now())
|
||||
_ = g.enqueueRefundEvent(o, att, r, "refund.failed", "")
|
||||
return &RefundResult{RefundID: refundID, Status: string(model.RefundFailed)}, rerr
|
||||
if errors.Is(rerr, provider.ErrRefundRejected) {
|
||||
// 渠道明确拒绝:钱确定没退成,安全标 failed 并释放预留额度(RefundSum
|
||||
// 守卫按 status<>failed 计,见 store.CreateRefundGuarded)。
|
||||
_, _ = g.refunds.MarkRefundStatus(refundID, model.RefundProcessing, model.RefundFailed, "", time.Now())
|
||||
_ = g.enqueueRefundEvent(o, att, r, "refund.failed", "")
|
||||
return &RefundResult{RefundID: refundID, Status: string(model.RefundFailed)}, rerr
|
||||
}
|
||||
// 歧义渠道错误(超时/网络/5xx 等结果不确定的失败):不改状态,留 processing
|
||||
// 继续占用预留额度——渠道那边可能已经实际执行了退款,标 failed 会在没有真退成
|
||||
// 的情况下释放额度,让同单能再退一次造成超退,而且 P6 只扫 processing 态的
|
||||
// RefundStuckAlertTask 对账/告警会因为状态被误标 failed 而永远扫不到它。
|
||||
// 退款结果不确定,留 processing 待人工核实/对账收敛。
|
||||
log.Printf("[gateway] refund %s 渠道结果不确定(非 ErrRefundRejected),留 processing 待人工/对账: %v", refundID, rerr)
|
||||
return &RefundResult{RefundID: refundID, Status: string(model.RefundProcessing)}, rerr
|
||||
}
|
||||
switch pstatus {
|
||||
case provider.PaidSucceeded:
|
||||
|
||||
Reference in New Issue
Block a user