翼度科技»论坛 编程开发 .net 查看内容

c# .net framework 实现微信支付v3 h5支付 签名 验签

9

主题

9

帖子

27

积分

新手上路

Rank: 1

积分
27
接口文档:微信支付-开发者文档 (qq.com)
  1.         public const string transactions_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5";
  2.         public static string certPath = AppDomain.CurrentDomain.BaseDirectory + @"\cert\apiclient_cert.p12";
  3.         public static string certificatesPath = AppDomain.CurrentDomain.BaseDirectory + @"\cert\certificates_cert.pem"; // 回调解密证书 根据接口获取后 保存为 pem 后缀  我请求后自己手动保存的。没写代码去保存
  4.         private static string certPassword = "888888888"; //.p12 的证书密码
  5.         public string BuildAuth(string mchid, string serial_no, string method, string uri, string body)
  6.         {
  7.         var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
  8.         string nonce = Guid.NewGuid().ToString();
  9.         //构造签名串
  10.         //HTTP请求方法\n + URL\n + 请求时间戳\n + 请求随机串\n + 请求报文主体\n
  11.         string message = method + "\n" + uri + "\n" + timestamp + "\n" + nonce + "\n" + body + "\n";
  12.         string signature = GenerateSignature(message);
  13.         //发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid
  14.         //商户API证书序列号serial_no,用于声明所使用的证书
  15.         //请求随机串nonce_str
  16.         //时间戳timestamp
  17.         //签名值signature
  18.         return "mchid="" + mchid + "",nonce_str="" + nonce + "",timestamp="" + timestamp + "",serial_no="" + serial_no + "",signature="" + signature + """;
  19.         }
  20.         /// <summary>
  21.         /// 生成签名
  22.         /// </summary>
  23.         /// <param name="message"></param>
  24.         /// <returns></returns>
  25.         public static string GenerateSignature(string message)
  26.         {
  27.         X509Certificate2 cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
  28.         RSA PrivateKey = cert.GetRSAPrivateKey();
  29.         byte[] dataBytes = Encoding.UTF8.GetBytes(message);
  30.         byte[] signatureBytes = PrivateKey.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
  31.         return Convert.ToBase64String(signatureBytes);
  32.         }
  33.         /// <summary>
  34.         /// 验证回调签名
  35.         /// </summary>
  36.         /// <param name="signature"></param>
  37.         /// <param name="timestamp"></param>
  38.         /// <param name="nonce"></param>
  39.         /// <param name="body"></param>
  40.         /// <returns></returns>
  41.         public static bool VerifySignature(string signature, string timestamp, string nonce, string body)
  42.         {
  43.         //应答时间戳\n
  44.         //应答随机串\n
  45.         //应答报文主体\n
  46.         X509Certificate2 wechatCert = new X509Certificate2(certificatesPath); //, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable
  47.         string combinedString = string.Format("{0}\n{1}\n{2}\n", timestamp, nonce, body);
  48.         byte[] buff = Encoding.UTF8.GetBytes(combinedString);
  49.         var rsaPar = wechatCert.GetRSAPublicKey().ExportParameters(false);
  50.         var rsa = new RSACryptoServiceProvider();
  51.         rsa.ImportParameters(rsaPar);
  52.         return rsa.VerifyData(buff, CryptoConfig.MapNameToOID("SHA256"), Convert.FromBase64String(signature));
  53.         }
  54.         #region 加密解密
  55.         public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext, string apikey)
  56.         {
  57.         GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
  58.         AeadParameters aeadParameters = new AeadParameters(
  59.         new KeyParameter(Encoding.UTF8.GetBytes(apikey)),
  60.         128,
  61.         Encoding.UTF8.GetBytes(nonce),
  62.         Encoding.UTF8.GetBytes(associatedData));
  63.         gcmBlockCipher.Init(false, aeadParameters);
  64.         byte[] data = Convert.FromBase64String(ciphertext);
  65.         byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
  66.         int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
  67.         gcmBlockCipher.DoFinal(plaintext, length);
  68.         return Encoding.UTF8.GetString(plaintext);
  69.         }
  70.         #endregion
  71.         
  72.         
复制代码
  遇到的问题有
  1、签名老验证不过去
  

  生成的签名老验证不过    \n 不要加转义符
  2、 发送的请求老是400  使用工具请求正常。代码不行。
  UserAgent = "m.cnblogs.com/WebRequest"; 
  不要留空就行 网址可填自己的。
  3、回调解密的证书是自己获取的。可以获取后自己保存为后缀 .pem的证书文件
   获取平台证书列表-文档中心-微信支付商户平台 (qq.com)

  4、请求到h5_url 后可以在后面拼接指定跳转链接  https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2916263004719461949c84457c735b0000&package=2150917749&redirect_url=System.Web.HttpUtility.UrlEncode("https://www.cnblogs.com/MIMU86")

  5、苹果手机不是默认浏览器会跳到默认浏览器 无解

来源:https://www.cnblogs.com/MIMU86/archive/2023/11/30/17867154.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具