如何理解.Net Core微信服务商二次进件的开发

技术如何理解.Net Core微信服务商二次进件的开发这篇文章主要介绍“如何理解.Net Core微信服务商二次进件的开发”,在日常操作中,相信很多人在如何理解.Net Core微信服务商二次进件的开发问题上存在疑惑,小

本文主要介绍“如何理解的发展。网芯微信服务商的二次feed”。在日常操作中,相信很多人对于如何理解的发展都有疑惑。网芯微信服务商的二次feed。边肖查阅了各种资料,整理出简单易用的操作方法,希望能帮助大家解答“如何理解的发展。网芯微信服务商的二次feed”。接下来,请和边肖一起学习!

最近商城进行了微信服务商第二feed的开发,有几点。

1.服务提供商签名。

二是服务商证书获取。

第三,上传图片。

敏感信息的加密。

5.查询来料零件状态。

此外,它是传入信息的集合。

电子商务二级商户入局申请表-状态流转。

如何理解.Net  Core微信服务商二次进件的开发

一 服务商签名

首先准备必要的配置:商户号、证书、密钥、applet appid和appsecret。

#地区服务提供商签名。

privatestringSrvPayBuildAuthAsync(string uri,stringbody,stringmethod='POST ')

{

vartimestamp=DateTimeOffset。now . ToUnixTimeSeconds();

stringnonce=Guid。NewGuid()。ToString();

string message=$ ' { method } \ n { uri } \ n { timestamp } \ n { nonce } \ n { body } \ n ';

stringsignature=SrvSign(消息);

返回$'mchid=\'{_wxCfg。SrvPayMerchantId } \ ',nonce_str=\'{nonce}\ ',timestamp=\'{timestamp}\ ',serial_no=\'{_wxCfg。SrvPayCertNo}\ ',签名=\ ' { signature } \

}

privatestringSrvSign(字符串消息)

{

varbytes=Utils。readbytesfexist(_ Wxcfg。SrvPayCertFile);

if(字节数)

{

返回“”;

sp;         }
            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微信服务商二次进件的开发”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/44636.html

(0)

相关推荐

  • 中药蜜丸的制作方法,中药密丸的制作方法谁知道呀?

    技术中药蜜丸的制作方法,中药密丸的制作方法谁知道呀?蜜丸制作方法中药蜜丸的制作方法: 1、蜂蜜用量:一般药粉与炼蜜的比例是10:3,炼蜜与水的比例为1:3。药粉的粘性的大小不同改变蜜水浓度与用蜜量。
    2、制作步骤:

    生活 2021年10月29日
  • 快速排序平均时间复杂度O(nlogn)的推导

    技术快速排序平均时间复杂度O(nlogn)的推导 快速排序平均时间复杂度O(nlogn)的推导快速排序作为随机算法的一种,不能通过常规方法来计算时间复杂度,本文记录了一种推导方法快速排序作为随机算法的一

    礼包 2021年11月13日
  • HTTP请求流程详解

    技术HTTP请求流程详解 HTTP请求流程详解HTTP协议是建立在TCP连接基础之上的,它是一种允许浏览器向服务器发送请求获取资源的协议,是Web的基础。通常都是由浏览器发起请求,来获取服务端的资源如H

    礼包 2021年12月3日
  • Fundebug后端Node.js插件更新至0.2.0是否支持监控Express慢请求

    技术Fundebug后端Node.js插件更新至0.2.0是否支持监控Express慢请求Fundebug后端Node.js插件更新至0.2.0是否支持监控Express慢请求,很多新手对此不是很清楚,为了帮助大家解决这

    攻略 2021年10月21日
  • 如何理解MultiScanner模块化文件扫描与分析框架

    技术如何理解MultiScanner模块化文件扫描与分析框架如何理解MultiScanner模块化文件扫描与分析框架,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个

    攻略 2021年11月25日
  • 第一次使用Swagger出现空指针异常

    技术第一次使用Swagger出现空指针异常 第一次使用Swagger出现空指针异常问题
    在第一次使用swagger时出现java.lang.NullPointerException。
    完整的错误信息如下

    礼包 2021年11月27日