SpringBoot 集成第三方聚合支付 微信、支付宝

SpringBoot 集成第三方聚合支付

  • 1. 创建Spring Boot项目
  • 2. 添加依赖
  • 3. 配置支付宝、微信
  • 4. 实现支付接口
  • 5. 实现支付服务
  • 6. 实现支付回调接口
  • 7. 测试支付
  • 8. 总结

在这篇博客中,我将介绍如何使用Spring Boot集成第三方支付聚合支付。聚合支付是一种将多种支付方式整合到一起的方式,使用户可以选择他们喜欢的支付方式进行支付。在本文中,我们将使用支付宝和微信支付作为示例。
SpringBoot 集成第三方聚合支付 微信、支付宝_第1张图片

1. 创建Spring Boot项目

首先,我们需要创建一个Spring Boot项目。我们可以使用Spring Initializr来创建项目。打开https://start.spring.io/,选择使用Gradle构建工具和Java语言,输入项目名称和组名,然后单击生成。

2. 添加依赖

我们需要添加以下依赖:

<dependency>
    <groupId>com.alipay.sdkgroupId>
    <artifactId>alipay-sdk-javaartifactId>
    <version>4.8.96.ALLversion>
dependency>
<dependency>
    <groupId>com.github.wxpaygroupId>
    <artifactId>wxpay-sdkartifactId>
    <version>3.0.9version>
dependency>

3. 配置支付宝、微信

我们需要在application.properties文件中添加以下配置:

# 支付宝支付配置
alipay:
  appId: xxxxxxxxxx
  notifyUrl: http://xxxxx.com/notify/alipay
  privateKey: xxxxxxxxxx
  publicKey: xxxxxxxxxx
# 微信支付配置
wxpay:
  appId: xxxxxxxxxx
  certPath: /path/to/cert
  key: xxxxxxxxxx
  mchId: xxxxxxxxxx
  notifyUrl: http://xxxxx.com/notify/wxpay

4. 实现支付接口

我们需要创建一个PaymentController类,实现支付接口。在这个类中,我们需要实现以下方法:

@RequestMapping("/pay")
public String pay(@RequestParam("type") String type, @RequestParam("amount") BigDecimal amount) {
    if ("alipay".equals(type)) {
        return alipayService.pay(amount);
    } else if ("wxpay".equals(type)) {
        return wxpayService.pay(amount);
    }
    return "Unknown payment type";
}

5. 实现支付服务

我们需要创建一个AlipayService类和一个WxpayService类,实现支付服务。在这些类中,我们需要实现以下方法:

AlipayService:

/**
 * 支付宝支付
 */
public class AlipayService {
    @Value("${alipay.appId}")
    private String appId;

    @Value("${alipay.appId}")
    private String privateKey;

    @Value("${alipay.appId}")
    private String publicKey;

    @Value("${alipay.appId}")
    private String notifyUrl;

    public String pay(BigDecimal amount) {
        // 构造请求参数
        AlipayClient client = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                appId, privateKey, "json", "utf-8", publicKey, "RSA2");
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        // 跳转地址
        request.setReturnUrl("http://xxxxx.com/return/alipay");
        // 异步通知
        request.setNotifyUrl(notifyUrl);
        request.setBizContent("{\"out_trade_no\":\"" + UUID.randomUUID().toString() + "\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
                "\"total_amount\":\"" + amount + "\",\"subject\":\"xxxxx\"}");
        // 发起支付请求
        try {
            return client.pageExecute(request).getBody();
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }
}

WxpayService:

/**
 * 微信支付
 */
public class WxpayService {
    @Value("${wxpay.appId}")
    private String appId;

    @Value("${wxpay.mchId}")
    private String mchId;

    @Value("${wxpay.key}")
    private String key;

    @Value("${wxpay.certPath}")
    private String certPath;

    @Value("${wxpay.notifyUrl}")
    private String notifyUrl;

    public String pay(BigDecimal amount) {
        try {
            WXPay wxpay = new WXPay(new WXPayConfig() {
                @Override
                public String getAppID() {
                    return appId;
                }

                @Override
                public String getMchID() {
                    return mchId;
                }

                @Override
                public String getKey() {
                    return key;
                }

                @Override
                public InputStream getCertStream() {
                    try {
                        return new FileInputStream(certPath);
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }

                @Override
                public int getHttpConnectTimeoutMs() {
                    return 0;
                }

                @Override
                public int getHttpReadTimeoutMs() {
                    return 0;
                }

            }, WXPayConstants.SignType.MD5);
            Map<String, String> data = new HashMap<String, String>();
            data.put("body", "xxxxx");
            data.put("out_trade_no", UUID.randomUUID().toString());
            data.put("fee_type", "CNY");
            data.put("total_fee", String.valueOf(amount.multiply(new BigDecimal(100)).intValue()));
            data.put("spbill_create_ip", "127.0.0.1");
            data.put("notify_url", notifyUrl);
            data.put("trade_type", "NATIVE");
            data.put("product_id", UUID.randomUUID().toString());
            // 发起支付请求
            Map<String, String> resp = wxpay.unifiedOrder(data);
            if ("SUCCESS".equals(resp.get("return_code")) && "SUCCESS".equals(resp.get("result_code"))) {
                return resp.get("code_url");
            } else {
                throw new RuntimeException("wxpay error");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

6. 实现支付回调接口

我们需要创建一个NotifyController类,实现支付回调接口。在这个类中,我们需要实现以下方法:

/**
 * 回调处理
 */
public class NotifyController {

    @Value("${alipay.publicKey}")
    private String publicKey;

    @RequestMapping("/notify/alipay")
    public String alipayNotify(HttpServletRequest request) throws AlipayApiException {
        // 解析支付宝回调请求参数
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            StringBuilder valueStr = new StringBuilder();
            for (int i = 0; i < values.length; i++) {
                valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
            }
            params.put(name, valueStr.toString());
        }
        // 验证支付宝回调请求签名
        boolean verifyResult = AlipaySignature.rsaCheckV1(params, publicKey, "utf-8", "RSA2");
        if (verifyResult) {
            // 处理支付宝回调请求
            String outTradeNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            String totalAmount = params.get("total_amount");
            // ...
            return "success";
        } else {
            return "fail";
        }
    }


    @Value("${wxpay.appId}")
    private String appId;
    @Value("${wxpay.mchId}")
    private String mchId;
    @Value("${wxpay.key}")
    private String key;
    @Value("${wxpay.certPath}")
    private String certPath;
    @Value("${wxpay.notifyUrl}")
    private String notifyUrl;

    @RequestMapping("/notify/wxpay")
    public String wxpayNotify(HttpServletRequest request) {
        try {
            // 解析微信支付回调请求参数
            InputStream inputStream = request.getInputStream();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
            }
            String xml = outputStream.toString("utf-8");
            Map<String, String> params = WXPayUtil.xmlToMap(xml);
            // 验证微信支付
            WXPay wxpay = new WXPay(new WXPayConfig() {
                @Override
                public String getAppID() {
                    return appId;
                }

                @Override
                public String getMchID() {
                    return mchId;
                }

                @Override
                public String getKey() {
                    return key;
                }

                @Override
                public InputStream getCertStream() {
                    try {
                        return new FileInputStream(certPath);
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }

                @Override
                public int getHttpConnectTimeoutMs() {
                    return 0;
                }

                @Override
                public int getHttpReadTimeoutMs() {
                    return 0;
                }

            }, WXPayConstants.SignType.MD5);
            boolean verifyResult = wxpay.isPayResultNotifySignatureValid(params);
            if (verifyResult) {
                // 处理微信支付回调请求
                String outTradeNo = params.get("out_trade_no");
                String transactionId = params.get("transaction_id");
                String totalFee = params.get("total_fee");
                // ...
                return "";
            } else {
                return "";
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

7. 测试支付

在实现了支付和回调接口之后,我们可以编写一个简单的测试用例,测试支付是否能够正常工作。

@RunWith(SpringRunner.class)
@SpringBootTest
public class PayTest {
	@Autowired
	private AlipayService alipayService;
	@Autowired
	private WxpayService wxpayService;
	
	@Test
	public void testAlipay() {
	    String payUrl = alipayService.pay(new BigDecimal("0.01"));
	    System.out.println("payUrl: " + payUrl);
	    // 手动调用支付宝回调接口,模拟支付宝异步通知
	    String notifyUrl = "http://localhost:8080/notify/alipay";
	    String outTradeNo = "xxxxxxxxxxxx";
	    String tradeNo = "xxxxxxxxxxxx";
	    String totalAmount = "0.01";
	    String sign = AlipaySignature.rsaSign(AlipayUtil.getParamsString(outTradeNo, tradeNo, totalAmount), privateKey, "utf-8", "RSA2");
	    String notifyResponse = HttpUtil.post(notifyUrl, AlipayUtil.getNotifyString(outTradeNo, tradeNo, totalAmount, sign));
	    System.out.println("notifyResponse: " + notifyResponse);
	}
	
	@Test
	public void testWxpay() {
	    String codeUrl = wxpayService.pay(new BigDecimal("0.01"));
	    System.out.println("codeUrl: " + codeUrl);
	    // 手动调用微信支付回调接口,模拟微信异步通知
	    String notifyUrl = "http://localhost:8080/notify/wxpay";
	    String outTradeNo = "xxxxxxxxxxxx";
	    String transactionId = "xxxxxxxxxxxx";
	    String totalFee = "1";
	    String sign = WXPayUtil.generateSignature(WXPayUtil.getPayParams(outTradeNo, transactionId, totalFee), key);
	    String notifyResponse = HttpUtil.post(notifyUrl, WXPayUtil.getNotifyString(outTradeNo, transactionId, totalFee, sign));
	    System.out.println("notifyResponse: " + notifyResponse);
	}
}

这就是整合第三方支付的Spring Boot应用的基本步骤。当然,不同的支付方式可能会有不同的实现细节,但整体流程是类似的。

8. 总结

本文介绍了如何使用Spring Boot框架将支付宝和微信支付集成到Web应用程序中。我们首先介绍了支付宝和微信支付的基本概念和流程,然后介绍了如何在Spring Boot中集成支付宝和微信支付,包括如何进行支付和回调处理。最后,我们还编写了简单的测试用例来测试我们的支付系统是否正常工作。

通过本文的学习,读者应该可以了解如何将第三方支付集成到Spring Boot应用程序中,也可以了解一些支付相关的技术和概念。

你可能感兴趣的:(Spring-Boot,java,spring,boot,spring)