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.
814 lines
25 KiB
814 lines
25 KiB
|
1 year ago
|
package call
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"encoding/json"
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"io/ioutil"
|
||
|
|
"net/http"
|
||
|
|
"server/common"
|
||
|
|
"server/config"
|
||
|
|
"server/db"
|
||
|
|
"server/natsClient"
|
||
|
|
"server/pb"
|
||
|
|
"server/util"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/gogo/protobuf/proto"
|
||
|
|
"github.com/liangdas/mqant/log"
|
||
|
|
mqrpc "github.com/liangdas/mqant/rpc"
|
||
|
|
"gorm.io/gorm"
|
||
|
|
)
|
||
|
|
|
||
|
|
func GetRechargeInfo(uid int) *common.RechargeInfo {
|
||
|
|
info := &common.RechargeInfo{UID: uid}
|
||
|
|
err := db.Mysql().Get(info)
|
||
|
|
if err != nil {
|
||
|
|
return info
|
||
|
|
}
|
||
|
|
now := time.Now().Unix()
|
||
|
|
if !util.IsSameDayTimeStamp(now, info.LastRecharge) {
|
||
|
|
info.DayRecharge = 0
|
||
|
|
}
|
||
|
|
return info
|
||
|
|
}
|
||
|
|
|
||
|
|
// Recharge 内部充值调用
|
||
|
|
func Recharge(data *pb.InnerRechargeReq) (*pb.InnerRechargeResp, error) {
|
||
|
|
to, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
|
|
defer cancel()
|
||
|
|
module := "pay"
|
||
|
|
if data.PaySource == common.PaySourceBlockPay {
|
||
|
|
module = "blockpay"
|
||
|
|
}
|
||
|
|
ret, err := GetCaller().GetApp().Call(to, module, "recharge", mqrpc.Param(data))
|
||
|
|
if err != "" {
|
||
|
|
return nil, errors.New(err)
|
||
|
|
}
|
||
|
|
retData := new(pb.InnerRechargeResp)
|
||
|
|
if err := proto.Unmarshal(ret.([]byte), retData); err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return retData, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Withdraw 内部退出调用
|
||
|
|
func Withdraw(data *pb.InnerWithdrawReq) (*pb.InnerWithdrawResp, error) {
|
||
|
|
log.Debug("withdraw req:%+v", *data)
|
||
|
|
to, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
|
|
defer cancel()
|
||
|
|
module := "pay"
|
||
|
|
if data.PaySource == common.PaySourceBlockPay {
|
||
|
|
module = "blockpay"
|
||
|
|
}
|
||
|
|
ret, err := GetCaller().GetApp().Call(to, module, "withdraw", mqrpc.Param(data))
|
||
|
|
retData := new(pb.InnerWithdrawResp)
|
||
|
|
if data, ok := ret.([]byte); ok {
|
||
|
|
if err := proto.Unmarshal(data, retData); err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if err != "" {
|
||
|
|
return retData, errors.New(err)
|
||
|
|
}
|
||
|
|
return retData, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// RechargeCallback 充值回调
|
||
|
|
func RechargeCallback(r *common.RechargeOrder, success bool, payAccount, extra string) (err error) {
|
||
|
|
log.Info("RechargeCallback:%+v,%v,%v,%v,", r, success, payAccount, extra)
|
||
|
|
if r == nil {
|
||
|
|
return errors.New("order invalid")
|
||
|
|
}
|
||
|
|
|
||
|
|
if !success {
|
||
|
|
ro := &common.RechargeOrder{OrderID: r.OrderID, Status: common.StatusROrderCreate}
|
||
|
|
return db.Mysql().Update(ro, &common.RechargeOrder{Status: common.StatusROrderFail})
|
||
|
|
}
|
||
|
|
|
||
|
|
uid := r.UID
|
||
|
|
re := new(common.RechargeInfo)
|
||
|
|
re.UID = uid
|
||
|
|
err = db.Mysql().Get(re)
|
||
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||
|
|
log.Error("get recharage info err:%v,uid:%v", err, r.UID)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// product := GetConfigPayProductByID(r.ProductID)
|
||
|
|
// if product == nil {
|
||
|
|
// log.Error("unkonwn product:%d", r.ProductID)
|
||
|
|
// return errors.New("unkonwn product")
|
||
|
|
// }
|
||
|
|
amount := r.Amount
|
||
|
|
|
||
|
|
notCharge := re.TotalRecharge == 0
|
||
|
|
re.TotalRecharge += amount
|
||
|
|
now := time.Now().Unix()
|
||
|
|
// var dayR, weekR bool
|
||
|
|
var dayR bool
|
||
|
|
if util.IsSameDayTimeStamp(re.LastRecharge, now) || re.LastRecharge == 0 {
|
||
|
|
dayR = true
|
||
|
|
re.DayRecharge += amount
|
||
|
|
}
|
||
|
|
// if util.IsSameWeek(re.LastRecharge, now) || re.LastRecharge == 0 {
|
||
|
|
// weekR = true
|
||
|
|
// re.WeekRecharge += amount
|
||
|
|
// }
|
||
|
|
|
||
|
|
re.LastRecharge = now
|
||
|
|
re.TotalRechargeCount++
|
||
|
|
// re.ProductPayCount = common.AddProductPayCount(re.ProductPayCount, r.ProductID)
|
||
|
|
// if product.IsFirstPayProduct() {
|
||
|
|
// json.Unmarshal([]byte(re.ProductFirstPay), &re.ProductFirstPaySub)
|
||
|
|
// if util.SliceContain(re.ProductFirstPaySub, product.ProductID) { // 该商品已购买,替换为可多次购买的同价值商品
|
||
|
|
// product = GetConfigPayProductShopByAmount(product.Amount)
|
||
|
|
// if product == nil {
|
||
|
|
// return errors.New("product invalid")
|
||
|
|
// }
|
||
|
|
// } else {
|
||
|
|
// re.ProductFirstPaySub = append(re.ProductFirstPaySub, int(product.ProductID))
|
||
|
|
// str, _ := json.Marshal(re.ProductFirstPaySub)
|
||
|
|
// re.ProductFirstPay = string(str)
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// var per int64 = 0
|
||
|
|
// level := GetConfigFirstPayLevelByAmount(r.Amount)
|
||
|
|
// playerPayData := GetPlayerPayData(uid)
|
||
|
|
tx := db.Mysql().Begin()
|
||
|
|
defer func() {
|
||
|
|
if err == nil {
|
||
|
|
if err := tx.Commit().Error; err != nil {
|
||
|
|
tx.Rollback()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}()
|
||
|
|
|
||
|
|
// 第一步,更新订单状态
|
||
|
|
updates := common.RechargeOrder{Status: common.StatusROrderPay, APIPayID: r.APIPayID, PayAccount: payAccount, Extra: extra, CallbackTime: now}
|
||
|
|
dbtx := tx.Table("recharge_order").Where(fmt.Sprintf("orderid = '%v' and status <> %v", r.OrderID, common.StatusROrderPay)).Updates(updates)
|
||
|
|
if dbtx.Error != nil {
|
||
|
|
return fmt.Errorf("update order err:%v", dbtx.Error)
|
||
|
|
}
|
||
|
|
// 已处理的单不返回错误了
|
||
|
|
if dbtx.RowsAffected == 0 {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// 更新paydata
|
||
|
|
// if playerPayData.ID == 0 {
|
||
|
|
// err = tx.Model(playerPayData).Create(playerPayData).Error
|
||
|
|
// if err != nil {
|
||
|
|
// log.Error("err:%v", err)
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
// } else {
|
||
|
|
// playerPayData.SubFirstPay = append(playerPayData.SubFirstPay, level)
|
||
|
|
// updatePayData, _ := json.Marshal(playerPayData.SubFirstPay)
|
||
|
|
// res := tx.Model(playerPayData).Where("id = ? and first_pay = ?", playerPayData.ID, playerPayData.FirstPay).Updates(map[string]interface{}{"first_pay": string(updatePayData)})
|
||
|
|
// if res.RowsAffected == 0 {
|
||
|
|
// log.Error("err:%v", err)
|
||
|
|
// return errors.New("update payData fail")
|
||
|
|
// }
|
||
|
|
// if err != nil {
|
||
|
|
// log.Error("update payData err:%v", err)
|
||
|
|
// return err
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// 第二步,更新recharge_info
|
||
|
|
payData := &common.ESPlayerPayData{UID: uid, Channel: r.ChannelID, Type: 1, CurrencyType: r.CurrencyType}
|
||
|
|
if re.ID == 0 {
|
||
|
|
err = tx.Model(re).Create(re).Error
|
||
|
|
if err != nil {
|
||
|
|
// 说明数据库出问题或者两单并发回调,一分钟后重试
|
||
|
|
time.AfterFunc(1*time.Minute, func() {
|
||
|
|
RechargeCallback(r, success, payAccount, extra)
|
||
|
|
})
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
payData.FirstAmount = amount
|
||
|
|
} else {
|
||
|
|
updates := map[string]interface{}{
|
||
|
|
"total_recharge_count": gorm.Expr("total_recharge_count + 1"),
|
||
|
|
"total_recharge": gorm.Expr("total_recharge + ?", amount),
|
||
|
|
"last_recharge": now,
|
||
|
|
// "product_paycount": re.ProductPayCount,
|
||
|
|
// "product_firstpay": re.ProductFirstPay,
|
||
|
|
}
|
||
|
|
if dayR {
|
||
|
|
updates["day_recharge"] = gorm.Expr("day_recharge + ?", amount)
|
||
|
|
} else {
|
||
|
|
updates["day_recharge"] = amount
|
||
|
|
}
|
||
|
|
// if weekR {
|
||
|
|
// updates["week_recharge"] = gorm.Expr("week_recharge + ?", amount)
|
||
|
|
// } else {
|
||
|
|
// updates["week_recharge"] = amount
|
||
|
|
// }
|
||
|
|
err = tx.Model(re).Where("uid=?", re.UID).Updates(updates).Error
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
log.Error("recharge err:%v", err)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// 第三步,给玩家发货
|
||
|
|
// 正常商城充值
|
||
|
|
var bonus int64
|
||
|
|
if r.ProductID == 0 {
|
||
|
|
amount := PayExtra(r) // 判断特殊购买,如优惠券
|
||
|
|
if amount == 0 {
|
||
|
|
amount = r.Amount
|
||
|
|
}
|
||
|
|
// cb := &common.CurrencyBalance{
|
||
|
|
// UID: r.UID,
|
||
|
|
// Type: r.CurrencyType,
|
||
|
|
// Value: amount,
|
||
|
|
// Event: common.CurrencyEvent(r.Event),
|
||
|
|
// Exs1: r.OrderID,
|
||
|
|
// Exi1: int(amount), // 充值金额传递
|
||
|
|
// Exi2: r.ProductID,
|
||
|
|
// NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceRecharge, amount),
|
||
|
|
// }
|
||
|
|
// err = UpdateCurrencyProReal(&common.UpdateCurrency{
|
||
|
|
// CurrencyBalance: cb,
|
||
|
|
// }).Err
|
||
|
|
// if err != nil {
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
// } else {
|
||
|
|
per := GetConfigFirstPayPerByAmount(notCharge, amount)
|
||
|
|
if per > 0 {
|
||
|
|
bonus = amount * per / 100
|
||
|
|
}
|
||
|
|
cb := &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Type: r.CurrencyType,
|
||
|
|
Value: amount + bonus,
|
||
|
|
Event: common.CurrencyEvent(r.Event),
|
||
|
|
Exs1: r.OrderID,
|
||
|
|
Exi1: int(amount), // 充值金额传递
|
||
|
|
Exi2: r.ProductID,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceRecharge, amount) + GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, bonus),
|
||
|
|
}
|
||
|
|
err = UpdateCurrencyProReal(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: cb,
|
||
|
|
}).Err
|
||
|
|
if err != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// 以上逻辑为处理订单,更新玩家充值信息,给玩家加钱。
|
||
|
|
// 下面逻辑处理活动,数据统计等,不影响以上效率,接下来逻辑并发执行
|
||
|
|
util.Go(func() {
|
||
|
|
// 更新活动数据上传
|
||
|
|
if bonus > 0 {
|
||
|
|
UploadActivityData(uid, common.ActivityIDRecharge, common.ActivityDataJoin, bonus)
|
||
|
|
}
|
||
|
|
user, _ := GetUserInfo(uid)
|
||
|
|
PayActivity(r, notCharge, user)
|
||
|
|
if r.Event != int(common.CurrencyEventGMRecharge) {
|
||
|
|
payData.Amount = amount
|
||
|
|
WritePlayerPayData(payData)
|
||
|
|
}
|
||
|
|
var uploads []func()
|
||
|
|
uploads = append(uploads, func() { UploadAdjust(common.AdjustEventAllPay, user, nil) })
|
||
|
|
// 24小时内注册的用户所有付费事件上报
|
||
|
|
if now-user.Birth <= 24*60*60 {
|
||
|
|
uploads = append(uploads, func() {
|
||
|
|
UploadAdjust(common.AdjustEventNewPay, user, map[string]string{"revenue": util.RoundFloat(float64(amount/1e6)/100, 2), "currency": "BRL"})
|
||
|
|
})
|
||
|
|
|
||
|
|
// 上报fb
|
||
|
|
UploadFB(uid, FBEventPurchase, amount/common.DecimalDigits)
|
||
|
|
UploadKwai(uid, KwaiEventPay, amount)
|
||
|
|
}
|
||
|
|
for _, f := range uploads {
|
||
|
|
f()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func WithdrawCallback(order *common.WithdrawOrder) error {
|
||
|
|
uid := order.UID
|
||
|
|
amount := order.Amount
|
||
|
|
var err error
|
||
|
|
// 不成功退款
|
||
|
|
if order.Status == common.StatusROrderFail {
|
||
|
|
err = ReturnBackWithdraw(order, common.StatusROrderFinish, common.StatusROrderFail)
|
||
|
|
} else {
|
||
|
|
tx := db.Mysql().Begin()
|
||
|
|
or := new(common.WithdrawOrder)
|
||
|
|
or.ID = order.ID
|
||
|
|
or.Status = uint8(common.StatusROrderFinish)
|
||
|
|
or.CallbackTime = time.Now().Unix()
|
||
|
|
or.APIPayID = order.APIPayID
|
||
|
|
or.FailReason = order.FailReason
|
||
|
|
if len(or.FailReason) > 200 {
|
||
|
|
or.FailReason = or.FailReason[:200]
|
||
|
|
}
|
||
|
|
res := tx.Model(or).Where("id = ? and status <> ?", or.ID, common.StatusROrderFinish).Updates(or)
|
||
|
|
if res.Error != nil {
|
||
|
|
log.Error("Withdraw callback err:%v", res.Error)
|
||
|
|
tx.Rollback()
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// 已处理的情况不返回错误了
|
||
|
|
if res.RowsAffected == 0 {
|
||
|
|
log.Error("Withdraw callback order:%v done", order.OrderID)
|
||
|
|
tx.Rollback()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
rei := &common.RechargeInfo{UID: uid}
|
||
|
|
db.Mysql().Get(rei)
|
||
|
|
payData := &common.ESPlayerPayData{UID: uid, Channel: order.ChannelID, Amount: amount, Type: 2}
|
||
|
|
if rei.TotalWithdrawCount == 0 {
|
||
|
|
payData.FirstAmount = amount
|
||
|
|
}
|
||
|
|
WritePlayerPayData(payData)
|
||
|
|
u := map[string]interface{}{
|
||
|
|
"total_withdraw_count": gorm.Expr("total_withdraw_count + ?", 1),
|
||
|
|
"total_withdraw": gorm.Expr("total_withdraw + ?", order.Amount),
|
||
|
|
"total_withdrawing": gorm.Expr("total_withdrawing - ?", amount),
|
||
|
|
"withdrawing_cash": gorm.Expr("withdrawing_cash - ?", order.WithdrawCash),
|
||
|
|
}
|
||
|
|
err = tx.Model(rei).Where("uid = ?", uid).Updates(u).Error
|
||
|
|
if err != nil {
|
||
|
|
log.Error("BaseWithdraw err :%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// err = UpdatePlayerRechargeInfoCurrency(uid, order.CurrencyType, map[string]interface{}{
|
||
|
|
// "total_withdrawing": gorm.Expr("total_withdrawing - ?", order.WithdrawCash),
|
||
|
|
// "total_withdraw": gorm.Expr("total_withdraw + ?", order.Amount),
|
||
|
|
// }, tx)
|
||
|
|
// if err != nil {
|
||
|
|
// log.Error("BaseWithdraw err :%v", err)
|
||
|
|
// tx.Rollback()
|
||
|
|
// return err
|
||
|
|
// }
|
||
|
|
if err := tx.Commit().Error; err != nil {
|
||
|
|
log.Error("ZYWithdraw callback err:%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
PublishWarn(WarnTypeWithdraw, 2, []int64{int64(order.ChannelID), int64(order.UID)})
|
||
|
|
con := GetBroadcastConfigWithID(common.BrocastIDWithdraw)
|
||
|
|
if con != nil {
|
||
|
|
up := con.ConditionUp
|
||
|
|
down := con.ConditionDown
|
||
|
|
if (amount <= int64(up) || up <= 0) && amount >= int64(down) {
|
||
|
|
BroadcastReq(con, fmt.Sprintf(con.Content, uid, amount))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// util.Go(func() {
|
||
|
|
// SendRealWithdrawMail(order)
|
||
|
|
// })
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
Publish(natsClient.TopicInnerPlayerWithdraw, &pb.InnerWithdrawCallback{UID: uint32(uid)})
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ReturnBackWithdraw 退出被拒绝或者失败,返还金币
|
||
|
|
func ReturnBackWithdraw(or *common.WithdrawOrder, originStatus, status uint8, payChannel ...int) error {
|
||
|
|
order := &common.WithdrawOrder{}
|
||
|
|
order.ID = or.ID
|
||
|
|
tx := db.Mysql().Begin()
|
||
|
|
u := map[string]interface{}{
|
||
|
|
"status": status,
|
||
|
|
"fail_reason": or.FailReason,
|
||
|
|
"callback_time": time.Now().Unix(),
|
||
|
|
}
|
||
|
|
if len(payChannel) > 0 {
|
||
|
|
u["pay_channel"] = payChannel[0]
|
||
|
|
}
|
||
|
|
if len(or.APIPayID) > 0 {
|
||
|
|
u["apipayid"] = or.APIPayID
|
||
|
|
}
|
||
|
|
update := tx.Model(order).Where("status <= ?", originStatus).Updates(u)
|
||
|
|
if update.Error != nil {
|
||
|
|
log.Error("err:%v", update.Error)
|
||
|
|
tx.Rollback()
|
||
|
|
return update.Error
|
||
|
|
}
|
||
|
|
// 已处理的情况不返回错误了
|
||
|
|
if update.RowsAffected == 0 {
|
||
|
|
err := fmt.Errorf("update fail:%+v", or)
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
uid := or.UID
|
||
|
|
re := new(common.RechargeInfo)
|
||
|
|
re.UID = uid
|
||
|
|
updateRe := map[string]interface{}{
|
||
|
|
"withdrawing_cash": gorm.Expr("withdrawing_cash - ?", or.WithdrawCash),
|
||
|
|
"total_withdrawing": gorm.Expr("total_withdrawing - ?", or.Amount),
|
||
|
|
"day_withdraw": gorm.Expr("day_withdraw - ?", or.Amount),
|
||
|
|
}
|
||
|
|
if status == common.StatusROrderFail {
|
||
|
|
updateRe["withdraw_count"] = gorm.Expr("withdraw_count + ?", -1)
|
||
|
|
}
|
||
|
|
err := tx.Model(re).Where("uid = ? and withdrawing_cash >= ? and total_withdrawing >= ?", or.UID, or.WithdrawCash, or.Amount).
|
||
|
|
Updates(updateRe).Error
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err :%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err := UpdateCurrency(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: or.UID,
|
||
|
|
Type: or.CurrencyType,
|
||
|
|
Value: or.WithdrawCash,
|
||
|
|
Event: common.CurrencyEventWithDrawBack,
|
||
|
|
Exs1: or.OrderID,
|
||
|
|
},
|
||
|
|
}, tx); err != nil {
|
||
|
|
log.Error("Withdraw callback err:%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// 退还代付券
|
||
|
|
// if or.Extra == "useFreeWithdraw" {
|
||
|
|
// if err := tx.Model(&common.PlayerItems{UID: uid}).Updates(map[string]interface{}{"free_withdraw": gorm.Expr("free_withdraw + 1")}).Error; err != nil {
|
||
|
|
// log.Error("err:%v", err)
|
||
|
|
// tx.Rollback()
|
||
|
|
// return err
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
if err := tx.Commit().Error; err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
tx.Rollback()
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// 失败的时候才发送邮件
|
||
|
|
// if status == common.StatusROrderFail {
|
||
|
|
// util.Go(func() {
|
||
|
|
// SendWithdrawMail(uid, MailWithdrawType3)
|
||
|
|
// SendRealWithdrawMail(or)
|
||
|
|
// })
|
||
|
|
// }
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func WritePlayerPayData(data *common.ESPlayerPayData) {
|
||
|
|
data.Time = time.Now().Unix()
|
||
|
|
ret, _ := GetUserXInfo(data.UID, "birth")
|
||
|
|
data.IsNew = IsNewPlayer(ret.Birth)
|
||
|
|
data.IsNew = util.IsSameDayTimeStamp(ret.Birth, data.Time)
|
||
|
|
db.ES().InsertToESGO(common.ESIndexBackPlayerPayData, data)
|
||
|
|
}
|
||
|
|
|
||
|
|
// PayExtra 支付extra字段判断
|
||
|
|
func PayExtra(r *common.RechargeOrder) (amount int64) {
|
||
|
|
if len(r.Extra) == 0 {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
extraData := &common.ActivityRechargeData{}
|
||
|
|
json.Unmarshal([]byte(r.Extra), extraData)
|
||
|
|
switch extraData.ID {
|
||
|
|
case common.ItemDiscountTicket:
|
||
|
|
list := GetUserItemByExi1(r.UID, common.ItemDiscountTicket, extraData.I1)
|
||
|
|
if len(list) == 0 {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
item := list[0]
|
||
|
|
rows, err := db.Mysql().UpdateRes(&common.PlayerItems{ID: item.ID, Status: common.ItemStatusNormal},
|
||
|
|
map[string]interface{}{"status": common.ItemStatusInvalid})
|
||
|
|
if err != nil || rows == 0 {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
amount = extraData.I2
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// PayActivity 支付活动
|
||
|
|
func PayActivity(r *common.RechargeOrder, notCharge bool, user *common.PlayerDBInfo) (err error) {
|
||
|
|
// VIP
|
||
|
|
UpdateVip(r.UID, r.Amount, 0, 0)
|
||
|
|
// 检查任务
|
||
|
|
CheckTask(r)
|
||
|
|
// 检查所有活动
|
||
|
|
CheckAllActivity(r)
|
||
|
|
|
||
|
|
// 更新loginrecord
|
||
|
|
if notCharge {
|
||
|
|
InsertLoginRecord(r.UID, r.ChannelID, user.IP, user.Birth, user.Platform)
|
||
|
|
CheckShare(r)
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func CheckTask(r *common.RechargeOrder) {
|
||
|
|
now := time.Now().Unix()
|
||
|
|
con := GetConfigTask()
|
||
|
|
for _, v := range con {
|
||
|
|
if (v.Type == common.TaskTypeOnceRecharge || v.Type == common.TaskTypeFirstRecharge) && r.Amount >= v.Target { // 单次充值任务 || 首次充值任务
|
||
|
|
data := GetUserTaskDataByTaskID(r.UID, v.TaskID)
|
||
|
|
if data.ID == 0 {
|
||
|
|
db.Mysql().Create(&common.TaskData{UID: r.UID, TaskID: v.TaskID, Time: now, Progress: v.Target})
|
||
|
|
} else if data.Progress == 0 {
|
||
|
|
db.Mysql().Update(&common.TaskData{UID: r.UID, TaskID: v.TaskID}, map[string]interface{}{"progress": v.Target, "time": now})
|
||
|
|
}
|
||
|
|
} else if v.Type == common.TaskTypeTotalRecharge { // 累充任务
|
||
|
|
data := GetUserTaskDataByTaskID(r.UID, v.TaskID)
|
||
|
|
if data.ID == 0 {
|
||
|
|
db.Mysql().Create(&common.TaskData{UID: r.UID, TaskID: v.TaskID, Time: now, Progress: r.Amount})
|
||
|
|
} else if data.Progress >= 0 {
|
||
|
|
db.Mysql().Update(&common.TaskData{UID: r.UID, TaskID: v.TaskID}, map[string]interface{}{"progress": gorm.Expr("progress + ?", r.Amount), "time": now})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivityFirstRechargeBack(r *common.RechargeOrder) {
|
||
|
|
now := time.Now().Unix()
|
||
|
|
if IsActivityValid(common.ActivityIDFirstRechargeBack) {
|
||
|
|
rechargeBackData := GetUserFirstRechargeBackData(r.UID)
|
||
|
|
if rechargeBackData.RechargeTime == 0 {
|
||
|
|
db.Mysql().Create(&common.ActivityFirstRechargeBackData{UID: r.UID, RechargeTime: time.Now().Unix(), Amount: r.Amount})
|
||
|
|
} else if now-rechargeBackData.RechargeTime < common.ActivityFirstRechargeBackTime {
|
||
|
|
db.Mysql().Update(&common.ActivityFirstRechargeBackData{UID: r.UID}, map[string]interface{}{"amount": gorm.Expr("amount + ?", r.Amount)})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func CheckAllActivity(r *common.RechargeOrder) {
|
||
|
|
// 首充返还活动
|
||
|
|
ActivityFirstRechargeBack(r)
|
||
|
|
|
||
|
|
var product *common.ConfigPayProduct
|
||
|
|
if r.ProductID > 0 {
|
||
|
|
product = GetConfigPayProductByID(r.ProductID)
|
||
|
|
}
|
||
|
|
// slots奖池活动
|
||
|
|
ActivitySlots(r, product)
|
||
|
|
|
||
|
|
if product == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
switch product.ActivityID {
|
||
|
|
case common.ActivityIDBreakGift:
|
||
|
|
ActivityBreakGift(r, product)
|
||
|
|
case common.ActivityIDWeekCard:
|
||
|
|
ActivityWeekCard(r, product)
|
||
|
|
case common.ActivityIDLuckyShop:
|
||
|
|
ActivityLuckyShop(r, product)
|
||
|
|
case common.ActivityIDSevenDayBox:
|
||
|
|
ActivitySevenDayBox(r, product)
|
||
|
|
case common.ActivityIDSuper:
|
||
|
|
ActivitySuper(r, product)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivityBreakGift(r *common.RechargeOrder, product *common.ConfigPayProduct) {
|
||
|
|
payData := GetPlayerPayData(r.UID)
|
||
|
|
gift := GetConfigActivityBreakGiftByProductID(r.ProductID)
|
||
|
|
if util.SliceContain(payData.SubBreakGift, gift.Level) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
payData.SubBreakGift = append(payData.SubBreakGift, gift.Level)
|
||
|
|
str, _ := json.Marshal(payData.SubBreakGift)
|
||
|
|
rows, err := db.Mysql().UpdateRes(&common.PlayerPayData{UID: r.UID, BreakGift: payData.BreakGift}, map[string]interface{}{"break_gift": string(str)})
|
||
|
|
if rows == 0 || err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
// ok
|
||
|
|
UpdateCurrencyPro(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Value: product.Value,
|
||
|
|
Event: common.CurrencyEventActivityBreakGift,
|
||
|
|
Type: common.CurrencyBrazil,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, product.Value),
|
||
|
|
ChannelID: r.ChannelID,
|
||
|
|
Exi1: product.ProductID,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
UploadActivityData(r.UID, common.ActivityIDBreakGift, common.ActivityDataJoin, product.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivityWeekCard(r *common.RechargeOrder, product *common.ConfigPayProduct) {
|
||
|
|
level := product.Exi
|
||
|
|
card := GetUserWeekCard(r.UID, level)
|
||
|
|
con := GetConfigActivityWeekCardByLevel(level)
|
||
|
|
if con == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if card.ID == 0 {
|
||
|
|
err := db.Mysql().Create(&common.ActivityWeekCardData{
|
||
|
|
UID: r.UID,
|
||
|
|
Level: level,
|
||
|
|
DayReward: con.DayReward,
|
||
|
|
Day: con.Day,
|
||
|
|
// LastDraw: time.Now().Unix(),
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if card.Day > 0 {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
rows, err := db.Mysql().UpdateResW(&common.ActivityWeekCardData{}, map[string]interface{}{
|
||
|
|
"day": con.Day, "day_reward": con.DayReward, "get_discount": 0, "last_draw": 0},
|
||
|
|
fmt.Sprintf("uid = %d and level = %d and day = 0", r.UID, level))
|
||
|
|
if err != nil || rows == 0 {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// ok
|
||
|
|
UpdateCurrencyPro(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Value: product.Value,
|
||
|
|
Event: common.CurrencyEventActivityWeekCard,
|
||
|
|
Type: common.CurrencyBrazil,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, product.Value),
|
||
|
|
ChannelID: r.ChannelID,
|
||
|
|
Exi1: product.ProductID,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
UploadActivityData(r.UID, common.ActivityIDWeekCard, common.ActivityDataJoin, product.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivityLuckyShop(r *common.RechargeOrder, product *common.ConfigPayProduct) {
|
||
|
|
rows, err := db.Mysql().UpdateResW(&common.ActivityLuckyShopData{}, map[string]interface{}{"buy": 1},
|
||
|
|
fmt.Sprintf("uid = %d and product_id = %d and buy = 0", r.UID, product.ProductID))
|
||
|
|
value := product.Value
|
||
|
|
if rows == 0 || err != nil {
|
||
|
|
// 直接给玩家按商品原价加钱
|
||
|
|
value = r.Amount
|
||
|
|
}
|
||
|
|
UpdateCurrencyProReal(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Type: r.CurrencyType,
|
||
|
|
Value: value,
|
||
|
|
Event: common.CurrencyEvent(r.Event),
|
||
|
|
Exs1: r.OrderID,
|
||
|
|
Exi1: int(r.Amount), // 充值金额传递
|
||
|
|
Exi2: r.ProductID,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, value),
|
||
|
|
},
|
||
|
|
})
|
||
|
|
UploadActivityData(r.UID, common.ActivityIDLuckyShop, common.ActivityDataJoin, product.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivitySlots(r *common.RechargeOrder, product *common.ConfigPayProduct) {
|
||
|
|
if !IsActivityValid(common.ActivityIDSlots) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if product != nil && product.ActivityID == common.ActivityIDSlots {
|
||
|
|
if product.Exi > 0 {
|
||
|
|
UpdateUserActivitySlotsData(r.UID, int(product.Exi))
|
||
|
|
}
|
||
|
|
UpdateCurrencyProReal(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Type: r.CurrencyType,
|
||
|
|
Value: product.Value,
|
||
|
|
Event: common.CurrencyEvent(r.Event),
|
||
|
|
Exs1: r.OrderID,
|
||
|
|
Exi1: int(r.Amount), // 充值金额传递
|
||
|
|
Exi2: r.ProductID,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, product.Value),
|
||
|
|
},
|
||
|
|
})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
count := r.Amount / 1000000000
|
||
|
|
if count >= 1 {
|
||
|
|
UpdateUserActivitySlotsData(r.UID, int(count))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivitySevenDayBox(r *common.RechargeOrder, product *common.ConfigPayProduct) {
|
||
|
|
data := &common.ActivitySevenDayBoxData{UID: r.UID}
|
||
|
|
db.Mysql().Get(data)
|
||
|
|
now := time.Now().Unix()
|
||
|
|
value := product.Value
|
||
|
|
if util.IsSameDayTimeStamp(now, data.Time) { // 一天只能买一次
|
||
|
|
value = r.Amount
|
||
|
|
} else {
|
||
|
|
if data.ID == 0 {
|
||
|
|
data.Time = now
|
||
|
|
data.Count = 1
|
||
|
|
err := db.Mysql().Create(data)
|
||
|
|
if err != nil {
|
||
|
|
value = r.Amount
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
rows, err := db.Mysql().UpdateResW(&common.ActivitySevenDayBoxData{}, map[string]interface{}{"count": gorm.Expr("count + 1"), "time": now},
|
||
|
|
fmt.Sprintf("uid = %d and count = %d and time = %d", r.UID, data.Count, data.Time))
|
||
|
|
if rows == 0 || err != nil {
|
||
|
|
// 直接给玩家按商品原价加钱
|
||
|
|
value = r.Amount
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if value > 0 {
|
||
|
|
UpdateCurrencyProReal(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Type: r.CurrencyType,
|
||
|
|
Value: value,
|
||
|
|
Event: common.CurrencyEvent(r.Event),
|
||
|
|
Exs1: r.OrderID,
|
||
|
|
Exi1: int(r.Amount), // 充值金额传递
|
||
|
|
Exi2: r.ProductID,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, value),
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func ActivitySuper(r *common.RechargeOrder, product *common.ConfigPayProduct) {
|
||
|
|
data := GetUserActivitySuperData(r.UID)
|
||
|
|
value := product.Value
|
||
|
|
if !data.CanBuy {
|
||
|
|
value = r.Amount
|
||
|
|
} else {
|
||
|
|
rows, err := db.Mysql().UpdateResW(&common.ActivitySuperData{}, map[string]interface{}{"open": 0, "time": time.Now().Unix()},
|
||
|
|
fmt.Sprintf("uid = %d and time = %d", r.UID, data.Time))
|
||
|
|
if rows == 0 || err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
value = r.Amount
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if value > 0 {
|
||
|
|
UpdateCurrencyProReal(&common.UpdateCurrency{
|
||
|
|
CurrencyBalance: &common.CurrencyBalance{
|
||
|
|
UID: r.UID,
|
||
|
|
Type: r.CurrencyType,
|
||
|
|
Value: value,
|
||
|
|
Event: common.CurrencyEvent(r.Event),
|
||
|
|
Exs1: r.OrderID,
|
||
|
|
Exi1: int(r.Amount), // 充值金额传递
|
||
|
|
Exi2: r.ProductID,
|
||
|
|
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, value),
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type IFSCRet struct {
|
||
|
|
Ifsc string `json:"IFSC"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func CheckIFSC(ifsc string) bool {
|
||
|
|
ret := &IFSCRet{}
|
||
|
|
client := http.Client{
|
||
|
|
Timeout: 2 * time.Second,
|
||
|
|
}
|
||
|
|
url := config.GetConfig().Web.IFSCURL + "/" + ifsc
|
||
|
|
log.Debug("url:%v", url)
|
||
|
|
resp, err := client.Get(url)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("get err:%v", err)
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
// if resp.StatusCode != http.StatusOK {
|
||
|
|
// log.Error("req fail err code:%v", resp.StatusCode)
|
||
|
|
// return true
|
||
|
|
// }
|
||
|
|
defer resp.Body.Close()
|
||
|
|
data, err := ioutil.ReadAll(resp.Body)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("read err %v", err)
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
json.Unmarshal(data, ret)
|
||
|
|
return ret.Ifsc != ""
|
||
|
|
}
|
||
|
|
|
||
|
|
func GetTotalRechargePer(thisWithdraw int64) int64 {
|
||
|
|
zero := util.GetZeroTime(time.Now()).Unix()
|
||
|
|
recharge := db.Mysql().Sum(&common.RechargeOrder{}, fmt.Sprintf("create_time >= %d and event = %d and status = %d", zero, common.CurrencyEventReCharge, common.StatusROrderPay), "amount")
|
||
|
|
withdraw := db.Mysql().Sum(&common.WithdrawOrder{}, fmt.Sprintf("create_time >= %d and event = %d and status = %d", zero, common.CurrencyEventWithDraw, common.StatusROrderFinish), "amount")
|
||
|
|
withdraw += thisWithdraw
|
||
|
|
if recharge == 0 {
|
||
|
|
return withdraw * 100 / common.DecimalDigits
|
||
|
|
}
|
||
|
|
return withdraw * 100 / recharge
|
||
|
|
}
|