印度包网
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.

668 lines
18 KiB

1 year ago
package handler
import (
"encoding/json"
"errors"
"fmt"
"server/call"
"server/common"
"server/config"
"server/db"
"server/modules/web/app"
"server/modules/web/values"
"server/pb"
"server/util"
1 year ago
"strings"
1 year ago
"time"
"github.com/gin-gonic/gin"
"github.com/liangdas/mqant/log"
"github.com/mitchellh/mapstructure"
"gorm.io/gorm"
)
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}
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, con.UFee)
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 {
1 year ago
for _, j := range resp.Channels {
if j.CurrencyType == common.CurrencyINR {
1 year ago
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)
}
a.Data = resp
}
func WithdrawHistory(c *gin.Context) {
a := app.NewApp(c)
defer func() {
a.Response()
}()
req := new(values.WithdrawHistoryReq)
if !a.S(req) {
return
}
if req.Num > 100 {
req.Num = 100
}
// log.Debug("withdraw history req:%+v", *req)
ret := []common.WithdrawOrder{}
var count int64
var err error
count, err = db.Mysql().QueryListW(req.Page, req.Num, "create_time desc",
&common.WithdrawOrder{UID: a.UID}, &ret, "uid = ? and event = ?",
a.UID, common.CurrencyEventWithDraw)
if err != nil {
log.Error("err:%v", err)
a.Code = values.CodeRetry
return
}
for i, v := range ret {
if v.Status == common.StatusROrderCreate || v.Status == common.StatusROrderWaitting {
ret[i].Status = common.StatusROrderPay
} else if v.Status == common.StatusROrderRefuse {
ret[i].Status = common.StatusROrderFail
}
}
resp := values.WithdrawHistoryResp{
Count: count,
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.UFee > 0 {
need += con.UFee
}
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(int(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: int(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)
1 year ago
}
func PlayerWithdraw(c *gin.Context) {
a := app.NewApp(c)
resp := &values.WithdrawResp{}
a.Data = resp
defer func() {
log.Debug("player %v PlayerWithdraw code:%v", a.UID, a.Code)
a.Response()
}()
req := new(values.WithdrawReq)
if !a.S(req) {
return
}
if req.CurrencyType != common.CurrencyINR {
1 year ago
log.Error("invalid type:%v", req.CurrencyType)
req.CurrencyType = common.CurrencyINR
1 year ago
}
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()
1 year ago
payInfo, code := NewWithdraw(req, uid, ip, a.UUID)
1 year ago
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
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(int(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 {
1 year ago
realAmount = common.RoundCurrency(req.CurrencyType, con.Fee) * realAmount
1 year ago
}
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: int(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
1 year ago
func NewWithdraw(req *values.WithdrawReq, uid int, ip string, uuid string) (string, int) {
1 year ago
one := common.WithdrawCommon{}
err := mapstructure.Decode(req.PayAccount, &one)
1 year ago
if err != nil || one.BankCode == "" {
1 year ago
log.Error("NewWithdrawImp err:%v,one:%+v", err, one)
return "", values.CodeParam
}
1 year ago
if one.PayType == common.PayTypeUPI {
return "The UPI channel is closed, please use the bank channel to withdraw cash.", values.CodeParam
}
if !one.PayType.Isvalid() {
log.Error("NewWithdrawImp err:%v,one:%+v", err, one)
return "", values.CodeParam
}
one.DeviceNo = uuid
one.AccountName = strings.TrimSpace(one.AccountName)
one.BankCardNo = strings.TrimSpace(one.BankCardNo)
one.BankCode = strings.TrimSpace(one.BankCode)
1 year ago
one.IP = ip
1 year ago
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
}
user, _ := call.GetUserXInfo(uid, "mobile")
if user.Mobile == "" {
return "", values.CodeParam
}
_ = mapstructure.Decode(req.PayAccount, &one)
if one.Mobile == "" {
one.Mobile = user.Mobile
}
1 year ago
// 判断是否是拉黑用户,拉黑用户不让代付
1 year ago
blackData := &common.BlackList{Phone: one.Mobile, PayAccount: one.BankCardNo, Email: one.Email, Name: one.AccountName}
if one.PayType == common.PayTypeUPI {
blackData.PayAccount = one.BankCode
}
if call.BlackListAndKick(uid, blackData) {
return "", values.CodeRetry
}
1 year ago
// 如果是银行那卡代付,验证ifsc
1 year ago
if one.PayType == common.PayTypeBank {
if !call.CheckIFSC(one.BankCode) {
return "The IFSC Code is invalid.", values.CodeParam
}
}
1 year ago
// 查询该银行卡是否已经绑定其他账号
1 year ago
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 "", 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 "", values.CodeBankCardNoLimit
}
}
}
1 year ago
info := &common.PayInfo{
1 year ago
UID: uid,
DeviceNo: one.DeviceNo,
// Device: one.Device,
PhoneModel: one.Model,
OperatorOs: one.OperatorOs,
AccountName: one.AccountName,
Mobile: one.Mobile,
Email: one.Email,
BankCardNo: one.BankCardNo,
PayType: one.PayType,
BankCode: one.BankCode,
// Address: one.Address,
1 year ago
}
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)
1 year ago
req.PayCode = send.BankCode
req.CardNo = send.BankCardNo
req.Name = send.AccountName
1 year ago
}
ret, err := call.Withdraw(req)
if ret != nil {
p.base.PayChannel = int(ret.Channel)
}
if err != nil {
log.Error("err:%v", err)
return err
}
1 year ago
or := &common.WithdrawOrder{
Status: common.StatusROrderPay, APIPayID: ret.APIOrderID,
PaySource: common.PaySourceModulePay}
1 year ago
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)
1 year ago
req.BankName = send.BankName
req.CardNo = send.BankCode
// req.Address = send.Address
// req.Number = send.Number
1 year ago
} 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
}