API v3版微信支付平台证书获取与自动更新

  • 关于微信证书
  • 获取平台证书
  • 证书自动更新
  • 首次下载证书

关于微信证书

微信支付开发有两份证书。
商户证书:商户平台证书私钥可以对请求进行签名,微信服务器进行验签可以验证请求者的身份和合法性;
微信平台证书:是由微信服务器使用私钥对响应签名之后,我们自己的服务器使用平台证书对响应进行验签,从而可以验证响应的合法性。

获取平台证书

微信官网有对应的API可以获取平台证书,请求之前也需要进行相应的签名,响应的数据大致如下。
若有新旧证书更替,则可能不止一条证书数据存在,且ciphertext证书字段为密文传输,需要对其进行解密才能正常使用。
解密使用的对称密钥是在微信平台(微信平台传送门)进行设置。【商户平台】->【API安全】->设置API v3密钥(注意不是API密钥)

{"data": [{"serial_no": "5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time ": "2018-06-08T10:34:56+08:00","expire_time ": "2018-12-08T10:34:56+08:00","encrypt_certificate": {"algorithm": "AEAD_AES_256_GCM","nonce": "61f9c719728a","associated_data": "certificate","ciphertext": "sRvt… "}},{"serial_no": "50062CE505775F070CAB06E697F1BBD1AD4F4D87","effective_time ": "2018-12-07T10:34:56+08:00","expire_time ": "2020-12-07T10:34:56+08:00","encrypt_certificate": {"algorithm": "AEAD_AES_256_GCM","nonce": "35f9c719727b","associated_data": "certificate","ciphertext": "aBvt… "}}]
}

解密响应体,解密ciphertext证书字段代码。

 /*** 使用微信平台证书对响应验签,和应答签名比较* @param wechatpaySerial      response.headers['Wechatpay-Serial']      当前使用的微信平台证书序列号* @param wechatpaySignature  response.headers['Wechatpay-Signature']       微信平台签名* @param wechatpayTimestamp  response.headers['Wechatpay-Timestamp']       微信服务器时间戳* @param wechatpayNonce        response.headers['Wechatpay-Nonce']           微信服务器提供的随机串* @param body                   response.headers['Wechatpay-body']            微信服务器的响应体* @return                     boolean* @throws SignatureException */public boolean responseSignVerify(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String body) {log.info("WXPayUtil responseSignVerify start : wechatpaySerial = " + wechatpaySerial + ", wechatpaySignature = " + wechatpaySignature + ", wechatpayTimestamp = " + wechatpayTimestamp +", wechatpayNonce = " + wechatpayNonce + ", body = " + body);if(CERTIFICATE_MAP.isEmpty() || !CERTIFICATE_MAP.containsKey(wechatpaySerial)) {refreshCertificate();}Certificate certificate = CERTIFICATE_MAP.get(wechatpaySerial);
//      log.info("WXPayUtil responseSignVerify CERTIFICATE_MAP证书:certificate" + certificate);// 构造验签名串final String strSignature = responseSign(wechatpayTimestamp, wechatpayNonce, body);log.info("WXPayUtil responseSignVerify 构造验签名串 strSignature : " + strSignature);try {// 加载 SHA256withRSA 签名器Signature signer = Signature.getInstance(SIGN_INSTANCE_SHA256WITHTSA);// 用微信平台公钥对签名器进行初始化signer.initVerify(certificate);// 将验签名串更新到签名器中signer.update(strSignature.getBytes(StandardCharsets.UTF_8));boolean ret = signer.verify(Base64Utils.decodeFromString(wechatpaySignature)); log.info("WXPayUtil responseSignVerify 验签结果 ret = " + ret);return ret;} catch (NoSuchAlgorithmException | SignatureException e) {// TODO Auto-generated catch blockthrow new IllegalStateException(e);} catch (InvalidKeyException e) {// TODO Auto-generated catch blockthrow new IllegalArgumentException(e);} }

证书自动更新

微信平台为了保证安全,定期会更换平台证书,这时我们自己的系统就需要自动更新对应证书来验签。

private static final Map<String, Certificate> CERTIFICATE_MAP = new ConcurrentHashMap<String, Certificate>();
/*** 证书动态刷新,将最新的证书放入Map中* */public void refreshCertificate(){WXPayNativeService nativeService = new WXPayNativeService();java.util.List<WXPlatCertificate> respCertList = nativeService.getWXCertList();log.info("NativeService-refreshCertificate 请求返回数据为:" + respCertList);// 选用证书启用时间最晚的证书  List<WXPlatCertificate> wx = respCertList.stream()                .sorted(Comparator.comparing((WXPlatCertificate w) -> w.getEffective_time()))                .collect(Collectors.toList());WXPlatCertificate wxPlatCertificate = wx.get(0);WXPlatCertificate wxPlatCertificate = respCertList.get(0);log.info("NativeService-refreshCertificate wxPlatCertificate 最近的证书为:" + wxPlatCertificate);
//      respCertList.stream().sorted()// 解密返回数据,得到证书String publicKey = WXPayUtil.decryptResponseBody(WXPayUtil.getConfigProperties("WX_APIV3_SYMMETRIC_KEY"),wxPlatCertificate.getEncrypt_certificate().getAssociated_data(),wxPlatCertificate.getEncrypt_certificate().getNonce(),wxPlatCertificate.getEncrypt_certificate().getCiphertext()); log.info("NativeService-getConfigProperties 解密返回数据,publicKey1:" + publicKey);try {final CertificateFactory cf = CertificateFactory.getInstance("X509");ByteArrayInputStream inputStream = new ByteArrayInputStream(publicKey.getBytes(StandardCharsets.UTF_8));Certificate certificate = cf.generateCertificate(inputStream);String responseSerialNo = wxPlatCertificate.getSerial_no(); System.out.println("NativeService-getConfigProperties 证书序列号为serial_no:" + responseSerialNo);// 清空HashMap()CERTIFICATE_MAP.clear();// 放入证书CERTIFICATE_MAP.put(responseSerialNo, certificate);} catch (CertificateException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

首次下载证书

首次下载证书的时候,这时候我们本地是没有证书的,所以下载证书的请求不能进行验签,否则可能会出现循环调用的情况,微信平台提供了工具可以进行第一次的证书下载。(微信证书下载工具)
将jar包下载之后cmd输入命令即可下载。当然也可以选择不进行验签。

java -jar F:\WXpayDemo\CertificateDownloader-1.1.jar -k erexxxrxxxxxxxxxxxxxxxxjled -m 15xxxxxxxxx61 -f F:\WXpayDemo\param\apiclient_key.pem -s 23B3AxxxxxxxxxxxxxxxxxxxxxxxC90B50 -o F:\WXpayDemo

完整命令如下:

java -jar F:\WXpayDemo\CertificateDownloader.jar -k java -jar F:\WXpayDemo\CertificateDownloader-1.1.jar -k erexxxrxxxxxxxxxxxxxxxxjled -m 15xxxxxxxxx61 -f F:\WXpayDemo\param\apiclient_key.pem -s 23B3AxxxxxxxxxxxxxxxxxxxxxxxC90B50 -o F:\WXpayDemo

证书下载完成之后就可以对响应进行验签。

相关文章链接:

API v3版微信支付开发JAVA
API v3版微信支付请求签名
API v3版微信支付 验签

API v3版微信支付平台证书获取与自动更新相关推荐

  1. V3微信支付平台证书获取、更新配置

    写这个版本 我尝试了三个不同的版本 决定把这一个最新版 0.4.2的版本分享出来 0.4.0已经替换掉0.3.0版本中的更新方式 我们需要在Config的文件配置中做一些更改 直接上配置 @Slf4j ...

  2. (PHP)获取微信支付平台证书步骤

    1.在个人项目中已经通过composer 安装微信支付包: 在更人项目根目录命令行窗口执行下面的安装命令 安装命令:composer require wechatpay/wechatpay 2.为什么 ...

  3. 微信支付证书如何部署在linux,微信支付平台证书更新指引

    最佳实践 由于旧证书过期前的5天内,微信支付会同时使用新旧证书,因此为实现新老证书的平滑切换,商户系统需支持多平台证书. 方式1 商户需通过平台证书下载API获取证书,并将其部署到生产环境中.线上服务 ...

  4. 下载微信支付平台证书及首次下载报错处理

    官方文档:https://github.com/wechatpay-apiv3/CertificateDownloader 参考文档1:https://blog.csdn.net/dling8/art ...

  5. thinkPHP生成微信支付平台证书

    1.先安装微信支付V3版本: 2.在目录 vendor/wechatpay/wechatpay下执行以下代码: 3.在本地VScode编辑器的终端运行命令行,执行以下代码: composer exec ...

  6. php微信退款 v3版,微信支付-JSAPI支付V3-查询退款

    字段名 变量名 必填 类型 示例值 描述 公众账号ID appid 是 String(32) wx8888888888888888 微信分配的公众账号ID 商户号 mch_id 是 String(32 ...

  7. 微信支付平台技术文档的一个小坑

    一.注意服务器的时间与微信接口是否相同,如时间不同接口也不通即使是0.1秒 二.调用支付相关接口需要加载私钥,和证书两个认证文件,官网文档给了java和php两个demo,逻辑应该是一样的,但实际却走 ...

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

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

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

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

最新文章

  1. 过拟合的原因以及解决办法(深度学习)
  2. 波音公司计划利用 3D 打印技术制作模块化卫星
  3. c语言无效参数视为严重错误,C语言编译错误:错误:‘-’参数类型无效(有‘int’)...
  4. maven的离线模式
  5. 解决: Cannot find module ‘webpack-cli/bin/config-yargs‘、Error: Cannot find module ‘webpack-cli‘
  6. 使用Office 365 试用账户 体验Office 365功能
  7. HDU 1012 u Calculate e(简单阶乘计算)
  8. NYOJ题目36-最长公共子序列(经典动态规划题)
  9. GitHub中文社区
  10. 立体栅格地图_高精地图之3D栅格地图的应用
  11. 为什么央行降息降准,会导致债券价格上涨?
  12. IDEA怎么查看现在的项目使用的JDK版本? 2016年4月19日22:51
  13. LWN:Linux audio plugin APIs综述!
  14. 纪中暑假培训 :Date:7 终章-剑之魂
  15. [原创] 简单的几个步骤`皮肤变得晶莹剔透
  16. centos打显卡驱动命令_centos7系统,显卡驱动安装教程
  17. 【蓝桥杯选拔赛真题50】Scratch小猫跑步 少儿编程scratch图形化编程 蓝桥杯选拔赛真题讲解
  18. 微信小程序数据绑定和简单的运算
  19. 计算机组成原理——TEC-2储存器实验
  20. Spring5底层原理 学习笔记(二)AOP篇

热门文章

  1. 字符转ASII码以及大小写之间的转换
  2. python开发注册机_用python 写 Atlantis Word Processor 注册机
  3. 基于Java毕业设计校园疫情防控管理系统源码+系统+mysql+lw文档+部署软件
  4. c语言程序拍照,拍照并获取照片
  5. 往后余生(简单的歌词分享)
  6. xposed框架 微信群发源码
  7. Android流星雨效果---史上最炫,浪漫,值得陪你女朋友一起看~ [捂脸]
  8. VScode 设置 背景图片
  9. 世界读书日送你畅销好书!前所未有4折购书福利
  10. CPU卡PSAM卡 响应指令