您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何理解.Net Core微信服務商二次進件的開發”,在日常操作中,相信很多人在如何理解.Net Core微信服務商二次進件的開發問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解.Net Core微信服務商二次進件的開發”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
最近商城進行微信服務商二次進件的開發,大致有幾個點
一,服務商簽名
二,服務商證書獲取
三,圖片上傳
四,敏感信息加密
五,查詢進件狀態
除此之外,就是進件信息的拼裝
電商二級商戶進件申請單-狀態流轉
首先準備必須的配置:商戶號、證書、秘鑰、小程序appid、appsecret
#region 服務商簽名 private string SrvPayBuildAuthAsync(string uri, string body, string method = "POST") { var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); string nonce = Guid.NewGuid().ToString(); string message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n"; string signature = SrvSign(message); return $"mchid=\"{_wxCfg.SrvPayMerchantId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{_wxCfg.SrvPayCertNo}\",signature=\"{signature}\""; } private string SrvSign(string message) { var bytes = Utils.ReadBytesIfExist(_wxCfg.SrvPayCertFile); if (bytes is null) { return ""; } X509Certificate2 cert = new(bytes, _wxCfg.SrvPayMerchantId); RSA rsa = cert.GetRSAPrivateKey(); var signData = rsa.SignData(Encoding.UTF8.GetBytes(message), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signData); }
分為:第一步獲取證書,第二步解密證書
1 獲取證書
https://api.mch.weixin.qq.com/v3/certificates
#region 獲取平臺證書 public async Task<CertificatesOutModel> GetSrvCert() { string uri = "/v3/certificates"; var auth = SrvPayBuildAuthAsync(uri, "", "GET"); var header = new Dictionary<string, string> { { "Authorization",$"WECHATPAY2-SHA256-RSA2048 {auth}"}, { "Accept","*/*" }, { "Accept-Encoding","gzip,deflate,brn" }, { "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.46" }, }; return await GetUrlAsync<CertificatesOutModel>(uri, header); } #endregion
使用的實體:CertificatesOutModel
public sealed class CertificatesOutModel : IWXResponse { [JsonPropertyName("data")] public IEnumerable<Certificates> Data { get; set; } public string Code { get; set; } public string Message { get; set; } } public class Certificates { [JsonPropertyName("serial_no")] public string SerialNo { get; set; } [JsonPropertyName("effective_time")] public string EffectiveTime { get; set; } [JsonPropertyName("expire_time")] public string ExpireTime { get; set; } [JsonPropertyName("encrypt_certificate")] public EncryptCertificate EncryptCertificate { get; set; } }
請求方法:GetUrlAsync
protected async Task<T> GetUrlAsync<T>(string url, Dictionary<string, string> headers = null) { HttpResponseMessage res = null; try { if (headers != null && headers.Count > 0) { foreach (var header in headers) { _client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value); } } res = await _client.GetAsync(url); res.EnsureSuccessStatusCode(); var result = await res.Content.ReadAsStringAsync(); if (result == null) { return default; } return result.ToJson<T>(); } catch { var result = await res.Content.ReadAsStringAsync(); if (result == null) { return default; } return result.ToJson<T>(); } }
解密方法
//獲取證書 var cert = await _wxClient.GetSrvCert(); var certificateModel = cert.Data.FirstOrDefault(); if (!cert.Data.Any()) { return new MKResult<V3WXPayApplymentIdOutModel>(code: 400, msg: "未獲取到平臺證書"); } if (!string.IsNullOrEmpty(applyment.Body.SerialNo)) { certificateModel = cert.Data.SingleOrDefault(s => s.SerialNo == applyment.Body.SerialNo); } certificateModel.EncryptCertificate.Ciphertext = AESUtility.AesGcmDecrypt( _wxCfg.SrvApiV3Key, certificateModel.EncryptCertificate.AssociatedData, certificateModel.EncryptCertificate.Nonce, certificateModel.EncryptCertificate.Ciphertext );
因為我的圖片保存在oss,首先要網絡圖片Bytes,對圖片進行sha256,方法在后面
protected async Task<byte[]> GetUrlBytesAsync(string url, Dictionary<string, string> headers = null) { try { if (headers != null && headers.Count > 0) { foreach (var header in headers) { _client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value); } } var res = await _client.GetAsync(url); res.EnsureSuccessStatusCode(); return await res.Content.ReadAsByteArrayAsync(); } catch { return default; } }
然后上傳圖片
/// <summary> /// 上傳圖片 /// </summary> /// <param name="url"></param> /// <returns></returns> public async Task<MKResult<V3WXPayFileUploadOutModel>> UploadFile(string url) { string fileContentType; string filetype; if (url!.Contains(".bmp", StringComparison.OrdinalIgnoreCase)) { fileContentType = "image/bmp"; filetype = ".bmp"; } else if (url!.Contains(".jpg", StringComparison.OrdinalIgnoreCase)) { fileContentType = "image/jpeg"; filetype = ".jpg"; } else if (url!.Contains(".jpeg", StringComparison.OrdinalIgnoreCase)) { fileContentType = "image/jpeg"; filetype = ".jpeg"; } else { fileContentType = "image/png"; filetype = ".png"; } UploadMerchantMediaImageRequest meta = new(); var fileBytes = await GetUrlBytesAsync(url);//獲取網絡圖片Bytes if ((fileBytes?.Length ?? 0) == 0) { return new MKResult<V3WXPayFileUploadOutModel>(code: 400, msg: "轉換圖片失敗"); } meta.FileHash = GetHash(fileBytes); meta.FileName = Guid.NewGuid().ToString("N").ToLower() + filetype; string boundary = "--BOUNDARY--" + DateTimeOffset.Now.Ticks.ToString("x"); using var fileContent = new ByteArrayContent(fileBytes); using var metaContent = new StringContent(meta.ToJson(), Encoding.UTF8, "application/json"); using var httpContent = new MultipartFormDataContent(boundary); httpContent.Add(metaContent, "\"meta\"");//meta 必須要加雙引號 httpContent.Add(fileContent, "\"file\"", "\"" + meta.FileName + "\"");//必須要加雙引號 httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data; boundary=" + boundary);// boundary不能加引號 metaContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(fileContentType); var uri = $"/v3/merchant/media/upload"; var res = await V3UpLoadFile<V3WXPayFileUploadOutModel>(uri, meta.ToJson(), httpContent); return new MKResult<V3WXPayFileUploadOutModel>(res, 1); }
private async Task<T> V3UpLoadFile<T>(string uri, string meta, MultipartFormDataContent content) { var auth = SrvPayBuildAuthAsync(uri, meta); var header = new Dictionary<string, string> { { "Authorization",$"WECHATPAY2-SHA256-RSA2048 {auth}"}, { "Accept","*/*" }, { "Accept-Encoding","gzip,deflate,brn" }, { "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.46" }, }; return await V3PostFileAsync<T>(uri, header, content); }
protected async Task<T> V3PostFileAsync<T>(string url, Dictionary<string, string> headers, MultipartFormDataContent content) { HttpResponseMessage res = null; try { if (headers != null && headers.Count > 0) { foreach (var header in headers) { _client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value); } } res = await _client.PostAsync(url, content); res.EnsureSuccessStatusCode(); var result = await res.Content.ReadAsStringAsync(); if (result == null) { return default; } return result.ToJson<T>(); } catch { var result = await res.Content.ReadAsStringAsync(); if (result == null) { return default; } return result.ToJson<T>(); } finally { if (content != null) { content.Dispose(); } } }
#region 二進制內容進行sha256 private static string GetHash(byte[] bytes) { if (bytes == null) throw new ArgumentNullException(nameof(bytes)); using SHA256 sha = SHA256.Create(); byte[] hashBytes = sha.ComputeHash(bytes); return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); }
使用獲取到的證書certificateModel,進行加密
public static class RSAUtility { public static string RSAEncrypt(string text, Certificates certificateModel) { var bytes = Encoding.UTF8.GetBytes(certificateModel.EncryptCertificate.Ciphertext); using var x509 = new X509Certificate2(bytes); var rsaParam = x509.GetRSAPublicKey().ExportParameters(false); var rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaParam); var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true); return Convert.ToBase64String(buff); } }
直接使用進件返回的Id,調用接口查詢就Ok了
到此,關于“如何理解.Net Core微信服務商二次進件的開發”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。