/// <summary>
        /// 获取关注信息。
        /// </summary>
        /// <param name="startDate">起始日期。</param>
        /// <param name="endDate">结束日期。</param>
        /// <returns>关注信息数组。</returns>
        public AttentionInfo[] GetAttentions(DateTime startDate, DateTime endDate)
        {
            //得到AppId和插件Token。
            var info = GetAppIdAndPluginToken();

            var appId       = info.Key;
            var pluginToken = info.Value;

            //关注数据请求Url。
            var url = string.Format(
                "https://mta.qq.com/mta/wechat/ctr_user_summary/get_table_data/?start_date={0}&end_date={1}&need_compare=0&start_compare_date=&end_compare_date=&app_id=&source_list=-1&source_show=35%2C3%2C43%2C17%2C0&appid={2}&pluginid=luopan&token={3}&from=&devtype=2&time_type=day&ajax=1",
                startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"), appId, pluginToken);

            using (var client = new LastingWebClient(_cookieContainer))
            {
                var data            = client.DownloadData(url);
                var json            = Encoding.UTF8.GetString(data);
                var weiXinAttention = new JavaScriptSerializer().Deserialize <WeiXinAttentionInfo>(json);

                return((weiXinAttention == null || weiXinAttention.Data == null) ? new AttentionInfo[0] : weiXinAttention.Data.Select(i =>
                                                                                                                                      new AttentionInfo
                {
                    CancelUser = i.GetCancelUser(),
                    CumulateUser = i.GetCumulateUser(),
                    Date = i.RefDate,
                    NewUser = i.GetNewUser(),
                    NetUser = i.GetNewUser(),
                }).ToArray());
            }
        }
        /// <summary>
        /// 用户微信用户信息。
        /// </summary>
        /// <returns>用户信息。</returns>
        public UserInfo GetUserInfo()
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                var html = Encoding.UTF8.GetString(client.DownloadData(
                                                       string.Format(
                                                           "https://mp.weixin.qq.com/cgi-bin/settingpage?t=setting/index&action=index&token={0}&lang=zh_CN",
                                                           LoginResult.Token)));
                var document = new HtmlDocument();
                document.LoadHtml(html);

                var offset = 0;
                var type   = GetMetaContent(document, 4);
                switch (type)
                {
                case "服务号":
                    offset = 0;
                    break;

                default:
                    offset = 1;
                    break;
                }

                var user = new UserInfo
                {
                    Picture = new Lazy <byte[]>(() =>
                    {
                        using (var c = new LastingWebClient(_cookieContainer))
                        {
                            return(c.DownloadData(
                                       document.DocumentNode.CssSelect(".avatar").FirstOrDefault().GetAttributeValue("src").Insert(0, "https://mp.weixin.qq.com")));
                        }
                    }),
                    Name               = GetMetaContent(document, 2),
                    LoginEmail         = GetMetaContent(document, 10 - offset),
                    OriginalId         = GetMetaContent(document, 11 - offset),
                    UserName           = GetMetaContent(document, 3),
                    Type               = type,
                    AuthenticateStatus = GetMetaContent(document, 6),
                    Body               = GetMetaContent(document, 9 - offset),
                    Area               = GetMetaContent(document, 8 - offset),
                    Description        = GetMetaContent(document, 5),
                    QrCode             = new Lazy <byte[]>(() =>
                    {
                        using (var c = new LastingWebClient(_cookieContainer))
                        {
                            return(c.DownloadData(
                                       document.DocumentNode.CssSelect(".verifyInfo").FirstOrDefault().GetAttributeValue("href").Insert(0, "https://mp.weixin.qq.com")));
                        }
                    })
                };
                return(user);
            }
        }
        /// <summary>
        /// 设置编辑或者开发者模式。
        /// </summary>
        /// <param name="type">类型,1代表编辑模式,2代表开发者模式。</param>
        /// <param name="enable">是否开启对应的模式。</param>
        private bool SetEditOrDevelopMode(int type, bool enable)
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                client.Headers.Add("Referer", "https://mp.weixin.qq.com/");

                var data = client.UploadData("https://mp.weixin.qq.com/misc/skeyform?form=advancedswitchform&lang=zh_CN", "POST",
                                             Encoding.UTF8.GetBytes(string.Format("flag={0}&type={1}&token={2}", enable ? 1 : 0, type, LoginResult.Token)));
                var json = Encoding.UTF8.GetString(data);
                return(json.StartsWith("{\"base_resp\":{\"ret\":0,\"err_msg\":\"ok\"}"));
            }
        }
 /// <summary>
 /// 设置OAuth回调域名。
 /// </summary>
 /// <param name="domain"></param>
 /// <returns></returns>
 public bool SetOAuthDomain(string domain)
 {
     using (var client = new LastingWebClient(_cookieContainer))
     {
         client.Headers.Add("Referer", "https://mp.weixin.qq.com/");
         var data = client.UploadData("https://mp.weixin.qq.com/merchant/myservice?action=set_oauth_domain&f=json",
                                      Encoding.UTF8.GetBytes(
                                          string.Format("token={0}&lang=zh_CN&f=json&ajax=1&random=0.18229547117417194&domain={1}",
                                                        _loginResult.Token, domain)));
         var content = Encoding.UTF8.GetString(data);
         return(content.Contains("ok"));
     }
 }
        private KeyValuePair <string, string> GetAppIdAndPluginToken()
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("Referer", string.Format("https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token={0}", _loginResult.Token));
                var url =
                    string.Format(
                        "https://mp.weixin.qq.com/misc/pluginloginpage?action=stat_user_summary&pluginid=luopan&t=statistics/index&token={0}&lang=zh_CN",
                        _loginResult.Token);
                var html = Encoding.UTF8.GetString(client.DownloadData(url));

                var appId       = GetJsonValue(html, "appid : '");
                var pluginToken = GetJsonValue(html, "pluginToken : '");

                return(new KeyValuePair <string, string>(appId, pluginToken));
            }
        }
        /// <summary>
        /// 登录微信。
        /// </summary>
        /// <param name="userName">用户名称。</param>
        /// <param name="password">用户密码。</param>
        /// <returns>登录结果。</returns>
        public LoginResult Login(string userName, string password)
        {
            _isLogin = true;
            _cookieContainer = new CookieContainer();
            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("Referer", "https://mp.weixin.qq.com/");
                client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                var data = client.UploadData("https://mp.weixin.qq.com/cgi-bin/login",
                    "POST",
                    Encoding.UTF8.GetBytes("username="******"&pwd=" + Md5Hash(password) + "&imgcode=&f=json"));

                var token = GetToken(Encoding.UTF8.GetString(data));
                return _loginResult = string.IsNullOrWhiteSpace(token) ? null : new LoginResult
                {
                    Token = token
                };
            }
        }
        /// <summary>
        /// 登录微信。
        /// </summary>
        /// <param name="userName">用户名称。</param>
        /// <param name="password">用户密码。</param>
        /// <returns>登录结果。</returns>
        public LoginResult Login(string userName, string password)
        {
            _isLogin         = true;
            _cookieContainer = new CookieContainer();
            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("Referer", "https://mp.weixin.qq.com/");
                client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                var data = client.UploadData("https://mp.weixin.qq.com/cgi-bin/login",
                                             "POST",
                                             Encoding.UTF8.GetBytes("username="******"&pwd=" + Md5Hash(password) + "&imgcode=&f=json"));

                var token = GetToken(Encoding.UTF8.GetString(data));
                return(_loginResult = string.IsNullOrWhiteSpace(token) ? null : new LoginResult
                {
                    Token = token
                });
            }
        }
        /// <summary>
        /// 设置开发者接口信息(会自动开启开发者模式)。
        /// </summary>
        /// <param name="url">Url地址。</param>
        /// <param name="token">令牌。</param>
        /// <param name="aeskey">EncodingAESKey。</param>
        /// <param name="encryptMode">加密模式。</param>
        /// <returns>是否更新成功。</returns>
        public bool SetDevelopInterface(string url, string token, string aeskey, EncryptMode encryptMode)
        {
            //开启开发者模式。
            if (!SetDevelopMode(true))
            {
                throw new WeiXinWebApiException("更新开发者接口信息失败,因为开启开发者模式失败。");
            }

            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("Referer", "https://mp.weixin.qq.com/");
                client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                var data = client.UploadData(
                    string.Format("https://mp.weixin.qq.com/advanced/callbackprofile?t=ajax-response&token={0}&lang=zh_CN", LoginResult.Token),
                    "POST", Encoding.UTF8.GetBytes(string.Format("url={0}&callback_token={1}&encoding_aeskey={2}&callback_encrypt_mode={3}", HttpUtility.UrlEncode(url), token, aeskey, (int)encryptMode)));
                var json = Encoding.UTF8.GetString(data);
                return(json.Contains("\"err_msg\":\"ok\""));
            }
        }
        /// <summary>
        /// 获取开发者凭据。
        /// </summary>
        /// <returns>如果具有开发者凭据则返回否则返回null。</returns>
        public DevelopCredential GetDevelopCredential()
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                var url = string.Format(
                    "https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token={0}&lang=zh_CN",
                    _loginResult.Token);
                var html     = Encoding.UTF8.GetString(client.DownloadData(url));
                var document = new HtmlDocument();
                document.LoadHtml(html);

                var items = document.DocumentNode.CssSelect(".developer_info_item").ToArray();

                if (items.Count() < 4)
                {
                    return(null);
                }

                var item = items.First();

                var controls = item.CssSelect(".frm_controls").ToArray();

                string appSecret;
                using (var reader = new StringReader(controls.Last().InnerText.Trim()))
                    appSecret = reader.ReadLine();

                if (!string.IsNullOrWhiteSpace(appSecret))
                {
                    var index = appSecret.Trim().IndexOf(" ", StringComparison.Ordinal);
                    if (index != -1)
                    {
                        appSecret = appSecret.Substring(0, index);
                    }
                }

                return(new DevelopCredential
                {
                    AppId = controls.First().InnerText.Trim(),
                    AppSecret = appSecret
                });
            }
        }
        /// <summary>
        /// 用户微信用户信息。
        /// </summary>
        /// <returns>用户信息。</returns>
        public UserInfo GetUserInfo()
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                var html = Encoding.UTF8.GetString(client.DownloadData(
                    string.Format(
                        "https://mp.weixin.qq.com/cgi-bin/settingpage?t=setting/index&action=index&token={0}&lang=zh_CN",
                        LoginResult.Token)));
                var document = new HtmlDocument();
                document.LoadHtml(html);

                var offset = 0;
                var type = GetMetaContent(document, 4);
                switch (type)
                {
                    case "服务号":
                        offset = 0;
                        break;

                    default:
                        offset = 1;
                        break;
                }

                var user = new UserInfo
                {
                    Picture = new Lazy<byte[]>(() =>
                    {
                        using (var c = new LastingWebClient(_cookieContainer))
                        {
                            return c.DownloadData(
                                document.DocumentNode.CssSelect(".avatar").FirstOrDefault().GetAttributeValue("src").Insert(0, "https://mp.weixin.qq.com"));
                        }
                    }),
                    Name = GetMetaContent(document, 2),
                    LoginEmail = GetMetaContent(document, 10 - offset),
                    OriginalId = GetMetaContent(document, 11 - offset),
                    UserName = GetMetaContent(document, 3),
                    Type = type,
                    AuthenticateStatus = GetMetaContent(document, 6),
                    Body = GetMetaContent(document, 9 - offset),
                    Area = GetMetaContent(document, 8 - offset),
                    Description = GetMetaContent(document, 5),
                    QrCode = new Lazy<byte[]>(() =>
                    {
                        using (var c = new LastingWebClient(_cookieContainer))
                        {
                            return c.DownloadData(
                                document.DocumentNode.CssSelect(".verifyInfo").FirstOrDefault().GetAttributeValue("href").Insert(0, "https://mp.weixin.qq.com"));
                        }
                    })
                };
                return user;
            }
        }
        /// <summary>
        /// 设置编辑或者开发者模式。
        /// </summary>
        /// <param name="type">类型,1代表编辑模式,2代表开发者模式。</param>
        /// <param name="enable">是否开启对应的模式。</param>
        private bool SetEditOrDevelopMode(int type, bool enable)
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                client.Headers.Add("Referer", "https://mp.weixin.qq.com/");

                var data = client.UploadData("https://mp.weixin.qq.com/misc/skeyform?form=advancedswitchform&lang=zh_CN", "POST",
                    Encoding.UTF8.GetBytes(string.Format("flag={0}&type={1}&token={2}", enable ? 1 : 0, type, LoginResult.Token)));
                var json = Encoding.UTF8.GetString(data);
                return json.StartsWith("{\"base_resp\":{\"ret\":0,\"err_msg\":\"ok\"}");
            }
        }
        private KeyValuePair<string, string> GetAppIdAndPluginToken()
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("Referer", string.Format("https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token={0}", _loginResult.Token));
                var url =
                    string.Format(
                        "https://mp.weixin.qq.com/misc/pluginloginpage?action=stat_user_summary&pluginid=luopan&t=statistics/index&token={0}&lang=zh_CN",
                        _loginResult.Token);
                var html = Encoding.UTF8.GetString(client.DownloadData(url));

                var appId = GetJsonValue(html, "appid : '");
                var pluginToken = GetJsonValue(html, "pluginToken : '");

                return new KeyValuePair<string, string>(appId, pluginToken);
            }
        }
 /// <summary>
 /// 设置OAuth回调域名。
 /// </summary>
 /// <param name="domain"></param>
 /// <returns></returns>
 public bool SetOAuthDomain(string domain)
 {
     using (var client = new LastingWebClient(_cookieContainer))
     {
         client.Headers.Add("Referer", "https://mp.weixin.qq.com/");
         var data = client.UploadData("https://mp.weixin.qq.com/merchant/myservice?action=set_oauth_domain&f=json",
             Encoding.UTF8.GetBytes(
                 string.Format("token={0}&lang=zh_CN&f=json&ajax=1&random=0.18229547117417194&domain={1}",
                     _loginResult.Token, domain)));
         var content = Encoding.UTF8.GetString(data);
         return content.Contains("ok");
     }
 }
        /// <summary>
        /// 获取关注信息。
        /// </summary>
        /// <param name="startDate">起始日期。</param>
        /// <param name="endDate">结束日期。</param>
        /// <returns>关注信息数组。</returns>
        public AttentionInfo[] GetAttentions(DateTime startDate, DateTime endDate)
        {
            //得到AppId和插件Token。
            var info = GetAppIdAndPluginToken();

            var appId = info.Key;
            var pluginToken = info.Value;

            //关注数据请求Url。
            var url = string.Format(
                "https://mta.qq.com/mta/wechat/ctr_user_summary/get_table_data/?start_date={0}&end_date={1}&need_compare=0&start_compare_date=&end_compare_date=&app_id=&source_list=-1&source_show=35%2C3%2C43%2C17%2C0&appid={2}&pluginid=luopan&token={3}&from=&devtype=2&time_type=day&ajax=1",
                startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"), appId, pluginToken);

            using (var client = new LastingWebClient(_cookieContainer))
            {
                var data = client.DownloadData(url);
                var json = Encoding.UTF8.GetString(data);
                var weiXinAttention = new JavaScriptSerializer().Deserialize<WeiXinAttentionInfo>(json);

                return (weiXinAttention == null || weiXinAttention.Data == null) ? new AttentionInfo[0] : weiXinAttention.Data.Select(i =>
                    new AttentionInfo
                    {
                        CancelUser = i.GetCancelUser(),
                        CumulateUser = i.GetCumulateUser(),
                        Date = i.RefDate,
                        NewUser = i.GetNewUser(),
                        NetUser = i.GetNewUser(),
                    }).ToArray();
            }
        }
        /// <summary>
        /// 获取开发者凭据。
        /// </summary>
        /// <returns>如果具有开发者凭据则返回否则返回null。</returns>
        public DevelopCredential GetDevelopCredential()
        {
            using (var client = new LastingWebClient(_cookieContainer))
            {
                var url = string.Format(
                    "https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token={0}&lang=zh_CN",
                    _loginResult.Token);
                var html = Encoding.UTF8.GetString(client.DownloadData(url));
                var document = new HtmlDocument();
                document.LoadHtml(html);

                var items = document.DocumentNode.CssSelect(".developer_info_item").ToArray();

                if (items.Count() < 4)
                    return null;

                var item = items.First();

                var controls = item.CssSelect(".frm_controls").ToArray();

                string appSecret;
                using (var reader = new StringReader(controls.Last().InnerText.Trim()))
                    appSecret = reader.ReadLine();

                if (!string.IsNullOrWhiteSpace(appSecret))
                {
                    var index = appSecret.Trim().IndexOf(" ", StringComparison.Ordinal);
                    if (index != -1)
                    {
                        appSecret = appSecret.Substring(0, index);
                    }
                }

                return new DevelopCredential
                {
                    AppId = controls.First().InnerText.Trim(),
                    AppSecret = appSecret
                };
            }
        }
        /// <summary>
        /// 设置开发者接口信息(会自动开启开发者模式)。
        /// </summary>
        /// <param name="url">Url地址。</param>
        /// <param name="token">令牌。</param>
        /// <param name="aeskey">EncodingAESKey。</param>
        /// <param name="encryptMode">加密模式。</param>
        /// <returns>是否更新成功。</returns>
        public bool SetDevelopInterface(string url, string token, string aeskey, EncryptMode encryptMode)
        {
            //开启开发者模式。
            if (!SetDevelopMode(true))
                throw new WeiXinWebApiException("更新开发者接口信息失败,因为开启开发者模式失败。");

            using (var client = new LastingWebClient(_cookieContainer))
            {
                client.Headers.Add("Referer", "https://mp.weixin.qq.com/");
                client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                var data = client.UploadData(
                    string.Format("https://mp.weixin.qq.com/advanced/callbackprofile?t=ajax-response&token={0}&lang=zh_CN", LoginResult.Token),
                    "POST", Encoding.UTF8.GetBytes(string.Format("url={0}&callback_token={1}&encoding_aeskey={2}&callback_encrypt_mode={3}", HttpUtility.UrlEncode(url), token, aeskey, (int)encryptMode)));
                var json = Encoding.UTF8.GetString(data);
                return json.Contains("\"err_msg\":\"ok\"");
            }
        }