using APT.Infrastructure.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Xml.Linq;
using APT.Infrastructure.Api;

namespace APT.Utility
{
    public class WeChatPayHelper
    {
        // private static readonly Logger _logger = LogManager.GetCurrentClassLogger();

        public static WeixinToken GetToken()
        {
            var appId = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]).ToString();
            var secret = LibUtils.ToString(ConfigurationManager.WexinSettings["AppSecret"]).ToString();
            var toenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + secret;
            var res = HttpMethods.Get(toenUrl);
            WeixinToken token = JsonConvert.DeserializeObject<WeixinToken>(res);
            if (token == null || !string.IsNullOrEmpty(token.errcode))
                throw new Exception("获取token失败");
            APT.Infrastructure.Api.AppContext.WxToken = token;
            return token;
        }
        public class WxMessageModel
        {
            public string touser { get; set; }
            public string template_id { get; set; }
            public dynamic data { get; set; }

        }

        public class WxMessageReturnModel
        {
            public int errcode { get; set; }
            public string errmsg { get; set; }

        }
        public static int SendWxMessage(string openid, string token, string tmpId, dynamic data)
        {
            var msgUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token;
            var sendObj = new WxMessageModel
            {
                template_id = tmpId,
                touser = openid,
                data = data,
            };
            var sendStr = JsonConvert.SerializeObject(sendObj);
            var returnStr = HttpMethods.Post(msgUrl, sendStr);
            var retObj = JsonConvert.DeserializeObject<WxMessageReturnModel>(returnStr);
            return retObj.errcode;
        }

        public static PayRequesEntity Unifiedorder(string openid, int totalfee, string orderNo,string orderType, string macId, string wxPaykey)
        {
            //var PayUrl = AppSetting.Load().WechatPayStrings.FirstOrDefault().UnifiedorderURL;
            //获取统一下单参数
            var param = GetUnifiedOrderParam(openid, orderNo, totalfee, orderType, macId, wxPaykey);
            //_logger.Info(() => "微信支付统一下单 发送参数为 " + param + "");
            //统一下单后拿到的xml结果

            var payResXML = HttpMethods.Post(LibUtils.ToString(ConfigurationManager.WexinSettings["UnifiedorderURL"]).ToString(), param);
            //_logger.Info(() => "微信支付统一下单 返回参数为 " + payResXML + "");
            var payRes = XDocument.Parse(payResXML);
            var root = payRes.Element("xml");
            var res = GetPayRequestParam(root, wxPaykey);
            //_logger.Info(() => "微信支付统一下单 参数实体为 " + JsonConvert.SerializeObject(res) + "");
            return res;
        }
        /// <summary>
        /// 取消订单退款接口
        /// </summary>
        /// <param name="totalfee"></param>
        /// <param name="refundfee"></param>
        /// <param name="orderNo"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public static bool Cancelorder(int totalfee, int refundfee, string orderNo, string code)
        {
            //var PayUrl = AppSetting.Load().WechatPayStrings.FirstOrDefault().UnifiedorderURL;
            //获取统一下单参数
            var param = GetCancelOrderParam(orderNo, code, totalfee, refundfee);
            //_logger.Info(() => "微信支付统一下单 发送参数为 " + param + "");
            //统一下单后拿到的xml结果

            var payResXML = HttpMethods.PostByCert(param, LibUtils.ToString(ConfigurationManager.WexinSettings["CancelorderURL"]).ToString(), true, 5);
            //_logger.Info(() => "微信支付统一下单 返回参数为 " + payResXML + "");
            var payRes = XDocument.Parse(payResXML);
            var root = payRes.Element("xml");
            return GetCancelOrderParam(root);
            //_logger.Info(() => "微信支付统一下单 参数实体为 " + JsonConvert.SerializeObject(res) + "");
        }
        /// <summary>
        /// 取消订单退款接口
        /// </summary>
        /// <param name="totalfee"></param>
        /// <param name="refundfee"></param>
        /// <param name="orderNo"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public static bool CancelorderByTenant(int totalfee, int refundfee, string orderNo, string code, string orderType, string macId, string wxPaykey,string certpath,string certpassword)
        {
            //var PayUrl = AppSetting.Load().WechatPayStrings.FirstOrDefault().UnifiedorderURL;
            //获取统一下单参数
            var param = GetCancelOrderParamByTenant(orderNo, code, totalfee, refundfee ,orderType, macId, wxPaykey);
            //_logger.Info(() => "微信支付统一下单 发送参数为 " + param + "");
            //统一下单后拿到的xml结果

            var payResXML = HttpMethods.PostByCertByTenant(param, 
                    LibUtils.ToString(ConfigurationManager.WexinSettings["CancelorderURL"]).ToString(), true, 5, certpath, certpassword);
            //_logger.Info(() => "微信支付统一下单 返回参数为 " + payResXML + "");
            var payRes = XDocument.Parse(payResXML);
            var root = payRes.Element("xml");
            return GetCancelOrderParam(root);
            //_logger.Info(() => "微信支付统一下单 参数实体为 " + JsonConvert.SerializeObject(res) + "");
        }
        /// <summary>
        /// 微信转账到零钱接口
        /// </summary>
        /// <param name="orderNo">单号</param>
        /// <param name="openid">openId</param>
        /// <param name="username">用户名</param>
        /// <param name="fee">金额</param>
        /// <param name="desc">备注</param>
        /// <returns></returns>
        public static bool PayforChange(string orderNo, string openid, string username, int fee, string desc)
        {
            //var PayUrl = AppSetting.Load().WechatPayStrings.FirstOrDefault().UnifiedorderURL;
            //获取统一下单参数
            var param = GetPayforChangeParam(orderNo, openid, username, fee, desc);
            //_logger.Info(() => "微信支付统一下单 发送参数为 " + param + "");
            //统一下单后拿到的xml结果

            var payResXML = HttpMethods.PostByCert(param, LibUtils.ToString(ConfigurationManager.WexinSettings["PayForChangeUrl"]).ToString(), true, 5);
            //_logger.Info(() => "微信支付统一下单 返回参数为 " + payResXML + "");
            var payRes = XDocument.Parse(payResXML);
            var root = payRes.Element("xml");
            return GetCancelOrderParam(root);
            //_logger.Info(() => "微信支付统一下单 参数实体为 " + JsonConvert.SerializeObject(res) + "");
        }



        /// <summary>
        /// 取统一下单的请求参数
        /// </summary>
        /// <param name="openid"></param>
        /// <returns></returns>
        private static string GetUnifiedOrderParam(string openid, string orderNo, int totalfee, string orderType, string mch_id, string wxPaykey)
        {
            string appid = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]);
            string secret = LibUtils.ToString(ConfigurationManager.WexinSettings["AppSecret"]);
            //string mch_id = LibUtils.ToString(ConfigurationManager.WexinSettings["Mch_ID"]);

            string ip = LibUtils.ToString(ConfigurationManager.WexinSettings["IP"]);
            string PayResulturl = LibUtils.ToString(ConfigurationManager.WexinSettings["WxPayResultUrl"]);

            string strcode = "充电-下单";////商品描述交易字段格式根据不同的应用场景按照以下格式：APP——需传入应用市场上的APP名字-实际商品名称，天天爱消除-游戏充值。
            byte[] buffer = Encoding.UTF8.GetBytes(strcode);
            string body = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            System.Random Random = new System.Random();
            var dic = new Dictionary<string, string>
                {
                    {"appid", appid},
                    {"mch_id", mch_id},
                    {"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
                    {"body",body},
                    {"out_trade_no",orderNo+"_"+totalfee+"_" +orderType},//商户自己的订单号码
                    {"total_fee",totalfee.ToString()},
                    {"spbill_create_ip",ip},//服务器的IP地址
                    {"notify_url",PayResulturl},//异步通知的地址，不能带参数
                    {"trade_type","JSAPI" },
                    {"openid",openid}
                };
            //加入签名
            dic.Add("sign", GetSignStringByTenant(dic,wxPaykey));

            var sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (var d in dic)
            {
                sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
            }
            sb.Append("</xml>");
            return sb.ToString();
        }
        /// <summary>
        /// 取统一下单的请求参数
        /// </summary>
        /// <param name="openid"></param>
        /// <returns></returns>
        private static string GetCancelOrderParam(string orderNo, string code, int totalfee, int refundfee)
        {
            string appid = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]);
            //string secret = LibUtils.ToString(ConfigurationManager.WexinSettings["AppSecret"]);
            string mch_id = LibUtils.ToString(ConfigurationManager.WexinSettings["Mch_ID"]);
            string ip = LibUtils.ToString(ConfigurationManager.WexinSettings["IP"]);
            string WxPayCancelUrl = LibUtils.ToString(ConfigurationManager.WexinSettings["WxPayCancelUrl"]);

            string strcode = "充电-支付";////商品描述交易字段格式根据不同的应用场景按照以下格式：APP——需传入应用市场上的APP名字-实际商品名称，天天爱消除-游戏充值。
            byte[] buffer = Encoding.UTF8.GetBytes(strcode);
            string body = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            System.Random Random = new System.Random();
            var dic = new Dictionary<string, string>
                {
                    {"appid", appid},
                    {"mch_id", mch_id},
                    {"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
                    {"out_trade_no",orderNo+"_"+totalfee},//商户自己的订单号码
                    {"out_refund_no",code+"@"+totalfee},//退款单号
                    {"total_fee",totalfee.ToString()},
                    {"refund_fee", refundfee.ToString()},//退款金额
                    { "notify_url",WxPayCancelUrl},//异步通知的地址，不能带参数
                };
            //加入签名
            dic.Add("sign", GetSignString(dic));

            var sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (var d in dic)
            {
                sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
            }
            sb.Append("</xml>");
            return sb.ToString();
        }
        private static string GetCancelOrderParamByTenant(string orderNo, string code, int totalfee, int refundfee , string orderType, string mch_id, string wxPaykey)
        {
            string appid = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]);
            //string secret = LibUtils.ToString(ConfigurationManager.WexinSettings["AppSecret"]);
            //string mch_id = LibUtils.ToString(ConfigurationManager.WexinSettings["Mch_ID"]);
            string ip = LibUtils.ToString(ConfigurationManager.WexinSettings["IP"]);
            string WxPayCancelUrl = LibUtils.ToString(ConfigurationManager.WexinSettings["WxPayCancelUrl"]);

            string strcode = "充电-支付";////商品描述交易字段格式根据不同的应用场景按照以下格式：APP——需传入应用市场上的APP名字-实际商品名称，天天爱消除-游戏充值。
            byte[] buffer = Encoding.UTF8.GetBytes(strcode);
            string body = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            System.Random Random = new System.Random();
            var dic = new Dictionary<string, string>
                {
                    {"appid", appid},
                    {"mch_id", mch_id},
                    {"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
                    {"out_trade_no",orderNo+"_"+totalfee+"_"+orderType},//商户自己的订单号码
                    {"out_refund_no",code+"@"+totalfee},//退款单号
                    {"total_fee",totalfee.ToString()},
                    {"refund_fee", refundfee.ToString()},//退款金额
                    { "notify_url",WxPayCancelUrl},//异步通知的地址，不能带参数
                };
            //加入签名
            dic.Add("sign", GetSignStringByTenant(dic, wxPaykey));

            var sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (var d in dic)
            {
                sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
            }
            sb.Append("</xml>");
            return sb.ToString();
        }
        /// <summary>
        /// 取统一下单的请求参数
        /// </summary>
        /// <param name="openid"></param>
        /// <returns></returns>
        private static string GetPayforChangeParam(string orderNo, string openid, string username, int fee, string desc)
        {
            string appid = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]);
            //string secret = LibUtils.ToString(ConfigurationManager.AppSettings["AppSecret"]);
            string mch_id = LibUtils.ToString(ConfigurationManager.WexinSettings["Mch_ID"]);
          


            System.Random Random = new System.Random();
            var dic = new Dictionary<string, string>
                {
                    {"mch_appid", appid},
                    {"mchid", mch_id},
                    {"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
                    {"partner_trade_no",orderNo},//提现的订单号
                    {"openid",openid},
                    {"check_name","NO_CHECK"},//校验姓名:FORCE_CHECK，NO_CHECK：不校验
                    {"re_user_name",username},//用户姓名
                    {"amount", fee.ToString()},//退款金额
                    { "desc",desc},//异步通知的地址，不能带参数
                };
            //加入签名
            dic.Add("sign", GetSignString(dic));

            var sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (var d in dic)
            {
                sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
            }
            sb.Append("</xml>");
            return sb.ToString();
        }


        /// <summary>
        /// 获取返回给小程序的支付参数
        /// </summary>
        /// <param name="root"></param>
        /// <param name="appid"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        private static PayRequesEntity GetPayRequestParam(XElement root, string wxPaykey)
        {
            string appid = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]);
            //当return_code 和result_code都为SUCCESS时才有我们要的prepay_id
            if (root.Element("return_code").Value == "SUCCESS" && root.Element("result_code").Value == "SUCCESS")
            {
                var res = new Dictionary<string, string>
                {
                    {"appId", appid},
                    {"timeStamp", Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString()},
                    {"nonceStr", GetRandomString(20)},
                    {"package",  "prepay_id=" + root.Element("prepay_id").Value},
                    {"signType", "MD5"}
                };
                //在服务器上签名
                res.Add("paySign", GetSignStringByTenant(res, wxPaykey));

                var payEntity = new PayRequesEntity
                {
                    package = res["package"],
                    nonceStr = res["nonceStr"],
                    paySign = res["paySign"],
                    signType = res["signType"],
                    timeStamp = res["timeStamp"]
                };
                return payEntity;
            }
            else
            {
                throw new Exception("微信返回错误：" + root.Element("err_code_des").Value);
            }

            return new PayRequesEntity();
        }
        /// <summary>
        /// 取消订单退款接口
        /// </summary>
        /// <param name="root"></param>
        /// <returns></returns>
        private static bool GetCancelOrderParam(XElement root)
        {
            string appid = LibUtils.ToString(ConfigurationManager.WexinSettings["AppId"]);
            //当return_code 和result_code都为SUCCESS时才有我们要的prepay_id
            if (root.Element("return_code").Value == "SUCCESS" && root.Element("result_code").Value == "SUCCESS")
            {

                return true;
            }
            else
            {
                throw new Exception("微信返回错误：" + root.ToString());
            }

        }

        /// <summary>
        /// 从字符串里随机得到，规定个数的字符串.
        /// </summary>
        /// <param name="allChar"></param>
        /// <param name="CodeCount"></param>
        /// <returns></returns>
        private static string GetRandomString(int CodeCount)
        {
            string allChar = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,i,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
            string[] allCharArray = allChar.Split(',');
            string RandomCode = "";
            int temp = -1;
            Random rand = new Random();
            for (int i = 0; i < CodeCount; i++)
            {
                if (temp != -1)
                {
                    rand = new Random(temp * i * ((int)DateTime.Now.Ticks));
                }
                int t = rand.Next(allCharArray.Length - 1);
                while (temp == t)
                {
                    t = rand.Next(allCharArray.Length - 1);
                }
                temp = t;
                RandomCode += allCharArray[t];
            }

            return RandomCode;
        }


        private static string GetSignString(Dictionary<string, string> dic)
        {
            string key = LibUtils.ToString(ConfigurationManager.WexinSettings["WxPayKey"]);//商户平台 API安全里面设置的KEY  32位长度                                                                                                            
            dic = dic.OrderBy(d => d.Key).ToDictionary(d => d.Key, d => d.Value);//排序
                                                                                 //连接字段
            var sign = dic.Aggregate("", (current, d) => current + (d.Key + "=" + d.Value + "&"));
            sign += "key=" + key;
            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
            sign = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(sign))).Replace("-", null);
            return sign;
        }
        /// <summary>
        /// 运营商Key
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private static string GetSignStringByTenant(Dictionary<string, string> dic,string key)
        {
            //string key = LibUtils.ToString(ConfigurationManager.WexinSettings["WxPayKey"]);//商户平台 API安全里面设置的KEY  32位长度                                                                                                            
            dic = dic.OrderBy(d => d.Key).ToDictionary(d => d.Key, d => d.Value);//排序
                                                                                 //连接字段
            var sign = dic.Aggregate("", (current, d) => current + (d.Key + "=" + d.Value + "&"));
            sign += "key=" + key;
            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
            sign = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(sign))).Replace("-", null);
            return sign;
        }


        private static Object PostUnifiedOrder(string payUrl, string para)
        {
            string result = string.Empty;
            try
            {
                HttpClient client = new HttpClient();
                HttpContent httpContent = new StringContent(para);
                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                httpContent.Headers.ContentType.CharSet = "utf-8";
                HttpResponseMessage hrm = client.PostAsync(payUrl, httpContent).Result;
                return hrm;
            }
            catch (Exception e)
            {
                result = e.Message;
            }
            return result;
        }
    }
    public class PayRequesEntity
    {
        /// <summary>
        /// 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间
        /// </summary>
        public string timeStamp { get; set; }

        /// <summary>
        /// 随机字符串，长度为32个字符以下。
        /// </summary>
        public string nonceStr { get; set; }

        /// <summary>
        /// 统一下单接口返回的 prepay_id 参数值
        /// </summary>
        public string package { get; set; }

        /// <summary>
        /// 签名算法
        /// </summary>
        public string signType { get; set; }

        /// <summary>
        /// 签名
        /// </summary>
        public string paySign { get; set; }

        public dynamic order { get; set; }
    }

    /// <summary>
    ///     Http方法
    /// </summary>
    public class HttpMethods
    {
        /// <summary>
        /// 创建HttpClient
        /// </summary>
        /// <returns></returns>
        public static HttpClient CreateHttpClient(string url, IDictionary<string, string> cookies = null)
        {
            HttpClient httpclient;
            HttpClientHandler handler = new HttpClientHandler();
            var uri = new Uri(url);
            if (cookies != null)
            {
                foreach (var key in cookies.Keys)
                {
                    string one = key + "=" + cookies[key];
                    handler.CookieContainer.SetCookies(uri, one);
                }
            }
            //如果是发送HTTPS请求 
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
                httpclient = new HttpClient(handler);
            }
            else
            {
                httpclient = new HttpClient(handler);
            }
            return httpclient;
        }


        #region 同步请求

        /// <summary>
        /// post 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="jsonData">请求参数</param>
        /// <returns></returns>
        public static string Post(string url, string jsonData)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var postData = new StringContent(jsonData);
            postData.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
            Task<string> result = httpClient.PostAsync(url, postData).Result.Content.ReadAsStringAsync();
            return result.Result;
        }
        public static string PostByCert(string xml, string url, bool isUseCert, int timeout)
        {
            System.GC.Collect();//垃圾回收，回收没有正常关闭的http连接

            string result = "";//返回结果

            HttpWebRequest request = null;
            HttpWebResponse response = null;
            Stream reqStream = null;

            try
            {
                //设置最大连接数
                ServicePointManager.DefaultConnectionLimit = 200;
                //设置https验证方式
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback =
                            new RemoteCertificateValidationCallback(CheckValidationResult);
                }

                /***************************************************************
                * 下面设置HttpWebRequest的相关属性
                * ************************************************************/
                request = (HttpWebRequest)WebRequest.Create(url);
                //request.UserAgent = USER_AGENT;
                request.Method = "POST";
                request.Timeout = timeout * 1000;

                //设置POST的数据类型和长度
                request.ContentType = "text/xml";
                byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
                request.ContentLength = data.Length;

                //是否使用证书
                if (isUseCert)
                {
                    X509Certificate2 cert = new X509Certificate2(LibUtils.ToString(ConfigurationManager.WexinSettings["CertPath"]),
                        LibUtils.ToString(ConfigurationManager.WexinSettings["CertPassword"]));
                    request.ClientCertificates.Add(cert);
                }

                //往服务器写入数据
                reqStream = request.GetRequestStream();
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();

                //获取服务端返回
                response = (HttpWebResponse)request.GetResponse();

                //获取服务端返回数据
                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                result = sr.ReadToEnd().Trim();
                sr.Close();
            }
            catch (System.Threading.ThreadAbortException e)
            {
                System.Threading.Thread.ResetAbort();
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                //关闭连接和流
                if (response != null)
                {
                    response.Close();
                }
                if (request != null)
                {
                    request.Abort();
                }
            }
            return result;
        }
        public static string PostByCertByTenant(string xml, string url, bool isUseCert, int timeout, string certpath, string certpassword)
        {
            System.GC.Collect();//垃圾回收，回收没有正常关闭的http连接

            string result = "";//返回结果

            HttpWebRequest request = null;
            HttpWebResponse response = null;
            Stream reqStream = null;

            try
            {
                //设置最大连接数
                ServicePointManager.DefaultConnectionLimit = 200;
                //设置https验证方式
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback =
                            new RemoteCertificateValidationCallback(CheckValidationResult);
                }

                /***************************************************************
                * 下面设置HttpWebRequest的相关属性
                * ************************************************************/
                request = (HttpWebRequest)WebRequest.Create(url);
                //request.UserAgent = USER_AGENT;
                request.Method = "POST";
                request.Timeout = timeout * 1000;

                //设置POST的数据类型和长度
                request.ContentType = "text/xml";
                byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
                request.ContentLength = data.Length;

                //是否使用证书
                if (isUseCert)
                {
                    X509Certificate2 cert = new X509Certificate2(certpath,certpassword);
                    request.ClientCertificates.Add(cert);
                }

                //往服务器写入数据
                reqStream = request.GetRequestStream();
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();

                //获取服务端返回
                response = (HttpWebResponse)request.GetResponse();

                //获取服务端返回数据
                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                result = sr.ReadToEnd().Trim();
                sr.Close();
            }
            catch (System.Threading.ThreadAbortException e)
            {
                System.Threading.Thread.ResetAbort();
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                //关闭连接和流
                if (response != null)
                {
                    response.Close();
                }
                if (request != null)
                {
                    request.Abort();
                }
            }
            return result;
        }
        private static bool CheckValidationResult(object sender,
X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            if (errors == SslPolicyErrors.None)
                return true;
            return false;
        }

        /// <summary>
        /// post 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="req">请求参数</param>
        /// <returns></returns>
        public static string Post(string url, byte[] req)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var postData = new ByteArrayContent(req);
            Task<string> result = httpClient.PostAsync(url, postData).Result.Content.ReadAsStringAsync();
            return result.Result;
        }
        /// <summary>
        ///     post 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="pairs">请求参数</param>
        /// <returns></returns>
        public static string Post(string url, Dictionary<string, string> pairs)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var postData = new FormUrlEncodedContent(pairs);
            var result = httpClient.PostAsync(url, postData).Result.Content.ReadAsStringAsync();
            return result.Result;

        }
        /// <summary>
        /// get 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public static string Get(string url)
        {
            HttpClient httpClient = CreateHttpClient(url);
            Task<string> result = httpClient.GetAsync(url).Result.Content.ReadAsStringAsync();
            return result.Result;
        }

        #endregion

        #region 异步请求
        /// <summary>
        ///     post 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="jsonData">请求参数</param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> PostAsync(string url, string jsonData)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var postData = new StringContent(jsonData);
            postData.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
            var result = httpClient.PostAsync(url, postData);
            return result;
        }
        /// <summary>
        ///     post 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="req">请求参数</param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> PostAsync(string url, byte[] req)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var postData = new ByteArrayContent(req);
            var result = httpClient.PostAsync(url, postData);
            return result;
        }
        /// <summary>
        ///     post 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="pairs">请求参数</param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> PostAsync(string url, Dictionary<string, string> pairs)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var postData = new FormUrlEncodedContent(pairs);
            var result = httpClient.PostAsync(url, postData);
            return result;
        }

        /// <summary>
        ///     get 请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> GetAsync(string url)
        {
            HttpClient httpClient = CreateHttpClient(url);
            var result = httpClient.GetAsync(url);
            return result;
        }
        #endregion

    }
}
