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.Linq; using UnityEngine; namespace tysdk { public partial class TYSdkFacade : MonoBehaviour { public class AccountInfo { #if UNITY_ANDROID private static Dictionary accoutTypeMap = new Dictionary(){ {EAccoutType.hwGoogle.ToString(), EAccoutType.hwGoogle}, {EAccoutType.hwFacebook.ToString(), EAccoutType.hwFacebook}, {"tyGuest", EAccoutType.hwGuest} }; #else private static Dictionary accoutTypeMap = new Dictionary(){ {"google", EAccoutType.hwGoogle}, {"fb", EAccoutType.hwFacebook}, {"tyGuest", EAccoutType.hwGuest}, {"ios13", EAccoutType.Apple} }; #endif public int userId; public string token; public string jwtToken; public string strUserId => userId.ToString(); public string channelstr { set{ channel = accoutTypeMap[value]; linkedAccout.Add(channel); } } public HashSet linkedAccout = new HashSet(); public EAccoutType channel {get; private set;} private const string KEY_ACCOUNT_INFO = "KEY_ACCOUNT_INFO"; public void AddLinkedAccount(EAccoutType accoutType) { if (!linkedAccout.Contains(accoutType)) { linkedAccout.Add(accoutType); } } public void AddLinkedAccount(string channel) { if(accoutTypeMap.TryGetValue(channel, out var accoutType)) { if (!linkedAccout.Contains(accoutType)) { linkedAccout.Add(accoutType); } } } public void Save() { JObject jInfo = new JObject(); jInfo["channel"] = accoutTypeMap.First(x => x.Value == channel).Key; jInfo["token"] = token; jInfo["userId"] = userId; 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)); return new AccountInfo() { userId = (int)jInfo["userId"], token = (string)jInfo["token"], channelstr = (string)jInfo["channel"], jwtToken = (string)jInfo["jwtToken"], linkedAccout = jInfo["linkedAccout"].ToString().Split(',').Select(x => (EAccoutType)Enum.Parse(typeof(EAccoutType), x)).ToHashSet() }; } else { return null; } } } private static AccountInfo _accountInfo; public static AccountInfo TYAccountInfo => _accountInfo; private static IDictionary> callbacks = new Dictionary>(); 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 taskSource = new TaskCompletionSource(); callbacks.Add("LoginResult", (ITYSdkCallback callback) => { taskSource.SetResult((LoginInfo)callback); }); UnityBridgeFunc.UnityLogin(accoutType); return await taskSource.Task; #endif } public async Task LoginByToken() { var accoutInfo = AccountInfo.GetSavedAccoutInfo(); if(accoutInfo == null) return new LoginInfo(); var taskSource = new TaskCompletionSource(); callbacks.Add("LoginResult", (ITYSdkCallback callback) => { taskSource.SetResult((LoginInfo)callback); }); UnityBridgeFunc.UnityLoginByTokenFun(accoutInfo.token); return await taskSource.Task; } 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["respObj"]["result"]; var userId = (int)loginData["userId"]; var token = (string)loginData["token"]; var jwtToken = (string)loginData["jwttoken"]; var channelstr = (string)loginData["loginChannelTypeC"]; var savedInfo = AccountInfo.GetSavedAccoutInfo(); if(savedInfo == null || savedInfo.userId != userId) { _accountInfo = new AccountInfo() { userId = (int)loginData["userId"], token = (string)loginData["token"], jwtToken = (string)loginData["jwttoken"], channelstr = (string)loginData["loginChannelTypeC"] }; _accountInfo.Save(); } else { savedInfo.token = token; savedInfo.jwtToken = jwtToken; savedInfo.AddLinkedAccount(channelstr); savedInfo.Save(); _accountInfo = savedInfo; } result.isSuccess = true; result.userId = _accountInfo.userId; SetUserInfo(); } if (callbacks.TryGetValue("LoginResult", out var action)) { action.Invoke(result); callbacks.Remove("LoginResult"); } } 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 true; } #elif UNITY_IOS public async Task LinkAccount(EAccoutType accoutType) { if (_accountInfo == null) return false; if( _accountInfo.linkedAccout.Contains(accoutType)) return true; var taskSource = new TaskCompletionSource(); callbacks.Add("LinkAccoutResult", (ITYSdkCallback callback) => { taskSource.SetResult((LinkResult)callback); }); UnityBridgeFunc.LinkAccount(accoutType); var result = await taskSource.Task; if (result.isSuccess) { var savedInfo = AccountInfo.GetSavedAccoutInfo(); if(savedInfo != null) { savedInfo.AddLinkedAccount(accoutType); savedInfo.Save(); _accountInfo = savedInfo; } } return result.isSuccess; } public void LinkAccoutResult(string codestr) { var result = new LinkResult() { isSuccess = codestr == "1" }; if (callbacks.TryGetValue("LinkAccoutResult", out var action)) { action.Invoke(result); callbacks.Remove("LinkAccoutResult"); } } #elif UNITY_ANDROID public async Task LinkAccount(EAccoutType accoutType) { if (_accountInfo == null) return false; if( _accountInfo.linkedAccout.Contains(accoutType)) return true; var taskSource = new TaskCompletionSource(); callbacks.Add("LoginResult", (ITYSdkCallback callback) => { taskSource.SetResult((LoginInfo)callback); }); UnityBridgeFunc.LinkAccount(accoutType); var result = await taskSource.Task; return result.isSuccess; } #endif /// /// 检查是否已经绑定 /// /// 1 已经绑定 /// 0 未绑定 /// -1 失败 /// /// public async Task LinkCheck(EAccoutType accoutType) { if (_accountInfo == null) return false; if( _accountInfo.linkedAccout.Contains(accoutType)) return true; var taskSource = new TaskCompletionSource(); callbacks.Add("CheckLinkResult", (ITYSdkCallback callback) => { taskSource.SetResult((LinkCheckInfo)callback); }); UnityBridgeFunc.LinkCheck(accoutType); var code = (await taskSource.Task).code; if (code == 1 && !_accountInfo.linkedAccout.Contains(accoutType)) { _accountInfo.linkedAccout.Add(accoutType); _accountInfo.Save(); } if(code == -1) { Debug.LogError("[TYSdkFacade] CheckLinkResult error"); } return code == 1; } public void CheckLinkResult(string codestr) { if (callbacks.TryGetValue("CheckLinkResult", out var action)) { var result = new LinkCheckInfo(); result.code = int.Parse(codestr); action.Invoke(result); callbacks.Remove("CheckLinkResult"); } } 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(); } } }