基于WxJava实现微信支付SpringBoot后端接口的使用

3,655 阅读3分钟

一、前文

WxJava - 微信开发 Java SDK(开发工具包) weixin-java-pay-demo - 基于 WxJava 和 Spring Boot 构建,演示微信支付后端接口使用方法。

二、依赖

pom.xml

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
            <version>4.1.0</version>
        </dependency>

三、属性

3.1 application.yml

  • 如果没有子商户的话,subAppIdsubMchId可以直接注释掉
  • API证书apiclient_cert.p12直接放在application.yml同目录下
# 微信支付
wx:
  pay:
    appId: #微信公众号或者小程序等的appid
    mchId: #微信支付商户号
    mchKey: #微信支付商户密钥
#    subAppId: #服务商模式下的子商户公众账号ID
#    subMchId: #服务商模式下的子商户号
    keyPath: classpath:apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)

3.2 WxPayProperties

WxPayProperties


@Component
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties
{
    /**
     * 设置微信公众号或者小程序等的appid
     */
    private String appId;

    /**
     * 微信支付商户号
     */
    private String mchId;

    /**
     * 微信支付商户密钥
     */
    private String mchKey;

    /**
     * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
     */
    private String subAppId;

    /**
     * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
     */
    private String subMchId;

    /**
     * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
     */
    private String keyPath;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getMchId() {
        return mchId;
    }

    public void setMchId(String mchId) {
        this.mchId = mchId;
    }

    public String getMchKey() {
        return mchKey;
    }

    public void setMchKey(String mchKey) {
        this.mchKey = mchKey;
    }

    public String getSubAppId() {
        return subAppId;
    }

    public void setSubAppId(String subAppId) {
        this.subAppId = subAppId;
    }

    public String getSubMchId() {
        return subMchId;
    }

    public void setSubMchId(String subMchId) {
        this.subMchId = subMchId;
    }

    public String getKeyPath() {
        return keyPath;
    }

    public void setKeyPath(String keyPath) {
        this.keyPath = keyPath;
    }

    @Override
    public String toString() {
        return "WxPayProperties{" +
                "appId='" + appId + '\'' +
                ", mchId='" + mchId + '\'' +
                ", mchKey='" + mchKey + '\'' +
                ", subAppId='" + subAppId + '\'' +
                ", subMchId='" + subMchId + '\'' +
                ", keyPath='" + keyPath + '\'' +
                '}';
    }
}

四、配置Config

MyWxPayConfig


@Configuration
@ConditionalOnClass(WxPayService.class)
public class MyWxPayConfig {

    @Autowired
    private WxPayProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public WxPayService wxService() {
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
        payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
        payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
        payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
        payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));

        // 可以指定是否使用沙箱环境
        payConfig.setUseSandboxEnv(false);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }
}

五、应用Controller

LocalTestController

    @Autowired
    private WxPayService wxService;
 
 
    @ApiOperation("统一下单")
    @Log(title = "统一下单", businessType = BusinessType.UPDATE)
    @PostMapping("/unifiedOrder")
    public AjaxResult unifiedOrder(String outTradeNo) throws Exception
    {
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        wxPayUnifiedOrderRequest.setBody("测试");
        wxPayUnifiedOrderRequest.setOutTradeNo(outTradeNo);
        wxPayUnifiedOrderRequest.setTotalFee(520200);
        wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1");
        wxPayUnifiedOrderRequest.setNotifyUrl("payCallBack");
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        wxPayUnifiedOrderRequest.setOpenid("oU5Ta5f9Vx6f-***********");

        return AjaxResult.success(wxService.unifiedOrder(wxPayUnifiedOrderRequest));
    }

    @ApiOperation("查询订单")
    @Log(title = "查询订单", businessType = BusinessType.UPDATE)
    @PostMapping("/queryOrder")
    public AjaxResult queryOrder(String outTradeNo) throws Exception
    {
        WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(null, outTradeNo);
        logger.info(wxPayOrderQueryResult.toString());
        return AjaxResult.success(wxPayOrderQueryResult);
    }

六、PostMan调试

6.1 统一下单

在这里插入图片描述

20:40:45.259 [http-nio-8080-exec-1] INFO  c.g.b.w.s.i.WxPayServiceImpl - [post,73] - 
【请求地址】:https://api.mch.weixin.qq.com/pay/unifiedorder
【请求数据】:<xml>
  <appid>wx4e4c9427ec042a8a</appid>
  <mch_id>1547230971</mch_id>
  <nonce_str>1626784844711</nonce_str>
  <sign>199A4CFC84CBAC9AF5E633C73A6FD960</sign>
  <body>测试</body>
  <out_trade_no>8916a2eeedc15c7f140</out_trade_no>
  <total_fee>520200</total_fee>
  <spbill_create_ip>127.0.0.1</spbill_create_ip>
  <notify_url>payCallBack</notify_url>
  <trade_type>JSAPI</trade_type>
  <openid>oU5Ta5f9Vx6f-Q6doktEd4Z_aqHM</openid>
</xml>
【响应数据】:<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<result_code><![CDATA[SUCCESS]]></result_code>
<mch_id><![CDATA[1547230971]]></mch_id>
<appid><![CDATA[wx4e4c9427ec042a8a]]></appid>
<nonce_str><![CDATA[reL0fAT85nDlb7KV]]></nonce_str>
<sign><![CDATA[FB536447C788BEFADB4D8C487A187347]]></sign>
<prepay_id><![CDATA[wx20204045412219a6748aed26d324770000]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

6.1 查询订单(正常)

在这里插入图片描述

20:50:33.319 [http-nio-8080-exec-2] INFO  c.g.b.w.s.i.WxPayServiceImpl - [post,73] - 
【请求地址】:https://api.mch.weixin.qq.com/pay/orderquery
【请求数据】:<xml>
  <appid>wx4e4c9427ec042a8a</appid>
  <mch_id>1547230971</mch_id>
  <nonce_str>1626785433013</nonce_str>
  <sign>07BD88F4BD66E6CF0A63977DB5967097</sign>
  <out_trade_no>8916a2eeedc15c7f138</out_trade_no>
</xml>
【响应数据】:<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<result_code><![CDATA[SUCCESS]]></result_code>
<mch_id><![CDATA[1547230971]]></mch_id>
<appid><![CDATA[wx4e4c9427ec042a8a]]></appid>
<device_info><![CDATA[]]></device_info>
<trade_state><![CDATA[NOTPAY]]></trade_state>
<total_fee>520200</total_fee>
<out_trade_no><![CDATA[8916a2eeedc15c7f138]]></out_trade_no>
<trade_state_desc><![CDATA[订单未支付]]></trade_state_desc>
<nonce_str><![CDATA[OQcSkSb0wibGZ0I1]]></nonce_str>
<sign><![CDATA[37EED915AA5DF3C9465686D3B940F358]]></sign>
</xml>

6.1 查询订单(异常)

程序抛出异常,订单不存在 在这里插入图片描述

七、其他

微信支付—开发文档

签名错误讨论区-V2版

微信支付接口签名校验工具

觉得好,就一键三连呗(点赞+收藏+关注)