feat(pay-v2): P8 Task4 续费入账 invoice.paid→renewal order + subscription.renewed

This commit is contained in:
wangjia
2026-07-10 18:06:38 +08:00
parent 4c242607a7
commit c677d64529
5 changed files with 308 additions and 14 deletions
+35 -11
View File
@@ -180,20 +180,44 @@ func (p *Provider) VerifyCallback(_ context.Context, in provider.CallbackInput)
if err != nil {
return nil, fmt.Errorf("stripe: webhook 验签失败: %w", err)
}
if event.Type != "checkout.session.completed" {
switch event.Type {
case "checkout.session.completed":
var sess gostripe.CheckoutSession
if err := json.Unmarshal(event.Data.Raw, &sess); err != nil {
return nil, fmt.Errorf("stripe: 解析 session 失败: %w", err)
}
ev := sessionToEvent(&sess, in.Raw)
if event.Created > 0 {
paidAt := unixToTime(event.Created)
ev.PaidAt = &paidAt
}
return ev, nil
case "invoice.paid":
var inv gostripe.Invoice
if err := json.Unmarshal(event.Data.Raw, &inv); err != nil {
return nil, fmt.Errorf("stripe: 解析 invoice 失败: %w", err)
}
if inv.BillingReason != gostripe.InvoiceBillingReasonSubscriptionCycle {
// 首期(subscription_create)由 checkout.session.completed 入账;其余非续费忽略。
return &provider.PaidEvent{Kind: provider.EventPayment, Status: provider.PaidPending, Raw: string(in.Raw)}, nil
}
ev := &provider.PaidEvent{
Kind: provider.EventSubscriptionRenewal, Status: provider.PaidSucceeded,
InvoiceRef: inv.ID, PaidAmountMinor: inv.Total, PaidCurrency: strings.ToUpper(string(inv.Currency)),
Raw: string(in.Raw),
}
if inv.Subscription != nil {
ev.SubscriptionRef = inv.Subscription.ID
}
if event.Created > 0 {
t := unixToTime(event.Created)
ev.PaidAt = &t
}
return ev, nil
default:
// 其它事件此阶段不处理:归一化 pending(管线 Settle 视为 ignored)。
return &provider.PaidEvent{Status: provider.PaidPending, Raw: string(in.Raw)}, nil
}
var sess gostripe.CheckoutSession
if err := json.Unmarshal(event.Data.Raw, &sess); err != nil {
return nil, fmt.Errorf("stripe: 解析 session 失败: %w", err)
}
ev := sessionToEvent(&sess, in.Raw)
if event.Created > 0 {
paidAt := unixToTime(event.Created)
ev.PaidAt = &paidAt
}
return ev, nil
}
func (p *Provider) Query(_ context.Context, req provider.QueryRequest) (*provider.PaidEvent, error) {