package withdrawser import ( "errors" "fmt" "strconv" "sync" "time" "91porn-server/app/appg" "91porn-server/common" "91porn-server/common/constant/redisconst" "91porn-server/common/crypt" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models/v/txnmod" "91porn-server/models/v/usermod" "91porn-server/models/v/walletmod" "91porn-server/models/v/wdchannmod" "91porn-server/models/v/wdordmod" "91porn-server/models/v/wdtaxmod" ) // WithDraw 提现 func WithDraw(wd *wdordmod.WithdrawOrder) (err error) { now := time.Now() u, err := usermod.FindUserByUID(wd.UID) if err != nil || u == nil { return } wt, err := WithdrawType(u.GetSuperUser(now), wd.PayType) if err != nil { return err } if wd.ProductType == 1 { return errors.New("瓦力游戏已下架") } w, err := walletmod.GetWallet(wd.UID) if err != nil { return err } if wd.Name == "" { wd.Name = u.Name } if wd.DevID == "" { wd.DevID = u.DevID } wd.DeviceType = u.SysType wd.DiscDoc = u.DiscDoc switch wd.WithdrawType { case wdordmod.AgentWithdraw: //代理提现 wd.PayMoney = (wd.Money * (int64)(100-wt.CoinTax)) / 100 if wd.Money > w.Money { return errors.New("Insufficient balance") } //开启事务 return appg.VideoDB.Trans(func(t *db.MongoTool) error { wd.Status = wdordmod.DEFAULT if _, err = wdordmod.InsertWithdrawOrder(t, wd); err != nil { return err } _, err = walletmod.DebitMoney(t, wd.Money, wd.UID) return err }) default: //wdordmod.GoldWithdraw 金币提现 wd.Amount = wd.Money / 10 wd.PayMoney = (wd.Money * (int64)(100-wt.CoinTax)) / 100 if wd.Amount > w.Income { return errors.New("Insufficient balance") } //开启事务 return appg.VideoDB.Trans(func(t *db.MongoTool) error { wd.Status = wdordmod.DEFAULT if _, err = wdordmod.InsertWithdrawOrder(t, wd); err != nil { return err } wallet, err := walletmod.DebitIncome(t, wd.Amount, wd.UID) if err != nil { return err } //插入收支流水 tt := txnmod.TransactionLog{ TransNo: wd.ID, UID: wd.UID, Amount: -wd.Amount, TranType: txnmod.WithdrawTransfer.Key(), TranTypeInt: int64(txnmod.WithdrawTransfer), ChannelType: wd.PayType, Desc: "用户提现-" + strconv.FormatInt(wd.Amount, 10), DiscDoc: wd.DiscDoc, SysType: wd.DeviceType, ActualAmount: -float64(wd.Amount), RealAmount: walletmod.GetRealAmount(wallet), } //插入一条支出流水 return txnmod.InsertTransactionLog(t, &tt) }) } } // WithdrawType 获取提现方式 func WithdrawType(superUser bool, wType string) (res wdchannmod.WithdrawChannelRes, err error) { var wg sync.WaitGroup wg.Add(2) common.Go(func() { defer wg.Done() wc, err := wdchannmod.GetWithdrawChannel(wType) if err != nil { return } res.WithdrawChannel = *wc }) common.Go(func() { defer wg.Done() wt, err := wdtaxmod.GetWithDrawTariff() if err != nil { return } if superUser { res.WithdrawTariff.CoinTax = wt.SuperUserCoinTax } else { res.WithdrawTariff.CoinTax = wt.CoinTax } if wt.GameTax <= 0 { wt.GameTax = 2 } res.WithdrawTariff.GameTax = wt.GameTax }) wg.Wait() return } // GetWithdrawCfg 获取提现配置方式 func GetWithdrawCfg() (res wdchannmod.WithdrawChannelAppRes) { var wd []*wdchannmod.AppWithdrawChannels var wt wdtaxmod.WithdrawTariff var wg sync.WaitGroup wg.Add(2) common.Go(func() { defer wg.Done() str, err := appg.Redis.Get(redisconst.WithdrawCfgCacheKey()) if str != nil && err == nil { _ = crypt.JSON2Struct(*str, &wd) } else { wd, err = wdchannmod.GetActiveWithdrawChannels() if wd != nil && err == nil { normalstr, _ := crypt.StructToStrNormal(&wd) _ = appg.Redis.Set(redisconst.WithdrawCfgCacheKey(), normalstr, redisconst.WithdrawCfgExpire) } } }) common.Go(func() { defer wg.Done() str, err := appg.Redis.Get(redisconst.WithdrawTariffCacheKey()) if str != nil && err == nil { _ = crypt.JSON2Struct(*str, &wt) } else { wt, err = wdtaxmod.GetWithDrawTariff() if err == nil { normalstr, _ := crypt.StructToStrNormal(wt) _ = appg.Redis.Set(redisconst.WithdrawTariffCacheKey(), normalstr, redisconst.WithdrawTariffExpire) } } }) wg.Wait() res.Channels = wd res.CashTax = wt.CashTax res.CoinTax = wt.CoinTax return } // ExchgCallBack 提现回调 func ExchgCallBack(tradeNo string, oid string, money int64, status string, mark string) error { w, err := wdordmod.FindWithdrawOrderByID(tradeNo) if err != nil { return err } if w.Status == wdordmod.SUCCESS || w.Status == wdordmod.FAILURE { return nil } if w.Status != wdordmod.PROCESSING && w.Status != wdordmod.UNKNOWN { log.Error(fmt.Sprintf("Wtihdraw status error ,order:%+v:", w)) return errors.New("Wtihdraw status error") } if w.ProductType == 1 { return errors.New("瓦力游戏已下架") } now := time.Now() set := wdordmod.EditSelector{ OID: &oid, } switch status { case "paid": //已经打款 //修改订单状态 set.PayMoney = &money set.SuccessAt = &now set.ReceivedAt = &now set.Status = wdordmod.SUCCESS set.StatusDesc = wdordmod.SUCCESSStatus set.SuccessAt = &now if err = wdordmod.UpdateWithPROCESSINGAndUNKNOWN(nil, tradeNo, set); err != nil { return err } if w.PayType == wdordmod.TypeBankCard { _, err = usermod.Update(w.UID, usermod.UserSelector{BankActName: &w.ActName}) return err } return nil case "refused": //拒绝 return appg.VideoDB.Trans(func(t *db.MongoTool) error { switch w.WithdrawType { case wdordmod.GoldWithdraw: var wallet *walletmod.Wallet wallet, err = walletmod.CreditIncome(t, w.Amount, w.UID) if err != nil { return err } //插入收支流水 tk := txnmod.TransactionLog{ TransNo: w.ID, UID: w.UID, Amount: w.Amount, TranType: txnmod.WithdrawRefund.Key(), TranTypeInt: int64(txnmod.WithdrawRefund), ChannelType: w.PayType, Desc: "用户提现失败,退款" + strconv.FormatInt(w.Amount, 10), DiscDoc: w.DiscDoc, SysType: w.DeviceType, ActualAmount: float64(w.Amount), RealAmount: walletmod.GetRealAmount(wallet), } //插入一条支出流水 if err = txnmod.InsertTransactionLog(t, &tk); err != nil { return err } case wdordmod.AgentWithdraw: if err = walletmod.CreditMoney(t, w.Money, w.UID); err != nil { return err } case wdordmod.DiscWithdraw: // err = discWirhdrawRefund(t, w, "提现被平台拒绝") if err != nil { log.Error("discWirhdrawRefund failed", log.E(err), log.Any("witOrd", w)) return err } default: return errors.New("invalid type") } set.Status = wdordmod.FAILURE set.StatusDesc = mark set.FailureAt = &now if err = wdordmod.UpdateWithPROCESSINGAndUNKNOWN(t, tradeNo, set); err != nil { return err } //棋牌usdt兑换拒绝增加usdt可提现额度 if w.ProductType == 1 && w.PayType == wdordmod.TypeUsdt { if _, err = walletmod.IncUsdtAmount(w.UID, money); err != nil { return err } } return nil }) default: return nil } }