package model import ( "crypto/md5" "encoding/base64" "encoding/json" "fmt" "github.com/gin-gonic/gin" "net/http" "rocommon" "rocommon/rpc" "rocommon/service" "rocommon/socket" "rocommon/util" "strconv" "strings" "sync" ) type ServiceParam struct { ServiceName string ServiceType string //tcpAcceptor /tcpConnector ProcName string LisAddr string DiscoveryServiceName string //用于服务器发现 DiscoveryServiceZone int //用于服务器发现 } var ( httpParamMutex sync.RWMutex HttpNodeParam *ServiceParam ) func GetHttpNodeParam() ServiceParam { httpParamMutex.RLock() defer httpParamMutex.RUnlock() return *HttpNodeParam } func SetHttpNodeParam(param *ServiceParam) { httpParamMutex.Lock() defer httpParamMutex.Unlock() HttpNodeParam = param } func CreateHttpConnector(param ServiceParam) rocommon.ServerNode { if param.ServiceType == "" { param.ServiceType = "httpConnector" } node := socket.NewServerNode(param.ServiceType, param.ServiceName, param.LisAddr, nil) return node } /////////////////////////////////////////////////////////////// const ( SDKPlatform_Quick = "SDKQuick" SDKPlatform_NBSDK = "SDKNB" SDKPlatform_UniSDK = "SDKUni" //SDKUni SDKPlatform_YouYi = "SDKYOUYI" SDKPlatform_YouYi_IOS = "SDKYOUYI_IOS" ) // 区分不同平台 func ConvertPlatform(openId, platform string) string { if platform == SDKPlatform_YouYi || platform == SDKPlatform_YouYi_IOS { //除了quick和nb其他渠道都要加上渠道标识 openId = platform + openId } return openId } func SDKCheck(c *gin.Context) { platform := c.DefaultQuery("platform", "") ///default "" sdkUid := c.DefaultQuery("sdkuid", "") ///default "" sauthJson := c.DefaultQuery("sauthjson", "") ///default "" serverId := c.DefaultQuery("sid", "") ///default "" subPlatform := c.DefaultQuery("subplatform", "") ///default "" retSt := &UniSDKLoginClient{ Code: 1, Platform: platform, } if platform != "" { switch platform { case SDKPlatform_Quick: case SDKPlatform_NBSDK: case SDKPlatform_UniSDK: SDKUniCheck(sdkUid, sauthJson, serverId, c) case SDKPlatform_YouYi: fallthrough case SDKPlatform_YouYi_IOS: SDKYouYiCheck(sauthJson, c, subPlatform, platform) default: c.JSON(http.StatusOK, retSt) } } else { c.JSON(http.StatusOK, retSt) } } //SDK UniSDK type SDKUniLoginAuthCheckReq struct { GameId string `json:"gameid""` //游戏id(手游即游戏代号,小写) HostId int `json:"hostid"` //大于等于0, 游戏服务器id(指游戏划分的区服),如果有则传,没有传0 LoginChannel string `json:"login_channel"` //登录渠道( 如用网易sdk登录login_channel=netease,苹果支付pay_chan nel=app_store) AppChannel string `json:"app_channel"` //发行(分发)渠道,支持多级结构,通过UniSDK获取。格式如:netease.gs.123456 Platform string `json:"platform"` //平台名 Ip string `json:"ip"` //游戏登录时客户端用户ip, 形如255.255.255.255 SdkUid string `json:"sdkuid"` //渠道uid,不需要包含域名, 有些渠道的uid中包含有@符号 | wechat_mp_vr渠道传openid SessionId string `json:"sessionid"` //sdk返回的session SDKVersion string `json:"sdk_version"` //接入渠道sdk的版本号,从UniSDK获取 Udid string `json:"udid"` //玩家登录的移动设备号,通过UniSDK提供的接口获取 } type SDKUniLoginAuthCheckResp struct { Code int `json:"code"` //接口返回码 SubCode int `json:"subcode"` //接口返回子码 Status string `json:"status"` //接口调用状态 UniSDKLoginJson string `json:"unisdk_login_json"` Aid int `json:"aid"` AasMsg UniSDKLoginAasMsgSt `json:"aas_msg"` //aas_msg RetCode string ClientId uint64 ServiceId string OpenId string } type UniSDKLoginJsonSt struct { Aid string `json:"aid"` Sdkuid string `json:"sdkUid"` Username string `json:"username"` AccessToken string `json:"access_token"` ExpiresIn string `json:"expires_in"` } type UniSDKLoginAasMsgSt struct { NeedRealNameV2 bool `json:"need_realname_v2"` ReasonV2 string `json:"reason_v2"` NeedRoleEnterV2 bool `json:"need_role_enter_v2"` } //返回给客户端的json结构 type UniSDKLoginClient struct { Code int `json:"code"` //接口返回码 UniSDKLoginJson string `json:"unisdk_login_json"` UserInfo string `json:"userinfo"` //玩家信息包括错误码,aid和过期时间 userinfo.sign //SignInfo string `json:"sign"` //校验信息(userinfo使用aes加密后的结果) Platform string `json:"platform"` //用户平台 } type SDKCheckUserInfo struct { Code int `json:"code"` Aid string `json:"aid"` ExpireTime uint64 `json:"expiretime"` LoginChannel string `json:"login_channel"` //登录渠道( 如用网易sdk登录login_channel=netease,苹果支付pay_chan nel=app_store) AppChannel string `json:"app_channel"` //发行(分发)渠道,支持多级结构,通过UniSDK获取。格式如:netease.gs.123456 EnterSN string `json:"enter_sn"` } var sdkUniSignAesKey = []byte("wenting123456789") func SDKUniCheck(sdkUid, sauthJson, sid string, c *gin.Context) { tmpRequest := &rocommon.HTTPRequest{} tmpRequest.ReqCodecName = "httpjson" //sauthJson解析并替换 //sauthJson = strings.Replace(sauthJson, "\\", "", -1) authHttpAddr := service.GetServiceConfig().SDKConfig.UniHttpAddr ip := c.ClientIP() serverId, _ := strconv.Atoi(sid) tmpKVList := map[string]interface{}{} err := json.Unmarshal([]byte(sauthJson), &tmpKVList) if err != nil { util.InfoF("LoginVerifySignUniSDK sdkuid=%v err=%v", sdkUid, err) c.JSON(http.StatusOK, fmt.Sprintf("invalid sauthjson")) return } tmpKVList["hostid"] = serverId ipStrList := strings.Split(ip, ":") if len(ipStrList) > 0 { tmpKVList["ip"] = ipStrList[0] } tmpRequest.ReqMsg = tmpKVList tmpRequest.ResMsg = &SDKUniLoginAuthCheckResp{} parm := GetHttpNodeParam() parm.LisAddr = authHttpAddr httpNode := CreateHttpConnector(parm) err = httpNode.(rocommon.HTTPConnector).Request("POST", "", tmpRequest) if err != nil { //tmpRequest.ResMsg.(*SDKUniLoginAuthCheckResp).RetCode = "0" util.InfoF("LoginVerifySignUniSDK http Request sdkUid=%v err=%v", sdkUid, err) c.JSON(http.StatusOK, err) return } res := tmpRequest.ResMsg.(*SDKUniLoginAuthCheckResp) if res.AasMsg.NeedRoleEnterV2 { //todo... // 获取enter_sn } retSt := &UniSDKLoginClient{ Code: res.Code, Platform: SDKPlatform_UniSDK, } tmpJson, err := base64.StdEncoding.DecodeString(res.UniSDKLoginJson) if err == nil { loginJsonSt := &UniSDKLoginJsonSt{} err = json.Unmarshal(tmpJson, loginJsonSt) if err == nil { loginChannel := tmpKVList["login_channel"] appChannel := tmpKVList["app_channel"] checkUserInfo := &SDKCheckUserInfo{ Code: res.Code, Aid: loginJsonSt.Aid, ExpireTime: uint64(util.GetTimeSeconds() + 5*60*60), LoginChannel: loginChannel.(string), AppChannel: appChannel.(string), } userInfoData, _ := json.Marshal(checkUserInfo) signInfoData, err := rpc.AESCtrEncrypt(userInfoData, sdkUniSignAesKey, sdkUniSignAesKey...) userInfoStr := base64.StdEncoding.EncodeToString(userInfoData) signInfoStr := base64.StdEncoding.EncodeToString(signInfoData) if err == nil { retSt.UniSDKLoginJson = res.UniSDKLoginJson retSt.UserInfo = userInfoStr + "." + signInfoStr c.JSON(http.StatusOK, retSt) return } } } c.JSON(http.StatusOK, retSt) } type SDKYouYiLoginAuthCheckResp struct { Code int `json:"code"` //接口返回码 Message string `json:"message"` //接口调用状态 //Data []YouYiSDKLoginDataSt `json:"data"` Data interface{} `json:"data"` RetCode string ClientId uint64 ServiceId string OpenId string } type YouYiSDKLoginDataSt struct { CPUid string `json:"cp_uid"` } //返回给客户端的json结构 type YouYiSDKLoginClient struct { Code int `json:"code"` //接口返回码 UserInfo string `json:"userinfo"` //玩家信息包括错误码,aid和过期时间 userinfo.sign //SignInfo string `json:"sign"` //校验信息(userinfo使用aes加密后的结果) Platform string `json:"platform"` //用户平台 } func SDKYouYiCheck(sauthJson string, c *gin.Context, subPlatform, platform string) { tmpRequest := &rocommon.HTTPRequest{} tmpRequest.ReqCodecName = "httpjson" sConfig := service.GetServiceConfig() authHttpAddr := sConfig.SDKConfig.YouYiHttpAddr tmpRequest.ResMsg = &SDKYouYiLoginAuthCheckResp{} gameId := sConfig.SDKConfig.YouYiGameId if platform == SDKPlatform_YouYi_IOS { gameId = sConfig.SDKConfig.YouYiGameIdIOS for idx := 0; idx < len(sConfig.SDKConfig.YouYiGameIdListIOS); idx++ { if strings.Contains(sConfig.SDKConfig.YouYiGameIdListIOS[idx], subPlatform) { idStrList := strings.Split(sConfig.SDKConfig.YouYiGameIdListIOS[idx], ":") if len(idStrList) >= 2 { gameId = idStrList[1] } break } } } else { for idx := 0; idx < len(sConfig.SDKConfig.YouYiGameIdList); idx++ { if strings.Contains(sConfig.SDKConfig.YouYiGameIdList[idx], subPlatform) { idStrList := strings.Split(sConfig.SDKConfig.YouYiGameIdList[idx], ":") if len(idStrList) >= 2 { gameId = idStrList[1] } break } } } authHttpAddr += "?oauth_token=" + sauthJson + "&game_id=" + gameId retSt := &YouYiSDKLoginClient{ Code: 1001, Platform: platform, } parm := GetHttpNodeParam() parm.LisAddr = authHttpAddr httpNode := CreateHttpConnector(parm) err := httpNode.(rocommon.HTTPConnector).Request("GET", "", tmpRequest) if err != nil { //tmpRequest.ResMsg.(*SDKUniLoginAuthCheckResp).RetCode = "0" util.InfoF("SDKYouYiCheck http Request token=%v err=%v", sauthJson, err) c.JSON(http.StatusOK, retSt) return } res := tmpRequest.ResMsg.(*SDKYouYiLoginAuthCheckResp) if res == nil { util.InfoF("SDKYouYiCheck http Request token=%v err=%v", sauthJson, err) retSt.Code = 1002 c.JSON(http.StatusOK, retSt) return } retSt.Code = res.Code if res.Code == 0 { checkUserInfo := &SDKCheckUserInfo{ Code: res.Code, //Aid: res.Data[0].CPUid, Aid: res.Data.(map[string]interface{})["cp_uid"].(string), ExpireTime: uint64(util.GetTimeSeconds() + 5*60*60), LoginChannel: "", AppChannel: "", } userInfoData, _ := json.Marshal(checkUserInfo) signInfoData, err := rpc.AESCtrEncrypt(userInfoData, sdkUniSignAesKey, sdkUniSignAesKey...) userInfoStr := base64.StdEncoding.EncodeToString(userInfoData) signInfoStr := base64.StdEncoding.EncodeToString(signInfoData) if err == nil { retSt.UserInfo = userInfoStr + "." + signInfoStr } else { retSt.Code = 1003 } } c.JSON(http.StatusOK, retSt) } /* * 产品名称:仙境传说RO:初心者大冒险 * 产品代号/专区标识(pid):ma112 * 产品key(salt):E0FE384E5D814644 * 产品语言:中文 */ type UniSdkWebTokenRes struct { Refer string `json:"refer"` Token string `json:"token"` Code int `json:"code"` ExpireTime int64 `json:"expireTime"` Message string `json:"message"` } func UniSdkWebToken(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") ///default "" typeStr := c.DefaultQuery("type", "") ///default "" gameServerStr := c.DefaultQuery("game_server", "") ///default "" gameUidStr := c.DefaultQuery("game_uid", "") ///default "" nickName := c.DefaultQuery("nickname", "") ///default "" osStr := c.DefaultQuery("os", "") ///default "" curTime := util.GetTimeSeconds() webTokenHttpAddr := service.GetServiceConfig().SDKConfig.UniWebTokenAddr pidStr := service.GetServiceConfig().SDKConfig.UniWebPid saltStr := service.GetServiceConfig().SDKConfig.UniWebSalt data := pidStr + uidStr + strconv.FormatInt(curTime, 10) + saltStr md5Str := fmt.Sprintf("%x", md5.Sum([]byte(data))) webTokenHttpAddr += "?uid=" + uidStr + "&pid=" + pidStr + "&type=" + typeStr + "&game_server=" + gameServerStr + "&game_uid=" + gameUidStr + "&nickname=" + nickName + "&sign=" + string(md5Str) + "&time=" + strconv.FormatInt(curTime, 10) + "&os=" + osStr tmpRequest := &rocommon.HTTPRequest{} tmpRequest.ReqCodecName = "httpjson" tmpRequest.ResMsg = &UniSdkWebTokenRes{} parm := GetHttpNodeParam() parm.LisAddr = webTokenHttpAddr httpNode := CreateHttpConnector(parm) err := httpNode.(rocommon.HTTPConnector).Request("GET", "", tmpRequest) if err != nil { //tmpRequest.ResMsg.(*SDKUniLoginAuthCheckResp).RetCode = "0" util.InfoF("LoginVerifySignUniSDK http Request uid=%v err=%v", uidStr, err) c.JSON(http.StatusOK, err) return } resMsg := tmpRequest.ResMsg.(*UniSdkWebTokenRes) c.JSON(http.StatusOK, resMsg) }