微信支付v3

新需求为了在网页上进行Native支付,在开发过程中走了很多弯路,网上的代码很多运行无法正常加解密,经过几天的读文档,百度,终于调通.
微信文档详见微信支付开发文档

签名

HTTP请求方法\n URL\n 请求时间戳\n 请求随机串\n 请求报文主体\n

对上述串进行SHA256 WITH RSA加密得到signature再填充到HTTP头中

‘Authorization: WECHATPAY2-SHA256-RSA2048
mchid=“1900009191”,nonce_str=“593BEC0C930BF1AFEB40B4A08C8FB242”,signature=“uOVRnA4qG/MNnYzdQxJanN+zU+lTgIcnU9BxGw5dKjK+VdEUz2FeIoC+D5sB/LN+nGzX3hfZg6r5wT1pl2ZobmIc6p0ldN7J6yDgUzbX8Uk3sD4a4eZVPTBvqNDoUqcYMlZ9uuDdCvNv4TM3c1WzsXUrExwVkI1XO5jCNbgDJ25nkT/c1gIFvqoogl7MdSFGc4W4xZsqCItnqbypR3RuGIlR9h9vlRsy7zJR9PBI83X8alLDIfR1ukt1P7tMnmogZ0cuDY8cZsd8ZlCgLadmvej58SLsIkVxFJ8XyUgx9FmutKSYTmYtWBZ0+tNvfGmbXU7cob8H/4nLBiCwIUFluw==”,timestamp=“1554208460”,serial_no=“1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C”’

 /// <summary>/// 签名/// </summary>/// <param name="filePath">证书地址</param>/// <param name="body">请求的报文内容 若为Get则为空</param>/// <param name="method">请求方法</param>/// <param name="url">链接 绝对路径</param>/// <returns></returns>public string CreateSign(string filePath,string body,string method,string url) {//0时间戳 1随机串 2报文主题string seconds = (DateTime.Now - DateTime.Parse("1970-01-01 08:00:00")).TotalSeconds.ToString().Split('.')[0];string randoms = new Random().Next().ToString("X")+ new Random().Next().ToString("X");string s = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n", method, url, seconds, randoms, body);s = Encryption.SHA256WithRSA(filePath, WeChatKey.mch_id,s);string sign = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",serial_no=\"{2}\",timestamp=\"{3}\",signature=\"{4}\"",WeChatKey.mch_id,randoms, WeChatKey.certnum, seconds,s);return sign;}
/// <summary>
/// SHA256WithRSA加密 签名
/// </summary>
/// <param name="pfxFilePath">证书路径</param>
/// <param name="pfxPassword">证书密码 默认为商家的商户号</param>
/// <param name="s">需要加密的明文</param>
/// <returns></returns>
public static string SHA256WithRSA(string pfxFilePath, string pfxPassword,string s)
{           X509Certificate2 privateCert = new X509Certificate2(pfxFilePath, pfxPassword, X509KeyStorageFlags.Exportable);RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)privateCert.PrivateKey;    RSACryptoServiceProvider privateKey1 = new RSACryptoServiceProvider();privateKey1.ImportParameters(privateKey.ExportParameters(true));byte[] data = Encoding.UTF8.GetBytes(s);byte[] signature = privateKey1.SignData(data, "SHA256");//密文string sign = Convert.ToBase64String(signature);return sign;
}

验签

应答时间戳\n 应答随机串\n 应答报文主体\n

对上述的明文使用微信支付平台公钥对验签名串和签名进行SHA256 with RSA签名验证

/// <summary>
/// 验证签名
/// </summary>
/// <param name="filePath">证书文件地址</param>
/// <param name="time">时间戳</param>
/// <param name="randoms">随机字符串</param>
/// <param name="body">报文主题</param>
/// <param name="sign">签名</param>
/// <param name="certnum">所使用的证书编号</param>
/// <returns></returns>
public bool VerifiedSign(string filePath ,string time,string randoms,string body,string sign,string certnum) {//先验证平台证书是否使用的一致 如果不一致 则重新获取证书 if (certnum != WeChatKey.PtzsNum) {string tosign = CreateSign(filePath, "", "GET", ApiUrlList.wqmscUrl.Substring(ApiUrlList.wqmscUrl.IndexOf("com") + 3));string ptzs = HttpUtils.Get(ApiUrlList.wqmscUrl, tosign);JObject o = JObject.Parse(ptzs);//返回的证书json是一个数组JArray data = (JArray)o["data"];                //解密证书所需要的数据 随机字符串 解密类型string nonce = data[0]["encrypt_certificate"]["nonce"].ToString();string associated_data = data[0]["encrypt_certificate"]["associated_data"].ToString();//密文string ciphertext= data[0]["encrypt_certificate"]["ciphertext"].ToString();//更新平台证书WeChatKey.PtzsNum = data[0]["serial_no"].ToString();WeChatKey.PtzspublicKey = Encryption.AesGcmDecrypt(associated_data, nonce, ciphertext);//获取最新证书依旧不相等 则可能为恶意操作 不予处理if (certnum != WeChatKey.PtzsNum) {return false;}}//验签string s = string.Format("{0}\n{1}\n{2}\n", time, randoms, body);return Encryption.VerifySign(WeChatKey.PtzspublicKey, sign, s);
}
/// <summary>
/// SHA256WithRSA加密 验签
/// </summary>
/// <param name="certPublickey">公钥</param>
/// <param name="sign">密文</param>
/// <param name="s">明文</param>
/// <returns></returns>
public static bool VerifySign(string certPublickey, string sign,string s)
{X509Certificate2 publicCert = new X509Certificate2(Encoding.UTF8.GetBytes(certPublickey));RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)publicCert.PublicKey.Key;SHA256CryptoServiceProvider sHA = new SHA256CryptoServiceProvider();return publicKey.VerifyData(Encoding.UTF8.GetBytes(s), sHA, Convert.FromBase64String(sign));
}
/// <summary>
/// AEAD_AES_256_GCM 用于解密 微信支付回调的密文ciphertext
/// </summary>
/// <param name="associatedData">原数据类型</param>
/// <param name="nonce">随机字符串</param>
/// <param name="ciphertext">密文</param>
/// <returns></returns>
public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext)
{GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());AeadParameters aeadParameters = new AeadParameters(new KeyParameter(Encoding.UTF8.GetBytes(WeChatKey.Apiv3Key)),128,Encoding.UTF8.GetBytes(nonce),Encoding.UTF8.GetBytes(associatedData));gcmBlockCipher.Init(false, aeadParameters);byte[] data = Convert.FromBase64String(ciphertext);byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);gcmBlockCipher.DoFinal(plaintext, length);return Encoding.UTF8.GetString(plaintext);
}

低版本的.net找不到GcmBlockCipher AeadParameters 需要引入BouncyCastle.Crypto.dll

微信支付v3 签名与验签相关推荐

  1. 微信支付生成签名和验签SDK源码分析

    目录 一.签名分析 1.1 流程分析 1.构造签名串 2.计算签名值 3.设置请求头 二.源码级别分析 二.获取平台证书分析 三.验签分析 3.1 验签使用场景: 3.2 验证流程: 1.获取微信平台 ...

  2. 微信支付V3版本回调+验签流程

    本文主要是接前面2篇微信V3支付参数准备和微信V3支付整合进项目中的后续之微信支付后的回调. 一.回调验签流程介绍 二.核心流程操作 本文主要是接前面2篇微信V3支付参数准备和微信V3支付整合进项目中 ...

  3. 微信支付API v3签名与验签-APP支付问题

    目录 使用API v3微信支付遇到的问题: 1.微信请求客户端配置 2.生成预付款订单 3.拼接字符串使用API v3签名 4.微信支付成功后通知 使用API v3微信支付遇到的问题: 1.jdk版本 ...

  4. PHP对微信支付v2回调进行验签并将相关数据加入数据库

    PS:对于V2版本微信支付的回调需要在线上环境进行,本文中出现的数据库的相关字段,各位请按照个人需求进行修改,此处只对微信回调数据进行相关解析; 代码方面写的比较杂乱,多看注释,相关代码根据个人需求进 ...

  5. PHP 微信支付v3签名生成

    签名生成方法 // 解析url $url_parts = parse_url($url); $canonical_url = ($url_parts['path'] . (!empty($url_pa ...

  6. java微信支付验证签名_Java中的微信支付(3):API V3对微信服务器响应进行签名验证...

    1. 前言 牢记一句话:公钥加密,私钥解密:私钥加签,公钥验签. 微信支付V3版本前两篇分别讲了如何对请求做签名和如何获取并刷新微信平台公钥,本篇将继续展开如何对微信支付响应结果的验签. 2. 为什么 ...

  7. springboot利用官方SDK(wechatpay-apache-httpclient)接入微信支付V3

    利用微信官方提供的SDK wechatpay-apache-httpclient 实现.以微信小程序支付为例,其他支付也是一样的,就是参数和接口地址不同. 微信支付V3文档 首先要在微信商户平台设置好 ...

  8. 微信支付V3版本的 签名生成,验签,解密,统一下单的简单封装

    微信支付 V3版本的 签名生成,验签,解密,统一下单的简单封装 V3Base 获取平台证书 回调报文解密 统一下单 暂时看了文档只完成了这部分,感觉封装的不是特别完美,希望有大佬指点一下,想着封装好一 ...

  9. 记录微信获取平台证书支付错误 错误的签名,验签失败

    错误的签名,验签失败 前言 解决方案 前言 我这里使用的是 微信支付 v3 sdk,sdk会帮我拼接签名,所以我初步判断是公司给我证书序列号错误 // 加载平台证书(mchId:商户号,mchSeri ...

最新文章

  1. 白话经典算法系列之七 堆与堆排序
  2. LSTM之父:吐槽了两年,来划划重点:“这5篇最高引论文都源于我们。”
  3. Oracle 9 - redo和undo
  4. flask+sqlite3+echarts3+ajax 异步数据加载
  5. [保护模式]非PAE模式
  6. 关于@property()的那些属性及ARC简介【nonatomic,atomic,assign,retain,strong,weak,copy。】
  7. Hadoop Map/Reduce的工作流
  8. 将dll制作成控件_全国首例将“影视作品”制作成“网络图片集”方式侵权案宣判...
  9. 一文领略 HTTP 的前世今生
  10. hive中实现行转列_Hive之行转列lateral view用法
  11. 技术人如何加速成长?提升你的思维和学习方式
  12. String字符串格式化为:00001
  13. python绘制降水色斑图
  14. Spring:Spring支持的bean作用域有哪些
  15. 等值线图的Python绘制方法
  16. java调用javascript函数_Java调用javascript函数
  17. 被static修饰的map、list GC问题
  18. 海报看起来很普通?数字平原概念设计来制作
  19. 2022年RocketMQ面试题及答案
  20. CSS的Flex布局的学习

热门文章

  1. CSDN赚取积分(转)
  2. 解决首次安装Captura免费录屏软件时出现FFMPEG was not found on your system的问题
  3. H.266/VVC技术学习:熵编码
  4. H.266/VVC代码学习:xCompressCU函数
  5. HTML5+CSS3制作底部导航栏
  6. 发布 'xx' 的并发快照不可用,因为该快照尚未完全生成,或者日志读取器代理未运行,无法激活它。如果并发快照的生成过程中断,则必须重新启动用于该发布的快照代理,直到生成完整的快照。
  7. 2022出海东南亚:泰国电商市场现状及网红营销特点
  8. 【牛客刷题】游戏行业通识(更新中)
  9. 积分商场APP开发的新用途
  10. iPhone 12屏幕发黄怎么办?拯救屏幕变黄的解决办法!