package daytask import ( "app/commons/model/entity" "app/commons/services" "encoding/json" "fmt" "github.com/gin-gonic/gin" "time" ) // WalletInfo 钱包信息 func (s *Server) WalletInfo(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() user := &entity.DtUser{} if err := db.Where("id = ?", userId).First(user).Error; err != nil { ctx.Fail("user_not_found") return } ctx.OK(gin.H{ "balance": user.Balance, "frozenBalance": user.FrozenBalance, "totalRecharge": user.TotalRecharge, "totalWithdraw": user.TotalWithdraw, "totalTaskIncome": user.TotalTaskIncome, "totalInviteIncome": user.TotalInviteIncome, }) } // BalanceLog 余额流水 func (s *Server) BalanceLog(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() logType := ctx.QueryInt64("type", 0) // 0表示全部 paging := &services.Pagination{ Current: ctx.QueryInt64("current", 1), Size: ctx.QueryInt64("size", 20), } query := db.Model(&entity.DtBalanceLog{}).Where("user_id = ?", userId) if logType > 0 { query = query.Where("type = ?", logType) } query.Count(&paging.Total) paging.Computer() logs := make([]*entity.DtBalanceLog, 0) query.Order("created_at DESC"). Offset(int(paging.Start)). Limit(int(paging.Size)). Find(&logs) ctx.OK(gin.H{ "list": logs, "paging": paging, }) } // WalletWithdraw 申请提现 func (s *Server) WalletWithdraw(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() type WithdrawRequest struct { Amount float64 `json:"amount" binding:"required"` PaymentId int64 `json:"paymentId" binding:"required"` } var req WithdrawRequest if err := c.ShouldBindJSON(&req); err != nil { ctx.Fail("invalid_params") return } // 获取用户 user := &entity.DtUser{} if err := db.Where("id = ?", userId).First(user).Error; err != nil { ctx.Fail("user_not_found") return } // 检查余额 if user.Balance < req.Amount { ctx.Fail("balance_not_enough") return } // 获取最低提现金额配置 minWithdraw := 100.0 // 默认100 config := &entity.DtConfig{} if err := db.Where("`key` = ?", "min_withdraw").First(config).Error; err == nil { fmt.Sscanf(config.Value, "%f", &minWithdraw) } if req.Amount < minWithdraw { ctx.Fail("amount_too_small") return } // 检查金额是否是10的倍数 if int(req.Amount)%10 != 0 { ctx.Fail("amount_must_be_multiple_of_10") return } // 获取收款账户 payment := &entity.DtUserPayment{} if err := db.Where("id = ? AND user_id = ?", req.PaymentId, userId).First(payment).Error; err != nil { ctx.Fail("payment_not_found") return } // 获取手续费率 feeRate := 0.02 // 默认2% feeConfig := &entity.DtConfig{} if err := db.Where("`key` = ?", "withdraw_fee").First(feeConfig).Error; err == nil { fmt.Sscanf(feeConfig.Value, "%f", &feeRate) } fee := req.Amount * feeRate actualAmount := req.Amount - fee // 生成订单号 orderNo := fmt.Sprintf("W%d%d", time.Now().UnixNano(), userId) // 序列化收款账户信息 paymentInfo, _ := json.Marshal(payment) // 开始事务 tx := db.Begin() // 扣除余额 if err := tx.Model(&entity.DtUser{}). Where("id = ? AND balance >= ?", userId, req.Amount). Update("balance", db.Raw("balance - ?", req.Amount)).Error; err != nil { tx.Rollback() ctx.Fail("deduct_balance_failed") return } // 创建提现订单 order := &entity.DtWithdrawOrder{ OrderNo: orderNo, UserId: userId, Amount: req.Amount, Fee: fee, ActualAmount: actualAmount, PaymentType: payment.Type, PaymentId: payment.Id, PaymentInfo: string(paymentInfo), Status: entity.WithdrawStatusPending, } if err := tx.Create(order).Error; err != nil { tx.Rollback() ctx.Fail("create_order_failed") return } // 记录余额变动 balanceLog := &entity.DtBalanceLog{ UserId: userId, Type: entity.BalanceLogTypeWithdraw, Amount: -req.Amount, BeforeBalance: user.Balance, AfterBalance: user.Balance - req.Amount, RelatedId: order.Id, Remark: fmt.Sprintf("提现申请 %s", orderNo), } tx.Create(balanceLog) tx.Commit() ctx.OK(order) } // WithdrawLog 提现记录 func (s *Server) WithdrawLog(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() status := ctx.QueryInt64("status", -99) // -99表示全部 paging := &services.Pagination{ Current: ctx.QueryInt64("current", 1), Size: ctx.QueryInt64("size", 20), } query := db.Model(&entity.DtWithdrawOrder{}).Where("user_id = ?", userId) if status != -99 { query = query.Where("status = ?", status) } query.Count(&paging.Total) paging.Computer() orders := make([]*entity.DtWithdrawOrder, 0) query.Order("created_at DESC"). Offset(int(paging.Start)). Limit(int(paging.Size)). Find(&orders) ctx.OK(gin.H{ "list": orders, "paging": paging, }) }