HttpClientService.cs:

    /// <summary>
    /// HTTP请求方法
    /// 兼容微信支付V3版本api请求
    /// </summary>
    public class HttpClientService
    {
        private static HttpClientService _instance;
        private static readonly object _lock = new object();
        private static HttpClient _client;

        public HttpClientService() { }

        public static HttpClientService GetInstance()
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new HttpClientService();
                    }
                    if (_client == null)
                    {
                        _client = new HttpClient();
                    }
                }
            }
            return _instance;
        }

        /// <summary>
        /// 参数对象转换为uri网址参数形式 (主要用于GET的url生成)
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetUriParam(object obj, string url = "")
        {
            PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            StringBuilder sb = new StringBuilder();
            sb.Append(url);
            sb.Append("?");
            foreach (var p in properties)
            {
                var v = p.GetValue(obj, null);
                if (v == null) continue;
                sb.Append(p.Name);
                sb.Append("=");
                sb.Append(Uri.EscapeDataString(v.ToString()));//将字符串转换为它的转义表示形式,HttpUtility.UrlEncode是小写
                sb.Append("&");
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
        /// <summary>
        /// Get方法
        /// </summary>
        /// <param name="url">请求的地址</param>
        /// <param name="authorization">Authorization标头 scheme:认证类型 parameter:签名信息
        /// 如:Bearer your_access_token、API-Key your_api_key,微信支付V3的 WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"
        /// { scheme = "Bearer", parameter="your_access_token" }、
        /// { scheme = "API-Key", parameter="your_api_key" }、
        /// { scheme = "WECHATPAY2-SHA256-RSA2048", parameter="mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"" }
        /// </param>
        /// <param name="accept">Accept代表发送端(客户端)希望接受的数据类型。 比如:Accept:text/xml; 代表客户端希望接受的数据类型是xml类型。放在请求头中。</param>
        /// <param name="encoding">编码方式 默认为UTF8</param>
        /// <param name="timeOut">默认值是 100 秒,单位为秒</param>
        /// <returns></returns>
        public static string HttpGet(string url, HttpAuthorization authorization = null, string userAgent = "", string accept = "application/json", Encoding encoding = null, int timeOut = 100)
        {
            string result = "";
            HttpResultModel model = null;

            //编码方式
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            try
            {
                if (_client.BaseAddress is null)
                {
                    _client.BaseAddress = new Uri(url);
                }

                //超时设置
                _client.Timeout = TimeSpan.FromSeconds(timeOut);

                //Accept代表发送端(客户端)希望接受的数据类型
                if (!string.IsNullOrWhiteSpace(accept))
                {
                    _client.DefaultRequestHeaders.Accept.Clear();
                    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(accept));
                }

                //HTTP头User-Agent
                if (!string.IsNullOrWhiteSpace(userAgent))
                {
                    string USER_AGENT = string.Format("{2} ({0}) .net/{1}", Environment.OSVersion, Environment.Version, userAgent);
                    _client.DefaultRequestHeaders.Add("user-agent", USER_AGENT);
                }

                //Authorization  Bearer your_access_token、API-Key your_api_key
                if (authorization != null)
                {
                    _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authorization.scheme, authorization.parameter);
                }

                //能解读https类型 指定 ServicePoint 安全协议
                if (url.StartsWith("https"))
                {
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
                }

                using (HttpResponseMessage response = _client.GetAsync(url).Result)
                {
                    response.EnsureSuccessStatusCode();
                    string body = response.Content.ReadAsStringAsync().Result;

                    string serial = ((string[])response.Headers.GetValues("Wechatpay-Serial"))[0].ToString();
                    string signature = ((string[])response.Headers.GetValues("Wechatpay-Signature"))[0].ToString();
                    string timestamp = ((string[])response.Headers.GetValues("Wechatpay-Timestamp"))[0].ToString();
                    string nonce = ((string[])response.Headers.GetValues("Wechatpay-Nonce"))[0].ToString();
                    //构造验签名串
                    string signSource = timestamp + "\n" + nonce + "\n" + body + "\n";

                    model = new HttpResultModel()
                    {
                        code = 0,
                        message = "成功",
                        data = body,
                        serial = serial,  //微信支付V3 验证签名时 需要
                        signature = signature,  //微信支付V3 验证签名时 需要
                        signSource = signSource  //微信支付V3 验证签名时 需要
                    };
                }
            }
            catch (Exception ex)
            {
                var actualException = ex.InnerException;
                if (actualException != null)
                {
                    if (actualException is SocketException)
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = "网络中断," + ex.Message
                        };
                    }
                    else if (actualException is TimeoutException)
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = "连时超时," + ex.Message
                        };
                    }
                    else if (actualException is WebException webEx)
                    {
                        switch (webEx.Status)
                        {
                            case WebExceptionStatus.NameResolutionFailure:
                                {
                                    // DNS 域名解析失败的处理逻辑
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法解析主机名," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ConnectFailure:
                                {
                                    //The remote service point could not be contacted at the transport level.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "连接失败," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestCanceled:
                                {
                                    //The request was canceled, the System.Net.WebRequest.Abort method was called, or an unclassifiable error occurred. This is the default value for System.Net.WebException.Status.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "请求被取消," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ConnectionClosed:
                                {
                                    //The connection was prematurely closed.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "连接关闭," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ReceiveFailure:
                                {
                                    //A complete response was not received from the remote server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "未收到远程服务器的响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.SendFailure:
                                {
                                    //A complete request could not be sent to the remote server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法向远程服务器发送请求," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.PipelineFailure:
                                {
                                    //The request was a pipelined request and the connection was closed before the response was received.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "收到响应之前关闭了连接," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ProtocolError:
                                {
                                    //The response received from the server was complete but indicated a protocol-level or example, an HTTP protocol error such as 401 Access Denied would use this status.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "HTTP协议错误," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.TrustFailure:
                                {
                                    //A server certificate could not be validated.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法验证服务器证书," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.SecureChannelFailure:
                                {
                                    //An error occurred while establishing a connection using SSL.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "使用SSL建立连接时出错," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ServerProtocolViolation:
                                {
                                    //The server response was not a valid HTTP response.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "服务器响应不是有效的HTTP响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.KeepAliveFailure:
                                {
                                    //The connection for a request that specifies the Keep-alive header was closed unexpectedly.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "指定Keep-alive标头的请求的连接意外关闭," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.Pending:
                                {
                                    //An internal asynchronous request is pending.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "一个内部异步请求正在等待处理," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.Timeout:
                                {
                                    //No response was received during the time-out period for a request.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "在请求的超时期间未收到任何响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ProxyNameResolutionFailure:
                                {
                                    //The name resolver service could not resolve the proxy host name.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法解析代理主机名," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.UnknownError:
                                {
                                    //An exception of unknown type has occurred.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "发生未知类型的异常," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.MessageLengthLimitExceeded:
                                {
                                    //A message was received that exceeded the specified limit when sending a request or receiving a response from the server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "消息的长度超过了允许的最大限制," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.CacheEntryNotFound:
                                {
                                    //The specified cache entry was not found.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "找不到指定的缓存条目," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestProhibitedByCachePolicy:
                                {
                                    //The request was not permitted by the cache policy. In general, this occurs when a request is not cacheable and the effective policy prohibits sending the request to the server.
                                    //You might receive this status if a request method implies the presence of a request body, a request method requires direct interaction with the server, or a request contains a conditional header.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "缓存策略不允许该请求," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestProhibitedByProxy:
                                {
                                    //This request was not permitted by the proxy.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "代理不允许此请求," + ex.Message
                                    };
                                    break;
                                }
                            default:
                                {
                                    HttpWebResponse response = (HttpWebResponse)webEx.Response;
                                    using (Stream resStream = response.GetResponseStream())
                                    {
                                        using (StreamReader reader = new StreamReader(resStream, encoding))
                                        {
                                            result = reader.ReadToEnd().Trim();
                                        }
                                    }
                                }
                                break;
                        }
                    }
                    else
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = ex.Message
                        };
                    }
                }
                else
                {
                    model = new HttpResultModel()
                    {
                        code = -1,
                        message = ex.Message
                    };
                }
            }
            if (string.IsNullOrWhiteSpace(result))
            {
                if (model != null)
                {
                    result = JsonHelper.SerializeObject(model);
                }
            }
            return result;
        }

        /// <summary>
        /// Post方法
        /// </summary>
        /// <param name="url">请求的地址(不含请求参数)</param>
        /// <param name="data">请求参数json字符串</param>
        /// <param name="authorization">Authorization标头 scheme:认证类型 parameter:签名信息
        /// 如:Bearer your_access_token、API-Key your_api_key,微信支付V3的 WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"
        /// { scheme = "Bearer", parameter="your_access_token" }、
        /// { scheme = "API-Key", parameter="your_api_key" }、
        /// { scheme = "WECHATPAY2-SHA256-RSA2048", parameter="mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"" }
        /// </param>
        /// <param name="accept">Accept代表发送端(客户端)希望接受的数据类型。 比如:Accept:text/xml; 代表客户端希望接受的数据类型是xml类型。放在请求头中。</param>
        /// <param name="contentType">Content-Type代表发送端(客户端|服务器)发送的实体数据的数据类型。</param>
        /// <param name="encoding"></param>
        /// <param name="timeOut">默认值是 100,000 毫秒(100 秒)</param>
        /// <returns></returns>
        public static string HttpPost(string url, string data, HttpAuthorization authorization = null, string accept = "application/json", string contentType = "application/json", Encoding encoding = null, int timeOut = 100)
        {
            string result = "";
            HttpResultModel model = null;

            //编码方式
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            try
            {
                if (_client.BaseAddress is null)
                {
                    _client.BaseAddress = new Uri(url);
                }

                //超时设置
                _client.Timeout = new TimeSpan(timeOut * 1000);

                //Accept代表发送端(客户端)希望接受的数据类型
                if (!string.IsNullOrWhiteSpace(accept))
                {
                    _client.DefaultRequestHeaders.Accept.Clear();
                    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(accept));
                }

                //Authorization (Bearer) Bearer your_access_token、API-Key your_api_key
                if (!string.IsNullOrWhiteSpace(authorization))
                {
                    _client.DefaultRequestHeaders.Add("Authorization", authorization);
                }

                //能解读https类型  指定 ServicePoint 安全协议
                if (url.StartsWith("https"))
                {
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
                }

                using (StringContent content = new StringContent(data))
                {
                    content.Headers.ContentType = new MediaTypeHeaderValue(contentType);

                    using (HttpResponseMessage response = _client.GetAsync(url).Result)
                    {
                        response.EnsureSuccessStatusCode();
                        string body = response.Content.ReadAsStringAsync().Result;

                        string serial = response.Headers.GetValues("Wechatpay-Serial").ToString();
                        string signature = response.Headers.GetValues("Wechatpay-Signature").ToString();
                        string timestamp = response.Headers.GetValues("Wechatpay-Timestamp").ToString();
                        string nonce = response.Headers.GetValues("Wechatpay-Nonce").ToString();
                        //构造验签名串
                        string signSource = timestamp + "\n" + nonce + "\n" + body + "\n";

                        model = new HttpResultModel()
                        {
                            code = 0,
                            message = "成功",
                            data = body,
                            serial = serial,  //微信支付V3 验证签名时 需要
                            signature = signature,  //微信支付V3 验证签名时 需要
                            signSource = signSource  //微信支付V3 验证签名时 需要
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                var actualException = ex.InnerException;
                if (actualException != null)
                {
                    if (actualException is SocketException)
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = "网络中断," + ex.Message
                        };
                    }
                    else if (actualException is TimeoutException)
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = "连时超时," + ex.Message
                        };
                    }
                    else if (actualException is WebException webEx)
                    {
                        switch (webEx.Status)
                        {
                            case WebExceptionStatus.NameResolutionFailure:
                                {
                                    // DNS 域名解析失败的处理逻辑
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法解析主机名," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ConnectFailure:
                                {
                                    //The remote service point could not be contacted at the transport level.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "连接失败," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestCanceled:
                                {
                                    //The request was canceled, the System.Net.WebRequest.Abort method was called, or an unclassifiable error occurred. This is the default value for System.Net.WebException.Status.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "请求被取消," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ConnectionClosed:
                                {
                                    //The connection was prematurely closed.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "连接关闭," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ReceiveFailure:
                                {
                                    //A complete response was not received from the remote server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "未收到远程服务器的响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.SendFailure:
                                {
                                    //A complete request could not be sent to the remote server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法向远程服务器发送请求," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.PipelineFailure:
                                {
                                    //The request was a pipelined request and the connection was closed before the response was received.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "收到响应之前关闭了连接," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ProtocolError:
                                {
                                    //The response received from the server was complete but indicated a protocol-level or example, an HTTP protocol error such as 401 Access Denied would use this status.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "HTTP协议错误," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.TrustFailure:
                                {
                                    //A server certificate could not be validated.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法验证服务器证书," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.SecureChannelFailure:
                                {
                                    //An error occurred while establishing a connection using SSL.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "使用SSL建立连接时出错," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ServerProtocolViolation:
                                {
                                    //The server response was not a valid HTTP response.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "服务器响应不是有效的HTTP响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.KeepAliveFailure:
                                {
                                    //The connection for a request that specifies the Keep-alive header was closed unexpectedly.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "指定Keep-alive标头的请求的连接意外关闭," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.Pending:
                                {
                                    //An internal asynchronous request is pending.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "一个内部异步请求正在等待处理," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.Timeout:
                                {
                                    //No response was received during the time-out period for a request.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "在请求的超时期间未收到任何响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ProxyNameResolutionFailure:
                                {
                                    //The name resolver service could not resolve the proxy host name.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法解析代理主机名," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.UnknownError:
                                {
                                    //An exception of unknown type has occurred.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "发生未知类型的异常," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.MessageLengthLimitExceeded:
                                {
                                    //A message was received that exceeded the specified limit when sending a request or receiving a response from the server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "消息的长度超过了允许的最大限制," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.CacheEntryNotFound:
                                {
                                    //The specified cache entry was not found.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "找不到指定的缓存条目," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestProhibitedByCachePolicy:
                                {
                                    //The request was not permitted by the cache policy. In general, this occurs when a request is not cacheable and the effective policy prohibits sending the request to the server.
                                    //You might receive this status if a request method implies the presence of a request body, a request method requires direct interaction with the server, or a request contains a conditional header.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "缓存策略不允许该请求," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestProhibitedByProxy:
                                {
                                    //This request was not permitted by the proxy.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "代理不允许此请求," + ex.Message
                                    };
                                    break;
                                }
                            default:
                                {
                                    HttpWebResponse response = (HttpWebResponse)webEx.Response;
                                    using (Stream resStream = response.GetResponseStream())
                                    {
                                        using (StreamReader reader = new StreamReader(resStream, encoding))
                                        {
                                            result = reader.ReadToEnd().Trim();
                                        }
                                    }
                                }
                                break;
                        }
                    }
                    else
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = ex.Message
                        };
                    }
                }
                else
                {
                    model = new HttpResultModel()
                    {
                        code = -1,
                        message = ex.Message
                    };
                }
            }
            if (string.IsNullOrWhiteSpace(result))
            {
                if (model != null)
                {
                    result = JsonHelper.SerializeObject(model);
                }
            }
            return result;
        }

        /// <summary>
        /// POST上传文件
        /// </summary>
        /// <param name="url">请求的地址</param>
        /// <param name="filePathList">form-data 文件列表(name,文件路径)</param>
        /// <param name="formDataList">form-data 参数列表(name,文本参数内容)</param>
        /// <param name="authorization">Authorization标头 scheme:认证类型 parameter:签名信息
        /// 如:Bearer your_access_token、API-Key your_api_key,微信支付V3的 WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"
        /// { scheme = "Bearer", parameter="your_access_token" }、
        /// { scheme = "API-Key", parameter="your_api_key" }、
        /// { scheme = "WECHATPAY2-SHA256-RSA2048", parameter="mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"" }
        /// </param>
        /// <param name="encoding">编码方式 默认为null时 使用 UTF8</param>
        /// <param name="timeOut">默认值是 100,000 毫秒(100 秒)</param>
        /// <returns></returns>
        public static string HttpPostFile(string url, Dictionary<string, string> filePathList, Dictionary<string, string> formDataList = null, HttpAuthorization authorization = null, Encoding encoding = null, int timeOut = 100)
        {
            string result = "";
            HttpResultModel model = null;

            //编码方式
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            try
            {
                if (_client.BaseAddress is null)
                {
                    _client.BaseAddress = new Uri(url);
                }

                //超时设置
                _client.Timeout = new TimeSpan(timeOut * 1000);

                //Authorization  Bearer your_access_token、API-Key your_api_key
                if (authorization != null)
                {
                    _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authorization.scheme, authorization.parameter);
                }

                //能解读https类型  指定 ServicePoint 安全协议
                if (url.StartsWith("https"))
                {
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
                }

                using (var content = new MultipartFormDataContent())
                {
                    // 添加表单数据
                    if (formDataList != null)
                    {
                        foreach (var keyValuePair in formDataList)
                        {
                            //方法一
                            //content.Add(new StringContent(keyValuePair.Value, encoding), keyValuePair.Key);

                            //方法二
                            var byteArrayContent = new ByteArrayContent(encoding.GetBytes(keyValuePair.Value));
                            byteArrayContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                            {
                                Name = keyValuePair.Key
                            };
                            content.Add(byteArrayContent);
                        }
                    }

                    // 添加文件
                    foreach (var file in filePathList)
                    {
                        //方法一
                        //content.Add(new ByteArrayContent(File.ReadAllBytes(file.Value)), file.Key, Path.GetFileName(file.Value));

                        //方法二
                        var fileContent = new ByteArrayContent(File.ReadAllBytes(file.Value));
                        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                        {
                            Name = file.Key, //接口匹配name
                            FileName = Path.GetFileName(file.Value) //附件文件名
                        };
                    }

                    // 发送请求

                    using (var response = _client.GetAsync(url).Result)
                    {
                        response.EnsureSuccessStatusCode();
                        string body = response.Content.ReadAsStringAsync().Result;

                        model = new HttpResultModel()
                        {
                            code = 0,
                            message = "成功",
                            data = body
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                var actualException = ex.InnerException;
                if (actualException != null)
                {
                    if (actualException is SocketException)
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = "网络中断," + ex.Message
                        };
                    }
                    else if (actualException is TimeoutException)
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = "连时超时," + ex.Message
                        };
                    }
                    else if (actualException is WebException webEx)
                    {
                        switch (webEx.Status)
                        {
                            case WebExceptionStatus.NameResolutionFailure:
                                {
                                    // DNS 域名解析失败的处理逻辑
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法解析主机名," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ConnectFailure:
                                {
                                    //The remote service point could not be contacted at the transport level.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "连接失败," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestCanceled:
                                {
                                    //The request was canceled, the System.Net.WebRequest.Abort method was called, or an unclassifiable error occurred. This is the default value for System.Net.WebException.Status.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "请求被取消," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ConnectionClosed:
                                {
                                    //The connection was prematurely closed.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "连接关闭," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ReceiveFailure:
                                {
                                    //A complete response was not received from the remote server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "未收到远程服务器的响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.SendFailure:
                                {
                                    //A complete request could not be sent to the remote server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法向远程服务器发送请求," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.PipelineFailure:
                                {
                                    //The request was a pipelined request and the connection was closed before the response was received.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "收到响应之前关闭了连接," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ProtocolError:
                                {
                                    //The response received from the server was complete but indicated a protocol-level or example, an HTTP protocol error such as 401 Access Denied would use this status.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "HTTP协议错误," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.TrustFailure:
                                {
                                    //A server certificate could not be validated.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法验证服务器证书," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.SecureChannelFailure:
                                {
                                    //An error occurred while establishing a connection using SSL.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "使用SSL建立连接时出错," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ServerProtocolViolation:
                                {
                                    //The server response was not a valid HTTP response.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "服务器响应不是有效的HTTP响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.KeepAliveFailure:
                                {
                                    //The connection for a request that specifies the Keep-alive header was closed unexpectedly.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "指定Keep-alive标头的请求的连接意外关闭," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.Pending:
                                {
                                    //An internal asynchronous request is pending.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "一个内部异步请求正在等待处理," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.Timeout:
                                {
                                    //No response was received during the time-out period for a request.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "在请求的超时期间未收到任何响应," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.ProxyNameResolutionFailure:
                                {
                                    //The name resolver service could not resolve the proxy host name.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "无法解析代理主机名," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.UnknownError:
                                {
                                    //An exception of unknown type has occurred.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "发生未知类型的异常," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.MessageLengthLimitExceeded:
                                {
                                    //A message was received that exceeded the specified limit when sending a request or receiving a response from the server.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "消息的长度超过了允许的最大限制," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.CacheEntryNotFound:
                                {
                                    //The specified cache entry was not found.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "找不到指定的缓存条目," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestProhibitedByCachePolicy:
                                {
                                    //The request was not permitted by the cache policy. In general, this occurs when a request is not cacheable and the effective policy prohibits sending the request to the server.
                                    //You might receive this status if a request method implies the presence of a request body, a request method requires direct interaction with the server, or a request contains a conditional header.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "缓存策略不允许该请求," + ex.Message
                                    };
                                    break;
                                }
                            case WebExceptionStatus.RequestProhibitedByProxy:
                                {
                                    //This request was not permitted by the proxy.
                                    model = new HttpResultModel()
                                    {
                                        code = -1,
                                        message = "代理不允许此请求," + ex.Message
                                    };
                                    break;
                                }
                            default:
                                {
                                    HttpWebResponse response = (HttpWebResponse)webEx.Response;
                                    using (Stream resStream = response.GetResponseStream())
                                    {
                                        using (StreamReader reader = new StreamReader(resStream, encoding))
                                        {
                                            result = reader.ReadToEnd().Trim();
                                        }
                                    }
                                }
                                break;
                        }
                    }
                    else
                    {
                        model = new HttpResultModel()
                        {
                            code = -1,
                            message = ex.Message
                        };
                    }
                }
                else
                {
                    model = new HttpResultModel()
                    {
                        code = -1,
                        message = ex.Message
                    };
                }
            }
            if (string.IsNullOrWhiteSpace(result))
            {
                if (model != null)
                {
                    result = JsonHelper.SerializeObject(model);
                }
            }
            return result;
        }
    }

    /// <summary>
    /// HTTP请求返回结果
    /// </summary>
    public class HttpResultModel
    {
        /// <summary>
        /// 请求状态码 0为正确 其他为失败
        /// </summary>
        public int code { set; get; }
        /// <summary>
        /// 请求失败信息描述
        /// </summary>
        public string message { set; get; }
        /// <summary>
        /// 返回的数据
        /// </summary>
        public string data { set; get; }

        #region 微信支付V3版本需要返回的信息
        /// <summary>
        /// 请求返回的平台证书序列号
        /// </summary>
        public string serial { set; get; }
        /// <summary>
        /// 请求返回的应答签名
        /// </summary>
        public string signature { set; get; }
        /// <summary>
        /// 应答时间戳 应答随机串
        /// <summary>
        public string signSource { set; get; }
        /// <summary>
        /// 详细错误码
        /// </summary>
        public HttpResultDetail detail { set; get; }
        #endregion 微信支付V3版本需要返回的信息
    }

    /// <summary>
    /// 微信支付V3版本返回详细错误码
    /// </summary>
    public class HttpResultDetail
    {
        /// <summary>
        /// 指示错误参数的位置。当错误参数位于请求body的JSON时,填写指向参数的JSON Pointer 。当错误参数位于请求的url或者querystring时,填写参数的变量名。
        /// </summary>
        public string field { set; get; }
        /// <summary>
        /// 错误的值
        /// </summary>
        public string value { set; get; }
        /// <summary>
        /// 具体错误原因
        /// </summary>
        public string issue { set; get; }
        /// <summary>
        /// 
        /// </summary>
        public string location { set; get; }
    }

    /// <summary>
    /// HTTP请求头认证信息
    /// </summary>
    public class HttpAuthorization
    {
        /// <summary>
        /// 认证类型 
        /// </summary>
        public string scheme { set; get; }
        /// <summary>
        /// 签名信息
        /// </summary>
        public string parameter { set; get; }
    }
        /// <summary>
        /// 生成随机字符串
        /// </summary>
        /// <param name="length">要生成字符串的长度</param>
        /// <returns></returns>
        public static string GetRandomString(int length)
        {
            char[] _characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".ToCharArray();
            Random random = new Random();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(_characters[random.Next(_characters.Length)]);
            }
            return sb.ToString();
        }

调用方法:

(1)微信支付V3版本API调用方式:

            string merchantId = ""; //微信支付商户号mchid
            string nonce_str = "";  //请求随机串nonce_str
            string timestamp = ""; //时间戳timestamp
            string serialNo = ""; //商户API证书序列号serial_no
            string signature = ""; //签名值signature

            string userAgent = string.Format("TenPay/V3 {0}", merchantId);
            HttpAuthorization authorization = new HttpAuthorization();
            authorization.scheme = "WECHATPAY2-SHA256-RSA2048";
            authorization.parameter = string.Format("mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"", merchantId, nonce_str, timestamp, serialNo, signature);

            HttpClientService.GetInstance();
            string result = HttpClientService.HttpGet(url, authorization, userAgent);

(2)Bearer 认证的调用方式:

            HttpAuthorization authorization = new HttpAuthorization();
            authorization.scheme = "Bearer";
            authorization.parameter = "your_access_token";

            HttpClientService.GetInstance();
            string result = HttpClientService.HttpGet(url, authorization);

(3)其他自定义认证的调用方式:

            HttpAuthorization authorization = new HttpAuthorization();
            authorization.scheme = "API-Key";
            authorization.parameter = "your_api_key";

            HttpClientService.GetInstance();
            string result = HttpClientService.HttpGet(url, authorization);
posted on 2024-08-22 10:45  £冷☆月№  阅读(21)  评论(0编辑  收藏  举报