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.
834 lines
23 KiB
834 lines
23 KiB
package handler |
|
|
|
import ( |
|
"encoding/json" |
|
"errors" |
|
"fmt" |
|
"gorm.io/gorm/clause" |
|
"server/call" |
|
"server/common" |
|
"server/config" |
|
"server/db" |
|
"server/modules/web/app" |
|
"server/modules/web/values" |
|
"server/pb" |
|
"server/util" |
|
"strings" |
|
"time" |
|
|
|
"github.com/gin-gonic/gin" |
|
"github.com/liangdas/mqant/log" |
|
"github.com/mitchellh/mapstructure" |
|
"gorm.io/gorm" |
|
) |
|
|
|
func checkWithdrawInfo(uid int, withdrawInfo values.WithdrawInfo) (err error) { |
|
log.Debug("check withdraw info, %d %+v", uid, withdrawInfo) |
|
if withdrawInfo.AccountNumber == "" && withdrawInfo.UserName == "" && withdrawInfo.Email == "" { |
|
err = errors.New("the Bank Card No should not be empty") |
|
return |
|
} |
|
if len(withdrawInfo.AccountNumber) != 11 { |
|
err = errors.New("the IFSC Code shall be 11 digital letters") |
|
return |
|
} |
|
// 判断是否是拉黑用户,拉黑用户不让代付 |
|
blackData := &common.BlackList{Phone: withdrawInfo.PhoneNumber, PayAccount: withdrawInfo.AccountNumber, Email: withdrawInfo.Email, Name: withdrawInfo.UserName} |
|
if call.BlackListAndKick(uid, blackData) { |
|
err = common.ErrCodeBlack |
|
return |
|
} |
|
if !call.CheckIFSC(withdrawInfo.IFSCCode) { |
|
err = errors.New("the IFSC Code is invalid") |
|
return |
|
} |
|
return nil |
|
} |
|
|
|
func WithdrawInfoSet(c *gin.Context) { |
|
a := app.NewApp(c) |
|
resp := &values.WithdrawInfoSetResp{} |
|
a.Data = resp |
|
defer func() { |
|
log.Debug("player %v PlayerWithdraw code:%v, msg:%s", a.UID, a.Code, a.Msg) |
|
a.Response() |
|
}() |
|
|
|
req := new(values.WithdrawInfoSetReq) |
|
if !a.S(req) { |
|
return |
|
} |
|
uid := a.UID |
|
log.Debug("uid:%d set withdraw info:%+v", uid, req) |
|
|
|
ip := a.GetRemoteIP() |
|
|
|
if req.PhoneNumber == "" { |
|
user := common.PlayerDBInfo{Id: uid} |
|
err := db.Mysql().Get(&user) |
|
if err != nil { |
|
log.Error("get user err:%s", err.Error()) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
req.PhoneNumber = user.Mobile |
|
} |
|
|
|
if err := checkWithdrawInfo(uid, req.WithdrawInfo); err != nil && errors.Is(err, common.ErrCodeBlack) { |
|
log.Error("check withdraw info err, %s", err.Error()) |
|
a.Code = values.CodeParam |
|
return |
|
} |
|
|
|
withdrawInfo := common.WithdrawInfo{ |
|
UID: uid, |
|
AccountNumber: req.AccountNumber, |
|
UserName: req.UserName, |
|
IFSCCode: req.IFSCCode, |
|
BankName: req.BankName, |
|
BankBranchName: req.BankBranchName, |
|
PhoneNumber: req.PhoneNumber, |
|
Email: req.Email, |
|
UpdateIp: ip, |
|
UpdatedAt: time.Now().Unix(), |
|
} |
|
err := db.Mysql().C().Model(&common.WithdrawInfo{}).Clauses(clause.OnConflict{ |
|
Columns: []clause.Column{{Name: "uid"}}, |
|
DoUpdates: clause.Assignments(map[string]interface{}{ |
|
"update_ip": ip, |
|
"updated_at": withdrawInfo.UpdatedAt, |
|
"account_number": withdrawInfo.AccountNumber, |
|
"user_name": withdrawInfo.UserName, |
|
"ifsc_code": withdrawInfo.IFSCCode, |
|
"bank_name": withdrawInfo.BankName, |
|
"bank_branch_name": withdrawInfo.BankBranchName, |
|
"phone_number": withdrawInfo.PhoneNumber, |
|
"email": withdrawInfo.Email, |
|
}), |
|
}).Create(&withdrawInfo).Error |
|
if err != nil { |
|
log.Error("err:%v", err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
} |
|
|
|
func WithdrawInfoGet(c *gin.Context) { |
|
a := app.NewApp(c) |
|
resp := &values.WithdrawInfoGetResp{} |
|
a.Data = resp |
|
defer func() { |
|
log.Debug("player %v PlayerWithdraw code:%v, msg:%s", a.UID, a.Code, a.Msg) |
|
a.Response() |
|
}() |
|
uid := a.UID |
|
var withdrawInfo common.WithdrawInfo |
|
err := db.Mysql().C().Model(&common.WithdrawInfo{}).Where("uid = ?", uid).Find(&withdrawInfo).Error |
|
if err != nil { |
|
log.Error("err:%v", err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
if withdrawInfo.ID == 0 { |
|
return |
|
} |
|
resp.BankName = withdrawInfo.BankName |
|
resp.BankBranchName = withdrawInfo.BankBranchName |
|
resp.PhoneNumber = withdrawInfo.PhoneNumber |
|
resp.UserName = withdrawInfo.UserName |
|
resp.IFSCCode = withdrawInfo.IFSCCode |
|
resp.AccountNumber = withdrawInfo.AccountNumber |
|
resp.Email = withdrawInfo.Email |
|
} |
|
|
|
func WithdrawInfo(c *gin.Context) { |
|
a := app.NewApp(c) |
|
defer func() { |
|
a.Response() |
|
}() |
|
info := new(common.RechargeInfo) |
|
info.UID = a.UID |
|
if err := db.Mysql().Get(info); err != nil && err != gorm.ErrRecordNotFound { |
|
log.Error("err:%v", err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
resp := &values.WithDrawInfoResp{Tips: call.GetConfigPlatform().WithdrawTips} |
|
a.Data = resp |
|
if util.IsSameDayTimeStamp(time.Now().Unix(), info.LastWithdraw) { |
|
resp.WithDrawCount = info.WithdrawCount |
|
} else { |
|
resp.WithDrawCount = 0 |
|
} |
|
con := call.GetVipCon(a.UID) |
|
if con != nil { |
|
resp.TotalWithdrawCount = con.WithdrawCount |
|
} |
|
resp.Fees = append(resp.Fees, con.Fee) |
|
resp.Channels = call.GetConfigWithdrawChannels() |
|
list := call.GetConfigWithdrawProduct() |
|
for _, v := range list { |
|
if v.IfSell == 2 { |
|
continue |
|
} |
|
one := *v |
|
if v.Type == common.CurrencyUSDT { |
|
for _, j := range resp.Channels { |
|
if j.CurrencyType == common.CurrencyUSDT { |
|
if j.PayDown <= v.Amount && j.PayUp >= v.Amount { |
|
one.Channels = append(one.Channels, j.ChannelID) |
|
} |
|
} |
|
} |
|
resp.List = append(resp.List, one) |
|
} else if v.Type == common.CurrencyINR { |
|
for _, j := range resp.Channels { |
|
if j.CurrencyType == common.CurrencyINR { |
|
if j.PayDown <= v.Amount && j.PayUp >= v.Amount { |
|
one.Channels = append(one.Channels, j.ChannelID) |
|
} |
|
} |
|
} |
|
resp.List = append(resp.List, one) |
|
} |
|
} |
|
for i := common.CurrencyTypeZero + 1; i < common.CurrencyAll; i++ { |
|
// bet := call.GetPlayerProfileByCurrency(a.UID, i).TotalBet |
|
info := call.GetPlayerRechargeInfoByCurrency(a.UID, i) |
|
canWithdraw := call.GetUserCurrency(a.UID, i) |
|
if canWithdraw < 0 || info.TotalRecharge == 0 { |
|
canWithdraw = 0 |
|
} |
|
resp.Bets = append(resp.Bets, canWithdraw) |
|
} |
|
vipInfo := call.GetVIP(a.UID) |
|
vipCfg := call.GetConfigVIPByLevel(vipInfo.Level) |
|
resp.NeedBet = call.GetUserNeedBet(a.UID) |
|
if int64(vipCfg.WithdrawAmount)-info.DayWithdraw > 0 { |
|
resp.WithdrawalLimit = int64(vipCfg.WithdrawAmount) - info.DayWithdraw |
|
} |
|
|
|
resp.Cash = call.GetUserCurrencyTotal(a.UID, common.CurrencyType(0)) |
|
if resp.NeedBet == 0 { |
|
resp.CanWithdraw = resp.Cash |
|
} |
|
var withdrawInfo common.WithdrawInfo |
|
err := db.Mysql().C().Model(&common.WithdrawInfo{}).Where("uid = ?", a.UID).Find(&withdrawInfo).Error |
|
if err != nil { |
|
log.Error("err:%v", err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
if withdrawInfo.ID == 0 { |
|
return |
|
} |
|
resp.WithdrawInfo = &values.WithdrawInfo{ |
|
BankName: withdrawInfo.BankName, |
|
BankBranchName: withdrawInfo.BankBranchName, |
|
PhoneNumber: withdrawInfo.PhoneNumber, |
|
UserName: withdrawInfo.UserName, |
|
IFSCCode: withdrawInfo.IFSCCode, |
|
AccountNumber: withdrawInfo.AccountNumber, |
|
Email: withdrawInfo.Email, |
|
} |
|
} |
|
|
|
func WithdrawHistory(c *gin.Context) { |
|
a := app.NewApp(c) |
|
defer func() { |
|
a.Response() |
|
}() |
|
req := new(values.WithdrawHistoryReq) |
|
if !a.S(req) { |
|
return |
|
} |
|
if req.PageSize > 100 { |
|
req.PageSize = 100 |
|
} |
|
resp := &values.WithdrawHistoryResp{} |
|
a.Data = resp |
|
|
|
// log.Debug("withdraw history req:%+v", *req) |
|
ret := []common.WithdrawOrder{} |
|
var count, totalAmount int64 |
|
var err error |
|
mdb := db.Mysql().C().Model(&common.WithdrawOrder{}).Where("uid = ? and event = ?", a.UID, common.CurrencyEventWithDraw) |
|
|
|
if req.StartAt != 0 && req.EndAt != 0 { |
|
mdb = mdb.Where("create_time >= ? and create_time <= ?", req.StartAt, req.EndAt) |
|
} |
|
|
|
err = mdb.Count(&count).Error |
|
if err != nil { |
|
log.Error("get count err, %s", err.Error()) |
|
} |
|
|
|
err = mdb.Order("create_time desc").Offset(req.Page * req.PageSize).Limit(req.PageSize).Find(&ret).Error |
|
if err != nil { |
|
log.Error("get withdraw history err, %s", err.Error()) |
|
} |
|
|
|
err = mdb.Select("COALESCE(SUM(amount), 0)").Scan(&totalAmount).Error |
|
if err != nil { |
|
log.Error("get total withdraw amount err, %s", err.Error()) |
|
} |
|
|
|
resp.TotalAmount = totalAmount * common.DecimalDigits |
|
for i, v := range ret { |
|
ret[i].Amount *= common.DecimalDigits |
|
var status uint8 |
|
if v.Status == common.StatusROrderCreate || v.Status == common.StatusROrderWaitting { |
|
status = 0 |
|
} else if v.Status == common.StatusROrderRefuse { |
|
status = 2 |
|
} else if v.Status == common.StatusROrderPay { |
|
status = 1 |
|
} |
|
ret[i].Status = status |
|
} |
|
resp.Count = count |
|
resp.List = ret |
|
a.Data = resp |
|
} |
|
|
|
func PlayerWithdrawBlock(c *gin.Context) { |
|
a := app.NewApp(c) |
|
resp := &values.WithdrawResp{} |
|
defer func() { |
|
a.Data = resp |
|
log.Debug("player %v PlayerWithdraw code:%v", a.UID, a.Code) |
|
a.Response() |
|
}() |
|
|
|
req := new(values.WithdrawBlockReq) |
|
if !a.S(req) { |
|
return |
|
} |
|
if req.CurrencyType != common.CurrencyUSDT { |
|
a.Code = values.CodeParam |
|
return |
|
} |
|
uid := a.UID |
|
log.Debug("player %v withdrawblock %+v", uid, *req) |
|
req.Amount = common.RoundCurrency(req.CurrencyType, req.Amount) |
|
|
|
// 退出条件限制 |
|
if !a.CheckWithdrawCondition(req.Amount, req.CurrencyType) { |
|
return |
|
} |
|
|
|
has := call.GetUserCurrency(a.UID, req.CurrencyType) |
|
need := req.Amount |
|
con := call.GetVipCon(uid) |
|
if con != nil && con.Fee > 0 { |
|
need += req.Amount * con.Fee / 100 |
|
} |
|
if has < need { |
|
log.Error("err not enough cash:%v,%v", has, need) |
|
a.Code = values.CodeWithdrawNotEnough |
|
return |
|
} |
|
|
|
// 拉取玩家退出信息 |
|
re := call.GetRechargeInfo(a.UID) |
|
now := time.Now().Unix() |
|
if re.ID == 0 { |
|
re.LastWithdraw = now |
|
if err := db.Mysql().Create(re); err != nil { |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
} else { |
|
u := map[string]interface{}{"last_withdraw": now} |
|
if !util.IsSameDayTimeStamp(now, re.LastWithdraw) { |
|
u["withdraw_count"] = 0 |
|
u["day_withdraw"] = 0 |
|
} |
|
rows, err := db.Mysql().UpdateRes(&common.RechargeInfo{UID: uid, LastWithdraw: re.LastWithdraw}, u) |
|
if err != nil || rows == 0 { |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
} |
|
|
|
orderID := "USDT" + util.NewOrderID(uid) |
|
// 第一步,先扣钱 |
|
err := call.MineCurrencyProReal(&common.UpdateCurrency{ |
|
CurrencyBalance: &common.CurrencyBalance{ |
|
UID: a.UID, |
|
Event: common.CurrencyEventWithDraw, |
|
Type: common.CurrencyUSDT, |
|
Value: -need, |
|
Exs1: orderID, |
|
ChannelID: a.Channel, |
|
}, |
|
}).Err |
|
if err != nil { |
|
log.Error("player %v mines cash err:%v", uid, err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
|
|
// 直接发起退出 |
|
shouldAuto := call.CanAutoWithdraw(uid, re.TotalRecharge, re.TotalWithdraw+re.TotalWithdrawing+need) |
|
// 第二步,创建订单 |
|
orderStatus := common.StatusROrderCreate |
|
if shouldAuto { |
|
orderStatus = common.StatusROrderWaitting |
|
} |
|
|
|
order := &common.WithdrawOrder{ |
|
UID: uid, |
|
OrderID: orderID, |
|
APIPayID: "", |
|
// ProductID: one.ID, |
|
CreateTime: time.Now().Unix(), |
|
Amount: req.Amount, |
|
WithdrawCash: need, |
|
Status: uint8(orderStatus), |
|
PaySource: common.PaySourceBlockPay, |
|
CurrencyType: req.CurrencyType, |
|
Event: int(common.CurrencyEventWithDraw), |
|
PayAccount: req.Address, |
|
ChannelID: a.Channel, |
|
} |
|
if err := db.Mysql().Create(order); err != nil { |
|
log.Error("player %v create WithdrawBlock order fail err:%v", uid, err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
|
|
u := map[string]interface{}{} |
|
u["withdraw_count"] = gorm.Expr("withdraw_count + ?", 1) |
|
db.Mysql().Update(&common.RechargeInfo{UID: uid}, u) |
|
call.UpdatePlayerRechargeInfoCurrency(uid, req.CurrencyType, map[string]interface{}{"total_withdrawing": gorm.Expr("total_withdrawing + ?", need)}) |
|
// 直接发起退出 |
|
// util.Go(func() { |
|
// call.SendWithdrawMail(uid, call.MailWithdrawType2) |
|
// }) |
|
} |
|
|
|
func PlayerWithdrawCheck(c *gin.Context) { |
|
a := app.NewApp(c) |
|
defer func() { |
|
log.Debug("player %v PlayerWithdrawCheck code:%v,msg:%v", a.UID, a.Code, a.Msg) |
|
a.Response() |
|
}() |
|
req := new(values.WithdrawCheckReq) |
|
if !a.S(req) { |
|
return |
|
} |
|
a.CheckWithdrawCondition(req.Amount, common.CurrencyINR) |
|
} |
|
|
|
func PlayerWithdraw(c *gin.Context) { |
|
a := app.NewApp(c) |
|
resp := &values.WithdrawResp{} |
|
a.Data = resp |
|
defer func() { |
|
log.Debug("player %v PlayerWithdraw code:%v, msg:%s", a.UID, a.Code, a.Msg) |
|
a.Response() |
|
}() |
|
|
|
req := new(values.WithdrawReq) |
|
if !a.S(req) { |
|
return |
|
} |
|
if req.CurrencyType != common.CurrencyINR { |
|
req.CurrencyType = common.CurrencyINR |
|
} |
|
uid := a.UID |
|
log.Debug("player %v withdraw %+v", uid, *req) |
|
req.Amount = common.RoundCurrency(req.CurrencyType, req.Amount) |
|
|
|
// 退出条件限制 |
|
if !a.CheckWithdrawCondition(req.Amount, req.CurrencyType) { |
|
return |
|
} |
|
|
|
ip := a.GetRemoteIP() |
|
|
|
payInfo, code := NewWithdraw(req, uid, ip, a.UUID) |
|
if code != values.CodeOK { |
|
a.Code = code |
|
a.Msg = payInfo |
|
return |
|
} |
|
|
|
if len(payInfo) > 500 { |
|
a.Code = values.CodeParam |
|
a.Msg = "Withdrawal information too long." |
|
return |
|
} |
|
|
|
user := new(common.PlayerDBInfo) |
|
user.Id = uid |
|
if err := db.Mysql().Get(user); err != nil { |
|
log.Error("err:%v", err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
need := req.Amount |
|
has := call.GetUserCurrency(a.UID, req.CurrencyType) |
|
if need > has { |
|
log.Error("err not enough cash:%v,%v", has, need) |
|
a.Code = values.CodeWithdrawNotEnough |
|
a.Msg = "not enough cash" |
|
return |
|
} |
|
|
|
re := call.GetRechargeInfo(a.UID) |
|
now := time.Now().Unix() |
|
if re.ID == 0 { |
|
re.LastWithdraw = now |
|
if err := db.Mysql().Create(re); err != nil { |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
} else { |
|
u := map[string]interface{}{"last_withdraw": now} |
|
if !util.IsSameDayTimeStamp(now, re.LastWithdraw) { |
|
u["withdraw_count"] = 0 |
|
u["day_withdraw"] = 0 |
|
} |
|
rows, err := db.Mysql().UpdateRes(&common.RechargeInfo{UID: uid, LastWithdraw: re.LastWithdraw}, u) |
|
if err != nil || rows == 0 { |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
} |
|
|
|
orderID := util.NewOrderID(uid) |
|
// 第一步,先扣钱 |
|
pro := call.MineCurrencyProReal(&common.UpdateCurrency{ |
|
CurrencyBalance: &common.CurrencyBalance{ |
|
UID: uid, |
|
Value: -need, |
|
Event: common.CurrencyEventWithDraw, |
|
Type: req.CurrencyType, |
|
Exs1: orderID, |
|
ChannelID: a.Channel, |
|
}, |
|
}) |
|
if pro.Err != nil { |
|
log.Error("err:%v", pro.Err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
|
|
con := call.GetVipCon(uid) |
|
realAmount := need // 实际打款 |
|
if con != nil && con.Fee > 0 { |
|
realAmount = common.RoundCurrency(req.CurrencyType, (1000-int64(con.Fee))*realAmount/1000) - 600 // 固定税费 |
|
} |
|
|
|
var shouldAuto = false |
|
// 在总赠送比配置比例小时才判断个人 |
|
// if call.GetTotalRechargePer(realAmount) < config.GetConfig().Web.TotalWithdrawPer { |
|
// 直接发起退出 |
|
shouldAuto = call.CanAutoWithdraw(uid, re.TotalRecharge, re.TotalWithdraw+re.TotalWithdrawing+realAmount) |
|
// } |
|
// 第二步,创建订单 |
|
withdrawChannel := -1 |
|
if req.ChannelID != nil { |
|
withdrawChannel = *req.ChannelID |
|
} |
|
|
|
orderStatus := common.StatusROrderCreate |
|
if shouldAuto { |
|
orderStatus = common.StatusROrderWaitting |
|
} |
|
|
|
order := &common.WithdrawOrder{ |
|
UID: uid, |
|
OrderID: orderID, |
|
APIPayID: "", |
|
// ProductID: one.ID, |
|
CreateTime: time.Now().Unix(), |
|
Amount: realAmount, |
|
WithdrawCash: need, |
|
Status: uint8(orderStatus), |
|
PaySource: common.PaySourceModulePay, |
|
Event: int(common.CurrencyEventWithDraw), |
|
CurrencyType: req.CurrencyType, |
|
PayAccount: payInfo, |
|
ChannelID: a.Channel, |
|
UPI: withdrawChannel, |
|
} |
|
if err := db.Mysql().Create(order); err != nil { |
|
log.Error("player %v create withdraw order fail err:%v", uid, err) |
|
a.Code = values.CodeRetry |
|
return |
|
} |
|
resp.Balance = pro.Balance |
|
resp.WithdrawBalance = has - need |
|
u := map[string]interface{}{} |
|
u["withdrawing_cash"] = gorm.Expr("withdrawing_cash + ?", need) |
|
u["withdraw_count"] = gorm.Expr("withdraw_count + ?", 1) |
|
u["total_withdrawing"] = gorm.Expr("total_withdrawing + ?", realAmount) |
|
u["day_withdraw"] = gorm.Expr("day_withdraw + ?", realAmount) |
|
db.Mysql().Update(&common.RechargeInfo{UID: uid}, u) |
|
// call.UpdatePlayerRechargeInfoCurrency(uid, req.CurrencyType, map[string]interface{}{"total_withdrawing": gorm.Expr("total_withdrawing + ?", need)}) |
|
// 直接发起退出 |
|
// util.Go(func() { |
|
// call.SendWithdrawMail(uid, call.MailWithdrawType2) |
|
// }) |
|
} |
|
|
|
// 返回值在code不为0的时候,代表错误msg |
|
func NewWithdraw(req *values.WithdrawReq, uid int, ip string, uuid string) (string, int) { |
|
one := common.WithdrawCommon{} |
|
err := mapstructure.Decode(req.PayAccount, &one) |
|
if err != nil { |
|
log.Error("NewWithdrawImp err:%s", err.Error()) |
|
return "", values.CodeParam |
|
} |
|
one.PayType = common.PayTypeBank |
|
one.DeviceNo = uuid |
|
one.AccountName = strings.TrimSpace(one.AccountName) |
|
one.BankCardNo = strings.TrimSpace(one.BankCardNo) |
|
one.BankCode = strings.TrimSpace(one.BankCode) |
|
one.IP = ip |
|
|
|
if one.AccountName == "" || one.BankCode == "" { |
|
withdrawInfo, err := call.WithdrawInfoGet(uid) |
|
if err != nil { |
|
log.Error("get withdraw info err, %d %s", uid, err.Error()) |
|
return "", values.CodeRetry |
|
} |
|
if withdrawInfo.ID == 0 { |
|
log.Error("get withdraw wrong, %d", uid) |
|
return "", values.CodeParam |
|
} |
|
one.AccountName = withdrawInfo.UserName |
|
one.BankCardNo = withdrawInfo.AccountNumber |
|
one.BankCode = withdrawInfo.IFSCCode |
|
one.Mobile = withdrawInfo.PhoneNumber |
|
} |
|
|
|
if one.PayType == common.PayTypeBank && len(one.BankCode) != 11 { |
|
return "The IFSC Code shall be 11 digital letters.", values.CodeParam |
|
} |
|
if one.PayType == common.PayTypeBank && one.BankCardNo == "" && one.AccountName == "" && one.Email == "" { |
|
log.Error("NewWithdrawImp 银行卡支付,银行卡号不能为空 one:%+v", one) |
|
return "The Bank Card No should not be empty.", values.CodeParam |
|
} |
|
// 判断是否是拉黑用户,拉黑用户不让代付 |
|
blackData := &common.BlackList{Phone: one.Mobile, PayAccount: one.BankCardNo, Email: one.Email, Name: one.AccountName} |
|
if call.BlackListAndKick(uid, blackData) { |
|
return "", values.CodeRetry |
|
} |
|
// 如果是银行那卡代付,验证ifsc |
|
if one.PayType == common.PayTypeBank { |
|
if !call.CheckIFSC(one.BankCode) { |
|
return "The IFSC Code is invalid.", values.CodeParam |
|
} |
|
} |
|
|
|
// 查询该银行卡是否已经绑定其他账号 |
|
pi := &common.PayInfo{UID: uid} |
|
_ = db.Mysql().Get(pi) |
|
if one.PayType == common.PayTypeBank { |
|
if pi.BankCardNo != one.BankCardNo { |
|
sql := fmt.Sprintf("bank_card_no = '%v'", one.BankCardNo) |
|
if db.Mysql().Count(&common.PayInfo{}, sql) >= int64(config.GetConfig().Web.MaxBankCardCount) { |
|
return "Bank card error", values.CodeBankCardNoLimit |
|
} |
|
} |
|
} else if one.PayType == common.PayTypeUPI { // UPI |
|
if pi.BankCode != one.BankCode { |
|
sql := fmt.Sprintf("bank_code = '%v'", one.BankCode) |
|
if db.Mysql().Count(&common.PayInfo{}, sql) >= int64(config.GetConfig().Web.MaxBankCardCount) { |
|
return "Bank card error", values.CodeBankCardNoLimit |
|
} |
|
} |
|
} |
|
info := &common.PayInfo{ |
|
UID: uid, |
|
DeviceNo: one.DeviceNo, |
|
PhoneModel: one.Model, |
|
OperatorOs: one.OperatorOs, |
|
AccountName: one.AccountName, |
|
Mobile: one.Mobile, |
|
Email: one.Email, |
|
BankCardNo: one.BankCardNo, |
|
PayType: one.PayType, |
|
BankCode: one.BankCode, |
|
} |
|
if _, err := db.Mysql().Upsert(fmt.Sprintf("uid = %v", uid), info); err != nil { |
|
return "", values.CodeParam |
|
} |
|
ret, err := json.Marshal(one) |
|
if err != nil { |
|
log.Error("err:%v", err) |
|
return "", values.CodeParam |
|
} |
|
return string(ret), values.CodeOK |
|
} |
|
|
|
func NewWithdrawImp(order *common.WithdrawOrder) *WithdrawImp { |
|
base := new(WithdrawImp) |
|
// uid := order.UID |
|
cid := order.ChannelID |
|
base.Channel = call.GetChannelByID(cid) |
|
if base.Channel == nil { |
|
log.Error("invalid cid:%v", cid) |
|
return nil |
|
} |
|
base.order = order |
|
one := new(PayWithdraw) |
|
base.SubWithdraw = one |
|
one.base = base |
|
return base |
|
} |
|
|
|
// WithdrawImp 发起退出对象 |
|
type WithdrawImp struct { |
|
order *common.WithdrawOrder |
|
// tx *gorm.DB |
|
SubWithdraw WithdrawInter |
|
Channel *common.Channel |
|
PayChannel int |
|
} |
|
|
|
func (w *WithdrawImp) BaseWithdraw() error { |
|
var err error |
|
// uid := w.order.UID |
|
defer func() { |
|
if err != nil { |
|
call.ReturnBackWithdraw(w.order, common.StatusROrderPay, common.StatusROrderFail, w.PayChannel) |
|
} |
|
}() |
|
res := db.Mysql().C().Model(w.order).Where("status = ?", common.StatusROrderCreate).Updates(map[string]interface{}{"status": common.StatusROrderPay}) |
|
if res.Error != nil { |
|
// w.tx.Rollback() |
|
log.Error("sub withdraw err:%v", err) |
|
return res.Error |
|
} |
|
if res.RowsAffected == 0 { |
|
// w.tx.Rollback() |
|
log.Error("sub withdraw err:%v", err) |
|
return errors.New("invalid order") |
|
} |
|
err = w.SubWithdraw.Withdraw() |
|
if err != nil { |
|
// w.tx.Rollback() |
|
log.Error("sub withdraw err:%v", err) |
|
return err |
|
} |
|
// err = w.tx.Commit().Error |
|
// if err != nil { |
|
// log.Error("commit BaseWithdraw err:%v", err) |
|
// return err |
|
// } |
|
return nil |
|
} |
|
|
|
func (w *WithdrawImp) AutoWithdraw() error { |
|
err := w.SubWithdraw.AutoWithdraw() |
|
if err != nil { |
|
return err |
|
} |
|
return nil |
|
} |
|
|
|
type WithdrawInter interface { |
|
Withdraw() error |
|
AutoWithdraw() error |
|
} |
|
|
|
// PayWithdraw pay模块退出 |
|
type PayWithdraw struct { |
|
base *WithdrawImp |
|
} |
|
|
|
func (p *PayWithdraw) Withdraw() error { |
|
order := p.base.order |
|
req := &pb.InnerWithdrawReq{ |
|
OrderID: order.OrderID, |
|
Amount: order.Amount, |
|
UID: uint32(order.UID), |
|
Channel: int64(order.UPI), |
|
PaySource: uint32(order.PaySource), |
|
} |
|
if req.PaySource == common.PaySourceModulePay { |
|
send := new(common.WithdrawCommon) |
|
err := json.Unmarshal([]byte(order.PayAccount), &send) |
|
if err != nil { |
|
log.Error("withdraw unmarshal err %v", err) |
|
return err |
|
} |
|
req.Phone = send.Mobile |
|
req.Name = send.Name |
|
req.Email = send.Email |
|
req.PayType = int64(send.PayType) |
|
req.PayCode = send.BankCode |
|
req.CardNo = send.BankCardNo |
|
req.Name = send.AccountName |
|
|
|
} |
|
ret, err := call.Withdraw(req) |
|
if ret != nil { |
|
p.base.PayChannel = int(ret.Channel) |
|
} |
|
if err != nil { |
|
log.Error("err:%v", err) |
|
return err |
|
} |
|
|
|
or := &common.WithdrawOrder{ |
|
Status: common.StatusROrderPay, APIPayID: ret.APIOrderID, |
|
PaySource: common.PaySourceModulePay} |
|
or.ID = order.ID |
|
res := db.Mysql().C().Model(order).Updates(or) |
|
err = res.Error |
|
if err != nil { |
|
log.Error("update order err:%v", err) |
|
return err |
|
} |
|
if res.RowsAffected == 0 { |
|
log.Error("update order fail orderid:%v", order.ID) |
|
return errors.New("update order fail") |
|
} |
|
return nil |
|
} |
|
|
|
func (p *PayWithdraw) AutoWithdraw() error { |
|
order := p.base.order |
|
req := &pb.InnerWithdrawReq{ |
|
OrderID: order.OrderID, |
|
Amount: order.Amount, |
|
UID: uint32(order.UID), |
|
Channel: int64(order.UPI), |
|
PaySource: uint32(order.PaySource), |
|
} |
|
if req.PaySource == common.PaySourceModulePay { |
|
send := new(common.WithdrawCommon) |
|
err := json.Unmarshal([]byte(order.PayAccount), &send) |
|
if err != nil { |
|
log.Error("withdraw unmarshal err %v", err) |
|
return err |
|
} |
|
req.Phone = send.Mobile |
|
req.Name = send.Name |
|
req.Email = send.Email |
|
req.PayType = int64(send.PayType) |
|
req.BankName = send.BankName |
|
req.CardNo = send.BankCode |
|
// req.Address = send.Address |
|
// req.Number = send.Number |
|
} else { |
|
req.Address = order.PayAccount |
|
} |
|
ret, err := call.Withdraw(req) |
|
if ret != nil { |
|
p.base.PayChannel = int(ret.Channel) |
|
} |
|
if err != nil { |
|
return err |
|
} |
|
p.base.order.APIPayID = ret.APIOrderID |
|
p.base.order.Status = common.StatusROrderPay |
|
p.base.order.PayChannel = int(ret.Channel) |
|
return nil |
|
}
|
|
|