Alipay Integration Guide: Web Setup, Java Configuration, Payment and Refund Implementation
This article provides a step‑by‑step tutorial for integrating Alipay in a Java Spring application, covering sandbox web configuration, Maven dependency setup, YAML and Java config classes, payment controller implementation, asynchronous callback handling, refund processing, and automatic order cancellation using RabbitMQ.
This guide walks through the complete process of integrating Alipay payment services into a Java Spring project.
Web operation steps
1. Log in to the Alipay Open Platform sandbox with a developer account. 2. Enter the sandbox environment and configure the interface signing method, choosing either the system default key or a custom key (the guide uses the default key). 3. Set up the application gateway to receive asynchronous notifications (required only for HTTP subscription mode). 4. Generate your own key, completing the web configuration.
IDE (IntelliJ IDEA) operation steps
1. Add the Alipay SDK Maven dependency:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.110.ALL</version>
</dependency>2. Configure the required properties in application.yml :
alipay:
appId:
appPrivateKey:
alipayPublicKey:
notifyUrl: (callback interface)3. Create a configuration class AliPayConfig.java to map the YAML values:
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
private String appId;
private String appPrivateKey;
private String alipayPublicKey;
private String notifyUrl;
}4. Implement the payment controller AliPayController.java :
@Data
public class AliPay {
private String traceNo;
private double totalAmount;
private String subject;
private String alipayTraceNo;
}
private static final String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do";
private static final String FORMAT = "JSON";
private static final String CHARSET = "UTF-8";
private static final String SIGN_TYPE = "RSA2";
@Resource
private AliPayConfig aliPayConfig;
@Resource
private OrdersMapper ordersMapper;
@GetMapping("/pay")
public void pay(AliPay aliPay, HttpServletResponse httpResponse) throws Exception {
AlipayClient alipayClient = new DefaultAlipayClient(
GATEWAY_URL, aliPayConfig.getAppId(), aliPayConfig.getAppPrivateKey(),
FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl(aliPayConfig.getNotifyUrl());
JSONObject bizContent = new JSONObject();
bizContent.set("out_trade_no", aliPay.getTraceNo());
bizContent.set("total_amount", aliPay.getTotalAmount());
bizContent.set("subject", aliPay.getSubject());
bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY");
request.setBizContent(bizContent.toString());
String form = "";
try {
form = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpResponse.setContentType("text/html;charset=" + CHARSET);
httpResponse.getWriter().write(form);
httpResponse.getWriter().flush();
httpResponse.getWriter().close();
}5. Add an interceptor rule to ignore Alipay‑related URLs.
Common pitfalls: URL encoding issues with Chinese characters, choosing between the easy‑sdk and the full SDK (the full SDK handles Chinese subjects correctly).
Asynchronous callback interface
@PostMapping("/notify")
public String payNotify(HttpServletRequest request) throws Exception {
if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
Map
params = new HashMap<>();
for (String name : request.getParameterMap().keySet()) {
params.put(name, request.getParameter(name));
}
String sign = params.get("sign");
String content = AlipaySignature.getSignCheckContentV1(params);
boolean checkSignature = AlipaySignature.rsa256CheckContent(
content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8");
if (checkSignature) {
// Log details and update order status
ordersMapper.updateState(params.get("out_trade_no"), "已支付",
params.get("gmt_payment"), params.get("trade_no"));
}
}
return "success";
}Refund process
@GetMapping("/return")
public Result returnPay(AliPay aliPay) throws AlipayApiException {
String now = DateUtil.now();
Orders orders = ordersMapper.getByNo(aliPay.getTraceNo());
if (orders != null) {
long between = DateUtil.between(DateUtil.parseDateTime(orders.getPaymentTime()),
DateUtil.parseDateTime(now), DateUnit.DAY);
if (between > 7) {
return Result.error("-1", "该订单已超过7天,不支持退款");
}
}
AlipayClient alipayClient = new DefaultAlipayClient(
GATEWAY_URL, aliPayConfig.getAppId(), aliPayConfig.getAppPrivateKey(),
FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
JSONObject bizContent = new JSONObject();
bizContent.set("trade_no", aliPay.getAlipayTraceNo());
bizContent.set("refund_amount", aliPay.getTotalAmount());
bizContent.set("out_request_no", aliPay.getTraceNo());
request.setBizContent(bizContent.toString());
AlipayTradeRefundResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
ordersMapper.updatePayState(aliPay.getTraceNo(), "已退款", now);
return Result.success();
} else {
return Result.error(response.getCode(), response.getBody());
}
}Automatic order cancellation after 30 minutes
Use RabbitMQ delayed queues: set x-message-ttl on messages and configure dead‑letter exchange/routing‑key to re‑queue expired messages. A consumer checks the order status; if still unpaid after 30 minutes, the order is marked as cancelled.
Conclusion
The author encourages readers to like, share, and follow the article, and promotes a paid knowledge community offering additional Spring, MyBatis, RocketMQ, and large‑scale data tutorials.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.