You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
6.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}