删除钱包充值功能并消除重复入账风险

钱包充值为开发态测试功能(生产环境本就禁用),且支付回调存在重复入账风险:入账与标记 paid 两步非原子、wallet_ledger 去重无唯一索引、幂等键使用了可变的 ProviderOrderID。直接删除该功能从根本上消除风险。

后端:
- payment 移除 StartWalletRecharge/QueryWalletRecharge 及相关 handler/DTO/常量;confirmPaid 增加 OrderID 守卫;解除对 wallet 仓库的依赖
- wallet 移除 Recharge/ConfirmRechargeFromChannel 及相关定义
- 移除三条充值路由;adminfinance 财务统计口径只统计 order_pay
- 清理充值相关测试用例

前端:
- 移除充值 API、WalletView 充值面板/弹窗、admin 充值标签与筛选
- 保留钱包余额、流水、提现等核心能力

go build/vet 与 vue-tsc typecheck 均通过。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
yml2213
2026-06-14 02:45:46 +08:00
co-authored by Claude Opus 4.8
parent 3ef7705776
commit e8621728fd
23 changed files with 28 additions and 863 deletions
@@ -64,59 +64,6 @@ func (r *Repository) Ledger(ctx context.Context, userID uint64, page, pageSize i
return &PaginatedResult{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
}
func (r *Repository) Recharge(ctx context.Context, userID uint64, amountCent int64) (*AccountDTO, error) {
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
return AppendEntries(tx, Entry{
UserID: userID,
Direction: "in",
AmountCent: amountCent,
BalanceType: "available",
BizType: "dev_recharge",
BizNo: "DEV",
Remark: "开发环境充值",
})
})
if err != nil {
return nil, err
}
return r.Account(ctx, userID)
}
func (r *Repository) ConfirmRechargeFromChannel(ctx context.Context, userID uint64, bizNo string, amountCent int64) error {
if userID == 0 || amountCent <= 0 || bizNo == "" {
return ErrInvalidAmount
}
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := ensureAccount(tx, userID); err != nil {
return err
}
var account model.WalletAccount
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
Where("user_id = ?", userID).
First(&account).Error; err != nil {
return err
}
var existing int64
if err := tx.Model(&model.WalletLedger{}).
Where("user_id = ? AND biz_type = ? AND biz_no = ?", userID, "channel_recharge", bizNo).
Count(&existing).Error; err != nil {
return err
}
if existing > 0 {
return nil
}
return AppendEntries(tx, Entry{
UserID: userID,
Direction: "in",
AmountCent: amountCent,
BalanceType: "available",
BizType: "channel_recharge",
BizNo: bizNo,
Remark: "渠道充值入账",
})
})
}
// Withdraw 保留仓库能力;当前公开提现入口在 service 层标记为待开发,不会调用到这里。
func (r *Repository) Withdraw(ctx context.Context, userID uint64, amountCent int64) (*AccountDTO, error) {
if userID == 0 || amountCent <= 0 {