tnblog
首页
视频
资源
登录

.NET接入微信支付(三)加解密验签

3381人阅读 2023/2/23 17:01 总访问:28316 评论:0 收藏:0 手机
分类: 微信支付
  • 签名等所需要的加解密

      1.     /// <summary>
      2.     /// 解密类
      3.     /// </summary>
      4.     public class WxPayDecrypt
      5.     {
      6.         /// <summary>
      7.         /// 解析密文
      8.         /// </summary>
      9.         /// <param name="associated_data"></param>
      10.         /// <param name="nonce"></param>
      11.         /// <param name="ciphertext"></param>
      12.         /// <returns></returns>
      13.         public static string GetAesGcmDecrypt(string associated_data, string nonce, string ciphertext)
      14.         {
      15.             return Encoding.UTF8.GetString(AesGcmDecrypt(associated_data, nonce, ciphertext,WxPayConfig.KEY));
      16.         }
      17.         /// <summary>
      18.         /// AesGcm256解密
      19.         /// </summary>
      20.         /// <see cref="https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_2.shtml"/>
      21.         /// <param name="associatedData"></param>
      22.         /// <param name="nonce"></param>
      23.         /// <param name="ciphertext"></param>
      24.         /// <param name="aesKey"></param>
      25.         /// <returns></returns>
      26.         public static byte[] AesGcmDecrypt(string associatedData, string nonce, string ciphertext, string aesKey)
      27.         {
      28.             GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
      29.             AeadParameters aeadParameters = new AeadParameters(
      30.                 new KeyParameter(Encoding.UTF8.GetBytes(aesKey)),
      31.                 128,
      32.                 Encoding.UTF8.GetBytes(nonce),
      33.                 Encoding.UTF8.GetBytes(associatedData));
      34.             gcmBlockCipher.Init(false, aeadParameters);
      35.             byte[] data = Convert.FromBase64String(ciphertext);
      36.             byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
      37.             int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
      38.             gcmBlockCipher.DoFinal(plaintext, length);
      39.             return plaintext;
      40.         }
      41.         /// <summary>
      42.         /// AEAD_AES_256_GCM
      43.         /// https://tools.ietf.org/html/rfc5116#page-15
      44.         /// GCM加密后附加128位TAG形成密文
      45.         /// </summary>
      46.         /// <param name="key"></param>
      47.         /// <returns></returns>
      48.         public static byte[] Decrypt(string key, EncryptInfo encryptInfo)
      49.         {
      50.             var data = Convert.FromBase64String(encryptInfo.ciphertext);
      51.             var cipher = data.AsEnumerable().Take(data.Length - 16).ToArray();
      52.             var tag = data.AsEnumerable().Skip(data.Length - 16).ToArray();
      53.             return AesGcmDecrypt(encryptInfo.associated_data, encryptInfo.nonce, encryptInfo.ciphertext, key);
      54.         }
      55.     }
      1.     /// <summary>
      2.     /// 加密类
      3.     /// </summary>
      4.     public static class WxPayEncrypt
      5.     {
      6.         /// <summary>
      7.         /// 构造签名头
      8.         /// </summary>
      9.         /// <param name="url"></param>
      10.         /// <param name="method"></param>
      11.         /// <param name="body"></param>
      12.         /// <param name="options"></param>
      13.         /// <returns></returns>
      14.         public static string BuildToken(string url, string method, string body, X509Certificate2 certificate, string merchantId)
      15.         {
      16.             string uri = string.Empty, nonce = string.Empty, message = string.Empty, signature = string.Empty, SerialNumber = string.Empty;
      17.             try
      18.             {
      19.                 uri = new Uri(url).PathAndQuery;
      20.                 long timestamp = WxPayUitls.GenerateTimeStamp();
      21.                 nonce = Guid.NewGuid().ToString("N");
      22.                 message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n";
      23.                 signature = message.ToRSAPrivateString(certificate);
      24.                 SerialNumber = certificate.SerialNumber;
      25.                 return $"mchid=\"{merchantId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{SerialNumber}\",signature=\"{signature}\"";
      26.             }
      27.             catch (Exception ex)
      28.             {
      29.                 Logger loger = LogManager.GetCurrentClassLogger();
      30.                 loger.Info("生成TOKEN失败 :" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")
      31.                     + "\n message --> " + message + "--- SerialNumber --> " + SerialNumber
      32.                     + "\n" + ex.Message + "\n" + ex.StackTrace);
      33.                 throw;
      34.             }
      35.         }
      36.         /// <summary>
      37.         /// 调起支付生成签名
      38.         /// </summary>
      39.         /// <param name="request"></param>
      40.         /// <returns></returns>
      41.         public static string MakePaySign(string message)
      42.         {
      43.             try
      44.             {
      45.                 X509Certificate2 Certificate = null;
      46.                 Certificate = new X509Certificate2(WxPayConfig.SSLCERT_PATH, WxPayConfig.SSLCERT_PASSWORD, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
      47.                 if (Certificate == null)
      48.                 {
      49.                     throw new WxPayException("证书获取失败");
      50.                 }
      51.                 return message.ToRSAPrivateString(Certificate);
      52.             }
      53.             catch (Exception e)
      54.             {
      55.                 Logger loger = LogManager.GetCurrentClassLogger();
      56.                 loger.Error("调起支付生成签名异常:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "\r Message-->" + e.Message + "\r StackTrace--> " + e.StackTrace);
      57.                 throw;
      58.             }
      59.         }
      60.         /// <summary>
      61.         /// RSA 加密
      62.         /// </summary>
      63.         /// <param name="message">消息</param>
      64.         /// <param name="certificate">证书</param>
      65.         /// <returns></returns>
      66.         private static string ToRSAPrivateString(this string message, X509Certificate2 certificate)
      67.         {
      68.             string signature = string.Empty;
      69.             using (RSA rsa = certificate.GetRSAPrivateKey())
      70.             {
      71.                 signature = Convert.ToBase64String(rsa.SignData(Encoding.UTF8.GetBytes(message), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
      72.             }
      73.             return signature;
      74.         }
      75.         /// <summary>
      76.         /// 平台证书验签
      77.         /// </summary>
      78.         /// <param name="responseContent">响应原文</param>
      79.         /// <param name="payHeader">请求头</param>
      80.         /// <returns></returns>
      81.         public static bool VerifySign(string responseContent, WechatPayHeader payHeader)
      82.         {
      83.             try
      84.             {
      85.                 X509Certificate2 certificate = null;
      86.                 string pemPath = WxPayConfig.PLATEFORMSSLCERT_PATH + payHeader.SerialNo + ".pem";
      87.                 if (File.Exists(pemPath))
      88.                 {
      89.                     certificate = new X509Certificate2(pemPath, WxPayConfig.SSLCERT_APIV3KEY, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
      90.                 }
      91.                 if (certificate == null)
      92.                 {
      93.                     certificate = WxPayApi.GetPlatformCertificate(payHeader.SerialNo);
      94.                 }
      95.                 string message = $"{payHeader.TimeStamp}\n{payHeader.Nonce}\n{responseContent}\n";
      96.                 using (var rsa = certificate.GetRSAPublicKey())
      97.                 {
      98.                     var res = rsa.VerifyData(Encoding.UTF8.GetBytes(message), Convert.FromBase64String(payHeader.Signature), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
      99.                     return res;
      100.                 }
      101.             }
      102.             catch (Exception e)
      103.             {
      104.                 Logger loger = LogManager.GetCurrentClassLogger();
      105.                 loger.Error("平台证书验签异常:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "\r Message-->" + e.Message + "\r StackTrace--> " + e.StackTrace);
      106.                 throw;
      107.             }
      108.         }
      109.     }
评价

net core 使用 EF Code First

下面这些内容很老了看这篇:https://www.tnblog.net/aojiancc2/article/details/5365 项目使用多层,把数据库访问...

cAPS.net 保存base64位格式的图片

publicvoidUpload() { //取出图片对应的base64位字符 stringimgBase=Request[&quot;imgBase&quot;]; //c#里边的base6...

Quartz.net实例动态改变周期调度。misfire、Cron

Quartz:Java编写的开源的任务调度作业框架 类似Timer之类定时执行的功能,但是更强大Quartz.NET:是把Quartz转成C# NuGet...

.net Windows服务发布、安装、卸载、监听脚本。服务调试

一、脚本 为方便不用每次都去写安装卸载的脚本1.安装脚本@echooff @echo开始安装【服务】 %SystemRoot%\Microsoft.NET\Fr...

c、VB.net中全角半角转换方法

///&lt;summary&gt; ///转全角的函数(SBCcase) ///&lt;/summary&gt; ///&lt;paramname=&quot;input&quot;&gt;任意字符串...

.net mvc分部页,.net core分部页

.net分部页的三种方式第一种:@Html.Partial(&quot;_分部页&quot;)第二种:@{ Html.RenderPartial(&quot;分部页&quot;);}...

C.net 配合小程序实现经过第方服务器中转文件

某些时候,微信小程序前段上传文件的时候需要经过第三方服务器再将文件上传到客户的服务器;操作如下:1:(小程序内向中端服...

.net实现QQ邮箱发送邮件功能

1、微软已经帮我们封装好了发送邮件的类MailMessage,MailMessage类构造一些邮件信息,然后通过SmtpClient进行邮件发送。Mai...

StackExchange.Redis操作redis(net core支持)

官方git开源地址https://github.com/StackExchange/StackExchange.Redis官方文档在docs里边都是官方的文档通过nuget命令下...

windows 自带的netsh进行端口映射

使用netsh 把本地任意ip的25566端口 映射到192.168.81.234的25565端口netshinterfaceportproxyaddv4tov4listenaddress=0.0....

确保.net程序始终以管理员身份运行

usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; ...

ASP.net Timer细节处理

Timer的用法:1:本人称之为计时器,是asp.net官方的一种。用法即是计时所用 2:关于计时有很多中方式,本人学识有限,暂...

.net core 使用session

tip:net core 2.2后可以直接启用session了,不用在自己添加一次session依赖,本身就添加了使用nuget添加引用Microsoft.AspN...

通俗易懂,什么是.net?什么是.net Framework?什么是.net core?

朋友圈@蓝羽 看到一篇文章写的太详细太通俗了,搬过来细细看完,保证你对.NET有个新的认识理解原文地址:https://www.cnblo...

asp.net core2.0 依赖注入 AddTransient与AddScoped的区别

asp.net core主要提供了三种依赖注入的方式其中AddTransient与AddSingleton比较好区别AddTransient瞬时模式:每次都获取一...

asp.net主动推送百度seo

虽然可以使用百度提供的js自动推送,但是估计度娘还是希望主动推送一点。哈哈^_^,女孩子嘛大多都喜欢被动一点。publicclass...
一木浮沉,吾与之。
排名
63
文章
6
粉丝
2
评论
3
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术
只羡忘羡不羡仙,说是天天就天天