fix(v2): 订阅激活门改按结算结果(unpaid session 不再无付款激活)

HandleCallback 原门 serr==nil && SubscriptionRef!="" 挡不住 Settle() 对非
PaidSucceeded 事件返回 (SettleIgnored, nil) 的情况(如 Stripe
checkout.session.completed 异步支付 payment_status=unpaid),导致
onSubscriptionActivated 无确认付款先激活订阅。改为按结算结果开门
(SettleProcessed/SettleDuplicate),并在 onSubscriptionActivated 内加
o.Status.Settled() 纵深防御。
This commit is contained in:
wangjia
2026-07-10 18:09:56 +08:00
parent c677d64529
commit b8bdb2c193
3 changed files with 55 additions and 1 deletions
+5 -1
View File
@@ -120,7 +120,11 @@ func (g *Gateway) HandleCallback(ctx context.Context, method string, in provider
return g.recordChargeback(ctx, method, ev) // Task 6
default: // EventPayment:一次性 / 订阅首期
res, serr := g.Settle(ctx, ev)
if serr == nil && ev.SubscriptionRef != "" {
// 门必须按结算结果开,不能只看 serr==nil:Settle 对非成功状态(如 Stripe
// checkout.session.completed 的 payment_status=unpaid 异步支付)返回
// (SettleIgnored, nil)——serr 为 nil 但订单并未结算,不能诞生订阅。
// Duplicate = 成功结算的重放(已 paid/已终态),安全且保证重投幂等路径仍能补建订阅行。
if (res == SettleProcessed || res == SettleDuplicate) && ev.SubscriptionRef != "" {
if aerr := g.onSubscriptionActivated(ctx, ev); aerr != nil {
return SettleFailed, aerr // 诞生订阅失败可重试(Stripe 重投)
}