优化支付退款钱包链路

This commit is contained in:
yml
2026-06-03 21:47:04 +08:00
parent 04193ae687
commit c80d3f960e
26 changed files with 1342 additions and 504 deletions
+4
View File
@@ -13,6 +13,10 @@ type RechargeRequest struct {
Amount float64 `json:"amount" binding:"required"`
}
type WithdrawRequest struct {
Amount float64 `json:"amount" binding:"required"`
}
type LedgerDTO struct {
ID uint64 `json:"id"`
LedgerNo string `json:"ledger_no"`
@@ -81,6 +81,25 @@ func (h *Handler) Recharge(c *gin.Context) {
response.OK(c, account)
}
func (h *Handler) Withdraw(c *gin.Context) {
userID, ok := currentUserID(c)
if !ok {
response.Unauthorized(c, "缺少用户上下文")
return
}
var req WithdrawRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "提现金额不正确")
return
}
account, err := h.service.Withdraw(userID, req)
if err != nil {
writeWalletError(c, err)
return
}
response.OK(c, account)
}
func (h *Handler) AdminLedger(c *gin.Context) {
query, ok := parseAdminLedgerQuery(c)
if !ok {
@@ -136,6 +155,10 @@ func writeWalletError(c *gin.Context, err error) {
response.BadRequest(c, "充值金额不正确")
case errors.Is(err, ErrInsufficientBalance):
response.Error(c, 409, "insufficient_balance", "钱包余额不足")
case errors.Is(err, ErrRechargeDisabled):
response.Error(c, 410, "wallet_recharge_disabled", "钱包充值已关闭")
case errors.Is(err, ErrFeaturePending):
response.Error(c, 501, "feature_pending", "提现功能待开发")
default:
response.ServiceUnavailable(c, "钱包服务暂时不可用")
}
@@ -117,6 +117,29 @@ func (r *Repository) ConfirmRechargeFromChannel(userID uint64, bizNo string, amo
})
}
// Withdraw 保留仓库能力;当前公开提现入口在 service 层标记为待开发,不会调用到这里。
func (r *Repository) Withdraw(userID uint64, amount float64) (*AccountDTO, error) {
amount = roundWalletMoney(amount)
if userID == 0 || amount <= 0 {
return nil, ErrInvalidAmount
}
err := r.db.Transaction(func(tx *gorm.DB) error {
return AppendEntries(tx, Entry{
UserID: userID,
Direction: "out",
Amount: amount,
BalanceType: "available",
BizType: "withdraw_apply",
BizNo: fmt.Sprintf("WD%d", time.Now().UnixNano()),
Remark: "卖家申请提现",
})
})
if err != nil {
return nil, err
}
return r.Account(userID)
}
func (r *Repository) AdminLedger(query AdminLedgerQuery) (*PaginatedResult, error) {
db := r.db.Table("wallet_ledger AS wl").
Select(`wl.id, wl.ledger_no, wl.user_id, COALESCE(u.phone, '') AS user_phone,
+9 -3
View File
@@ -6,6 +6,8 @@ var (
ErrDependencyUnavailable = errors.New("dependency unavailable")
ErrInvalidAmount = errors.New("invalid amount")
ErrInsufficientBalance = errors.New("insufficient balance")
ErrFeaturePending = errors.New("feature pending")
ErrRechargeDisabled = errors.New("wallet recharge disabled")
)
const MinRechargeAmount = 0.01
@@ -36,10 +38,14 @@ func (s *Service) Recharge(userID uint64, req RechargeRequest) (*AccountDTO, err
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if req.Amount < MinRechargeAmount {
return nil, ErrInvalidAmount
return nil, ErrRechargeDisabled
}
func (s *Service) Withdraw(userID uint64, req WithdrawRequest) (*AccountDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.Recharge(userID, req.Amount)
return nil, ErrFeaturePending
}
func (s *Service) AdminLedger(query AdminLedgerQuery) (*PaginatedResult, error) {