/// <summary>
        /// 手机验证码登录(发送验证码)
        /// </summary>
        /// <param name="phoneNumber">手机号</param>
        /// <param name="chk">通过GetSecretKeyAsync()获取到的Chk密钥</param>
        /// <returns>void</returns>
        public async Task MobileLoginAsync(string phoneNumber, string chk)
        {
            string     mobile = CpdailyCrypto.DESEncrypt(phoneNumber, CpdailyCrypto.GetDESKey(chk), CpdailyCrypto.IV);
            string     url    = "https://mobile.campushoy.com/app/auth/authentication/mobile/messageCode/v-8213";
            RestClient client = new RestClient(url)
            {
                CookieContainer = CookieContainer
            };
            var request = new RestRequest(Method.POST);

            request.AddHeader("sessionTokenKey", "szFn6zAbjjU=");
            request.AddHeader("SessionToken", "szFn6zAbjjU=");
            request.AddHeader("clientType", "cpdaily_student");
            request.AddHeader("deviceType", "1");
            request.AddHeader("CpdailyClientType", "CPDAILY");
            request.AddHeader("CpdailyStandAlone", "0");
            request.AddHeader("CpdailyInfo", DeviceInfo.EncryptCache);
            request.AddHeader("User-Agent", ApiUserAgent);
            request.AddJsonBody(new { a = mobile, b = "firstv" });
            var response = await client.ExecutePostAsync(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("非200状态响应");
            }
            // TODO: parse error message.
        }
        /// <summary>
        /// 获取学校的详细信息(用于登录或其他)
        /// </summary>
        /// <param name="schoolId">学校ID</param>
        /// <param name="chk">通过GetSecretKeyAsync()获取到的Chk密钥</param>
        /// <returns>SchoolDetails</returns>
        public async Task <SchoolDetails> GetSchoolDetailsAsync(string schoolId, string chk)
        {
            var        encryptedId = CpdailyCrypto.DESEncrypt(schoolId, CpdailyCrypto.GetDESKey(chk), CpdailyCrypto.IV);
            string     url         = $"https://mobile.campushoy.com/v6/config/guest/tenant/info/v-8213";
            RestClient client      = new RestClient(url)
            {
                CookieContainer = CookieContainer
            };
            var request = new RestRequest(Method.GET);

            request.AddHeader("sessionTokenKey", "szFn6zAbjjU=");
            request.AddHeader("SessionToken", "szFn6zAbjjU=");
            request.AddHeader("CpdailyClientType", "CPDAILY");
            request.AddHeader("CpdailyStandAlone", "0");
            request.AddHeader("CpdailyInfo", DeviceInfo.EncryptCache);
            request.AddHeader("User-Agent", ApiUserAgent);
            request.AddParameter("a", encryptedId);
            request.AddParameter("b", "firstv");
            request.AddParameter("oick", CpdailyCrypto.GetOick());
            var response = await client.ExecuteGetAsync(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("非200状态响应");
            }
            var apiResponse = JsonConvert.DeserializeObject <ApiResponse>(response.Content);

            if (apiResponse.ErrorCode != 0)
            {
                throw new Exception($"出现错误: {apiResponse.ErrorMessage}, 错误代码: {apiResponse.ErrorCode}。");
            }
            string decretedData = CpdailyCrypto.DESDecrypt(apiResponse.Data, CpdailyCrypto.GetDESKey(chk), CpdailyCrypto.IV);

            return(JArray.Parse(decretedData)[0].ToObject <SchoolDetails>());
        }
        /// <summary>
        /// 通用登录,今日校园的Auth阶段(未完成)
        /// </summary>
        /// <param name="encryptedToken">通过LoginWorker得到的Token</param>
        /// <param name="schoolId">School Id</param>
        /// <param name="chk">通过GetSecretKeyAsync()获取到的Chk密钥</param>
        /// <returns>CookieContainer(以后将会修改)</returns>
        public async Task <CookieContainer> CpdailyAuth(string encryptedToken, string schoolId, string chk)
        {
            string encryptedData = JsonConvert.SerializeObject(new { c = schoolId, d = encryptedToken });

            encryptedData = CpdailyCrypto.DESEncrypt(encryptedData, CpdailyCrypto.GetDESKey(chk), CpdailyCrypto.IV);
            var        result = new CookieContainer();
            string     url    = "https://mobile.campushoy.com/app/auth/authentication/notcloud/login/v-8213";
            RestClient client = new RestClient(url)
            {
                CookieContainer = result
            };
            var request = new RestRequest(Method.POST);

            request.AddHeader("sessionTokenKey", "szFn6zAbjjU=");
            request.AddHeader("SessionToken", "szFn6zAbjjU=");
            request.AddHeader("clientType", "cpdaily_student");
            request.AddHeader("deviceType", "1");
            request.AddHeader("CpdailyClientType", "CPDAILY");
            request.AddHeader("CpdailyStandAlone", "0");
            request.AddHeader("CpdailyInfo", DeviceInfo.EncryptCache);
            request.AddHeader("User-Agent", ApiUserAgent);
            request.AddJsonBody(new { a = encryptedData, b = "firstv" });
            var response = await client.ExecutePostAsync(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("非200状态响应");
            }
            var apiResponse = JsonConvert.DeserializeObject <ApiResponse>(response.Content);

            if (apiResponse.ErrorCode != 0)
            {
                throw new Exception($"出现错误: {apiResponse.ErrorMessage}, 错误代码: {apiResponse.ErrorCode}。");
            }
            var    json = JObject.Parse(CpdailyCrypto.DESDecrypt(apiResponse.Data, CpdailyCrypto.GetDESKey(chk), CpdailyCrypto.IV));
            string tgc  = json["tgc"].Value <string>();

            if (string.IsNullOrEmpty(tgc))   // TODO:
            {
                string mobile = json["mobile"].Value <string>();
                await SendVerifyMessage(result, mobile);

                string code = Console.ReadLine();
                await VerifyCode(result, encryptedToken, mobile, code);
            }
            return(result);
        }
        /// <summary>
        /// 手机验证码登录(提交验证码)
        /// </summary>
        /// <param name="phoneNumber">手机号码</param>
        /// <param name="code">验证码</param>
        /// <param name="chk">通过GetSecretKeyAsync()获取到的Chk密钥</param>
        /// <returns>LoginResult</returns>
        public async Task <LoginResult> MobileLoginAsync(string phoneNumber, string code, string chk)
        {
            string data = CpdailyCrypto.DESEncrypt(
                JsonConvert.SerializeObject(new { d = code, c = phoneNumber }),
                CpdailyCrypto.GetDESKey(chk),
                CpdailyCrypto.IV);
            string     url    = "https://mobile.campushoy.com/app/auth/authentication/mobileLogin/v-8213";
            RestClient client = new RestClient(url)
            {
                CookieContainer = CookieContainer
            };
            var request = new RestRequest(Method.POST);

            request.AddHeader("sessionTokenKey", "szFn6zAbjjU=");
            request.AddHeader("SessionToken", "szFn6zAbjjU=");
            request.AddHeader("clientType", "cpdaily_student");
            request.AddHeader("deviceType", "1");
            request.AddHeader("CpdailyClientType", "CPDAILY");
            request.AddHeader("CpdailyStandAlone", "0");
            request.AddHeader("CpdailyInfo", DeviceInfo.EncryptCache);
            request.AddHeader("User-Agent", ApiUserAgent);
            request.AddJsonBody(new { a = data, b = "firstv" });
            var response = await client.ExecutePostAsync(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("非200状态响应");
            }
            var apiResponse = JsonConvert.DeserializeObject <ApiResponse>(response.Content);

            if (apiResponse.ErrorCode != 0)
            {
                throw new Exception($"出现错误: {apiResponse.ErrorMessage}, 错误代码: {apiResponse.ErrorCode}。");
            }
            var json = JObject.Parse(CpdailyCrypto.DESDecrypt(apiResponse.Data, CpdailyCrypto.GetDESKey(chk), CpdailyCrypto.IV));

            return(json.ToObject <LoginResult>());
        }