完成剩余模块 Context 超时控制改造

This commit is contained in:
yml2213
2026-06-10 12:58:59 +08:00
parent d2858c529d
commit 6ae8f0e830
24 changed files with 370 additions and 323 deletions
@@ -30,7 +30,7 @@ func (h *Handler) Create(c *gin.Context) {
return
}
withdrawal, err := h.service.Create(userID, req)
withdrawal, err := h.service.Create(c.Request.Context(), userID, req)
if err != nil {
writeError(c, err)
return
@@ -49,7 +49,7 @@ func (h *Handler) List(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
result, err := h.service.List(userID, page, pageSize)
result, err := h.service.List(c.Request.Context(), userID, page, pageSize)
if err != nil {
writeError(c, err)
return
@@ -70,7 +70,7 @@ func (h *Handler) FindByID(c *gin.Context) {
return
}
withdrawal, err := h.service.FindByID(userID, id)
withdrawal, err := h.service.FindByID(c.Request.Context(), userID, id)
if err != nil {
writeError(c, err)
return
@@ -91,7 +91,7 @@ func (h *Handler) Cancel(c *gin.Context) {
return
}
if err := h.service.Cancel(userID, id); err != nil {
if err := h.service.Cancel(c.Request.Context(), userID, id); err != nil {
writeError(c, err)
return
}
@@ -108,7 +108,7 @@ func (h *Handler) AdminList(c *gin.Context) {
query.Size = 20
}
result, err := h.service.AdminList(query)
result, err := h.service.AdminList(c.Request.Context(), query)
if err != nil {
writeError(c, err)
return
@@ -123,7 +123,7 @@ func (h *Handler) AdminFindByID(c *gin.Context) {
return
}
withdrawal, err := h.service.AdminFindByID(id)
withdrawal, err := h.service.AdminFindByID(c.Request.Context(), id)
if err != nil {
writeError(c, err)
return
@@ -150,7 +150,7 @@ func (h *Handler) Review(c *gin.Context) {
return
}
withdrawal, err := h.service.Review(adminID, id, req)
withdrawal, err := h.service.Review(c.Request.Context(), adminID, id, req)
if err != nil {
writeError(c, err)
return
@@ -177,7 +177,7 @@ func (h *Handler) ConfirmPayment(c *gin.Context) {
return
}
withdrawal, err := h.service.ConfirmPayment(adminID, id, req)
withdrawal, err := h.service.ConfirmPayment(c.Request.Context(), adminID, id, req)
if err != nil {
writeError(c, err)
return
@@ -1,6 +1,7 @@
package withdrawal
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
@@ -28,10 +29,11 @@ func NewRepository(db *gorm.DB, walletRepo *wallet.Repository) *Repository {
}
// 用户创建提现申请
func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
func (r *Repository) Create(ctx context.Context, userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
db := r.db.WithContext(ctx)
// 验证收款账号
var paymentAccount model.UserPaymentAccount
if err := r.db.Where("id = ? AND user_id = ? AND status = ?", req.PaymentAccountID, userID, "active").
if err := db.Where("id = ? AND user_id = ? AND status = ?", req.PaymentAccountID, userID, "active").
First(&paymentAccount).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("payment account not found")
@@ -71,7 +73,7 @@ func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*Withdr
}
// 事务处理
err = r.db.Transaction(func(tx *gorm.DB) error {
err = db.Transaction(func(tx *gorm.DB) error {
// 创建提现申请
if err := tx.Create(&withdrawal).Error; err != nil {
return err
@@ -105,13 +107,14 @@ func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*Withdr
return nil, err
}
return r.FindByID(userID, withdrawal.ID)
return r.FindByID(ctx, userID, withdrawal.ID)
}
// 用户查询提现列表
func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult, error) {
func (r *Repository) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
db := r.db.WithContext(ctx)
var total int64
if err := r.db.Model(&model.WithdrawalRequest{}).
if err := db.Model(&model.WithdrawalRequest{}).
Where("user_id = ?", userID).
Count(&total).Error; err != nil {
return nil, err
@@ -119,7 +122,7 @@ func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult,
offset := (page - 1) * pageSize
var withdrawals []model.WithdrawalRequest
if err := r.db.Where("user_id = ?", userID).
if err := db.Where("user_id = ?", userID).
Order("created_at DESC").
Offset(offset).Limit(pageSize).
Find(&withdrawals).Error; err != nil {
@@ -140,9 +143,9 @@ func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult,
}
// 用户查询提现详情
func (r *Repository) FindByID(userID, id uint64) (*WithdrawalDTO, error) {
func (r *Repository) FindByID(ctx context.Context, userID, id uint64) (*WithdrawalDTO, error) {
var withdrawal model.WithdrawalRequest
if err := r.db.Where("id = ? AND user_id = ?", id, userID).
if err := r.db.WithContext(ctx).Where("id = ? AND user_id = ?", id, userID).
First(&withdrawal).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrWithdrawalNotFound
@@ -154,9 +157,10 @@ func (r *Repository) FindByID(userID, id uint64) (*WithdrawalDTO, error) {
}
// 用户取消提现
func (r *Repository) Cancel(userID, id uint64) error {
func (r *Repository) Cancel(ctx context.Context, userID, id uint64) error {
db := r.db.WithContext(ctx)
var withdrawal model.WithdrawalRequest
if err := r.db.Where("id = ? AND user_id = ?", id, userID).
if err := db.Where("id = ? AND user_id = ?", id, userID).
First(&withdrawal).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrWithdrawalNotFound
@@ -169,7 +173,7 @@ func (r *Repository) Cancel(userID, id uint64) error {
return ErrWithdrawalLocked
}
return r.db.Transaction(func(tx *gorm.DB) error {
return db.Transaction(func(tx *gorm.DB) error {
// 更新状态
if err := tx.Model(&withdrawal).Update("status", "cancelled").Error; err != nil {
return err
@@ -201,8 +205,8 @@ func (r *Repository) Cancel(userID, id uint64) error {
}
// 管理员查询提现列表
func (r *Repository) AdminList(query AdminListQuery) (*AdminPaginatedResult, error) {
db := r.db.Model(&model.WithdrawalRequest{})
func (r *Repository) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
db := r.db.WithContext(ctx).Model(&model.WithdrawalRequest{})
if query.Status != "" {
db = db.Where("status = ?", query.Status)
@@ -226,7 +230,7 @@ func (r *Repository) AdminList(query AdminListQuery) (*AdminPaginatedResult, err
items := make([]WithdrawalDetailDTO, 0, len(withdrawals))
for _, w := range withdrawals {
dto, err := r.toDetailDTO(w)
dto, err := r.toDetailDTO(ctx, w)
if err != nil {
continue
}
@@ -242,21 +246,22 @@ func (r *Repository) AdminList(query AdminListQuery) (*AdminPaginatedResult, err
}
// 管理员查询提现详情
func (r *Repository) AdminFindByID(id uint64) (*WithdrawalDetailDTO, error) {
func (r *Repository) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
var withdrawal model.WithdrawalRequest
if err := r.db.First(&withdrawal, id).Error; err != nil {
if err := r.db.WithContext(ctx).First(&withdrawal, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrWithdrawalNotFound
}
return nil, err
}
return r.toDetailDTO(withdrawal)
return r.toDetailDTO(ctx, withdrawal)
}
// 管理员审核提现
func (r *Repository) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
func (r *Repository) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
db := r.db.WithContext(ctx)
var withdrawal model.WithdrawalRequest
if err := r.db.First(&withdrawal, id).Error; err != nil {
if err := db.First(&withdrawal, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrWithdrawalNotFound
}
@@ -282,7 +287,7 @@ func (r *Repository) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*W
withdrawal.ReviewedAt = &now
withdrawal.ReviewRemark = req.Remark
err := r.db.Transaction(func(tx *gorm.DB) error {
err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Save(&withdrawal).Error; err != nil {
return err
}
@@ -317,13 +322,14 @@ func (r *Repository) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*W
return nil, err
}
return r.AdminFindByID(id)
return r.AdminFindByID(ctx, id)
}
// 管理员确认打款
func (r *Repository) ConfirmPayment(adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
func (r *Repository) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
db := r.db.WithContext(ctx)
var withdrawal model.WithdrawalRequest
if err := r.db.First(&withdrawal, id).Error; err != nil {
if err := db.First(&withdrawal, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrWithdrawalNotFound
}
@@ -342,7 +348,7 @@ func (r *Repository) ConfirmPayment(adminID, id uint64, req ConfirmPaymentReques
withdrawal.PaymentProofURL = req.PaymentProofURL
withdrawal.PaymentRemark = req.Remark
err := r.db.Transaction(func(tx *gorm.DB) error {
err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Save(&withdrawal).Error; err != nil {
return err
}
@@ -367,7 +373,7 @@ func (r *Repository) ConfirmPayment(adminID, id uint64, req ConfirmPaymentReques
return nil, err
}
return r.AdminFindByID(id)
return r.AdminFindByID(ctx, id)
}
// 转换为用户DTO
@@ -393,16 +399,17 @@ func toDTO(w model.WithdrawalRequest) WithdrawalDTO {
}
// 转换为管理员详细DTO
func (r *Repository) toDetailDTO(w model.WithdrawalRequest) (*WithdrawalDetailDTO, error) {
func (r *Repository) toDetailDTO(ctx context.Context, w model.WithdrawalRequest) (*WithdrawalDetailDTO, error) {
db := r.db.WithContext(ctx)
// 查询用户信息
var user model.User
r.db.Select("nickname, phone").First(&user, w.UserID)
db.Select("nickname, phone").First(&user, w.UserID)
// 查询审核人信息
var reviewedByName string
if w.ReviewedBy != nil {
var admin model.AdminUser
if err := r.db.Select("nickname").First(&admin, *w.ReviewedBy).Error; err == nil {
if err := db.Select("nickname").First(&admin, *w.ReviewedBy).Error; err == nil {
reviewedByName = admin.Nickname
}
}
@@ -411,7 +418,7 @@ func (r *Repository) toDetailDTO(w model.WithdrawalRequest) (*WithdrawalDetailDT
var paidByName string
if w.PaidBy != nil {
var admin model.AdminUser
if err := r.db.Select("nickname").First(&admin, *w.PaidBy).Error; err == nil {
if err := db.Select("nickname").First(&admin, *w.PaidBy).Error; err == nil {
paidByName = admin.Nickname
}
}
@@ -421,7 +428,7 @@ func (r *Repository) toDetailDTO(w model.WithdrawalRequest) (*WithdrawalDetailDT
var certificateURLs []string
if w.PaymentAccountID != nil {
var paymentAccount model.UserPaymentAccount
if err := r.db.First(&paymentAccount, *w.PaymentAccountID).Error; err == nil {
if err := db.First(&paymentAccount, *w.PaymentAccountID).Error; err == nil {
// 解密账号
decrypted, err := crypto.Decrypt(paymentAccount.AccountNo)
if err == nil {
+21 -18
View File
@@ -1,6 +1,9 @@
package withdrawal
import "errors"
import (
"context"
"errors"
)
var (
ErrDependencyUnavailable = errors.New("dependency unavailable")
@@ -14,7 +17,7 @@ var (
)
const (
MinWithdrawalAmountCent = 1000 // 最低提现金额:10元 = 1000分
MinWithdrawalAmountCent = 1000 // 最低提现金额:10元 = 1000分
MaxWithdrawalAmountCent = 500000 // 单笔最高提现金额:5000元 = 500000分
WithdrawalFeeRate = 0.0 // 手续费率(暂时0%
)
@@ -28,7 +31,7 @@ func NewService(repo *Repository) *Service {
}
// 用户端方法
func (s *Service) Create(userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
func (s *Service) Create(ctx context.Context, userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
@@ -41,10 +44,10 @@ func (s *Service) Create(userID uint64, req CreateWithdrawalRequest) (*Withdrawa
return nil, ErrMaxWithdrawalAmount
}
return s.repo.Create(userID, req)
return s.repo.Create(ctx, userID, req)
}
func (s *Service) List(userID uint64, page, pageSize int) (*PaginatedResult, error) {
func (s *Service) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
@@ -54,25 +57,25 @@ func (s *Service) List(userID uint64, page, pageSize int) (*PaginatedResult, err
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
return s.repo.List(userID, page, pageSize)
return s.repo.List(ctx, userID, page, pageSize)
}
func (s *Service) FindByID(userID, id uint64) (*WithdrawalDTO, error) {
func (s *Service) FindByID(ctx context.Context, userID, id uint64) (*WithdrawalDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.FindByID(userID, id)
return s.repo.FindByID(ctx, userID, id)
}
func (s *Service) Cancel(userID, id uint64) error {
func (s *Service) Cancel(ctx context.Context, userID, id uint64) error {
if s.repo == nil {
return ErrDependencyUnavailable
}
return s.repo.Cancel(userID, id)
return s.repo.Cancel(ctx, userID, id)
}
// 管理员端方法
func (s *Service) AdminList(query AdminListQuery) (*AdminPaginatedResult, error) {
func (s *Service) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
@@ -82,26 +85,26 @@ func (s *Service) AdminList(query AdminListQuery) (*AdminPaginatedResult, error)
if query.Size < 1 || query.Size > 100 {
query.Size = 20
}
return s.repo.AdminList(query)
return s.repo.AdminList(ctx, query)
}
func (s *Service) AdminFindByID(id uint64) (*WithdrawalDetailDTO, error) {
func (s *Service) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.AdminFindByID(id)
return s.repo.AdminFindByID(ctx, id)
}
func (s *Service) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
func (s *Service) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.Review(adminID, id, req)
return s.repo.Review(ctx, adminID, id, req)
}
func (s *Service) ConfirmPayment(adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
func (s *Service) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.ConfirmPayment(adminID, id, req)
return s.repo.ConfirmPayment(ctx, adminID, id, req)
}