using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using asap.core; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; namespace tysdk { public partial class TYSdkFacade : MonoBehaviour { public class AccountInfo { public int userId; public string token; public string jwtToken; public string strUserId => userId.ToString(); public HashSet linkedAccout = new HashSet(); public EAccoutType channel { get; set; } public string userName; public string avatar; private const string KEY_ACCOUNT_INFO = "KEY_ACCOUNT_INFO"; public void AddLinkedAccount(EAccoutType accoutType) { if (!linkedAccout.Contains(accoutType)) { linkedAccout.Add(accoutType); } } private static Dictionary accoutTypeMap = new Dictionary(){ {"google", EAccoutType.hwGoogle}, {"fb", EAccoutType.hwFacebook}, {"tyGuest", EAccoutType.hwGuest}, {"ios13", EAccoutType.Apple} }; private static EAccoutType ConvertAccoutType(string accountType) { if (accoutTypeMap.ContainsKey(accountType)) { return accoutTypeMap[accountType]; } return (EAccoutType)Enum.Parse(typeof(EAccoutType), accountType); } public void Save() { JObject jInfo = new JObject(); jInfo["channel"] = channel.ToString(); jInfo["token"] = token; jInfo["userId"] = userId; jInfo["userName"] = userName; jInfo["avatar"] = avatar; jInfo["jwtToken"] = jwtToken; jInfo["linkedAccout"] = string.Join(",", linkedAccout.Select(x => x.ToString())); PlayerPrefs.SetString(KEY_ACCOUNT_INFO, jInfo.ToString()); } public static void Remove() { PlayerPrefs.DeleteKey(KEY_ACCOUNT_INFO); } public static AccountInfo GetSavedAccoutInfo() { if (PlayerPrefs.HasKey(KEY_ACCOUNT_INFO)) { var jInfo = JObject.Parse(PlayerPrefs.GetString(KEY_ACCOUNT_INFO)); var accountInfo = new AccountInfo() { userId = (int)jInfo["userId"], token = (string)jInfo["token"], channel = ConvertAccoutType((string)jInfo["channel"]), jwtToken = (string)jInfo["jwtToken"], linkedAccout = jInfo["linkedAccout"].ToString().Split(',').Select(x => ConvertAccoutType(x)).ToHashSet() }; if (jInfo.TryGetValue("userName", out var userName)) { accountInfo.userName = (string)userName; } if (jInfo.TryGetValue("avatar", out var avatar)) { accountInfo.avatar = (string)avatar; } return accountInfo; } else { return null; } } } private static AccountInfo _accountInfo; public static AccountInfo TYAccountInfo => _accountInfo; private static TYSdkFacade _instance; public static TYSdkFacade Instance { get { if (_instance == null) { _instance = new GameObject("TYSdkFacade").AddComponent(); DontDestroyOnLoad(_instance.gameObject); } return _instance; } } public void Init() { #if UNITY_ANDROID UnityBridgeFunc.InitSDK(); #endif } /*================================================ _ _ / \ ___ ___ ___ _ _ _ __ | |_ / _ \ / __/ __/ _ \| | | | '_ \| __| / ___ \ (_| (_| (_) | |_| | | | | |_ /_/ \_\___\___\___/ \__,_|_| |_|\__| =================================================*/ public static bool IsLoggedIn => _accountInfo != null; public void Logout() { UnityEngine.Debug.Log("Logout"); if (_accountInfo != null) { UnityBridgeFunc.UnityLogOutByChannel(_accountInfo.channel); } _accountInfo = null; AccountInfo.Remove(); } public async Task Login(EAccoutType accoutType) { #if UNITY_EDITOR await Task.Yield(); var deviceId = UnityEngine.Device.SystemInfo.deviceUniqueIdentifier.Split('-')[0].Substring(0, 8); var userId = (int)ulong.Parse(deviceId, System.Globalization.NumberStyles.HexNumber); _accountInfo = new AccountInfo() { userId = userId, }; return new LoginInfo() { isSuccess = true, userId = userId }; #elif UNITY_ANDROID || UNITY_IOS var task = TYSDKCallbackManager.Instance.RegisterCallback(TimeSpan.FromSeconds(30)); UnityBridgeFunc.UnityLogin(accoutType); try { var loginInfo = await task; if(loginInfo.isSuccess) { _accountInfo.channel = accoutType; _accountInfo.AddLinkedAccount(accoutType); _accountInfo.Save(); } return loginInfo; } catch(Exception e) { Debug.LogWarning($"[TYSdkFacade] Login failed: {e}"); return new LoginInfo(){isSuccess = false}; } #endif } public async Task LoginByToken() { var accoutInfo = AccountInfo.GetSavedAccoutInfo(); if (accoutInfo == null) return new LoginInfo(); var task = TYSDKCallbackManager.Instance.RegisterCallback(TimeSpan.FromSeconds(30)); UnityBridgeFunc.UnityLoginByTokenFun(accoutInfo.token); try { var loginInfo = await task; if (loginInfo.isSuccess) { _accountInfo.Save(); } return loginInfo; } catch (Exception e) { Debug.LogWarning($"[TYSdkFacade] Login by token failed: {e}"); return new LoginInfo() { isSuccess = false }; } } public async Task LoginBySns() { Debug.Log("[TYSdkFacade] LoginBySns"); var task = TYSDKCallbackManager.Instance.RegisterCallback(TimeSpan.FromSeconds(30)); var snsType = UnityBridgeFunc.UnityLoginBySnsInfoFun(); try { var loginInfo = await task; if (loginInfo.isSuccess) { if (Enum.TryParse(snsType, out var accountType)) { _accountInfo.channel = accountType; } _accountInfo.AddLinkedAccount(accountType); _accountInfo.Save(); } else { Debug.Log($"[TYSdkFacade] LoginBySns failed snsType: {snsType}"); } return loginInfo; } catch (Exception e) { Debug.LogWarning($"[TYSdkFacade] Login by token failed: {e}"); return new LoginInfo() { isSuccess = false }; } } public void LoginResult(string json) { Debug.Log("[TYSdkFacade] Login callback:"); var result = new LoginInfo(); var data = JObject.Parse(json); var code = (int)data["code"]; result.code = code; if (code == 0) { var loginData = data["loginData"]; var userId = (int)loginData["userId"]; var token = (string)loginData["token"]; var jwtToken = (string)loginData["jwttoken"]; var savedInfo = AccountInfo.GetSavedAccoutInfo(); if (savedInfo == null || savedInfo.userId != userId) { _accountInfo = new AccountInfo() { userId = (int)loginData["userId"], userName = (string)loginData["userName"], avatar = (string)loginData["purl"], token = (string)loginData["token"], jwtToken = (string)loginData["jwttoken"], }; } else { savedInfo.token = token; savedInfo.jwtToken = jwtToken; _accountInfo = savedInfo; } result.isSuccess = true; result.userId = _accountInfo.userId; SetUserInfo(); } TYSDKCallbackManager.Instance.TryTriggerCallback(result); } private void SetUserInfo() { if (_accountInfo == null) return; var strUserId = _accountInfo.strUserId; UnityBridgeFunc.SetGaUserInfo(strUserId); } #if UNITY_EDITOR public async Task LinkAccount(EAccoutType accoutType) { await Task.Delay(300); return new LinkResult(){code = 1}; } #elif UNITY_IOS || UNITY_ANDROID public async Task LinkAccount(EAccoutType accoutType) { if (_accountInfo == null) return new LinkResult(){ code = 1}; if (_accountInfo.linkedAccout.Contains(accoutType)) return new LinkResult(){ code = 0}; var task = TYSDKCallbackManager.Instance.RegisterCallback(TimeSpan.FromMinutes(1)); UnityBridgeFunc.LinkAccount(accoutType); try { var result = await task; if (result.code == 0) { _accountInfo.channel = accoutType; _accountInfo.AddLinkedAccount(accoutType); _accountInfo.Save(); } return result; } catch (Exception e) { Debug.LogWarning($"[TYSdkFacade] Link account failed: {e}"); return new LinkResult() { code = 1 }; } } public void LinkAccoutResult(string message) { JObject data = JObject.Parse(message); var result = new LinkResult() { code = (int)data["code"], userId = (int)data["userId"] }; if (data.ContainsKey("bindInfo")) { result.bindInfo = JsonConvert.DeserializeObject>(data.GetValue(@"bindInfo").ToString()); } if (result.code == 0 && data.ContainsKey("loginData")) { var loginData = data["loginData"]; _accountInfo.token = (string)loginData["token"]; } TYSDKCallbackManager.Instance.TryTriggerCallback(result); } #endif public void CleanLinkTempSnSInfo() { UnityBridgeFunc.CleanLinkTmpSnsInfo(); } /// /// 检查是否已经绑定 /// /// 1 已经绑定 /// 0 未绑定 /// -1 失败 /// /// public async Task LinkCheck(EAccoutType accoutType) { if (_accountInfo == null) return false; if (_accountInfo.linkedAccout.Contains(accoutType)) return true; var task = TYSDKCallbackManager.Instance.RegisterCallback(TimeSpan.FromSeconds(30)); UnityBridgeFunc.LinkCheck(accoutType); try { var result = await task; if (result.code == 1 && !_accountInfo.linkedAccout.Contains(accoutType)) { _accountInfo.linkedAccout.Add(accoutType); _accountInfo.Save(); } if (result.code == -1) { Debug.LogError("[TYSdkFacade] CheckLinkResult error"); } return result.code == 1; } catch(Exception e) { Debug.LogWarning($"[TYSdkFacade] CheckLinkResult error: {e}"); return false; } } public void CheckLinkResult(string codestr) { var result = new LinkCheckInfo(); result.code = int.Parse(codestr); TYSDKCallbackManager.Instance.TryTriggerCallback(result); } public void Signout() { List list = new List(); string defaultTyurl = "https://128-hwsfsdk-sdk-online01.qijihdhk.com"; IConfig config = GContext.container.Resolve(); var tyurl = config.Get("AGG_SERVER", defaultTyurl); string tycs = tyurl == defaultTyurl ? "https://hwcsh.tygameworld.com/template/appCancel/note.html" : "https://customermanage-feature-test-web-test.tuyougame.cn/appCancel/note.html"; string sdkurl = $"sdkurl={tyurl}"; list.Add(sdkurl); string appid = "appid=20587"; list.Add(appid); #if UNITY_ANDROID string clientid = "Android_5.00_tyGuest,facebook.googleplay.0-hall20587.googleplay.FishingMaster"; #elif UNITY_IOS string clientid = "IOS_5.00_tyGuest,facebook,appStore.appStore.0-hall20587.appStore.FishingMaster"; #endif list.Add($"clientid={clientid}"); string uid = $"uid={_accountInfo.userId}"; list.Add(uid); string roleid = "roleid=0"; list.Add(roleid); string gameid = "gameid=20587"; list.Add(gameid); string cloudid = "cloudid=128"; list.Add(cloudid); string gamename = "gamename=FishingTravel"; list.Add(gamename); string certification = "certification=0"; list.Add(certification); string ischannel = "ischannel=1"; list.Add(ischannel); string tysdktoken = $"tysdktoken={_accountInfo.token}"; list.Add(tysdktoken); list.Sort(); string listStr = string.Join("&", list.ToArray()); string sign = listStr + "csh-api-6dfa879490a249be9fbc92e97e4d898d-api-csh"; //对sign进行MD5加密 string signMd5 = CalculateMD5Hash(sign); string url = $"{tycs}?{listStr}&sign={signMd5}&isAbroad=1&lan=en"; Debug.Log($"[TYSdkFacade:Signout] url \n{url}"); Application.OpenURL(url); } private string CalculateMD5Hash(string input) { // Create a new instance of the MD5CryptoServiceProvider object. MD5 md5Hasher = MD5.Create(); // Convert the input string to a byte array and compute the hash. byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input)); // Create a new Stringbuilder to collect the bytes // and create a string. StringBuilder sBuilder = new StringBuilder(); // Loop through each byte of the hashed data // and format each one as a hexadecimal string. for (int i = 0; i < data.Length; i++) { sBuilder.Append(data[i].ToString("x2")); } // Return the hexadecimal string. return sBuilder.ToString(); } } }