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; } }
调用方法:
(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);
/// <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; } } 标签:code,C#,ex,HttpResultModel,公共,new,model,message,HttpClient From: https://www.cnblogs.com/wsk198726/p/18373351