package wallet import ( "recook/internal/back" "recook/internal/dbc" "recook/internal/model/order" "recook/internal/model/user" "recook/internal/service/comFunc" user2 "recook/internal/v2/model/recook/user" "recook/tools" "time" "github.com/gin-gonic/gin" "github.com/golangkit/formatime" "github.com/shopspring/decimal" ) type submitWithdrawReq struct { UserID uint `json:"userId" validate:"required,numeric"` Amount float64 `json:"amount" validate:"required,numeric"` Alipay string `json:"alipay" validate:"omitempty,max=30"` BankAccount string `json:"bankAccount" validate:"omitempty,max=30"` BankName string `json:"bankName" validate:"omitempty,max=50"` Password string `json:"password" validate:"len=6,numeric"` } const password_lock_count = 5 // 提交提现申请 func SubmitWithdraw(c *gin.Context) { var p submitWithdrawReq if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } var userInfo user.Information if err := dbc.DB.First(&userInfo, p.UserID).Error; err != nil { back.Fail(c, "用户错误") return } if userInfo.RealInfoStatus != user.RealInfoPass { back.Fail(c, "请先通过实名认证") return } var userWallet user.Wallet dbc.DB.Where("user_id = ?", p.UserID).Find(&userWallet) if userWallet.ErrorCount == password_lock_count && userWallet.UnlockTime.Time.Unix() >= time.Now().Unix() { // 密码正在锁定中 back.Fail(c, "密码锁定中,请稍后再试") return } if userWallet.Balance.LessThan(decimal.NewFromFloat(p.Amount)) { back.Fail(c, "余额不足") return } // 验证支付密码 if userWallet.Password != tools.SHA256Str(p.Password) { if userWallet.ErrorCount == password_lock_count-1 { dbc.DB.Model(&userWallet).Updates(user.Wallet{ ErrorCount: userWallet.ErrorCount + 1, UnlockTime: formatime.NewSecondFrom(time.Now().Add(time.Hour)), }) back.Fail(c, "五次错误,密码已被锁定,请10分钟后再试") return } else { dbc.DB.Model(&userWallet).Updates(user.Wallet{ ErrorCount: userWallet.ErrorCount + 1, }) back.Fail(c, "密码错误") return } } else { dbc.DB.Model(&userWallet).Updates(map[string]interface{}{ "error_count": 0, "unlock_time": nil, }) } // 判断提取类型 var t int64 if len(p.Alipay) > 0 { t = user.AlipayType } else { t = user.BankType } if userInfo.IsEnterprise { back.Fail(c, "企业用户无法提现") return } tx := dbc.DB.Begin() var record []order.Profit tx.Where("user_id = ?", p.UserID).Where("deal_id = 0").Where("status = 2").Find(&record) // 普通用户 rate := decimal.NewFromFloat(0.13) cr := decimal.NewFromFloat(0.07) balance := decimal.Zero fee := decimal.Zero for _, v := range record { balance = balance.Add(v.Income) if v.Type == order.Card { fee = fee.Add(v.Income.Mul(cr).Round(2)) } else { fee = fee.Add(v.Income.Mul(rate).Round(2)) } } if balance.IsZero() { back.Fail(c, "余额不足") tx.Rollback() return } amount, _ := balance.Float64() withdrawl := &user.Withdraw{ UserId: p.UserID, UserName: userInfo.RealName, Type: t, Amount: amount, Alipay: p.Alipay, BankAccount: p.BankAccount, BankName: p.BankName, AuditTime: formatime.NewSecondFrom(getNextTenOrTwentyFive()), Status: user.UndoneWithdrawStatus, TaxFee: fee, ActualAmount: balance.Sub(fee), } err := tx.Create(withdrawl).Error if err != nil { tx.Rollback() back.Fail(c, "提现错误") return } recookUserWalletBalanceListModel := &user2.RecookUserWalletBalanceListModel{ UserId: p.UserID, IncomeType: user2.RecookUserWalletBalanceListIncomeTypeWithdraw, // 提现 Amount: balance, Title: "卡号:" + p.BankAccount + p.Alipay, Comment: "提现", } recookUserWalletBalanceListModel.SetDb(tx) recookUserWalletBalanceListModel.Create(recookUserWalletBalanceListModel) if recookUserWalletBalanceListModel.Id == 0 { back.Err(c, "系统异常") tx.Rollback() return } if err := tx.Table((&order.Profit{}).TableName()). Where("user_id = ?", p.UserID). Where("status = 2"). Where("deal_id = 0"). UpdateColumn("deal_id", withdrawl.ID).Error; err != nil { tx.Rollback() back.Fail(c, "提现错误") return } userWallet.Balance = userWallet.Balance.Sub(balance) err = tx.Save(&userWallet).Error if err != nil { tx.Rollback() back.Fail(c, "提现错误") return } tx.Commit() back.Suc(c, "提现已提交,请耐心等待", nil) return } //2.审核日是个变量,由后台提供,每月10号和25号为审核日,用户申请提现时,记录这条提现申请的审核日(记录后不变), // 审核日为接下来离申请日最近的10号或25号,例如,4月2号申请时审核日为4月10号,4月10号申请时审核日为4月25号,4月27号申请时审核日为5月10号 func getNextTenOrTwentyFive() time.Time { t1 := time.Now() year, month, day := t1.Date() if day < 10 { return time.Date(year, month, 10, 0, 0, 0, 0, t1.Location()) } if day >= 10 && day < 25 { return time.Date(year, month, 25, 0, 0, 0, 0, t1.Location()) } return t1.AddDate(0, 1, -(day - 10)) } type WithdrawListReq struct { UserID uint `json:"userId" validate:"required,numeric"` Date string `json:"date"` } // 提现列表 func WithdrawList(c *gin.Context) { var p WithdrawListReq if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } var list []user.Withdraw if len(p.Date) > 0 { t, err := time.Parse("2006-01", p.Date) if err != nil { back.Fail(c, "错误的参数") return } err = dbc.DB.Where("user_id = ? and created_at >= ? and created_at < ?", p.UserID, comFunc.GetTheFirstDayOfMonth(t), comFunc.GetTheFirstDayOfMonth(t.AddDate(0, 1, 0))). Order("id DESC").Find(&list).Error if err != nil { back.Fail(c, "操作失败") return } } else { err := dbc.DB.Where("user_id = ?", p.UserID).Order("id DESC").Find(&list).Error if err != nil { back.Fail(c, "操作失败") return } } back.Suc(c, "操作成功", &list) return } type WithdrawDetailReq struct { ID uint `json:"id" validate:"required,numeric"` } // 提现详情 func WithdrawDetail(c *gin.Context) { var p WithdrawDetailReq if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } var detail user.Withdraw if err := dbc.DB.First(&detail, p.ID).Error; err != nil { back.Fail(c, "操作失败") return } back.Suc(c, "操作成功", &detail) return }