1、介绍

image.png

2、引入支付参数

微信支付相关参数配置
image.png

  1. # 微信支付相关参数
  2. # 商户号
  3. wxpay.mch-id=1558950191
  4. # 商户API证书序列号
  5. wxpay.mch-serial-no=34345964330B66427E0D3D28826C4993C77E631F
  6. # 商户私钥文件
  7. wxpay.private-key-path=apiclient_key.pem
  8. # APIv3密钥
  9. wxpay.api-v3-key=UDuLFDcmy5Eb6o0nTNZdu6ek4DDh4K8B
  10. # APPID
  11. wxpay.appid=wx74862e0dfcf69954
  12. # 微信服务器地址
  13. wxpay.domain=https://api.mch.weixin.qq.com
  14. # 接收结果通知地址
  15. wxpay.notify-domain=https://7d92-115-171-63-135.ngrok.io

证书序列号查询
image.png
接收结果通知,需要用到natapp内网穿透软件
地址:https://natapp.cn/
image.png
读取微信支付相关参数的配置类

  1. package com.gmw.payment.config;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.context.annotation.PropertySource;
  6. @Configuration
  7. @PropertySource("classpath:wxpay.properties") //读取配置文件
  8. @ConfigurationProperties(prefix="wxpay") //读取wxpay节点
  9. @Data //使用set方法将wxpay节点中的值填充到当前类的属性中
  10. public class WxPayConfig {
  11. // 商户号
  12. private String mchId;
  13. // 商户API证书序列号
  14. private String mchSerialNo;
  15. // 商户私钥文件
  16. private String privateKeyPath;
  17. // APIv3密钥
  18. private String apiV3Key;
  19. // APPID
  20. private String appid;
  21. // 微信服务器地址
  22. private String domain;
  23. // 接收结果通知地址
  24. private String notifyDomain;
  25. }

3、加载商户私钥

微信支付开发者文档:https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml
image.png
https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient
image.png
https://gitee.com/toutatis/wechatpay-apache-httpclient
image.png
如何加载商户私钥
image.png

  1. # 示例:私钥存储在文件
  2. PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
  3. new FileInputStream("/path/to/apiclient_key.pem"));
  4. # 示例:私钥为String字符串
  5. PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
  6. new ByteArrayInputStream(privateKey.getBytes("utf-8")));
  1. /**
  2. * 加载商户的私钥
  3. */
  4. private PrivateKey getPrivateKey(String filename) {
  5. PrivateKey merchantPrivateKey = null;
  6. try {
  7. //# 示例:私钥存储在文件
  8. merchantPrivateKey = PemUtil.loadPrivateKey(
  9. new FileInputStream(filename));
  10. } catch (FileNotFoundException e) {
  11. throw new RuntimeException("商户私钥文件不存在",e);
  12. }
  13. return merchantPrivateKey;
  14. }

测试加载商户私钥

  1. @Resource
  2. public WxPayConfig wxPayConfig;
  3. @Test
  4. void testGetPrivateKey() {
  5. //获取商户私钥路径
  6. String privateKeyPath = this.wxPayConfig.getPrivateKeyPath();
  7. //获取私钥文件
  8. PrivateKey privateKey = this.wxPayConfig.getPrivateKey(privateKeyPath);
  9. //打印私钥文件信息
  10. System.out.println(privateKey);
  11. }

打印结果
image.png

4、实现了请求签名的生成和应答签名的验证

如果你是使用Apache HttpClient的商户开发者,可以使用它构造HttpClient。得到的HttpClient在执行请求时将自动携带身份认证信息,并检查应答的微信支付签名。

定时更新平台证书功能

image.png

  1. // 获取证书管理器实例
  2. certificatesManager = CertificatesManager.getInstance();
  3. // 向证书管理器增加需要自动更新平台证书的商户信息
  4. certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
  5. new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
  6. // ... 若有多个商户号,可继续调用putMerchant添加商户信息
  7. // 从证书管理器中获取verifier
  8. verifier = certificatesManager.getVerifier(merchantId);
  9. WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
  10. .withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
  11. .withValidator(new WechatPay2Validator(verifier))
  12. // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
  13. // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
  14. CloseableHttpClient httpClient = builder.build();
  15. // 后面跟使用Apache HttpClient一样
  16. CloseableHttpResponse response = httpClient.execute(...);

进行封装
版本0.2.1

  1. <dependency>
  2. <groupId>com.github.wechatpay-apiv3</groupId>
  3. <artifactId>wechatpay-apache-httpclient</artifactId>
  4. <version>0.2.1</version>
  5. </dependency>
  1. /**
  2. * 获取签名验证器
  3. * @return
  4. */
  5. @Bean
  6. public ScheduledUpdateCertificatesVerifier getVerifier(){
  7. log.info("获取签名验证器");
  8. //获取商户私钥
  9. PrivateKey privateKey = getPrivateKey(privateKeyPath);
  10. //私钥签名对象
  11. PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);
  12. //身份认证对象
  13. WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
  14. // 使用定时更新的签名验证器,不需要传入证书
  15. ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
  16. wechatPay2Credentials,
  17. apiV3Key.getBytes(StandardCharsets.UTF_8));
  18. return verifier;
  19. }
  20. /**
  21. * 获取http请求对象
  22. * @param verifier
  23. * @return
  24. */
  25. @Bean(name = "wxPayClient")
  26. public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier){
  27. log.info("获取httpClient");
  28. //获取商户私钥
  29. PrivateKey privateKey = getPrivateKey(privateKeyPath);
  30. WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
  31. .withMerchant(mchId, mchSerialNo, privateKey)
  32. .withValidator(new WechatPay2Validator(verifier));
  33. // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
  34. // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
  35. CloseableHttpClient httpClient = builder.build();
  36. return httpClient;
  37. }

版本:0.4.7

  1. <dependency>
  2. <groupId>com.github.wechatpay-apiv3</groupId>
  3. <artifactId>wechatpay-apache-httpclient</artifactId>
  4. <version>0.4.7</version>
  5. </dependency>
  1. /**
  2. * 获取签名验证器
  3. */
  4. @Bean
  5. public Verifier getVerifier(){
  6. Verifier verifier = null;
  7. try {
  8. // 获取证书管理器实例
  9. CertificatesManager certificatesManager = CertificatesManager.getInstance();
  10. // 向证书管理器增加需要自动更新平台证书的商户信息
  11. //获取商户私钥
  12. PrivateKey privateKey = getPrivateKey(privateKeyPath);
  13. certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchSerialNo,
  14. new PrivateKeySigner(mchSerialNo, privateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
  15. // ... 若有多个商户号,可继续调用putMerchant添加商户信息
  16. // 从证书管理器中获取verifier
  17. verifier = certificatesManager.getVerifier(mchId);
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. } catch (GeneralSecurityException e) {
  21. e.printStackTrace();
  22. } catch (HttpCodeException e) {
  23. e.printStackTrace();
  24. } catch (NotFoundException e) {
  25. e.printStackTrace();
  26. }
  27. return verifier;
  28. }
  29. /**
  30. * 获取http请求对象
  31. */
  32. @Bean
  33. public CloseableHttpClient getWxPayClient(Verifier verifier){
  34. //获取商户私钥
  35. PrivateKey privateKey = getPrivateKey(privateKeyPath);
  36. WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
  37. .withMerchant(mchId, mchSerialNo, privateKey)
  38. .withValidator(new WechatPay2Validator(verifier));
  39. // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
  40. // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
  41. CloseableHttpClient httpClient = builder.build();
  42. return httpClient;
  43. }

5、API字典和相关工具

image.png