// *********************************************************************** // Assembly : Game // Author : Kimch // Created : 2021-05-01 // Description : // Last Modified By : // Last Modified On : // *********************************************************************** // // // *********************************************************************** #if UNITY_EDITOR || DEBUG_MY #define TEST_SERVER #endif using F; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; namespace G { /// /// 服务器 /// public class ServerProxy : F.GameProxy { public class ServerTask { public string taskName; public object taskData; } #region Field private string uid { get => UserProxy.AccountID; set => UserProxy.AccountID = value; } private string token { get => UserProxy.AccountToken; set => UserProxy.AccountToken = value; } public string openId { get; private set; } public static System.Action LoginSuccessEvent; #endregion #region Property public bool isSdkLoginSuccess { get; set; } public bool isLoginSuccess { get; private set; } public int loginStatus { get; private set; } public bool getUserInfoSuccess { get; private set; } public int banStatus { get; private set; } public string banMessage { get; private set; } #endregion #region Method /// /// /// /// /// /// 通过游客方式登录 LOGIN_TYPE_VISITOR = 1 /// // 正常登陆 NormalLogin = 1,// 账号绑定 AccountBind = 2,// 切换账号 SwitchAccount = 3, public void OnSDKLogin(string openId, string openToken, int loginType, int loginInvokeMode) { isLoginSuccess = false; Login(); } /// /// /// /// /// /// public void OnSDKLoginFail(int error, string errorMsg, int apiLoginType) { PostNotification(GlobalDefine.EVENT_SHOW_TOAST, "帐号登录失败,请重新登录"); } /// /// /// /// private bool CheckLogin() { if (string.IsNullOrEmpty(KPlatform.Instance.openId)) { PostNotification(GlobalDefine.EVENT_SHOW_TOAST, "帐号登录失败,请重新登录"); return false; } if (!isLoginSuccess) { PostNotification(GlobalDefine.EVENT_SHOW_TOAST, "帐号未登录,请检查网络"); return false; } return true; } /// /// /// public void Login() { // 临时登录 var dataTT = new Dictionary(); OnLoginSuccess(dataTT); loginStatus = 1; return; loginStatus = 0; _jsonData.Clear(); _jsonData.Add("device_id", KPlatform.Instance.deviceId); #if !UNITY_EDITOR && SDK_WECHAT_WASM if (!string.IsNullOrEmpty(KPlatform.Instance.openId)) _jsonData.Add("js_code", KPlatform.Instance.openId); #else _jsonData.Add("sdkid", KPlatform.Instance.openId); if (!string.IsNullOrEmpty(KPlatform.Instance.openToken)) _jsonData.Add("token", KPlatform.Instance.openToken); #endif _jsonData.Add("channel", KPlatform.Instance.channel); _jsonData.Add("sub_channel", KPlatform.Instance.subChanel); _jsonData.Add("plat", KPlatform.Instance.platform); _jsonData.Add("version", Application.version); var body = F.Utils.ToJsonBytes(_jsonData); StartCoroutine(Request("/api/user/auth", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); this.OnLoginSuccess(dataT); loginStatus = 1; } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); loginStatus = 2; } } else { OnNetworkError(error, data?.ToString()); loginStatus = 3; } } } /// /// /// /// private void OnLoginSuccess(IDictionary data) { if (data != null) { uid = data.GetString("uid"); token = data.GetString("token"); UserProxy.UserId = data.GetString("userid"); this.openId = data.GetString("sdkid"); var timestamp = data.GetInt("timestamp"); AntiCheatProxy.Instance.SetServerTimestamp(timestamp); Launch.SetServerTimestamp(timestamp); this.isLoginSuccess = true; banStatus = data.GetInt("ban_status"); if (banStatus != 0) { var banReason = data.GetString("ban_record"); var banTimestamp = data.GetInt("open_time"); banMessage = "封禁帐号\n" + UserProxy.UserId + "\n" + banReason + "\n封禁截止" + F.Utils.Time.ToDataTime(banTimestamp).ToLocalTime().ToString(); } else { LoginSuccessEvent?.Invoke(); LoginSuccessEvent = null; } if (KPlatform.Instance.loginInvokeMode != 1) ArchiveProxy.Instance.OnServerLogin(KPlatform.Instance.loginInvokeMode); } //StartCoroutine(ScheduleCO()); #if UNITY_EDITOR StartCoroutine(TestCO()); #endif } IEnumerator ScheduleCO() { yield return new WaitForSeconds(1f); KPlatform.Instance.GetUserNickName((error, message) => { if (error == 0) { UpdateUserInfo(PlayerProxy.Instance.socialNickName, PlayerProxy.Instance.socialAvatarUrl); } }); yield return new WaitForSeconds(1f); var inviteInfo = KPlatform.Instance.inviteInfo; if (inviteInfo != null) { Invite(inviteInfo.userId, (error, message) => { if (error != ErrorCode.NETWORK_ERROR) KPlatform.Instance.inviteInfo = null; }); } } IEnumerator TestCO() { yield return new WaitForSeconds(5f); GetInviteCount(null); yield return new WaitForSeconds(1f); } /// /// 获取用户信息 /// /// public void GetUserInfo(Callback3 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("nick", PlayerProxy.Instance.nickName); jsonData.Add("avatar", PlayerProxy.Instance.headURL); jsonData.Add("lv", PlayerProxy.Instance.grade); jsonData.Add("bat_power", PlayerProxy.Instance.combatValue); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/user/update_user", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { callback?.Invoke(0, "", null); } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg, null); } } else { OnNetworkError(error, data?.ToString()); callback?.Invoke(error, data?.ToString(), null); } }; } /// /// /// /// /// private void OnNetworkError(int errorCode, string errorMsg) { PostNotification(GlobalDefine.EVENT_SHOW_TOAST, errorMsg); Debug.Log($"网络错误 {errorCode} {errorMsg}"); } /// /// /// /// /// private void OnServerError(int errorCode, string errorMsg) { PostNotification(GlobalDefine.EVENT_SHOW_TOAST, errorMsg); Debug.Log($"服务器错误 {errorCode} {errorMsg}"); } /// /// /// /// /// public void UploadArchive(string archiveInfo, string archive, string archiveInfo2, string archive2, Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); var archives = new List(4); if (archiveInfo != null) archives.Add(new Dictionary { { "name", "archive_info" }, { "data",archiveInfo} }); if (archive != null) archives.Add(new Dictionary { { "name", "archive" }, { "data",archive} }); if (archiveInfo2 != null) archives.Add(new Dictionary { { "name", "archive2_info" }, { "data",archiveInfo2} }); if (archive2 != null) archives.Add(new Dictionary { { "name", "archive2" }, { "data",archive2} }); jsonData.Add("archives", archives); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/archive/upload", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { Debug.Log("上传存档"); callback?.Invoke(0, null); } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); callback?.Invoke(error, data?.ToString()); } } } /// /// /// public void DownloadArchive(string[] archiveKeys, Callback3 callback = null) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); if (archiveKeys == null) archiveKeys = new string[] { "archive_info", "archive" }; jsonData.Add("tb_names", archiveKeys); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/archive/get", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); if (dataT != null) { var archives = dataT.GetList("archives"); callback?.Invoke(0, "", archives); } else { callback?.Invoke(0, "", null); } } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(error, errorMsg, null); } } else { OnNetworkError(error, data?.ToString()); callback?.Invoke(error, data?.ToString(), null); } } } /// /// /// /// /// /// public void UploadScore(int rank_id, int score, string user_key) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("rank_id", rank_id); jsonData.Add("score", score); jsonData.Add("user_key", user_key); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/rank/update", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// /// public void UploadScore(object rank_data, string user_key) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("user_key", user_key); jsonData.Add("rank_data", rank_data); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/rank/batch_update", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// /// public void PullRanking(int rank_id, Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("rank_id", rank_id); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/rank/load", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); if (dataT != null) { var packet = new GamePacket { id = rank_id, data = dataT.GetList("list"), }; RankingProxy.Instance.Recv(packet); } } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } callback(error, ""); } } /// /// /// /// public void RedeemCode(string code) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(true); jsonData.Add("cdkey", code); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/api/exchange_cdkey", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); var text = dataT.GetString("gifts"); var gifts = text.Split(',', '|'); var results = F.ListPool.Get(); for (int i = 0; i < gifts.Length;) { int.TryParse(gifts[i++], out int id); int.TryParse(gifts[i++], out int count); if (id > 0) results.Add(new Item.ItemInfo { id = id, count = count, }); } RewardProxy.Instance.GetRewardsWithUI(results, null); F.ListPool.Release(results); } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); PostNotification(GlobalDefine.EVENT_SHOW_TOAST, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// 拉取邮件 /// /// /// public void PullMails(Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); //jsonData.Add("max_mail_id", 10); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/mail/load", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); var mailList = dataT.GetList("infos"); // id title content rewards var gp = new GamePacket { id = GlobalDefine.PACKET_ID_MAIL_GET_ALL, data = mailList }; PostNotification(GlobalDefine.EVENT_NETWORK_PACKET, gp, "server"); } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); PostNotification(GlobalDefine.EVENT_SHOW_TOAST, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// /// public void DeleteMails(string[] mailIds, Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("ids", mailIds); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/mail/delete", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); callback?.Invoke(0, ""); // id title content rewards } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// /// public void CreateOrder(string product_id, int product_count, string product_name, Callback3 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(true); jsonData.Add("product_id", product_id); jsonData.Add("product_count", product_count); jsonData.Add("product_name", product_name); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/order/create", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); callback?.Invoke(0, "", dataT); // id title content rewards } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg, null); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// public void GetOrderResult(Callback3 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(true); jsonData.Add("sdkid", this.openId); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/order/load_shopping_list", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); var itemList = dataT.GetList("list"); //for (int i = 0; i < itemList.Count; i++) //{ // var itemInfo = itemList.GetDictionary(i); // var id = itemInfo.GetString("id"); // var count = itemInfo.GetInt("count"); //} callback?.Invoke(0, "", itemList); // id title content rewards } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg, null); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// public void Invite(string invit_userid, Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("invit_userid", invit_userid); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/invit/agree", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); callback?.Invoke(0, ""); // id title content rewards } else { string errorMsg = table.GetString("msg"); //OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg); } } else { //OnNetworkError(error, data?.ToString()); } } } /// /// /// /// public void GetInviteCount(Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/invit/get_invit_count", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); int count = dataT.GetInt("count"); var gp = new GamePacket { id = GlobalDefine.PACKET_ID_GET_INVITE_COUNT, data = count }; InviteProxy.Instance.Recv(gp); //SendNotification(GlobalDefine.EVENT_NETWORK_PACKET, gp, "server"); callback?.Invoke(0, ""); // id title content rewards } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// public void GetInviteList(Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/invit/list", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); var invited_list = dataT.GetList("invited_list"); var gp = new GamePacket { id = GlobalDefine.PACKET_ID_GET_INVITE_LIST, data = invited_list }; InviteProxy.Instance.Recv(gp); //SendNotification(GlobalDefine.EVENT_NETWORK_PACKET, gp, "server"); callback?.Invoke(0, ""); // id title content rewards } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// public void GetTimestamp(Callback2 callback) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/api/timestamp", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { var dataT = table.GetDictionary("data"); int timestamp = dataT.GetInt("timestamp"); Launch.SetServerTimestamp(timestamp); AntiCheatProxy.Instance.SetServerTimestamp(timestamp); callback?.Invoke(0, ""); } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); callback?.Invoke(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } /// /// /// /// public void UpdateUserInfo(string nickName, string avatarURL) { if (!CheckLogin()) { return; } var jsonData = GetCommonData(); jsonData.Add("nick", nickName); jsonData.Add("avatar", avatarURL); var body = F.Utils.ToJsonBytes(jsonData); StartCoroutine(Request("/api/user/update_user", body, process)); void process(int error, object data) { if (error == 0) { var table = F.Utils.ToJsonTable((byte[])data); int errorCode = table.GetInt("code"); if (errorCode == 0) { } else { string errorMsg = table.GetString("msg"); OnServerError(errorCode, errorMsg); } } else { OnNetworkError(error, data?.ToString()); } } } private readonly Dictionary _jsonData = new Dictionary(); /// /// /// /// private Dictionary GetCommonData(bool withChannel = false) { _jsonData.Clear(); _jsonData.Add("uid", uid); if (withChannel) { _jsonData.Add("channel", KPlatform.Instance.channel); } return _jsonData; } #endregion #region Sign && Request #if TEST_SERVER public static string SERVER_URL = "https://dev-shaoxia.lanfeitech.com"; #else public static string SERVER_URL = "https://prod-shaoxia.lanfeitech.com"; #endif IEnumerator Request(string api, byte[] body, System.Action callback) { var url = SERVER_URL + api; var webRequest = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST) { uploadHandler = new UploadHandlerRaw(body) { contentType = "application/json" }, downloadHandler = new DownloadHandlerBuffer() }; var timeStr = Launch.Timestamp.ToString(); var requestSign = GetSign(body, timeStr); webRequest.SetRequestHeader("sign", requestSign); webRequest.SetRequestHeader("time", timeStr); if (!string.IsNullOrEmpty(token)) { webRequest.SetRequestHeader("authorization", token); } #if UNITY_EDITOR Debug.Log("send:" + System.Text.Encoding.UTF8.GetString(body)); #endif yield return webRequest.SendWebRequest(); if (webRequest.isNetworkError || webRequest.isHttpError) { #if UNITY_EDITOR Debug.Log("recv_error:" + webRequest.error); #endif callback(ErrorCode.NETWORK_ERROR, webRequest.error); } else { var data = webRequest.downloadHandler.data; #if UNITY_EDITOR Debug.Log("recv:" + System.Text.Encoding.UTF8.GetString(data)); #endif var responseSign = webRequest.GetResponseHeader("sign"); #if SDK_WECHAT_WASM var headers = webRequest.GetResponseHeaders(); if ((headers.Count < 2 && string.IsNullOrEmpty(responseSign)) || responseSign == GetSign(data, timeStr)) #else if (responseSign == GetSign(data, timeStr)) #endif { callback(0, data); } else { callback(2, "签名错误"); } } } #if TEST_SERVER //"appid=KHQiAUtB&body={0}&signkey=3c3c3aa984ccbbc791655fbf9f8e0fb1&time={1}&" static readonly byte[] _KeyArray = new byte[] { 97, 112, 112, 105, 100, 61, 75, 72, 81, 105, 65, 85, 116, 66, 38, 98, 111, 100, 121, 61, 123, 48, 125, 38, 115, 105, 103, 110, 107, 101, 121, 61, 51, 99, 51, 99, 51, 97, 97, 57, 56, 52, 99, 99, 98, 98, 99, 55, 57, 49, 54, 53, 53, 102, 98, 102, 57, 102, 56, 101, 48, 102, 98, 49, 38, 116, 105, 109, 101, 61, 123, 49, 125, 38 }; //static readonly int _Key1Index = 20; #else //"appid=KHQiAUtB&body={0}&signkey=8adb871756f5bdea6b3d57547fdec8d9&time={1}&" readonly static byte[] _KeyArray = new byte[] { 97, 112, 112, 105, 100, 61, 75, 72, 81, 105, 65, 85, 116, 66, 38, 98, 111, 100, 121, 61, 123, 48, 125, 38, 115, 105, 103, 110, 107, 101, 121, 61, 56, 97, 100, 98, 56, 55, 49, 55, 53, 54, 102, 53, 98, 100, 101, 97, 54, 98, 51, 100, 53, 55, 53, 52, 55, 102, 100, 101, 99, 56, 100, 57, 38, 116, 105, 109, 101, 61, 123, 49, 125, 38 }; #endif static string _KeyIn; /// /// /// /// /// /// public static string GetSign(string body, string timestamp) { if (string.IsNullOrEmpty(_KeyIn)) _KeyIn = System.Text.Encoding.ASCII.GetString(_KeyArray); var raw_str = F.Utils.Text.Format(_KeyIn, body, timestamp); return F.Utils.Security.GetMd5Hex(raw_str); } static System.IO.MemoryStream _SignStream; public static string GetSign(byte[] body, string timestamp) { if (_SignStream == null) _SignStream = new System.IO.MemoryStream(); _SignStream.SetLength(0); _SignStream.Write(_KeyArray, 0, 20); _SignStream.Write(body, 0, body.Length); _SignStream.Write(_KeyArray, 23, 47); var timeBytes = System.Text.Encoding.UTF8.GetBytes(timestamp); _SignStream.Write(timeBytes, 0, timeBytes.Length); _SignStream.Write(_KeyArray, 73, 1); _SignStream.Position = 0; return F.Utils.Security.GetMd5Hex(_SignStream); } #endregion #region Proxy public static ServerProxy Instance => GetInstance(); #endregion } }