using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; using UnityEngine.UIElements; using Button = UnityEngine.UI.Button; using Image = UnityEngine.UI.Image; using Toggle = UnityEngine.UI.Toggle; using ScrollView = PhxhSDK.PhxhScrollView; using Framework; using Gameplay.Net; using NLDPB; using Cysharp.Threading.Tasks; using UnityEngine.Networking; using System.Text; using System.Linq; using System.Security.Cryptography; using System; using Gameplay; using Newtonsoft.Json; public class UI_StartGameInterfaceController : UIWindow { enum LoginType { Account, PhoneCode } #region UI_obj //UI GameObj ///Auto Gen Start/// public Image Image_Bg; public Image Image_BgDark; public Button Button_StartGame; public Image Image_LoginBg; public Button Button_AccountLogin_1; public Image Image_YellowLine_Account_1; public Button Button_VerifyCodeLogin_1; public Image Image_YellowLine_VerifyCode_1; public TMP_InputField InputField_Account; public Image Image_AccountIcon; public TMP_InputField InputField_Password; public Image Image_PasswordIcon; public Toggle Toggle_RememberPassword; public TMP_Text Text_RememberPassword; public Toggle Toggle_Agreement_1; public TMP_Text Text_Agreement_1; public Button Button_UnLogin_1; public Button Button_Login_1; public TMP_InputField InputField_PhoneNumber; public Image Image_PhoneIcon; public TMP_InputField InputField_VerifyCode; public Image Image_VerifyCodeIcon; public Button Button_GetVerifyCode; public Button Button_GetVerifyCodeCooling; public Toggle Toggle_Agreement_2; public TMP_Text Text_Agreement_2; public Button Button_UnLogin_2; public Button Button_Login_2; public Image Image_UpdateBg; public Button Button_Confirm; public Button Button_Cancle; public Image Image_BottomLine; public Button Button_UserCenter; public Button Button_Notice; public TMP_Text Text_UID; public TMP_Text Text_Version; public Image Image_DarkSide; public GameObject AccountLoginPanel; public GameObject VerifyCodeLoginPanel; ///Auto Gen End/// #endregion LoginType loginType; LoginData loginSaveData; LoginData tempSaveData; bool loginOK = false; int serverIndex = 1; // deal with input data public override void PreLoad(object data = null) { loginSaveData = StorageMgr.Instance.GetStorage("LoginData"); if (loginSaveData == null) loginSaveData = new(); } // Use this for initialization public override void OnInit() { //bind UI GameObj UI_StartGameInterfaceBinder.GetComponents(this); AccountLoginPanel = FindObj("UI_LoginWindow/Image_LoginBg/LoginPanel/AccountLogin"); VerifyCodeLoginPanel = FindObj("UI_LoginWindow/Image_LoginBg/LoginPanel/VerifyCodeLogin"); #if DEVELOPMENT_BUILD || UNITY_EDITOR FindObj("UI_LoginWindow/Image_LoginBg/ALDropdown").gameObject.SetActive(true); TMP_Dropdown dropdown = FindObj("UI_LoginWindow/Image_LoginBg/ALDropdown").GetComponent(); dropdown.options.Clear(); var serverInfo = AppConfig.Instance.GetServerInfo(); if (serverInfo.Count <= 0) { return; } foreach (var item in serverInfo) { dropdown.options.Add(new TMP_Dropdown.OptionData() { text = item.name }); } var index = PlayerPrefs.GetInt("ServerIndex", 1); serverIndex = index; if (index >= 0 && index < serverInfo.Count) { dropdown.captionText.text = serverInfo[index].name; dropdown.value = index; } else { dropdown.captionText.text = serverInfo[0].name; dropdown.value = 0; } AppConfig.Instance.Select(index); dropdown.onValueChanged.AddListener((int index) => { DebugUtil.Log("选择服务器:" + index); AppConfig.Instance.Select(index); serverIndex = index; }); #endif BindButton(Button_AccountLogin_1, () => SetLoginType(LoginType.Account)); BindButton(Button_VerifyCodeLogin_1, () => SetLoginType(LoginType.PhoneCode)); BindButton(Button_Login_1, OnButtonLogin); BindButton(Button_Login_2, OnPhoneCodeLoginClick);//OnButtonLogin BindButton(Button_GetVerifyCode, SendPhoneCodeRequest); BindButton(Button_UserCenter, OnCancelCurConnect); BindButton(Button_Notice, OnNoticeClick); BindButton(Button_StartGame, OnStartGame); Toggle_RememberPassword.onValueChanged.AddListener(OnRememberPassword); Toggle_Agreement_1.onValueChanged.AddListener(OnAgreementAccept); Toggle_Agreement_2.onValueChanged.AddListener(OnAgreementAccept); InputField_Account.onValueChanged.AddListener(AccountEdit); InputField_Password.onValueChanged.AddListener(PasswordEdit); InputField_PhoneNumber.onValueChanged.AddListener(PhoneEdit); InputField_VerifyCode.onValueChanged.AddListener(PhoneVerifyCodeEdit); Text_Version.text = "version:" + Application.version; Text_UID.gameObject.SetActive(false); EventManager.Instance.Register(EventManager.EventName.LoginComplete, OnLoginOK); EventManager.Instance.Register(Framework.EventManager.EventName.NetError, OnCancelCurConnect); EventManager.Instance.Register(EventManager.EventName.PhoneCodeLoginSuc, OnPhoneCodeLoginSuc); EventManager.Instance.Register(EventManager.EventName.PhoneCodeLoginFail, OnPhoneCodeLoginFailed); EventManager.Instance.Register(EventManager.EventName.PhoneCodeRequsetFail, OnPhoneCodeRequestFailed); if (loginSaveData.LoginByPhone) { SetLoginType(LoginType.PhoneCode); } else { SetLoginType(LoginType.Account); } if (loginSaveData.LoginByAccount && loginSaveData.rememberPassword) { DebugUtil.Log("已有账号密码,自动登录"); LoginAction(); } } /// /// 进入账号登录界面 /// /// void SetLoginType(LoginType type) { loginType = type; Text_UID.gameObject.SetActive(false); Button_StartGame.gameObject.SetActive(false); Button_UserCenter.gameObject.SetActive(false); Button_Notice.gameObject.SetActive(false); switch (loginType) { case LoginType.Account://账号密码登录 Image_LoginBg.gameObject.SetActive(true); Image_UpdateBg.gameObject.SetActive(false); Image_YellowLine_Account_1.gameObject.SetActive(true); Image_YellowLine_VerifyCode_1.gameObject.SetActive(false); Toggle_RememberPassword.isOn = loginSaveData.rememberPassword; Toggle_Agreement_1.isOn = loginSaveData.agreement; AccountLoginPanel.SetActive(true); VerifyCodeLoginPanel.SetActive(false); if (loginSaveData.account != default) { InputField_Account.text = loginSaveData.account; } if (loginSaveData.password != default && loginSaveData.rememberPassword) { InputField_Password.text = loginSaveData.password; } else { InputField_Password.text = string.Empty; } break; case LoginType.PhoneCode://手机号验证码登录 Image_LoginBg.gameObject.SetActive(true); Image_UpdateBg.gameObject.SetActive(false); Image_YellowLine_Account_1.gameObject.SetActive(false); Image_YellowLine_VerifyCode_1.gameObject.SetActive(true); Toggle_Agreement_2.isOn = loginSaveData.agreement; AccountLoginPanel.SetActive(false); VerifyCodeLoginPanel.SetActive(true); CheckPhoneCodeButton(); break; default: DebugUtil.LogError("SetLoginType error"); break; } CheckLoginButton(); } void HideLoginPanel() { Image_LoginBg.gameObject.SetActive(false); Button_StartGame.gameObject.SetActive(true); Button_Notice.gameObject.SetActive(true); Button_UserCenter.gameObject.SetActive(true); } void CheckLoginButton() { switch (loginType) { case LoginType.Account: if(InputField_Account.text.Length > 0 && InputField_Password.text.Length > 0 && loginSaveData.agreement) { Button_Login_1.gameObject.SetActive(true); } else { Button_Login_1.gameObject.SetActive(false); } break; case LoginType.PhoneCode: if (InputField_PhoneNumber.text.Length > 0 && InputField_VerifyCode.text.Length > 0 && loginSaveData.agreement) { Button_Login_2.gameObject.SetActive(true); } else { Button_Login_2.gameObject.SetActive(false); } break; } } void CheckPhoneCodeButton() { if(InputField_PhoneNumber.text.Length == 11) { Button_GetVerifyCode.interactable = true; } else { Button_GetVerifyCode.interactable = false; } } //invoke when open window protected override void OnShowWindow(object data = null) { DebugUtil.Log("新版登录界面!目前仅支持登录测试服,密码随意\n====如需登录其他服务器,请: ===="); DebugUtil.Log("在运行游戏前修改DebugStart节点内CmpFakeStart组件内选项,选择旧版登录界面"); } //invoke when reload window protected override void OnReloadWindow(object data = null) { } //invoke when close window protected override void OnHideWindow() { } //invoke when destroy public override void OnRelease() { base.OnRelease(); EventManager.Instance.Unregister(EventManager.EventName.PhoneCodeLoginFail, OnPhoneCodeLoginFailed); EventManager.Instance.Unregister(EventManager.EventName.PhoneCodeRequsetFail, OnPhoneCodeRequestFailed); EventManager.Instance.Unregister(EventManager.EventName.PhoneCodeLoginSuc, OnPhoneCodeLoginSuc); EventManager.Instance.Unregister(EventManager.EventName.LoginComplete, OnLoginOK); EventManager.Instance.Unregister(Framework.EventManager.EventName.NetError, OnCancelCurConnect); } #region Button_Listener void OnRememberPassword(bool isOn) { loginSaveData.rememberPassword = isOn; } void OnAgreementAccept(bool isOn) { loginSaveData.agreement = isOn; CheckLoginButton(); } void AccountEdit(string text) { loginSaveData.account = text; InputField_Password.text = string.Empty; CheckLoginButton(); } void PasswordEdit(string text) { loginSaveData.password = text; CheckLoginButton(); } void PhoneEdit(string text) { loginSaveData.phoneNumber = text; //CheckLoginButton(); CheckPhoneCodeButton(); } void PhoneVerifyCodeEdit(string text) { //loginSaveData.verifyCode = text; CheckLoginButton(); } /// /// 尝试登录 /// void OnButtonLogin() { if (!loginSaveData.rememberPassword) { loginSaveData.password = default; } tempSaveData = new(loginSaveData);//暂存登录数据 LoginAction(); } /// /// 请求发送验证码 /// void SendPhoneCodeRequest() { PhoneVerifyTool.Instance.PhoneNumber = loginSaveData.phoneNumber; PhoneVerifyTool.Instance.PhoneCodeWebRequest(); isTimer = true; CoolingTimer().Forget(); DebugUtil.Log("发送验证码请求"); } bool isTimer = false; /// /// 手机验证码登录 /// void OnPhoneCodeLoginClick() { PhoneVerifyTool.Instance.PhoneNumber = loginSaveData.phoneNumber; PhoneVerifyTool.Instance.HttpVerifyCode = InputField_VerifyCode.text; Actor.Instance.StartLogin(NLDPB.LoginType.Phxhphone, loginSaveData.phoneNumber); DebugUtil.Log("尝试登录"); } async UniTask CoolingTimer() { int duration = 60; Button_GetVerifyCode.gameObject.SetActive(false); Button_GetVerifyCodeCooling.gameObject.SetActive(true); while (duration > 0) { if (!isTimer) { duration = 0; break; } Button_GetVerifyCodeCooling.GetComponentInChildren().text = duration + "s"; await UniTask.WaitForSeconds(1); duration--; } Button_GetVerifyCode.gameObject.SetActive(true); Button_GetVerifyCodeCooling.gameObject.SetActive(false); } /// /// 服务器登录 /// void LoginAction() { #if DEVELOPMENT_BUILD || UNITY_EDITOR PlayerPrefs.SetInt("ServerIndex", serverIndex); #else DebugUtil.Log("尝试登录测试服,在此处修改登录逻辑,连接超时以及登录失败请后续补充"); var serverInfos = AppConfig.Instance.GetServerInfo(); AppConfig.Instance.Select(1); for (int i = 0; i < serverInfos.Count; i++) { if (serverInfos[i].name == "测试服1") { AppConfig.Instance.Select(i); DebugUtil.Log("登录测试服"); break; } } #endif Gameplay.Net.Actor.Instance.StartLogin(NLDPB.LoginType.Phxh, loginSaveData.account); } void OnLoginOK() { loginOK = true; HideLoginPanel(); loginSaveData = StorageMgr.Instance.GetStorage("LoginData"); if (loginSaveData == null) loginSaveData = new(); if (tempSaveData != null) loginSaveData.SetData(tempSaveData); loginSaveData.LoginByAccount = true; StorageMgr.Instance.SyncForce = true; Text_UID.gameObject.SetActive(true); Text_UID.text = "UID: " + Actor.Instance.Base.GetProp(ActorProp.ActorId); //return; var adultStatus = (int)Actor.Instance.Logic.GetCount((uint)LogicID.AdultAuthStatus); if (adultStatus == (int)AAStatus.AasNone) { DebugUtil.Log("未实名认证"); //UI_RealNameIdentifyController.Open().Forget(); UI_NoticeWindowController.Open().Forget(); } } void OnPhoneCodeRequestFailed(string errorMsg) { CommonUtils.ShowMessageTips(errorMsg); isTimer = false; } void OnPhoneCodeLoginSuc() { if (tempSaveData != null) { tempSaveData.AuthCode = PhoneVerifyTool.Instance.HttpReturnCode; } loginSaveData.AuthCode = PhoneVerifyTool.Instance.HttpReturnCode; DebugUtil.Log("验证码登录成功!保存登录凭证:" + loginSaveData.AuthCode); } void OnPhoneCodeLoginFailed(string errorMsg) { CommonUtils.ShowMessageTips(errorMsg); } /// /// 用户中心按钮 /// void OnCancelCurConnect() { if (loginOK)//TODO 点开用户中心退出原先账号是否需要断开连接 { DebugUtil.Log("登出!断开连接"); Actor.Instance.OnLogout(); NetManager.Instance.CloseClient(); loginOK = false; } if (loginSaveData.LoginByPhone) { SetLoginType(LoginType.PhoneCode); } else { SetLoginType(LoginType.Account); } } async void OnNoticeClick() { await UI_NoticeController.Open(); } void OnStartGame() { Actor.Instance.OnEnterGame(); } #endregion /// /// 手机验证登录工具 /// /*class PhoneVerifyTool { /// /// 加密拼接密钥 /// static string key = "OfqCL-_jJa9Sm1Nl-TPXvm3drI9td1RPoWn3eLjTe18="; #region class public class WebRequestData { public string phone; public WebRequestData(string phone) { this.phone = phone; } } public class CheckPhoneLoginRequestData { public string phone; public int sms_code; public CheckPhoneLoginRequestData(string phone, string code) { this.phone = phone; this.sms_code = int.Parse(code); } } class EncodeData { Dictionary data = new Dictionary(); public EncodeData(Dictionary data) { this.data = data; } public string GetEncodeData() { List key = data.Keys.Where(k => k != "signature").ToList(); key.Sort(); List keyValuePairs = key.Select(k => k + "=" + data[k]).ToList(); string concatenate = string.Join("&", keyValuePairs); DebugUtil.Log("排序结果:" + concatenate); return concatenate; } public static string GetMd5Hash(string input) { using (MD5 md5 = MD5.Create()) { byte[] inputBytes = Encoding.UTF8.GetBytes(input); byte[] hashBytes = md5.ComputeHash(inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append(hashBytes[i].ToString("x2")); } return sb.ToString(); } } public static string GetSha256Hash(string input) { using (SHA256 sha256 = SHA256.Create()) { byte[] inputBytes = Encoding.UTF8.GetBytes(input); byte[] hashBytes = sha256.ComputeHash(inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append(hashBytes[i].ToString("x2")); } return sb.ToString(); } } } #endregion /// /// 请求发送手机验证码 /// /// /// public static async void PhoneCodeWebRequest(string url, WebRequestData sendData) { DebugUtil.Log("发送验证码请求"); DateTimeOffset now = DateTimeOffset.UtcNow; string timeStamp = now.ToUnixTimeSeconds().ToString(); var encodeData = new EncodeData(new Dictionary { {"phone",sendData.phone }, {"timestamp", timeStamp } }); string encodeStr = encodeData.GetEncodeData(); var md5 = EncodeData.GetMd5Hash(encodeStr); string linkStr = md5 + key; string sign = EncodeData.GetSha256Hash(linkStr); DebugUtil.Log("验证码请求信息:" + "\n时间戳:" + timeStamp + "\nphone:" + sendData.phone + "\n排序结果:" + encodeStr + "\nmd5:" + md5 + "\n最终sign:" + sign); //header data Dictionary header = new(); header["signature"] = sign; header["timestamp"] = timeStamp; //post data var jsonData = JsonUtility.ToJson(sendData); byte[] bytes = Encoding.UTF8.GetBytes(jsonData); DebugUtil.Log("发送请求内容:" + sendData.ToString()); UnityWebRequest www = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST) { uploadHandler = new UploadHandlerRaw(bytes), downloadHandler = new DownloadHandlerBuffer(), }; www.SetRequestHeader("Content-Type", "application/json;charset=utf-8");//为了保证客户端发送的json格式在后端能解析 www.SetRequestHeader("signature", sign); www.SetRequestHeader("timestamp", timeStamp); await www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { DebugUtil.LogError(www.error); } else { DebugUtil.Log("http消息请求成功!\n返回内容:" + www.downloadHandler.text); } } /// /// 注册登录请求 /// /// /// public static async void PhoneCodeWebRequest(string url, CheckPhoneLoginRequestData sendData) { //List formData = new List(); DebugUtil.Log("注册登录请求"); DateTimeOffset now = DateTimeOffset.UtcNow; string timeStamp = now.ToUnixTimeSeconds().ToString(); var encodeData = new EncodeData(new Dictionary { {"phone",sendData.phone }, {"timestamp", timeStamp }, {"sms_code",sendData.sms_code.ToString() } }); string encodeStr = encodeData.GetEncodeData(); var md5 = EncodeData.GetMd5Hash(encodeStr); string linkStr = md5 + key; string sign = EncodeData.GetSha256Hash(linkStr); DebugUtil.Log("手机号登录验证信息:" + "\n时间戳:" + timeStamp + "\nphone:" + sendData.phone + "\n验证码:" + sendData.sms_code + "\n排序结果:" + encodeStr + "\nmd5:" + md5 + "\n最终sign:" + sign); //header data Dictionary header = new(); header["signature"] = sign; header["timestamp"] = timeStamp; //post data var jsonData = JsonUtility.ToJson(sendData); byte[] bytes = Encoding.UTF8.GetBytes(jsonData); DebugUtil.Log("发送请求内容:" + sendData.ToString()); UnityWebRequest www = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST) { uploadHandler = new UploadHandlerRaw(bytes), downloadHandler = new DownloadHandlerBuffer(), }; www.SetRequestHeader("Content-Type", "application/json;charset=utf-8");//为了保证客户端发送的json格式在后端能解析 www.SetRequestHeader("signature", sign); www.SetRequestHeader("timestamp", timeStamp); try { await www.SendWebRequest(); } catch (UnityWebRequestException e) { DebugUtil.LogError(e.Message); } if (www.result != UnityWebRequest.Result.Success) { DebugUtil.LogError(www.error); CommonUtils.ShowMessageTips("登录失败!"); } else { //DebugUtil.Log("http消息请求成功!\n返回内容:" + www.downloadHandler.text); WebRequestResult result = JsonConvert.DeserializeObject(www.downloadHandler.text); if (result.code == 0) { DebugUtil.Log("登录成功!验证code:" + result.data.code); } else { DebugUtil.Log("登录失败!" + www.downloadHandler.text); } } } /// /// http请求返回结果 /// class WebRequestResult { public int code; public string message; public ResultData data; public class ResultData { public string code; } } }*/ class LoginData { /// /// 用账号密码成功登录 /// public bool LoginByAccount = false; /// /// 用手机验证成功登录 /// public bool LoginByPhone = false; public string account; public string password; public bool rememberPassword; public bool agreement; public string phoneNumber; public string AuthCode; public LoginData() { } public LoginData(LoginData loginData) { this.LoginByAccount = loginData.LoginByAccount; this.LoginByPhone = loginData.LoginByPhone; this.account = loginData.account; this.password = loginData.password; this.rememberPassword = loginData.rememberPassword; this.agreement = loginData.agreement; this.phoneNumber = loginData.phoneNumber; } public void SetData(LoginData loginData) { this.LoginByAccount = loginData.LoginByAccount; this.LoginByPhone = loginData.LoginByPhone; this.account = loginData.account; this.password = loginData.password; this.rememberPassword = loginData.rememberPassword; this.agreement = loginData.agreement; this.phoneNumber = loginData.phoneNumber; } } }