diff --git a/call/config.go b/call/config.go index 303bed1..6ec9a34 100644 --- a/call/config.go +++ b/call/config.go @@ -549,7 +549,7 @@ func LoadGames() (err error) { for _, v := range tmplist { for _, k := range providers { if v.GameProvider == k.ProviderID { - if k.Open == 1 { + if v.GameProvider == common.ProviderPG2 || k.Open == 1 { // 特殊过滤 list = append(list, v) } break @@ -712,6 +712,9 @@ func GetConfigGameList(num int, cond ...int) []*common.ConfigGameList { continue } } + if v.GameProvider == common.ProviderPG2 { + continue + } ret = append(ret, v) if num > 0 && len(ret) >= num { return ret diff --git a/common/provider.go b/common/provider.go index 5cf39f1..188be5e 100644 --- a/common/provider.go +++ b/common/provider.go @@ -35,6 +35,7 @@ const ( ProviderJDB ProviderCMD368 ProviderSBO + ProviderPG2 ProviderAll ) diff --git a/modules/web/handler/firstpage.go b/modules/web/handler/firstpage.go index 9662bdd..814d7a1 100644 --- a/modules/web/handler/firstpage.go +++ b/modules/web/handler/firstpage.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "math/rand" "server/call" "server/common" "server/db" @@ -73,9 +72,9 @@ func FirstPage(c *gin.Context) { one.List = call.GetConfigGameList(gameNum, 0, v.JumpID) } if gameNum != req.GameNum { - rand.Shuffle(len(one.List), func(i, j int) { - one.List[i], one.List[j] = one.List[j], one.List[i] - }) + // rand.Shuffle(len(one.List), func(i, j int) { + // one.List[i], one.List[j] = one.List[j], one.List[i] + // }) if len(one.List) > req.GameNum { one.List = one.List[:req.GameNum] } diff --git a/modules/web/handler/game.go b/modules/web/handler/game.go index a2f9618..4703ef4 100644 --- a/modules/web/handler/game.go +++ b/modules/web/handler/game.go @@ -2,6 +2,7 @@ package handler import ( "fmt" + "math/rand" "server/call" "server/common" "server/db" @@ -81,6 +82,18 @@ func EnterGame(c *gin.Context) { resp.Method = provider.Method } a.Data = resp + // step:特殊逻辑处理 + if req.Provider == common.ProviderPGSoft { + a.Code = values.CodeParam + a.Msg = "Under Maintenance,please try later." + return + provider = call.GetConfigGameProvider(common.ProviderPG2) + game := call.GetConfigGameListByID(common.ProviderPG2, req.GameID) + if game != nil && game.Open == 1 && rand.Intn(100) < 100 { + req.Provider = common.ProviderPG2 + resp.Method = provider.Method + } + } if req.IsDemo { log.Debug("player enter demo game %+v", *req) enter := &base.EnterGameReq{ diff --git a/modules/web/providers/all/all.go b/modules/web/providers/all/all.go index cbb3720..a809053 100644 --- a/modules/web/providers/all/all.go +++ b/modules/web/providers/all/all.go @@ -7,6 +7,7 @@ import ( "server/db" "server/modules/web/providers/base" "server/modules/web/providers/gs" + "server/modules/web/providers/pg2" "server/modules/web/providers/pgsoft" "server/modules/web/providers/tada" @@ -47,6 +48,7 @@ type AllProvider struct { JDB func(b *base.Base) CMD368 func(b *base.Base) SBO func(b *base.Base) + PG2 func(b *base.Base) } var All = &AllProvider{} @@ -87,6 +89,7 @@ func initAll() { All.JDB = gs.NewSub All.CMD368 = gs.NewSub All.SBO = gs.NewSub + All.PG2 = pg2.NewSub } func InitRouter(r *gin.RouterGroup) { diff --git a/modules/web/providers/pg2/api.go b/modules/web/providers/pg2/api.go new file mode 100644 index 0000000..6491e49 --- /dev/null +++ b/modules/web/providers/pg2/api.go @@ -0,0 +1,144 @@ +package pg2 + +import ( + "fmt" + "server/common" + "server/db" + "server/util" + "strconv" + "time" +) + +const ( + ErrCodeSuccess = 0 + ErrCodePlayerNotFound = 2000 // 玩家不存在 + ErrCodePlayerToken = 2001 // Token错误 + ErrCodeInvalidGameID = 102 // 无效的GameDI + ErrCodeInternalError = 3000 // 内部错误 + ErrCodeInsufficientBal = 2010 // 投注失败,如余额不足 +) + +type GameListResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data GameListData `json:"data"` +} + +type GameListData struct { + GameList []GameListItem `json:"glist"` +} + +type GameListItem struct { + Icon string `json:"icon"` + MapID string `json:"mapid"` + Name string `json:"name"` + Site string `json:"site"` + GameID string `json:"gameid"` +} + +// EnterGameRequest 进入游戏 +type EnterGameRequest struct { + Uname string `json:"uname"` + GameID string `json:"gameid"` + Token string `json:"token,omitempty"` + Lang string `json:"lang,omitempty"` + Nick string `json:"nick,omitempty"` +} + +type EnterGameResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + GameURL string `json:"gameurl"` + } `json:"data"` +} + +// PlaceBetRequest 下注 +type PlaceBetRequest struct { + Uname string `json:"uname"` + Token string `json:"token"` + BetID string `json:"betid"` + SessionID string `json:"sessionid"` + GameID string `json:"gameid"` + Bet float64 `json:"bet"` + Award float64 `json:"award"` + IsEndRound bool `json:"is_end_round"` + Ctime int64 `json:"ctime"` +} + +type PlaceBetResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + Uname string `json:"uname"` + BetID string `json:"betid"` + Balance float64 `json:"balance"` + } `json:"data"` +} + +type VerifySessionReq struct { + Uname string `json:"uname"` + Token string `json:"token"` +} + +type VerifySessionResp struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + Uname string `json:"uname"` + Balance float64 `json:"balance"` + } `json:"data"` +} + +type GetBalanceRequest struct { + GameId string `json:"gameid"` + Uname string `json:"uname"` +} + +type GetBalanceResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + Uname string `json:"uname"` + Balance float64 `json:"balance"` + } `json:"data"` +} + +func GetGameList() { + API = APITest + AgentMap = AgentMapTest + url := fmt.Sprintf("%s/api/game/loadlist", APITest) + mchid := "" + key := "" + timestamp := time.Now().Unix() + headers := map[string]string{ + "X-Atgame-Mchid": mchid, + "X-Atgame-Timestamp": strconv.FormatInt(timestamp, 10), + "Content-Type": "application/json;charset=UTF-8", + } + type empty struct{} + var e empty + // Generate sign + emptyBody := "{}" + sign := GenerateSign(emptyBody, timestamp, key) + headers["X-Atgame-Sign"] = sign + + var response GameListResponse + err := util.HttpPost(url, e, &response, headers) + if err != nil { + return + } + + var gameList []*common.ConfigGameList + for _, item := range response.Data.GameList { + id, _ := strconv.Atoi(item.MapID) + gameList = append(gameList, &common.ConfigGameList{ + GameProvider: common.ProviderPG2, + GameID: id, + GameCode: item.GameID, + Icon: item.Icon, + Name: item.Name, + }) + } + db.Mysql().Create(gameList) +} diff --git a/modules/web/providers/pg2/base.go b/modules/web/providers/pg2/base.go new file mode 100644 index 0000000..ecaaa06 --- /dev/null +++ b/modules/web/providers/pg2/base.go @@ -0,0 +1,94 @@ +package pg2 + +import ( + "encoding/json" + "fmt" + "server/call" + "server/common" + "server/config" + "server/modules/web/providers/base" + utils "server/util" + "strconv" + "time" + + "github.com/liangdas/mqant/log" +) + +type Sub struct { + Base *base.Base +} + +func NewSub(base *base.Base) { + base.Sub = &Sub{Base: base} + base.SubInitRouter = PG +} + +func (s *Sub) Init() { + API = APITest + AgentMap = AgentMapTest + if config.GetBase().Release { + API = APIRlease + AgentMap = AgentMapRelease + } +} + +func (s *Sub) EnterGame() string { + url := fmt.Sprintf("%s/api/usr/ingame", API) + timestamp := time.Now().Unix() + uid := s.Base.EnterGameReq.UID + token := s.Base.EnterGameReq.Token + providerID := s.Base.EnterGameReq.ProviderID + gameID := s.Base.EnterGameReq.GameID + /** + 玩家再次点击游戏,根据玩家盈利倍数(盈利倍数=(玩家余额+已提现金额)/玩家总充值金额),调取假PG不同档位的接口: + 1、盈利倍数≤1,进入90%档位 + 2、盈利倍数1-7,进入80%档位 + 3、盈利倍数7-10,进入60%档位 + 4、盈利倍数≥10,进入30%档位 + */ + rechargeInfo := call.GetRechargeInfo(uid) + cash := call.GetUserCurrency(uid, common.CurrencyINR) + earnBet := (rechargeInfo.TotalWithdraw + cash) / rechargeInfo.TotalRecharge + log.Info("uid:%d,earnBet:%d", uid, earnBet) + mchid := "" + key := "" + if earnBet <= 7 { + mchid = AgentMap[80].MchId + key = AgentMap[80].Key + } else if earnBet <= 10 { + mchid = AgentMap[60].MchId + key = AgentMap[60].Key + } else { + mchid = AgentMap[30].MchId + key = AgentMap[30].Key + } + headers := map[string]string{ + "X-Atgame-Mchid": mchid, + "X-Atgame-Timestamp": strconv.FormatInt(timestamp, 10), + "Content-Type": "application/json;charset=UTF-8", + } + // Generate sign + game := call.GetConfigGameListByID(providerID, gameID) + if game == nil { + return "" + } + request := EnterGameRequest{ + Uname: fmt.Sprintf("%d", uid), + GameID: game.GameCode, + Token: token, + Lang: Lang, + Nick: "", + } + body, _ := json.Marshal(request) + sign := GenerateSign(string(body), timestamp, key) + headers["X-Atgame-Sign"] = sign + // Decode response + var response EnterGameResponse + err := utils.HttpPost(url, request, &response, headers) + if err != nil { + log.Error("err:%v", err) + return "" + } + + return response.Data.GameURL +} diff --git a/modules/web/providers/pg2/handler.go b/modules/web/providers/pg2/handler.go new file mode 100644 index 0000000..9a36947 --- /dev/null +++ b/modules/web/providers/pg2/handler.go @@ -0,0 +1,143 @@ +package pg2 + +import ( + "server/call" + "server/common" + "server/db" + "server/modules/web/app" + "server/modules/web/providers/base" + "server/util" + "strconv" + "time" + + "github.com/gin-gonic/gin" + "github.com/liangdas/mqant/log" +) + +func PG(e *gin.RouterGroup) { + e.POST("/VerifySession", VerifySession) + e.POST("/Cash/Get", GetPlayerBalance) + e.POST("/Cash/Bet", PlaceBet) +} + +func GetGameID(providerID int, gameCode string) int { + game := call.GetConfigGameListByCode(providerID, gameCode) + if game != nil { + return game.GameID + } + return 0 +} + +func VerifySession(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.ResponseB() + }() + req := &VerifySessionReq{} + resp := &VerifySessionResp{} + a.RetData = resp + if !a.SB(req) { + resp.Code = ErrCodeInternalError + return + } + log.Debug("VerifySession req:%+v", req) + uid, err := strconv.Atoi(req.Uname) + if err != nil { + log.Error("err:%v", err) + resp.Code = ErrCodePlayerNotFound + return + } + + currency, err := db.Redis().GetInt(common.GetRedisKeyGameCurrency(uid)) + if err != nil { + log.Error("err:%v", err) + resp.Code = ErrCodeInternalError + return + } + + resp.Data.Balance = call.GetUserCurrencyFloat(uid, common.CurrencyType(currency), 2) + + a.Data = resp +} + +func GetPlayerBalance(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.ResponseB() + }() + req := &GetBalanceRequest{} + resp := &GetBalanceResponse{} + a.RetData = resp + if !a.SB(req) { + resp.Code = ErrCodeInternalError + return + } + log.Debug("GetPlayerBalance req:%+v", req) + uid, err := strconv.Atoi(req.Uname) + if err != nil { + log.Error("err:%v", err) + resp.Code = ErrCodePlayerNotFound + return + } + + currency, err := db.Redis().GetInt(common.GetRedisKeyGameCurrency(uid)) + if err != nil { + log.Error("err:%v", err) + resp.Code = ErrCodeInternalError + return + } + resp.Data.Uname = req.Uname + resp.Data.Balance = call.GetUserCurrencyFloat(uid, common.CurrencyType(currency), 2) + a.Data = resp +} + +func PlaceBet(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.ResponseB() + }() + req := &PlaceBetRequest{} + resp := &PlaceBetResponse{} + a.RetData = resp + if !a.SB(req) { + resp.Code = ErrCodeInternalError + return + } + log.Debug("PlaceBet:%+v", req) + // 验证token + uid, _ := db.Redis().GetInt(common.GetRedisKeyToken(req.Token)) + if uid == 0 { + resp.Code = ErrCodePlayerNotFound + return + } + + provider := call.GetConfigGameProvider(common.ProviderPG2) + now := time.Now().Unix() + betReq := &base.BetReq{ + UID: uid, + CurrencyType: common.CurrencyINR, + BetAmount: int64(req.Bet * common.DecimalDigits), + TurnOver: int64(req.Bet * common.DecimalDigits), + SettleAmount: int64(req.Award * common.DecimalDigits), + SessionType: common.SessionTypeSettle, + GameID: GetGameID(common.ProviderPG2, req.GameID), + GameName: req.GameID, + Provider: provider, + BetID: req.BetID, + SessionID: req.SessionID, + Time: now, + } + betResp := base.SessionBet(betReq) + if betResp.Code != base.CodeOk { + resp.Code = ErrCodeInternalError + if betResp.Code == base.CodeAccepted { + resp.Code = ErrCodeInternalError + } else if betResp.Code == base.CodeNotEnoughAmount { + resp.Code = ErrCodeInsufficientBal + } + return + } + resp.Data.Balance = util.Decimal(float64(betResp.Balance)/common.DecimalDigits, 2) + + a.Data = resp +} diff --git a/modules/web/providers/pg2/sign.go b/modules/web/providers/pg2/sign.go new file mode 100644 index 0000000..41e3bd1 --- /dev/null +++ b/modules/web/providers/pg2/sign.go @@ -0,0 +1,14 @@ +package pg2 + +import ( + "crypto/md5" + "encoding/hex" + "strconv" + "strings" +) + +func GenerateSign(body string, timestamp int64, key string) string { + data := body + strconv.FormatInt(timestamp, 10) + key + hash := md5.Sum([]byte(data)) + return strings.ToUpper(hex.EncodeToString(hash[:])) +} diff --git a/modules/web/providers/pg2/values.go b/modules/web/providers/pg2/values.go new file mode 100644 index 0000000..f7b1957 --- /dev/null +++ b/modules/web/providers/pg2/values.go @@ -0,0 +1,55 @@ +package pg2 + +const ( + APIRlease = "https://openapi-br.atgameapp.com/pub" + APITest = "https://openapi.windygame.net/demo" + LaunchGameURL = "/api/usr/ingame" + GetGameListURL = "/api/game/loadlist" + Lang = "pt" +) + +type Agent struct { + MchId string `json:"mch_id"` + Key string `json:"key"` +} + +var ( + API = "" + AgentMap map[int]Agent + AgentMapTest = map[int]Agent{ + 90: { + "10055", + "170779CCC5E9FE29DBB3F5FEDBB304A0", + }, + 80: { + "10055", + "170779CCC5E9FE29DBB3F5FEDBB304A0", + }, + 60: { + "10055", + "170779CCC5E9FE29DBB3F5FEDBB304A0", + }, + 30: { + "10055", + "170779CCC5E9FE29DBB3F5FEDBB304A0", + }, + } + AgentMapRelease = map[int]Agent{ + 90: { + "10270", + "ECFEF01A0842C8F7BC9A4EFC089D7E6D", + }, + 80: { + "10269", + "0A18B714E125D9C99ABC41E7124D1B15", + }, + 60: { + "10268", + "AC846D0F6C83C2F65A7B07AB530DB978", + }, + 30: { + "10267", + "30C9928DC1240B507889D4768A186139", + }, + } +)