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.
 
 
 
 
 
 

479 lines
18 KiB

using System;
using System.Collections.Generic;
using System.Net.Http;
using Sog;
using LitJson;
using ProtoCSStruct;
using Sog.Crypto;
#if true
namespace HttpProxy
{
public class HeroUSDKAccountInfo
{
public string userId;
public string userName;
public int userType;
public string openId;
public string channel;
public int channelId;
public int compensation;
public string bindEmail;
}
public class HeroUSDKAuth
{
// 正式地址
private static string init_loginUrl = "https://hgsdkcdn.herogame.com/hgsrv";
private static string init_getUserInfoUrl = "/v1/login/checkUserInfo.lg";
private static string init_postContentType = "multipart/form-data; boundary=-----------------";
private static string init_amountUrl = "http://47.75.149.207/hgadmin/api/ext/account/amount/query";
private static string _getUserInfoUrl;
private static string _getUserInfoUrlBackup;
private static string _postContentType;
private static string[] _PCODE = new string[(int)HeroUSDKProj.Max];
private static string[] _APP_KEY = new string[(int)HeroUSDKProj.Max];
private static void InitDefaultProjectInfo()
{
// 游戏产品在SDK平台的应用ID, 默认值只是为了方便没有添加配置项的私人服务器
_PCODE[(int)HeroUSDKProj.Min] = "0";
_PCODE[(int)HeroUSDKProj.SEA] = "17310";
_PCODE[(int)HeroUSDKProj.JP] = "17303";
_PCODE[(int)HeroUSDKProj.KR] = "17323";
// 游戏产品在SDK平台的应用私钥, 默认值只是为了方便没有添加配置项的私人服务器
_APP_KEY[(int)HeroUSDKProj.Min] = "invalid_key";
_APP_KEY[(int)HeroUSDKProj.SEA] = "2dl4v39v93dmexqcvxku";
_APP_KEY[(int)HeroUSDKProj.JP] = "7czh206jaoh27zp5cv9x";
_APP_KEY[(int)HeroUSDKProj.KR] = "qqsm0uqbnx2omt2v7ox8";
}
public static void Init(HttpProxyServerConfig config)
{
string loginUrl = config.heroUsdk_loginUrl;
if (! string.IsNullOrEmpty(loginUrl))
{
_getUserInfoUrl = loginUrl + init_getUserInfoUrl;
}
else
{
_getUserInfoUrl = init_loginUrl + init_getUserInfoUrl;
}
//如果配置了本地校验地址,则优先使用本地校验
if(!string.IsNullOrEmpty(config.heroUsdk_loginUrlLocalCheck))
{
_getUserInfoUrl = config.heroUsdk_loginUrlLocalCheck;
}
if(! string.IsNullOrEmpty(config.heroUsdk_loginUrlBackup))
{
_getUserInfoUrlBackup = config.heroUsdk_loginUrlBackup + init_getUserInfoUrl;
}
TraceLog.Trace("HeroUSDKAuth.Init getUserInfoUrl {0}", _getUserInfoUrl);
_postContentType = init_postContentType + DateTime.Now.Ticks.ToString("x");
InitProjectInfo(config);
}
public static void InitProjectInfo(HttpProxyServerConfig config)
{
// 默认使用代码中的默认值, 方便没有配置的私人服务器
InitDefaultProjectInfo();
// 用config中的配置项替换默认值
if (config.heroUsdkProjCfg == null || config.heroUsdkProjCfg.Count == 0)
{
return;
}
foreach (HeroUsdkProjCfgOne one in config.heroUsdkProjCfg)
{
TraceLog.Trace("HeroUSDKAuth.InitProjectInfo cpId {0} cpName {1} pcode {2} appKey {3} callbackKey {4}"
, one.cpId, one.cpName, one.pcode, one.appKey, one.callbackKey);
if (0 <= one.cpId && one.cpId < _PCODE.Length && !string.IsNullOrEmpty(one.pcode))
{
_PCODE[one.cpId] = one.pcode;
}
if (0 <= one.cpId && one.cpId < _APP_KEY.Length && !string.IsNullOrEmpty(one.appKey))
{
_APP_KEY[one.cpId] = one.appKey;
}
}
for (int i = (int)HeroUSDKProj.Min + 1; i < (int)HeroUSDKProj.Max; i++)
{
if (_PCODE[i] != null)
{
TraceLog.Trace("HeroUSDKAuth.InitProjectInfo {0} pcode {1}", (HeroUSDKProj)i, _PCODE[i]);
}
if (_APP_KEY[i] != null)
{
TraceLog.Trace("HeroUSDKAuth.InitProjectInfo {0} appKey {1}", (HeroUSDKProj)i, _APP_KEY[i]);
}
}
}
public static HeroUSDKProj GetProject(string pcode)
{
if (string.IsNullOrEmpty(pcode))
{
return HeroUSDKProj.Min;
}
foreach (HeroUsdkProjCfgOne one in HttpProxyServerUtils.GetServerConfig().heroUsdkProjCfg)
{
if (one.pcode == pcode)
{
return (HeroUSDKProj)one.cpId;
}
}
return HeroUSDKProj.Min;
}
//public static string CreateData(Dictionary<string, string> dataParam)
//{
// JsonData data = new JsonData();
// foreach (KeyValuePair<string, string> pair in dataParam)
// {
// data[pair.Key] = new JsonData(pair.Value);
// }
// string jsonStr = data.ToJson();
// string finalData = Convert.ToBase64String(Encoding.ASCII.GetBytes(jsonStr));
// if (finalData.Length > 51)
// {
// char[] array = finalData.ToCharArray();
// SwapChar(array, 1, 33);
// SwapChar(array, 10, 42);
// SwapChar(array, 18, 50);
// SwapChar(array, 19, 51);
// finalData = new string(array);
// }
// return finalData;
//}
//private static void SwapChar(char[] str, int idx1, int idx2)
//{
// if (idx1 >= 0 && idx2 >= 0 && str.Length > Math.Max(idx1, idx2))
// {
// char tmp = str[idx1];
// str[idx1] = str[idx2];
// str[idx2] = tmp;
// }
//}
//private static string CreateParamsStr(Dictionary<string, string> allParam, bool sortParam)
//{
// // sign不参与签名
// allParam.Remove("sign");
// StringBuilder sb = new StringBuilder();
// // 生成签名串, "k1=v1&k2=v2...&_appKey"
// if (sortParam)
// {
// var sortPairs = from pair in allParam orderby pair.Key select pair;
// foreach (KeyValuePair<string, string> pair in sortPairs)
// {
// sb.Append(pair.Key).Append('=').Append(pair.Value).Append('&');
// }
// }
// else
// {
// foreach (KeyValuePair<string, string> pair in allParam)
// {
// sb.Append(pair.Key).Append('=').Append(pair.Value).Append('&');
// }
// }
// sb.Append(_APP_KEY);
// return sb.ToString();
//}
//// 传入按字母排序后的请求参数, 不包含_appKey, 返回签名
//private static string CalcSign(Dictionary<string, string> allParam)
//{
// var str = HeroUSDKSecurity.CreateParamsStr(allParam, true);
// byte[] md5Hash = _md5.ComputeHash(Encoding.UTF8.GetBytes(str));
// string md5Str = BitConverter.ToString(md5Hash).Replace("-", "").ToLower();
// //if (md5Str.Length > 23)
// //{
// // char[] array = md5Str.ToCharArray();
// // SwapChar(array, 1, 13);
// // SwapChar(array, 5, 17);
// // SwapChar(array, 7, 23);
// // md5Str = new string(array);
// //}
// return md5Str;
//}
public static HeroUSDKAccountInfo GetUserInfo(HeroUSDKProj proj, string cUid, string accessToken,
int oldCompensation = 0)
{
if ((int) proj >= _PCODE.Length || (int) proj >= _APP_KEY.Length)
{
TraceLog.Error("HeroUSDKAuth.GetUserInfo invalid project {0}", proj);
return null;
}
var dataParam = new Dictionary<string, string>();
dataParam["cUid"] = cUid;
dataParam["accessToken"] = accessToken;
var allParams = new Dictionary<string, string>();
allParams["pcode"] = _PCODE[(int)proj];
allParams["data"] = HeroUSDKSecurity.CreateData(dataParam);
allParams["timestamp"] = HttpProxyServerUtils.GetTimeSecond().ToString();
// sign以外的字段全部添加到上面用于计算签名
allParams["sign"] = HeroUSDKSecurity.CalcSign(_APP_KEY[(int)proj], allParams);
var content = new FormUrlEncodedContent(allParams);
string ret = HttpUtils.HttpPost(_getUserInfoUrl, content, out bool exception);
TraceLog.Error($"_getUserInfoUrl:{_getUserInfoUrl}\ncUid:{cUid}\naccessToken:{accessToken}\npcode:{allParams["pcode"]}\ndata:{allParams["data"]}\ntimestamp:{allParams["timestamp"]}\nsign:{allParams["sign"]}");
if (exception || ret == null)
{
TraceLog.Trace("HeroUSDKAuth.GetUserInfo call result exception {0} ret==null is {1}", exception, ret==null);
//增加一个sdk校验地址备份功能,英雄的本地校验进程会挂(2022/12/21日挂掉过一次,导致玩家1个小时无法登录)
if (!string.IsNullOrEmpty(_getUserInfoUrlBackup))
{
TraceLog.Trace("HeroUSDKAuth.GetUserInfo with _getUserInfoUrlBackup {0}", _getUserInfoUrlBackup);
ret = HttpUtils.HttpPost(_getUserInfoUrlBackup, content, out exception);
}
else
{
ret = HttpUtils.HttpPost(_getUserInfoUrl, content, out exception);
}
}
if (ret == null)
{
TraceLog.Error("HeroUSDKAuth.GetUserInfo HttpPost return null query failed");
return null;
}
TraceLog.Trace("HeroUSDKAuth.GetUserInfo ret {0}", ret);
JsonData jsonData = JsonMapper.ToObject(ret);
JsonData codeData = jsonData["code"];
int code = codeData != null ? (int) codeData : -1;
if (code != 0)
{
TraceLog.Trace("HeroUSDKAuth.GetUserInfo res code {0} not 0", code);
return null;
}
if (! jsonData.ContainsKey("cUid"))
{
TraceLog.Trace("HeroUSDKAuth.GetUserInfo json cUid not exist");
return null;
}
HeroUSDKAccountInfo usdkAccount = new HeroUSDKAccountInfo {userId = jsonData["cUid"].ToString()};
if (jsonData.ContainsKey("cName"))
{
usdkAccount.userName = jsonData["cName"].ToString();
}
if (jsonData.ContainsKey("ext"))
{
var extData = jsonData["ext"];
if (extData.ContainsKey("userType"))
{
usdkAccount.userType = (int)extData["userType"];
}
if (extData.ContainsKey("openId"))
{
usdkAccount.openId = extData["openId"].ToString();
}
if (extData.ContainsKey("bindEmail"))
{
usdkAccount.bindEmail = extData["bindEmail"].ToString();
}
}
if (jsonData.ContainsKey("channel"))
{
usdkAccount.channel = jsonData["channel"].ToString();
}
// usdk对渠道id的定义
if (jsonData.ContainsKey("imgId"))
{
usdkAccount.channelId = (int)jsonData["imgId"];
}
else
{
if (jsonData.ContainsKey("channelId"))
{
usdkAccount.channelId = (int)jsonData["channelId"];
}
}
//todo 测试模式
// usdkAccount.bindEmail = "lvyuedeyouxi@gmail.com";
//老玩家只会查询一次,新玩家由于没有bindEmail所以不会走到此接口
if (!string.IsNullOrEmpty(usdkAccount.bindEmail) && proj == HeroUSDKProj.JP2 && oldCompensation == 0)
{
TraceLog.Trace("HeroUSDKAuth.GetUserInfo get mail={0},uid={1}", usdkAccount.bindEmail,
usdkAccount.userId);
var from = new Dictionary<string, string>
{
["email"] = usdkAccount.bindEmail
};
ret = HttpUtils.HttpPost(init_amountUrl, new FormUrlEncodedContent(from), out exception);
TraceLog.Trace("HeroUSDKAuth.GetUserInfo request={0},result={1},", usdkAccount.bindEmail,
ret);
if (ret != null)
{
var resultJson = JsonMapper.ToObject(ret);
var resultCode = resultJson["code"];
code = resultCode != null ? (int)resultCode : -1;
if (code == 0)
{
var moneyData = resultJson["data"];
var compensation = 0.00;
if (moneyData != null)
{
if (moneyData.IsInt)
{
compensation = (int)moneyData;
}
if (moneyData.IsDouble)
{
compensation = (double)moneyData;
}
if (moneyData.IsLong)
{
compensation = (long)moneyData;
}
}
TraceLog.Trace("HeroUSDKAuth.GetUserInfo get mail={0},uid={1},compensation={2}", usdkAccount.bindEmail,
usdkAccount.userId, compensation);
//1.2倍
//1代表查询过了。但是不会发奖
usdkAccount.compensation = Math.Max(1, (int)(compensation * 1.2));
}
}
}
usdkAccount.compensation = Math.Max(oldCompensation, usdkAccount.compensation);
return usdkAccount;
}
#if HERO_AUTH_POST_FORM_DATA
public static string GetAccessToken(string authCode)
{
string timeSec = HttpProxyServerUtils.GetTimeSecond().ToString();
var allParams = new Dictionary<string, string>();
allParams["productId"] = _productId;
allParams["code"] = authCode;
allParams["timeStamp"] = timeSec;
MultipartFormDataContent content = new MultipartFormDataContent();
content.Headers.Add("ContentType", _postContentType);
content.Add(new StringContent(_productId), "productId");
content.Add(new StringContent(authCode), "code");
content.Add(new StringContent(timeSec), "timeStamp");
content.Add(new StringContent(CalcSign(allParams)), "sign");
string ret = HttpUtils.HttpPost(_getAccTokenUrl, content, out bool exception);
if (ret == null)
{
TraceLog.Error("HeroUSDKAuth.GetAccessToken HttpPost return null query failed");
return null;
}
TraceLog.Trace("HeroUSDKAuth.GetAccessToken ret {0}", ret);
JsonData jsonData = JsonMapper.ToObject(ret);
JsonData codeData = jsonData["code"];
int code = codeData != null ? (int)codeData : -1;
if (code != 200)
{
TraceLog.Trace("HeroUSDKAuth.GetAccessToken res code {0} not 200 (succ)", code);
return null;
}
return jsonData["data"].ToString();
}
public static bool GetUserInfo(string accessToken, out string userId, out string userName)
{
userId = null;
userName = null;
string timeSec = HttpProxyServerUtils.GetTimeSecond().ToString();
var allParams = new Dictionary<string, string>();
allParams["productId"] = _productId;
allParams["accessToken"] = accessToken;
allParams["timeStamp"] = timeSec;
MultipartFormDataContent content = new MultipartFormDataContent();
content.Headers.Add("ContentType", _postContentType);
content.Add(new StringContent(_productId), "productId");
content.Add(new StringContent(accessToken), "accessToken");
content.Add(new StringContent(timeSec), "timeStamp");
content.Add(new StringContent(CalcSign(allParams)), "sign");
string ret = HttpUtils.HttpPost(_getUserInfoUrl, content, out bool exception);
if (ret == null)
{
TraceLog.Error("HeroUSDKAuth.GetUserInfo HttpGet return null query failed");
return false;
}
TraceLog.Trace("HeroUSDKAuth.GetUserInfo ret {0}", ret);
JsonData jsonData = JsonMapper.ToObject(ret);
JsonData codeData = jsonData["code"];
int code = codeData != null ? (int)codeData : -1;
if (code != 200)
{
TraceLog.Trace("HeroUSDKAuth.GetAccessToken res code {0} not 200 (succ)", code);
return false;
}
JsonData data = jsonData["data"];
userId = data["userId"].ToString();
userName = data["userName"].ToString();
return true;
}
#endif
}
}
#endif