package webapi import ( "bytes" "crypto/tls" "errors" "fmt" "io" "net" "net/http" "net/url" "strconv" "strings" "sync/atomic" "time" "google.golang.org/protobuf/proto" "mongo.games.com/game/common" webapi_proto "mongo.games.com/game/protocol/webapi" "mongo.games.com/goserver/core/logger" ) const ( XHJ_StartGameUrl = "rocket/game_srv_third/register_or_login" XHJ_ExitGameUrl = "rocket/game_srv_third/login_out" ) type XHJThridPlatform struct { ThirdPlatformBase } func (this *XHJThridPlatform) InitMappingRelation(db map[int32]*WebAPI_ThirdPlatformGameMapping) { this.GamefreeIdMappingInfo = make(map[int32]*WebAPI_ThirdPlatformGameMapping) this.ThirdgameIdMappingInfo = make(map[string]*WebAPI_ThirdPlatformGameMapping) for _, v := range db { if v.ThirdPlatformName == this.Name { this.GamefreeIdMappingInfo[v.GameFreeID] = v this.ThirdgameIdMappingInfo[v.ThirdGameID] = v } } } func (this *XHJThridPlatform) GamefreeId2ThirdGameInfo(gamefreeid int32) (thirdInfo *WebAPI_ThirdPlatformGameMapping) { if v, exist := this.GamefreeIdMappingInfo[gamefreeid]; exist { return v } return } func (this *XHJThridPlatform) ThirdGameInfo2GamefreeId(thirdInfo *WebAPI_ThirdPlatformGameMapping) (gamefreeid int32) { if thirdInfo != nil { for _, v := range this.GamefreeIdMappingInfo { if thirdInfo.Desc == v.Desc { return v.GameFreeID } } } return 0 } func (this *XHJThridPlatform) GetPlatformBase() ThirdPlatformBase { return this.ThirdPlatformBase } func (this *XHJThridPlatform) ReqCreateAccount(Snid int32, Platform, Channel, ip string) error { return nil } func (this *XHJThridPlatform) ReqUserBalance(Snid int32, Platform, Channel, ip string) (err error, balance int64) { pack := &webapi_proto.SARocketLoginOut{ Snid: int64(Snid), Platform: Platform, } buff, err := this.postRequest(common.GetAppId(), XHJ_ExitGameUrl, nil, pack, "http", DEFAULT_TIMEOUT) if err != nil { return err, 0 } ar := webapi_proto.ASRocketLoginOut{} err = proto.Unmarshal(buff, &ar) if err != nil { return errors.New(ar.Msg), 0 } logger.Trace("XHJReqUserBalance Return:", Snid, ar.Amount) return err, int64(ar.Amount) // return nil, 0 } func (this *XHJThridPlatform) ReqIsAllowTransfer(Snid int32, Platform, Channel string) bool { return true } func (this *XHJThridPlatform) ReqCheckTransferIsSuccess(Snid int32, TransferId string, Platform, Channel string) error { return nil } func (this *XHJThridPlatform) ReqTransfer(Snid int32, Amount int64, TransferId string, Platform, Channel, ip string) (e error, timeout bool) { return nil, false } func (this *XHJThridPlatform) ReqEnterGame(Snid int32, gameid string, clientIP string, Platform, Channel string, amount int64) (err error, ret_url string) { pack := &webapi_proto.SARocketLogin{ Snid: int64(Snid), Amount: amount, Platform: Platform, } buff, err := this.postRequest(common.GetAppId(), XHJ_StartGameUrl, nil, pack, "http", DEFAULT_TIMEOUT) //DEFAULT_TIMEOUT if err != nil { return err, "" } ar := webapi_proto.ASRocketLogin{} err = proto.Unmarshal(buff, &ar) if err == nil && ar.Url == "" { return errors.New(ar.Msg), "" } logger.Trace("XHJReqEnterGame Return:", Snid, ar.Url) return err, ar.Url } func (this *XHJThridPlatform) ReqLeaveGame(Snid int32, gameid string, clientIP string, Platform, Channel string) (err error, amount int64) { pack := &webapi_proto.SARocketLoginOut{ Snid: int64(Snid), Platform: Platform, } buff, err := this.postRequest(common.GetAppId(), XHJ_ExitGameUrl, nil, pack, "http", DEFAULT_TIMEOUT) if err != nil { return err, 0 } ar := webapi_proto.ASRocketLoginOut{} err = proto.Unmarshal(buff, &ar) if err != nil { return errors.New("proto.Unmarshal error"), 0 } if ar.Tag == 2 { //请求失败 return errors.New(ar.Msg), 0 } logger.Trace("XHJReqLeaveGame Return:", Snid, ar.Amount) return err, int64(ar.Amount) } func (this *XHJThridPlatform) MappingGameName(snid int32) string { return strconv.Itoa(int(snid)) + "_XHJ" } func (this *XHJThridPlatform) postRequest(appId, action string, params map[string]string, body proto.Message, protocol string, dura time.Duration) ([]byte, error) { var client *http.Client if strings.ToUpper(protocol) == "HTTPS" { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client = &http.Client{Transport: tr} } else { client = &http.Client{} } data, err := proto.Marshal(body) if err != nil { return nil, err } callUrl := makeURL(appId, action, params, data) //println("callurl=", callUrl) req, err := http.NewRequest("POST", callUrl, bytes.NewBuffer(data)) if err != nil { return nil, err } var stats *ApiStats if v, exist := WebApiStats.Load(action); exist { stats = v.(*ApiStats) } else { stats = &ApiStats{} WebApiStats.Store(action, stats) } var isTimeout bool start := time.Now() defer func() { ps := int64(time.Now().Sub(start) / time.Millisecond) if stats != nil { if isTimeout { atomic.AddInt64(&stats.TimeoutTimes, 1) } atomic.AddInt64(&stats.RunTimes, 1) atomic.AddInt64(&stats.TotalRuningTime, ps) if atomic.LoadInt64(&stats.MaxRuningTime) < ps { atomic.StoreInt64(&stats.MaxRuningTime, ps) } } }() //设置超时 client.Timeout = dura req.Close = true resp, err := client.Do(req) if err != nil { if uerr, ok := err.(net.Error); ok { isTimeout = uerr.Timeout() } logger.Logger.Errorf(" postRequest Timeout: %v", err) return nil, ErrRequestTimeout } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } return body, err } //println("callurl=", callUrl, "code=", resp.StatusCode) return nil, fmt.Errorf("StatusCode:%d", resp.StatusCode) } // 生成请求串 func makeURL(appId, action string, params map[string]string, data []byte) string { var buf bytes.Buffer buf.WriteString(ReqCgAddr) buf.WriteString(action) buf.WriteString("?") if len(params) > 0 { for k, v := range params { buf.WriteString(k) buf.WriteString("=") buf.WriteString(url.QueryEscape(v)) buf.WriteString("&") } } ts := time.Now().Nanosecond() buf.WriteString("nano=" + strconv.Itoa(ts) + "&") buf.WriteString("sign=") buf.WriteString(url.QueryEscape(MakeSig(appId, action, params, data, ts))) return buf.String() }