Back to Wxjava

wx-java-pay-multi-spring-boot-starter

spring-boot-starters/wx-java-pay-multi-spring-boot-starter/README.md

4.8.211.1 KB
Original Source

wx-java-pay-multi-spring-boot-starter

快速开始

本starter支持微信支付多公众号关联配置,适用于以下场景:

  • 一个服务商需要为多个公众号提供支付服务
  • 一个系统需要支持多个公众号的支付业务
  • 需要根据不同的appId动态切换支付配置

使用说明

1. 引入依赖

在项目的 pom.xml 中添加以下依赖:

xml
<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>wx-java-pay-multi-spring-boot-starter</artifactId>
    <version>${version}</version>
</dependency>

2. 添加配置

application.ymlapplication.properties 中配置多个公众号的支付信息。

配置示例(application.yml)

V2版本配置
yml
wx:
  pay:
    configs:
      # 配置1 - 可以使用appId作为key
      wx1234567890abcdef:
        appId: wx1234567890abcdef
        mchId: 1234567890
        mchKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        keyPath: classpath:cert/app1/apiclient_cert.p12
        notifyUrl: https://example.com/pay/notify
      # 配置2 - 也可以使用自定义标识作为key
      config2:
        appId: wx9876543210fedcba
        mchId: 9876543210
        mchKey: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
        keyPath: classpath:cert/app2/apiclient_cert.p12
        notifyUrl: https://example.com/pay/notify
V3版本配置
yml
wx:
  pay:
    configs:
      # 公众号1配置
      wx1234567890abcdef:
        appId: wx1234567890abcdef
        mchId: 1234567890
        apiV3Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        certSerialNo: 62C6CEAA360BCxxxxxxxxxxxxxxx
        privateKeyPath: classpath:cert/app1/apiclient_key.pem
        privateCertPath: classpath:cert/app1/apiclient_cert.pem
        notifyUrl: https://example.com/pay/notify
      # 公众号2配置  
      wx9876543210fedcba:
        appId: wx9876543210fedcba
        mchId: 9876543210
        apiV3Key: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
        certSerialNo: 73D7DFBB471CDxxxxxxxxxxxxxxx
        privateKeyPath: classpath:cert/app2/apiclient_key.pem
        privateCertPath: classpath:cert/app2/apiclient_cert.pem
        notifyUrl: https://example.com/pay/notify
V3服务商版本配置
yml
wx:
  pay:
    configs:
      # 服务商为公众号1提供服务
      config1:
        appId: wxe97b2x9c2b3d      # 服务商appId
        mchId: 16486610            # 服务商商户号
        subAppId: wx118cexxe3c07679  # 子商户公众号appId
        subMchId: 16496705         # 子商户号
        apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr
        privateKeyPath: classpath:cert/apiclient_key.pem
        privateCertPath: classpath:cert/apiclient_cert.pem
      # 服务商为公众号2提供服务
      config2:
        appId: wxe97b2x9c2b3d      # 服务商appId(可以相同)
        mchId: 16486610            # 服务商商户号(可以相同)
        subAppId: wx228dexxf4d18890  # 子商户公众号appId(不同)
        subMchId: 16496706         # 子商户号(不同)
        apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr
        privateKeyPath: classpath:cert/apiclient_key.pem
        privateCertPath: classpath:cert/apiclient_cert.pem

配置示例(application.properties)

properties
# 公众号1配置
wx.pay.configs.wx1234567890abcdef.app-id=wx1234567890abcdef
wx.pay.configs.wx1234567890abcdef.mch-id=1234567890
wx.pay.configs.wx1234567890abcdef.apiv3-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
wx.pay.configs.wx1234567890abcdef.cert-serial-no=62C6CEAA360BCxxxxxxxxxxxxxxx
wx.pay.configs.wx1234567890abcdef.private-key-path=classpath:cert/app1/apiclient_key.pem
wx.pay.configs.wx1234567890abcdef.private-cert-path=classpath:cert/app1/apiclient_cert.pem
wx.pay.configs.wx1234567890abcdef.notify-url=https://example.com/pay/notify

# 公众号2配置
wx.pay.configs.wx9876543210fedcba.app-id=wx9876543210fedcba
wx.pay.configs.wx9876543210fedcba.mch-id=9876543210
wx.pay.configs.wx9876543210fedcba.apiv3-key=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
wx.pay.configs.wx9876543210fedcba.cert-serial-no=73D7DFBB471CDxxxxxxxxxxxxxxx
wx.pay.configs.wx9876543210fedcba.private-key-path=classpath:cert/app2/apiclient_key.pem
wx.pay.configs.wx9876543210fedcba.private-cert-path=classpath:cert/app2/apiclient_cert.pem
wx.pay.configs.wx9876543210fedcba.notify-url=https://example.com/pay/notify

3. 使用示例

自动注入的类型:WxPayMultiServices

java
import com.binarywang.spring.starter.wxjava.pay.service.WxPayMultiServices;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.service.WxPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PayService {
  @Autowired
  private WxPayMultiServices wxPayMultiServices;

  /**
   * 为不同的公众号创建支付订单
   *
   * @param configKey 配置标识(即 wx.pay.configs.&lt;configKey&gt; 中的 key,可以是 appId 或自定义标识)
   */
  public void createOrder(String configKey, String openId, Integer totalFee, String body) throws Exception {
    // 根据配置标识获取对应的WxPayService
    WxPayService wxPayService = wxPayMultiServices.getWxPayService(configKey);

    if (wxPayService == null) {
      throw new IllegalArgumentException("未找到配置标识对应的微信支付配置: " + configKey);
    }
    
    // 使用WxPayService进行支付操作
    WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
    request.setOutTradeNo(generateOutTradeNo());
    request.setDescription(body);
    request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(totalFee));
    request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(openId));
    request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl());
    
    // V3统一下单
    WxPayUnifiedOrderV3Result.JsapiResult result = 
      wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request);
    
    // 返回给前端用于调起支付
    // ...
  }

  /**
   * 服务商模式示例
   */
  public void serviceProviderExample(String configKey) throws Exception {
    // 使用配置标识获取WxPayService
    WxPayService wxPayService = wxPayMultiServices.getWxPayService(configKey);
    
    if (wxPayService == null) {
      throw new IllegalArgumentException("未找到配置: " + configKey);
    }
    
    // 获取子商户的配置信息
    String subAppId = wxPayService.getConfig().getSubAppId();
    String subMchId = wxPayService.getConfig().getSubMchId();
    
    // 进行支付操作
    // ...
  }
  
  /**
   * 查询订单示例
   *
   * @param configKey 配置标识(即 wx.pay.configs.&lt;configKey&gt; 中的 key)
   */
  public void queryOrder(String configKey, String outTradeNo) throws Exception {
    WxPayService wxPayService = wxPayMultiServices.getWxPayService(configKey);

    if (wxPayService == null) {
      throw new IllegalArgumentException("未找到配置标识对应的微信支付配置: " + configKey);
    }
    
    // 查询订单
    WxPayOrderQueryV3Result result = wxPayService.queryOrderV3(null, outTradeNo);
    // 处理查询结果
    // ...
  }

  private String generateOutTradeNo() {
    // 生成商户订单号
    return "ORDER_" + System.currentTimeMillis();
  }
}

4. 配置说明

必填配置项

配置项说明示例
appId公众号或小程序的appIdwx1234567890abcdef
mchId商户号1234567890

V2版本配置项

配置项说明是否必填
mchKey商户密钥是(V2)
keyPathp12证书文件路径部分接口需要

V3版本配置项

配置项说明是否必填
apiV3KeyAPI V3密钥是(V3)
certSerialNo证书序列号是(V3)
privateKeyPathapiclient_key.pem路径是(V3)
privateCertPathapiclient_cert.pem路径是(V3)

服务商模式配置项

配置项说明是否必填
subAppId子商户公众号appId服务商模式必填
subMchId子商户号服务商模式必填

可选配置项

配置项说明默认值
notifyUrl支付结果通知URL
refundNotifyUrl退款结果通知URL
serviceId微信支付分serviceId
payScoreNotifyUrl支付分回调地址
payScorePermissionNotifyUrl支付分授权回调地址
useSandboxEnv是否使用沙箱环境false
apiHostUrl自定义API主机地址https://api.mch.weixin.qq.com
strictlyNeedWechatPaySerial是否所有V3请求都添加序列号头false
fullPublicKeyModel是否完全使用公钥模式false
publicKeyId公钥ID
publicKeyPath公钥文件路径

常见问题

1. 如何选择配置的key?

配置的key(即 wx.pay.configs.<configKey> 中的 <configKey> 部分)可以自由选择:

  • 可以使用appId作为key(如 wx.pay.configs.wx1234567890abcdef),这样调用 getWxPayService("wx1234567890abcdef") 时就像直接用 appId 获取服务
  • 可以使用自定义标识(如 wx.pay.configs.config1),调用时使用 getWxPayService("config1")

注意getWxPayService(configKey) 方法的参数是配置文件中定义的 key,而不是 appId。只有当你使用 appId 作为配置 key 时,才能直接传入 appId。

2. V2和V3配置可以混用吗?

可以。不同的配置可以使用不同的版本,例如:

yml
wx:
  pay:
    configs:
      app1:  # V2配置
        appId: wx111
        mchId: 111
        mchKey: xxx
      app2:  # V3配置
        appId: wx222
        mchId: 222
        apiV3Key: yyy
        privateKeyPath: xxx

3. 证书文件如何放置?

证书文件可以放在以下位置:

  • src/main/resources 目录下,使用 classpath: 前缀
  • 服务器绝对路径,直接填写完整路径
  • 建议为不同配置使用不同的目录组织证书

4. 服务商模式如何配置?

服务商模式需要同时配置服务商信息和子商户信息:

  • appIdmchId 填写服务商的信息
  • subAppIdsubMchId 填写子商户的信息

注意事项

  1. 配置安全:生产环境中的密钥、证书等敏感信息,建议使用配置中心或环境变量管理
  2. 证书管理:不同公众号的证书文件要分开存放,避免混淆
  3. 懒加载:WxPayService 实例采用懒加载策略,只有在首次调用时才会创建
  4. 线程安全:WxPayMultiServices 的实现是线程安全的
  5. 配置更新:如需动态更新配置,可调用 removeWxPayService(configKey) 方法移除缓存的实例

更多信息