feat(pay-v2): P8 Task6 拒付 chargeback 记录 + chargeback.received

This commit is contained in:
wangjia
2026-07-10 18:52:13 +08:00
parent 02b2fcfa41
commit b0714ca758
19 changed files with 502 additions and 22 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ func OpenTestDB(t *testing.T) *gorm.DB {
t.Fatalf("open test db: %v", err)
}
if err := db.AutoMigrate(&OrderV2{}, &Attempt{}, &Account{}, &Refund{}, &WebhookDelivery{},
&Product{}, &ProductPrice{}, &Subscription{}); err != nil {
&Product{}, &ProductPrice{}, &Subscription{}, &Chargeback{}); err != nil {
t.Fatalf("migrate: %v", err)
}
if err := UpgradeWebhookDeliveryIndex(db); err != nil {
+23
View File
@@ -72,6 +72,9 @@ type OrderV2 struct {
DiscountReason string `gorm:"size:128"`
PaidAt *time.Time
ExpiresAt *time.Time // 整体购买窗口
// Disputed 打标位(P8 Task6):渠道拒付(charge.dispute.created)命中该单时置 true,
// 仅留痕、不改状态机(§6 决策:不自动回收权益,业务方按 chargeback.received 自行冲正)。
Disputed bool `gorm:"default:false"`
}
// ---- 支付尝试(收款账本)----
@@ -151,3 +154,23 @@ type Subscription struct {
CurrentPeriodEnd *time.Time
CanceledAt *time.Time
}
// ---- 拒付(chargeback,P8 Task6)----
// Chargeback 记录渠道拒付(设计 §6「钱到账不可逆」的例外形态:卡组织裁定退单)。只有
// Stripe(卡)有此语义;alipay/微信本轮无拒付流,crypto 收款不可逆、永无 chargeback——
// 三者均不实现 Capabilities 里任何 chargeback 相关声明(P8 未新增该 capability 位,
// 靠 EventKind 是否产出 EventChargeback 天然区分)。
// 每次拒付(含重投)按 DisputeRef 幂等落一行留痕;是否成功定位/转发给业务方是另一回事
// (见 gateway.recordChargeback),Chargeback 表本身对"能否定位业务单"保持中立、全记录。
type Chargeback struct {
Base
DisputeRef string `gorm:"uniqueIndex;size:128;not null"` // 渠道拒付号(stripe dp_...)
OutTradeNo string `gorm:"index;size:64"` // 解析出的原单号(订阅拒付可能为空)
Channel string `gorm:"index;size:32;not null"`
ProviderPaymentRef string `gorm:"size:128"` // 关联 PaymentIntent id
AmountMinor int64 `gorm:"not null"`
Currency string `gorm:"size:16;not null"`
Reason string `gorm:"size:64"`
Status string `gorm:"size:24"` // 渠道拒付状态快照(needs_response/...)
}