fix(01-05): 提现冻结并发校验缺失(CRITICAL-08)
- 冻结余额改为 result := tx...Updates(),分离结果对象 - 检查 result.Error 处理数据库错误 - 检查 result.RowsAffected == 0 防止并发余额不足时仍创建提现单 - RowsAffected == 0 时返回 errors.New(CodeInsufficientBalance, ...)
This commit is contained in:
@@ -159,14 +159,19 @@ func (s *Service) CreateWithdrawalRequest(ctx context.Context, req *dto.CreateMy
|
|||||||
var withdrawalRequest *model.CommissionWithdrawalRequest
|
var withdrawalRequest *model.CommissionWithdrawalRequest
|
||||||
|
|
||||||
err = s.db.Transaction(func(tx *gorm.DB) error {
|
err = s.db.Transaction(func(tx *gorm.DB) error {
|
||||||
// 冻结余额
|
// 冻结余额(使用条件更新 + RowsAffected 校验,防止并发重复提现)
|
||||||
if err := tx.WithContext(ctx).Model(&model.AgentWallet{}).
|
result := tx.WithContext(ctx).Model(&model.AgentWallet{}).
|
||||||
Where("id = ? AND balance >= ?", wallet.ID, req.Amount).
|
Where("id = ? AND balance >= ?", wallet.ID, req.Amount).
|
||||||
Updates(map[string]interface{}{
|
Updates(map[string]interface{}{
|
||||||
"balance": gorm.Expr("balance - ?", req.Amount),
|
"balance": gorm.Expr("balance - ?", req.Amount),
|
||||||
"frozen_balance": gorm.Expr("frozen_balance + ?", req.Amount),
|
"frozen_balance": gorm.Expr("frozen_balance + ?", req.Amount),
|
||||||
}).Error; err != nil {
|
})
|
||||||
return errors.Wrap(errors.CodeInternalError, err, "冻结余额失败")
|
if result.Error != nil {
|
||||||
|
return errors.Wrap(errors.CodeInternalError, result.Error, "冻结余额失败")
|
||||||
|
}
|
||||||
|
// RowsAffected == 0 说明余额已不足(并发场景下被其他请求先行扣减)
|
||||||
|
if result.RowsAffected == 0 {
|
||||||
|
return errors.New(errors.CodeInsufficientBalance, "余额不足或并发冲突,请稍后重试")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建提现申请
|
// 创建提现申请
|
||||||
|
|||||||
Reference in New Issue
Block a user