微信支付特约商户进件中base64格式图片上传
阅读原文时间:2023年07月10日阅读:1

微信图片上传接口地址: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 ///

16 /// 头文件 17 ///
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 /// 26 /// 构造方法 27 ///
28 /// 商户号
29 /// 证书序列号
30 /// 证书路径
31 /// 证书秘钥
32 /// 签名json数据,默认不需要传入,获取body内容,如传入签名传入参数上传图片时需传入
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 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 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}\n{uri}\n{timestamp}\n{nonce}\n{body}\n";
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 }

仅此记录一下