SpringBoot 集成第三方聚合支付
- 1. 创建Spring Boot项目
- 2. 添加依赖
- 3. 配置支付宝、微信
- 4. 实现支付接口
- 5. 实现支付服务
- 6. 实现支付回调接口
- 7. 测试支付
- 8. 总结
在这篇博客中,我将介绍如何使用Spring Boot集成第三方支付聚合支付。聚合支付是一种将多种支付方式整合到一起的方式,使用户可以选择他们喜欢的支付方式进行支付。在本文中,我们将使用支付宝和微信支付作为示例。
1. 创建Spring Boot项目
首先,我们需要创建一个Spring Boot项目。我们可以使用Spring Initializr来创建项目。打开https://start.spring.io/,选择使用Gradle构建工具和Java语言,输入项目名称和组名,然后单击生成。
2. 添加依赖
我们需要添加以下依赖:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.8.96.ALL</version>
</dependency>
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>3.0.9</version>
</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 "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
} else {
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名验证失败]]></return_msg></xml>";
}
} 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应用程序中,也可以了解一些支付相关的技术和概念。