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

433 lines
10 KiB

1 year ago
package values
import (
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"server/call"
"server/common"
"server/config"
"server/db"
"server/util"
"sort"
"strings"
"sync"
"github.com/gin-gonic/gin"
"github.com/liangdas/mqant/log"
"gorm.io/gorm"
)
// 支付方式
type PayWay int
const (
InvalidPay PayWay = iota
IGeekPay
PlusPay
LuckinPay
BFPay
Grepay
PayAll
)
// 错误码
const (
CodeOk = iota
)
var (
PayWeightLock = new(sync.RWMutex)
)
// SelectPayWay 特定条件为玩家优先选择渠道
// func SelectPayWay(uid int, amount int64) PayWay {
// if !config.GetConfig().Pay.SelectPayWay {
// return -1
// }
// banList := []int{}
// zlist := db.Redis().ZRange(common.GetRedisKeyPlayerPay(uid))
// for _, v := range zlist {
// banList = append(banList, util.GetInt(v.Member))
// }
// lastSuccess := &common.RechargeOrder{UID: uid, Event: int(common.CurrencyEventReCharge), Status: common.StatusROrderPay}
// err := db.Mysql().GetLast(lastSuccess)
// if err == nil { // 直接按上次成功的渠道作为首选推荐渠道
// if !util.SliceContain(banList, lastSuccess.PayChannel) && IsTopChannel(lastSuccess.PayChannel, 3, amount) {
// return PayWay(lastSuccess.PayChannel)
// }
// }
// banAll := GetValidPayChannelsWithBanList(amount, banList)
// if PayStatus == PayStatusChannel {
// for _, v := range banAll {
// return PayWay(v.ChannelID)
// }
// }
// // 尝试当前权重最高的
// all := GetValidPayChannels(amount)
// if len(all) > 0 {
// if !util.SliceContain(banList, all[0].ChannelID) {
// return PayWay(all[0].ChannelID)
// }
// }
// return GetPayWayWeight(banAll)
// }
// 手动选择模式获取支付渠道
func GetPayWayChannel(index int, all []*common.ConfigPayChannels) (w PayWay) {
if len(all) == 0 {
w = -1
return
}
if index > len(all)-1 || index < 0 {
index = 0
}
w = PayWay(all[index].ChannelID)
return
}
// 权重模式获取支付渠道
func GetPayWayWeight(all []*common.ConfigPayChannels) PayWay {
total := 0
for _, v := range all {
total += v.PayPer
}
if total > 0 {
ran := rand.Intn(total)
rans := 0
for i := 0; i < len(all); i++ {
rans += all[i].PayPer
if ran < rans {
return PayWay(all[i].ChannelID)
}
}
}
return -1
}
// ChoosePayWay 选择充值渠道
// func ChoosePayWay(uid, index int, amount int64) PayWay {
// pw := SelectPayWay(uid, amount)
// if pw >= 0 {
// return pw
// }
// if PayStatus == PayStatusChannel {
// return GetPayWayChannel(index, GetValidPayChannels(amount))
// }
// return GetPayWayWeight(GetValidPayChannels(amount))
// }
func PayFail(w PayWay) {
failWeight := config.GetConfig().Pay.PayFailWeight
if failWeight <= 0 {
return
}
PayWeightLock.Lock()
for _, v := range call.ConfigPayChannels {
if v.ChannelID == int(w) {
v.PayPer -= failWeight
break
}
}
sort.Slice(call.ConfigPayChannels, func(i, j int) bool {
return call.ConfigPayChannels[i].PayPer > call.ConfigPayChannels[j].PayPer
})
PayWeightLock.Unlock()
AddPayChannel(int(w), -failWeight)
}
func PayCallback(w PayWay) {
successWeight := config.GetConfig().Pay.PaySuccessWeight
if successWeight <= 0 {
return
}
PayWeightLock.Lock()
for _, v := range call.ConfigPayChannels {
if v.ChannelID == int(w) {
v.PayPer += successWeight
break
}
}
sort.Slice(call.ConfigPayChannels, func(i, j int) bool {
return call.ConfigPayChannels[i].PayPer > call.ConfigPayChannels[j].PayPer
})
PayWeightLock.Unlock()
AddPayChannel(int(w), successWeight)
}
// 获取支付回调路径
func GetPayCallback(way PayWay) string {
return config.GetConfig().Pay.CallbackURL + config.GetConfig().Pay.Addr + "/callback/pay/" + fmt.Sprintf("%d", way)
}
// 获取退出回调路径
func GetWithdrawCallback(way PayWay) string {
return config.GetConfig().Pay.CallbackURL + config.GetConfig().Pay.Addr + "/callback/withdraw/" + fmt.Sprintf("%d", way)
}
func GetFrontCallback() string {
return config.GetConfig().Pay.CallbackURL + config.GetConfig().Pay.Addr + "/common/front/payCallback"
}
func GetFrontCallbackFail() string {
return config.GetConfig().Pay.CallbackURL + config.GetConfig().Pay.Addr + "/common/front/payCallback/fail"
}
// 根据body里的字段直接拼接出签名字符串
func GetSignStr(str string, pass ...string) string {
m := map[string]json.RawMessage{}
sortStrs := []string{}
json.Unmarshal([]byte(str), &m)
for i := range m {
sortStrs = append(sortStrs, i)
}
signStr := ""
sort.Strings(sortStrs)
for _, v := range sortStrs {
shouldPass := false
for _, s := range pass {
if v == s {
shouldPass = true
break
}
}
if shouldPass {
continue
}
if len(m[v]) > 1 && m[v][0] == 34 {
m[v] = m[v][1 : len(m[v])-1]
}
if len(m[v]) == 0 {
continue
}
signStr += fmt.Sprintf("%v=%v", v, string(m[v]))
signStr += "&"
}
signStr = signStr[:len(signStr)-1]
log.Debug("signStr:%v", signStr)
return signStr
}
// 根据body里的字段直接拼接出签名字符串(去除null)
func GetSignStrNull(str string, pass ...string) string {
m := map[string]json.RawMessage{}
sortStrs := []string{}
json.Unmarshal([]byte(str), &m)
for i := range m {
sortStrs = append(sortStrs, i)
}
signStr := ""
sort.Strings(sortStrs)
for _, v := range sortStrs {
shouldPass := false
for _, s := range pass {
if v == s {
shouldPass = true
break
}
}
if shouldPass {
continue
}
if len(m[v]) > 1 && m[v][0] == 34 {
m[v] = m[v][1 : len(m[v])-1]
}
if len(m[v]) == 0 || string(m[v]) == "null" {
continue
}
signStr += fmt.Sprintf("%v=%v", v, string(m[v]))
signStr += "&"
}
signStr = signStr[:len(signStr)-1]
log.Debug("signStr:%v", signStr)
return signStr
}
// 根据body里的字段直接拼接出签名字符串(包括空字符串)
func GetSignStrAll(str string, pass ...string) string {
m := map[string]json.RawMessage{}
sortStrs := []string{}
json.Unmarshal([]byte(str), &m)
for i := range m {
sortStrs = append(sortStrs, i)
}
signStr := ""
sort.Strings(sortStrs)
for _, v := range sortStrs {
shouldPass := false
for _, s := range pass {
if v == s {
shouldPass = true
break
}
}
if shouldPass {
continue
}
if len(m[v]) > 1 && m[v][0] == 34 {
m[v] = m[v][1 : len(m[v])-1]
}
signStr += fmt.Sprintf("%v=%v", v, string(m[v]))
signStr += "&"
}
signStr = signStr[:len(signStr)-1]
log.Debug("signStr:%v", signStr)
return signStr
}
// 根据body里的字段直接拼接出签名字符串(包括空字符串,unicode转码)
func GetSignStrAllUnicode(str string, pass ...string) string {
m := map[string]json.RawMessage{}
sortStrs := []string{}
json.Unmarshal([]byte(str), &m)
for i := range m {
sortStrs = append(sortStrs, i)
}
signStr := ""
sort.Strings(sortStrs)
for _, v := range sortStrs {
shouldPass := false
for _, s := range pass {
if v == s {
shouldPass = true
break
}
}
if shouldPass {
continue
}
str := string(m[v])
if len(str) > 1 && str[0] == 34 {
str = str[1 : len(str)-1]
}
tmp, err := util.ZhToUnicode(str)
if err == nil {
str = tmp
}
str = strings.ReplaceAll(str, `\`, "")
signStr += fmt.Sprintf("%v=%v", v, str)
signStr += "&"
}
signStr = signStr[:len(signStr)-1]
log.Debug("signStr:%v", signStr)
return signStr
}
func GetSignStrForm(c *gin.Context, pass ...string) string {
sortStrs := []string{}
for k := range c.Request.PostForm {
sortStrs = append(sortStrs, k)
}
signStr := ""
sort.Strings(sortStrs)
for _, v := range sortStrs {
shouldPass := false
for _, s := range pass {
if v == s {
shouldPass = true
break
}
}
if shouldPass {
continue
}
if len(c.PostForm(v)) == 0 {
continue
}
signStr += fmt.Sprintf("%v=%v", v, c.PostForm(v))
signStr += "&"
}
signStr = signStr[:len(signStr)-1]
log.Debug("signStr:%v", signStr)
return signStr
}
// status=1时,属于不知道第三方是什么情况的报错,不能当成业务中断
// status=0时,可以根据返回判断是否是业务错误
func Post(req *http.Request, ret interface{}) int {
client := &http.Client{}
log.Debug("req:%+v", req)
resp, err := client.Do(req)
if err != nil {
log.Error("http post call err:%v", err)
return 1
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
log.Debug("response Body%v:", string(body))
if err := json.Unmarshal(body, ret); err != nil {
log.Error("unmarshal fail err:%v", err)
return 1
}
return 0
}
func AddPayChannel(p int, amount int) {
if err := db.Mysql().C().Model(&common.ConfigPayChannels{}).Where("channel_id = ?", p).Updates(map[string]interface{}{"pay_per": gorm.Expr("pay_per + ?", amount)}).Error; err != nil {
log.Error("err:%v", err)
}
}
func SetPayChannel(p int, amount int) {
if err := db.Mysql().C().Model(&common.ConfigPayChannels{}).Where("channel_id = ?", p).Updates(map[string]interface{}{"pay_per": amount}).Error; err != nil {
log.Error("err:%v", err)
}
}
func GetValidPayChannels(amount int64) []*common.ConfigPayChannels {
PayWeightLock.RLock()
defer PayWeightLock.RUnlock()
all := []*common.ConfigPayChannels{}
for _, v := range call.ConfigPayChannels {
if v.PayPer > 0 && amount >= v.PayDown && (amount <= v.PayUp || v.PayUp <= 0) {
all = append(all, v)
}
}
return all
}
func GetValidPayChannelsWithBanList(amount int64, banList []int) []*common.ConfigPayChannels {
all := []*common.ConfigPayChannels{}
PayWeightLock.RLock()
defer PayWeightLock.RUnlock()
for _, v := range call.ConfigPayChannels {
if v.PayPer > 0 && amount >= v.PayDown && (amount <= v.PayUp || v.PayUp <= 0) {
if !util.SliceContain(banList, v.ChannelID) {
all = append(all, v)
}
}
}
return all
}
func IsPayChannelValid(cid int, amount int64) bool {
PayWeightLock.RLock()
defer PayWeightLock.RUnlock()
for _, v := range call.ConfigPayChannels {
if cid == v.ChannelID {
if v.PayPer > 0 && amount >= v.PayDown && (amount <= v.PayUp || v.PayUp <= 0) {
return true
}
break
}
}
return false
}
// IsTopChannel 判断渠道是否是排名前几的可用渠道
func IsTopChannel(cid, top int, amount int64) bool {
PayWeightLock.RLock()
defer PayWeightLock.RUnlock()
for i := 0; i < top; i++ {
v := call.ConfigPayChannels[i]
if cid == v.ChannelID {
if v.PayPer > 0 && amount >= v.PayDown && (amount <= v.PayUp || v.PayUp <= 0) {
return true
}
}
}
return false
}