Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

268 lines
7.1 KiB
Go

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