微信图片上传接口地址:https://api.mch.weixin.qq.com/v3/merchant/media/upload
1、上传方法
1 using HttpHandlerDemo; 2 using Newtonsoft.Json; 3 using System; 4 using System.Collections.Generic; 5 using System.IO; 6 using System.Linq; 7 using System.Net; 8 using System.Net.Http; 9 using System.Net.Http.Headers; 10 using System.Security.Cryptography; 11 using System.Text; 12 using HttpHandler = Lib.HttpHandler; 13 14 namespace API 15 { 16 public class Helper 17 { 18 public static string UploadImg(string b64) 19 { 20 byte[] data = Convert.FromBase64String(b64); 21 //证书本地路径 22 string certPath = @"***"; 23 //证书秘钥 24 string certPwd = "***"; 25 //商户号 26 string mchid = "***"; 27 //证书编号 28 string serialNo = "***"; 29 string boundary = string.Format("--{0}", DateTime.Now.Ticks.ToString("x")); 30 var sha256 = Sha256(data); 31 var meta = new 32 { 33 sha256 = sha256, 34 filename = Guid.NewGuid().ToString().Replace("-", "") + ".png" 35 }; 36 var json = JsonConvert.SerializeObject(meta); 37 var httpHandler = new HttpHandler(mchid, serialNo, certPath, certPwd, json); 38 HttpClient client = new HttpClient(httpHandler); 39 using (var content = new MultipartFormDataContent(boundary)) 40 { 41 content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data"); //这里必须添加 42 content.Add(new StringContent(json, Encoding.UTF8, "application/json"), ""meta""); //这里主要必须要双引号 43 44 var byteArrayContent = new ByteArrayContent(data); 45 byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpg"); 46 content.Add(byteArrayContent, ""file"", """ + meta.filename + """); //这里主要必须要双引号 47 try 48 { 49 using (var response = client.PostAsync("https://api.mch.weixin.qq.com/v3/merchant/media/upload", content)) //上传 50 using (var responseContent = response.Result.Content) 51 { 52 string responseBody = responseContent.ReadAsStringAsync().Result; 53 var dic = Newtonsoft.Json.Linq.JObject.Parse(responseBody); 54 return dic["media_id"].ToString(); 55 } 56 } 57 catch (Exception e) 58 { 59 return null; 60 } 61 62 63 } 64 } 65 66 public static string Sha256(byte[] bytes) 67 { 68 byte[] hash = SHA256Managed.Create().ComputeHash(bytes); 69 StringBuilder builder = new StringBuilder(); 70 for (int i = 0; i < hash.Length; i++) 71 { 72 builder.Append(hash[i].ToString("X2")); 73 } 74 return builder.ToString(); 75 } 76 77 } 78 }
2、Lib.HttpHandler代码
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Net.Http; 5 using System.Net.Http.Headers; 6 using System.Security.Authentication; 7 using System.Security.Cryptography; 8 using System.Security.Cryptography.X509Certificates; 9 using System.Text; 10 using System.Threading; 11 using System.Threading.Tasks; 12 13 namespace Lib 14 { 15 /// <summary> 16 /// 头文件 17 /// </summary> 18 public class HttpHandler : DelegatingHandler 19 { 20 private readonly string merchantId; 21 private readonly string serialNo; 22 private readonly string certPath; 23 private readonly string certPwd; 24 private readonly string json; 25 /// <summary> 26 /// 构造方法 27 /// </summary> 28 /// <param name="merchantId">商户号</param> 29 /// <param name="merchantSerialNo">证书序列号</param> 30 /// <param name="certPath">证书路径</param> 31 /// <param name="certPwd">证书秘钥</param> 32 /// <param name="json">签名json数据,默认不需要传入,获取body内容,如传入签名传入参数上传图片时需传入</param> 33 public HttpHandler(string merchantId, string merchantSerialNo, string certPath, string certPwd, string json = "") 34 { 35 36 HttpClientHandler handler = new HttpClientHandler(); 37 handler.ClientCertificateOptions = ClientCertificateOption.Manual; 38 handler.SslProtocols = SslProtocols.Tls12; 39 try 40 { 41 handler.ClientCertificates.Add(new X509Certificate2(certPath, certPwd, 42 X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet)); 43 } 44 catch (Exception e) 45 { 46 throw new Exception("ca err(证书错误)"); 47 } 48 handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; 49 handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true; 50 InnerHandler = handler; 51 this.merchantId = merchantId; 52 this.serialNo = merchantSerialNo; 53 this.certPath = certPath; 54 this.certPwd = certPwd; 55 this.json = json; 56 } 57 58 protected async override Task<HttpResponseMessage> SendAsync( 59 HttpRequestMessage request, 60 CancellationToken cancellationToken) 61 { 62 var auth = await BuildAuthAsync(request); 63 string value = $"WECHATPAY2-SHA256-RSA2048 {auth}"; 64 request.Headers.Add("Authorization", value); 65 request.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"); 66 MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeader = new MediaTypeWithQualityHeaderValue("application/json"); 67 request.Headers.Accept.Add(mediaTypeWithQualityHeader); 68 request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8")); 69 return await base.SendAsync(request, cancellationToken); 70 } 71 72 protected async Task<string> BuildAuthAsync(HttpRequestMessage request) 73 { 74 string method = request.Method.ToString(); 75 string body = ""; 76 if (method == "POST" || method == "PUT" || method == "PATCH") 77 { 78 if (!string.IsNullOrEmpty(json)) 79 body = json; 80 else 81 { 82 var content = request.Content; 83 body = await content.ReadAsStringAsync(); 84 } 85 } 86 string uri = request.RequestUri.PathAndQuery; 87 var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); 88 string nonce = Guid.NewGuid().ToString("n"); 89 string message = $"{method} {uri} {timestamp} {nonce} {body} "; 90 91 string signature = Sign(message); 92 return $"mchid="{merchantId}",nonce_str="{nonce}",timestamp="{timestamp}",serial_no="{serialNo}",signature="{signature}""; 93 } 94 95 //SHA256withRSA 96 public string Sign(string str) 97 { 98 byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str); 99 var sha256 = new SHA256CryptoServiceProvider(); 100 byte[] rgbHash = sha256.ComputeHash(bt); 101 102 try 103 { 104 var rsa = GetPrivateKey(); 105 var key = new RSACryptoServiceProvider(); 106 var paras = rsa.ExportParameters(true); 107 key.ImportParameters(paras); 108 RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key); 109 formatter.SetHashAlgorithm("SHA256"); 110 byte[] inArray = formatter.CreateSignature(rgbHash); 111 return Convert.ToBase64String(inArray); 112 } 113 catch (Exception e) 114 { 115 return e.Message; 116 } 117 } 118 119 private RSACryptoServiceProvider GetPrivateKey() 120 { 121 var pc = new X509Certificate2(certPath, certPwd, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); 122 return (RSACryptoServiceProvider)pc.PrivateKey; 123 } 124 125 } 126 }
仅此记录一下