|
|
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
|
|
|
}
|