SpringBoot 集成微信支付的各种支付产品

时间:2023-04-01 22:59:28

Spring Boot 是一款非常流行的 Java 开发框架,而微信支付则是众多移动支付产品中的佼佼者,整合两者可以让我们更方便地开发各种支付产品。在本篇博客中,我将介绍如何在 Spring Boot 中整合微信支付的各种支付产品。

SpringBoot 集成微信支付的各种支付产品

准备工作

微信支付官网

  • 注册一个微信支付商户账号
  • 创建一个微信支付应用程序并获取应用程序的AppID和AppSecret
  • 获取商户号和API密钥

首先,我们需要在 pom.xml 中添加以下依赖:

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

然后,我们需要在 application.yml 中配置微信支付的相关信息:

wx:
  pay:
    app-id: your_app_id
    mch-id: your_mch_id
    mch-key: your_mch_key
    key-path: your_key_path
    notify-url: your_notify_url

接下来,我们就可以开始整合微信支付的各种支付产品了。

微信公众号支付

微信公众号支付是指在微信公众号内进行支付。在 Spring Boot 中整合微信公众号支付,我们需要使用 WxPayService 对象来进行支付。

首先,我们需要在配置类中注入 WxPayService 对象:

@Configuration
public class WxPayConfig {

    @Value("${wx.pay.app-id}")
    private String appId;

    @Value("${wx.pay.mch-id}")
    private String mchId;

    @Value("${wx.pay.mch-key}")
    private String mchKey;

    @Value("${wx.pay.key-path}")
    private String keyPath;

    @Value("${wx.pay.notify-url}")
    private String notifyUrl;

    @Bean
    public WxPayService wxPayService() throws Exception {
        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setAppId(appId);
        wxPayConfig.setMchId(mchId);
        wxPayConfig.setMchKey(mchKey);
        wxPayConfig.setKeyPath(keyPath);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(wxPayConfig);
        wxPayService.setPayConfig(wxPayConfig);
        // 注册异步通知处理器
        wxPayService.setNotifyUrl(notifyUrl, "/notify");
        return wxPayService;
    }
}

然后,我们就可以在支付控制器中使用 WxPayService 对象来进行支付了:

@RestController
public class PayController {

    @Autowired
    private WxPayService wxPayService;

    @GetMapping("/pay")
    public String pay(HttpServletRequest request) throws Exception {
        // 构造订单信息
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody("订单描述");
        orderRequest.setOutTradeNo("订单号");
        orderRequest.setTotalFee(1);
        orderRequest.setSpbillCreateIp(request.getRemoteAddr());
        orderRequest.setNotifyUrl(notifyUrl);
        orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
        orderRequest.setOpenid("用户的openid");

        // 调用统一下单接口
        WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);

        // 构造支付参数
        Map<String, String> payParams = new HashMap<>();
        payParams.put("appId", orderResult.getAppId());
		payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
		payParams.put("nonceStr", orderResult.getNonceStr());
		payParams.put("package", "prepay_id=" + orderResult.getPrepayId());
		payParams.put("signType", "MD5");
		payParams.put("paySign", WXPayUtil.generateSignature(payParams, mchKey));

		return JSON.toJSONString(payParams);
	}
	
  	@PostMapping("/notify")
    public String notify(@RequestBody String xmlData) throws Exception {
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        if (!WxPayConstants.ResultCode.SUCCESS.equals(notifyResult.getResultCode())) {
            // 支付失败,处理失败逻辑
            return WxPayNotifyResponse.fail("支付失败");
        }
        // 支付成功,处理成功逻辑
        String orderId = notifyResult.getOutTradeNo();
        // 更新订单状态等业务逻辑
        return WxPayNotifyResponse.success("OK");
    }
}

在这里,我们使用了 WxPayService.parseOrderNotifyResult() 方法将微信支付异步通知的 XML 数据解析为 WxPayOrderNotifyResult 对象。如果支付成功,则处理成功逻辑,否则处理失败逻辑。

最后,我们需要编写一个 WxPayNotifyResponse 类来封装异步通知的响应信息:

public class WxPayNotifyResponse {

    private static final String SUCCESS = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    private static final String FAIL = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[%s]]></return_msg></xml>";

    public static String success(String msg) {
        return SUCCESS;
    }

    public static String fail(String msg) {
        return String.format(FAIL, msg);
    }
}

微信扫码支付

微信扫码支付是指用户使用微信扫描商家的二维码进行支付。在 Spring Boot 中整合微信扫码支付,我们需要使用 WxPayService 对象来进行支付。

首先,我们需要在配置类中注入 WxPayService 对象;配置信息同公众号支付一样:

@Configuration
public class WxPayConfig {

    @Value("${wx.pay.app-id}")
    private String appId;

    @Value("${wx.pay.mch-id}")
    private String mchId;

    @Value("${wx.pay.mch-key}")
    private String mchKey;

    @Value("${wx.pay.key-path}")
    private String keyPath;

    @Value("${wx.pay.notify-url}")
    private String notifyUrl;

    @Bean
    public WxPayService wxPayService() throws Exception {
        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setAppId(appId);
        wxPayConfig.setMchId(mchId);
        wxPayConfig.setMchKey(mchKey);
        wxPayConfig.setKeyPath(keyPath);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(wxPayConfig);
        wxPayService.setPayConfig(wxPayConfig);
        // 注册异步通知处理器
        wxPayService.setNotifyUrl(notifyUrl, "/notify");
        return wxPayService;
    }
}

然后,我们就可以在支付控制器中使用 WxPayService 对象来进行支付了:

@RestController
public class PayController {

    @Autowired
    private WxPayService wxPayService;

    @GetMapping("/pay")
    public String pay(HttpServletRequest request) throws Exception {
        // 构造订单信息
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody("订单描述");
        orderRequest.setOutTradeNo("订单号");
        orderRequest.setTotalFee(1);
        orderRequest.setSpbillCreateIp(request.getRemoteAddr());
        orderRequest.setNotifyUrl(notifyUrl);
        orderRequest.setTradeType(WxPayConstants.TradeType.NATIVE);
        orderRequest.setProductId("商品id");

        // 调用统一下单接口
        WxPayNativeOrderResult orderResult = wxPayService.createOrder(orderRequest);

        // 获取二维码链接
        String codeUrl = orderResult.getCodeUrl();

        return codeUrl;
    }
	
  	@PostMapping("/notify")
    public String notify(@RequestBody String xmlData) throws Exception {
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        if (!WxPayConstants.ResultCode.SUCCESS.equals(notifyResult.getResultCode())) {
            // 支付失败,处理失败逻辑
            return WxPayNotifyResponse.fail("支付失败");
        }
        // 支付成功,处理成功逻辑
        String orderId = notifyResult.getOutTradeNo();
        // 更新订单状态等业务逻辑
        return WxPayNotifyResponse.success("OK");
    }
}

在这里,我们将 tradeType 参数设置为 WxPayConstants.TradeType.NATIVE,表示使用扫码支付方式。我们通过调用 createOrder() 方法生成订单,并从返回结果中获取二维码链接,然后使用 QrCodeUtil.createQrCode() 方法生成二维码图片。

注意,生成的二维码链接有效期为2小时,超时后需要重新生成。

我们使用了 WxPayService.parseOrderNotifyResult() 方法将微信支付异步通知的 XML 数据解析为 WxPayOrderNotifyResult 对象。如果支付成功,则处理成功逻辑,否则处理失败逻辑。

最后,我们需要编写一个 WxPayNotifyResponse 类来封装异步通知的响应信息:

public class WxPayNotifyResponse {

    private static final String SUCCESS = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    private static final String FAIL = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[%s]]></return_msg></xml>";

    public static String success(String msg) {
        return SUCCESS;
    }

    public static String fail(String msg) {
        return String.format(FAIL, msg);
    }
}

微信APP支付

微信APP支付是指在微信内部或者第三方应用中进行支付。在 Spring Boot 中整合微信APP支付,我们需要使用 WxPayService 对象来进行支付。

首先,我们需要在配置类中注入 WxPayService 对象:

@Configuration
public class WxPayConfig {

    @Value("${wx.pay.app-id}")
    private String appId;

    @Value("${wx.pay.mch-id}")
    private String mchId;

    @Value("${wx.pay.mch-key}")
    private String mchKey;

    @Value("${wx.pay.key-path}")
    private String keyPath;
    
	@Value("${wx.pay.notify-url}")
	private String notifyUrl;
	
	@Bean
	public WxPayService wxPayService() throws Exception {
	    WxPayConfig wxPayConfig = new WxPayConfig();
	    wxPayConfig.setAppId(appId);
	    wxPayConfig.setMchId(mchId);
	    wxPayConfig.setMchKey(mchKey);
	    wxPayConfig.setKeyPath(keyPath);
	
	    WxPayService wxPayService = new WxPayServiceImpl();
	    wxPayService.setConfig(wxPayConfig);
	    wxPayService.setPayConfig(wxPayConfig);
        // 注册异步通知处理器
        wxPayService.setNotifyUrl(notifyUrl, "/notify");	
	    return wxPayService;
	}
}

然后,我们就可以在支付控制器中使用 WxPayService 对象来进行支付了:

@RestController
public class PayController {

    @Autowired
    private WxPayService wxPayService;

    @PostMapping("/pay")
    public String pay(@RequestBody PayRequest payRequest) throws Exception {
        // 构造订单信息
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody(payRequest.getSubject());
        orderRequest.setOutTradeNo(payRequest.getOrderId());
        orderRequest.setTotalFee(payRequest.getAmount().intValue());
        orderRequest.setSpbillCreateIp(payRequest.getClientIp());
        orderRequest.setNotifyUrl(notifyUrl);
        orderRequest.setTradeType(WxPayConstants.TradeType.APP);

        // 调用统一下单接口
        WxPayAppOrderResult orderResult = wxPayService.createOrder(orderRequest);

        // 构造APP支付参数
        Map<String, String> payParams = new HashMap<>();
        payParams.put("appid", orderResult.getAppId());
        payParams.put("partnerid", orderResult.getPartnerId());
        payParams.put("prepayid", orderResult.getPrepayId());
        payParams.put("package", "Sign=WXPay");
        payParams.put("noncestr", orderResult.getNonceStr());
        payParams.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        payParams.put("sign", WXPayUtil.generateSignature(payParams, mchKey));

        return JSON.toJSONString(payParams);
    }
    	
  	@PostMapping("/notify")
    public String notify(@RequestBody String xmlData) throws Exception {
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        if (!WxPayConstants.ResultCode.SUCCESS.equals(notifyResult.getResultCode())) {
            // 支付失败,处理失败逻辑
            return WxPayNotifyResponse.fail("支付失败");
        }
        // 支付成功,处理成功逻辑
        String orderId = notifyResult.getOutTradeNo();
        // 更新订单状态等业务逻辑
        return WxPayNotifyResponse.success("OK");
    }
}

在这里,我们使用了 WxPayService.parseOrderNotifyResult() 方法将微信支付异步通知的 XML 数据解析为 WxPayOrderNotifyResult 对象。如果支付成功,则处理成功逻辑,否则处理失败逻辑。

最后,我们需要编写一个 WxPayNotifyResponse 类来封装异步通知的响应信息:

public class WxPayNotifyResponse {

    private static final String SUCCESS = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    private static final String FAIL = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[%s]]></return_msg></xml>";

    public static String success(String msg) {
        return SUCCESS;
    }

    public static String fail(String msg) {
        return String.format(FAIL, msg);
    }
}

微信H5支付

微信H5支付是指在移动端网页上进行支付。在 Spring Boot 中整合微信H5支付,我们需要使用 WxPayService 对象来进行支付。

首先,我们需要在配置类中注入 WxPayService 对象:

@Configuration
public class WxPayConfig {

    @Value("${wx.pay.app-id}")
    private String appId;

    @Value("${wx.pay.mch-id}")
    private String mchId;

    @Value("${wx.pay.mch-key}")
    private String mchKey;

    @Value("${wx.pay.key-path}")
    private String keyPath;

    @Value("${wx.pay.notify-url}")
    private String notifyUrl;

    @Bean
    public WxPayService wxPayService() throws Exception {
        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setAppId(appId);
        wxPayConfig.setMchId(mchId);
        wxPayConfig.setMchKey(mchKey);
        wxPayConfig.setKeyPath(keyPath);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(wxPayConfig);
        wxPayService.setPayConfig(wxPayConfig);
        // 注册异步通知处理器
        wxPayService.setNotifyUrl(notifyUrl, "/notify");
        return wxPayService;
    }
}

然后,我们就可以在控制器中使用 WxPayService 对象来进行支付了:

@RestController
public class PayController {

    @Autowired
    private WxPayService wxPayService;

    @PostMapping("/pay")
    public String pay(@RequestBody PayRequest payRequest) throws Exception {
        // 构造订单信息
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody(payRequest.getSubject());
        orderRequest.setOutTradeNo(payRequest.getOrderId());
        orderRequest.setTotalFee(payRequest.getAmount().intValue());
        orderRequest.setSpbillCreateIp(payRequest.getClientIp());
        orderRequest.setNotifyUrl(notifyUrl);
        orderRequest.setTradeType(WxPayConstants.TradeType.MWEB);
        orderRequest.setSceneInfo("{\"h5_info\":{\"type\":\"Wap\",\"wap_url\":\"http://www.example.com\",\"wap_name\":\"Example网站\"}}");

        // 调用统一下单接口
        WxPayMwebOrderResult orderResult = wxPayService.createOrder(orderRequest);

        // 获取支付跳转链接
        String mwebUrl = orderResult.getMwebUrl();
        return mwebUrl;
    }
    	
  	@PostMapping("/notify")
    public String notify(@RequestBody String xmlData) throws Exception {
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        if (!WxPayConstants.ResultCode.SUCCESS.equals(notifyResult.getResultCode())) {
            // 支付失败,处理失败逻辑
            return WxPayNotifyResponse.fail("支付失败");
        }
        // 支付成功,处理成功逻辑
        String orderId = notifyResult.getOutTradeNo();
        // 更新订单状态等业务逻辑
        return WxPayNotifyResponse.success("OK");
    }
}

在这里,我们将 tradeType 参数设置为 WxPayConstants.TradeType.MWEB,表示使用H5支付方式。我们还设置了 sceneInfo 参数,它包含了 H5 支付的相关信息,比如 H5 网页的 URL 和名称。

注意,微信H5支付跳转链接的有效期为5分钟,所以在获取到跳转链接后应该尽快让用户跳转到支付页面。

总结

本文介绍了如何在 Spring Boot 中整合微信支付,包括微信公众号支付、微信APP支付、微信H5支付和微信扫码支付。我们使用了 WxPayService 对象来与微信支付接口进行交互,并在支付控制器中使用 WxPayService 对象来生成各种支付产品的支付参数或支付链接。在实际应用中,我们可以根据业务需求选择相应的支付产品和支付方式。

当然,本文只是简单介绍了微信支付的整合过程,实际的业务场景中可能还需要考虑一些其他因素,例如订单状态的处理、支付回调通知的处理等等。在实际开发中,我们还需要根据具体业务场景进行相应的定制化开发。

总的来说,通过本文的介绍,我们可以对 Spring Boot 中整合微信支付有一个基本的了解,并且可以快速上手进行开发。