/// <summary>
        /// 异步执行
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request">请求对象</param>
        /// <returns></returns>
        public async Task <T> ExecuteAsync <T>(IWxApiRequest <T> request) where T : WxApiResponse
        {
            try
            {
                var sortedParams = new WxApiDictionary(request.GetParameters());  //Url  参数
                var content      = Utility.BulidContent(sortedParams);
                var IsPost       = request.IsPost();
                var url          = !string.IsNullOrEmpty(content) ? $"{request.GetRequestUrl()}?{content}" : request.GetRequestUrl();

                var client      = new RestClient(url);
                var restRequest = new RestRequest(!IsPost ? Method.GET : Method.POST)
                {
                    Timeout = 10000,
                };
                if (IsPost)
                {
                    var bodyParams = new WxApiDictionary(request.GetBodyParametes()); //Body 参数
                    var body       = Utility.BulidJsonContent(bodyParams);

                    if (!string.IsNullOrEmpty(body))
                    {
                        restRequest.AddParameter(Constants.ContentType_Json, body, ParameterType.RequestBody);
                    }
                }

                var response = await client.ExecuteTaskAsync(restRequest);


                if (response.ContentType != null && !response.ContentType.Contains(Constants.Json) && !response.ContentType.Contains(Constants.Text))
                {
                    var contenttype = response.ContentType;

                    //判断返回的类型是否为空,若为空,根据数据获取对应的文件类型
                    if (string.IsNullOrEmpty(response.ContentType))
                    {
                        contenttype = FileContentType.Get(response.RawBytes);
                    }

                    return(new WxApiFileResponse
                    {
                        ErrCode = 0,
                        Errmsg = "",
                        Buffer = response.RawBytes,
                        ContentType = string.IsNullOrEmpty(response.ContentType) ? contenttype : response.ContentType
                    } as T);
                }

                return(JsonConvert.DeserializeObject <T>(response.Content));
            }
            catch (WxApiException ex)
            {
                throw new WxApiException(ex.Message);
            }
        }
        /// <summary>
        /// 异步执行
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request">请求对象</param>
        /// <param name="UploadFilePath">文件绝对路径</param>
        /// <returns></returns>
        public async Task <T> ExecuteAsync <T>(IWxApiRequest <T> request) where T : WxApiResponse
        {
            try
            {
                var sortedParams = new WxApiDictionary(request.GetParameters());
                var content      = Utility.BulidContent(sortedParams);
                var IsPost       = request.IsPost();
                var url          = !IsPost ? $"{request.GetRequestUrl()}?{content}" : request.GetRequestUrl();
                var filterKey    = new List <string>(); // Post 中进行过滤掉的请求参数

                if (IsPost)
                {
                    //判断是否存在access_token参数
                    if (sortedParams.ContainsKey(access_token))
                    {
                        filterKey.Add(access_token);
                        url += $"?{access_token}={sortedParams.GetValue(access_token)}";
                        if (sortedParams.ContainsKey(type) && !(request is WxApiGetMaterialListRequest))
                        {
                            url += $"&{type }={sortedParams.GetValue(type)}";
                            filterKey.Add(type);
                        }
                        if (sortedParams.ContainsKey(kf_account) && request is WxApiSetCustomerHeadImgRequest)//设置客服帐号的头像 -特殊
                        {
                            url += $"&{kf_account }={sortedParams.GetValue(kf_account)}";
                            filterKey.Add(kf_account);
                        }
                        if (request is WxApiTranslateContentRequest) //微信翻译
                        {
                            url += $"&{lfrom }={sortedParams.GetValue(lfrom)}";
                            filterKey.Add(lfrom);
                            url += $"&{lto}={sortedParams.GetValue(lto)}";
                            filterKey.Add(lto);
                        }
                        if (request is WxApiAddVoiceTorecofortextRequest)//提交语音
                        {
                            url += $"&{format}={sortedParams.GetValue(format)}";
                            filterKey.Add(format);
                            url += $"&{voice_id}={sortedParams.GetValue(voice_id)}";
                            filterKey.Add(voice_id);
                            url += $"&{lang}={sortedParams.GetValue(lang)}";
                            filterKey.Add(lang);
                        }
                    }
                }

                var client      = new RestClient(url);
                var restRequest = new RestRequest(!IsPost ? Method.GET : Method.POST)
                {
                    Timeout = 10000
                };
                if (IsPost)
                {
                    //判断文件是否存在
                    if (!string.IsNullOrEmpty(sortedParams.GetValue(media_path)?.ToString()) && System.IO.File.Exists(media_path))
                    {
                        /////把媒体文件上传到微信服务器。目前仅支持图片。用于发送客服消息或被动回复用户消息。
                        if (request is WxApiUploadTempMediaRequest || request is WxApiSetCustomerHeadImgRequest ||
                            request is WxApiImgSecCheckRequest || request is WxApiUploadImgRequest ||
                            request is WxApiUploadMaterialRequest || request is WxApiTranslateContentRequest)
                        {
                            var fileType    = System.IO.Path.GetExtension(sortedParams.GetValue(media_path).ToString());
                            var media_type  = sortedParams.GetValue(type).ToString();
                            var contentType = "application/x-www-form-urlencoded;charset=UTF-8";
                            //restRequest.AddFile(media_type == mediatype?"media": $"{Guid.NewGuid().ToString("N")}{fileType}", sortedParams.GetValue(media_path), contentType);
                            restRequest.AddFile("media", sortedParams.GetValue(media_path).ToString(), contentType);


                            if (request is WxApiUploadMaterialRequest && media_type == mediatype)
                            {
                                restRequest.AddParameter(description, sortedParams.GetValue(description));
                            }
                        }
                    }
                    //else if(request is WxApiCreateLandingPageRequest)
                    //{
                    //    content = Utility.BulidJsonContent(sortedParams, filterKey);
                    //    var bytes = System.Text.Encoding.Default.GetBytes(content);
                    //    var contentType = "application/x-www-form-urlencoded;charset=UTF-8";
                    //    //restRequest.AddFile(media_type == mediatype?"media": $"{Guid.NewGuid().ToString("N")}{fileType}", sortedParams.GetValue(media_path), contentType);
                    //    restRequest.AddFileBytes("buffer", bytes, contentType);
                    //}
                    else
                    {
                        var contentType = "application/json;charset=UTF-8";
                        if (sortedParams.ContainsKey(body)) //参数中是否包含 body 字符串,不是Json数据
                        {
                            contentType = "text/plain";
                            content     = sortedParams.GetValue(body).ToString();
                        }
                        else
                        {
                            content = Utility.BulidJsonContent(sortedParams, filterKey);
                        }

                        if (!string.IsNullOrEmpty(content))
                        {
                            restRequest.AddParameter(contentType, content, ParameterType.RequestBody);
                        }
                    }
                }



                using (var t = client.ExecuteTaskAsync(restRequest))
                {
                    t.Wait();
                    var response = await t;
                    if (request is WxApiGetTempMediaRequest || request is WxApiShowQRCodeRequest || request is WxApiGetMaterialRequest)
                    {
                        if (!response.ContentType.Contains("json") && !response.ContentType.Contains("text"))
                        {
                            var contenttype = response.ContentType;

                            ///判断返回的类型是否为空,若为空,根据数据获取对应的文件类型
                            if (string.IsNullOrEmpty(response.ContentType))
                            {
                                contenttype = FileContentType.Get(response.RawBytes);
                            }

                            ///获取永久素材返回
                            if (request is WxApiGetMaterialRequest)
                            {
                                return(new WxApiGetMaterialResponse
                                {
                                    ErrCode = 0,
                                    Errmsg = "",
                                    Buffer = response.RawBytes,
                                    ContentType = string.IsNullOrEmpty(response.ContentType) ? contenttype : response.ContentType
                                } as T);
                            }
                            return(new WxApiFileResponse
                            {
                                ErrCode = 0,
                                Errmsg = "",
                                Buffer = response.RawBytes,
                                ContentType = string.IsNullOrEmpty(response.ContentType) ? contenttype : response.ContentType
                            } as T);
                        }
                    }
                    return(JsonConvert.DeserializeObject <T>(response.Content));
                }
            }
            catch (Exception ex)
            {
            }
            return(null);
        }
        /// <summary>
        /// 异步执行 针对文件请求 media_path / body
        /// <para>
        /// 1、把媒体文件上传到微信服务器
        /// 2、设置客服帐号的头像
        /// 3、提交语音
        /// 4、微信翻译
        /// 5、上传图片
        /// 6、新增其他类型永久素材
        /// 7、校验一张图片是否含有违法违规内容
        /// </para>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request">请求对象</param>
        /// <returns></returns>
        public async Task <T> ExecuteFileAsync <T>(IWxApiRequest <T> request) where T : WxApiResponse
        {
            try
            {
                var sortedParams = new WxApiDictionary(request.GetParameters());  //Url  参数
                var content      = Utility.BulidContent(sortedParams);
                var IsPost       = request.IsPost();
                var url          = !string.IsNullOrEmpty(content) ? $"{request.GetRequestUrl()}?{content}" : request.GetRequestUrl();

                var client      = new RestClient(url);
                var restRequest = new RestRequest(!IsPost ? Method.GET : Method.POST)
                {
                    Timeout = 12000,
                };
                if (IsPost)
                {
                    var bodyParams = new WxApiDictionary(request.GetBodyParametes()); //Body 参数
                    if (!string.IsNullOrEmpty(bodyParams.GetValue(Constants.Media_path)?.ToString()) && System.IO.File.Exists(Constants.Media_path))
                    {
                        var fileType   = System.IO.Path.GetExtension(bodyParams.GetValue(Constants.Media_path).ToString());
                        var media_type = bodyParams.GetValue(Constants.Type).ToString();
                        restRequest.AddFile("media", bodyParams.GetValue(Constants.Media_path).ToString(), Constants.ContentType_Form);

                        if (media_type == Constants.Mediatype)
                        {
                            restRequest.AddParameter(Constants.Description, bodyParams.GetValue(Constants.Description));
                        }
                    }

                    if (bodyParams.ContainsKey(Constants.Body)) //参数中是否包含 body 字符串,不是Json数据
                    {
                        var contentType = Constants.ContentType_Text;
                        var body        = bodyParams.GetValue(Constants.Body).ToString();
                        //语音内容 或 翻译内容
                        if (!string.IsNullOrEmpty(body))
                        {
                            restRequest.AddParameter(contentType, body, ParameterType.RequestBody);
                        }
                    }
                }

                var response = await client.ExecuteTaskAsync(restRequest);

                if (response.ContentType != null && !response.ContentType.Contains(Constants.Json) && !response.ContentType.Contains(Constants.Text))
                {
                    var contenttype = response.ContentType;

                    //判断返回的类型是否为空,若为空,根据数据获取对应的文件类型
                    if (string.IsNullOrEmpty(response.ContentType))
                    {
                        contenttype = FileContentType.Get(response.RawBytes);
                    }

                    return(new WxApiFileResponse
                    {
                        ErrCode = 0,
                        Errmsg = "",
                        Buffer = response.RawBytes,
                        ContentType = string.IsNullOrEmpty(response.ContentType) ? contenttype : response.ContentType
                    } as T);
                }

                return(JsonConvert.DeserializeObject <T>(response.Content));
            }
            catch (WxApiException ex)
            {
                throw new WxApiException(ex.Message);
            }
        }