# Spring Boot 3.x 支付宝沙箱支付完整示例
# 预备
获取沙箱应用相关参数
# 1. Maven 依赖
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf 前端模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 支付宝 SDK -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.15.2.ALL</version>
</dependency>
<!-- Lombok(可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
# 2. 配置文件 application.yml
alipay:
app-id: xxx
private-key: xxx
public-key: xxx
server-url: https://openapi-sandbox.dl.alipaydev.com/gateway.do
notify-url: http://localhost:8080/alipay/notify
return-url: http://localhost:8080/alipay/return
# 3. 支付宝配置类
package com.example.demo.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AlipayConfig {
@Value("${alipay.app-id}")
private String appId;
@Value("${alipay.private-key}")
private String privateKey;
@Value("${alipay.public-key}")
private String publicKey;
@Value("${alipay.server-url}")
private String serverUrl;
@Bean
public AlipayClient alipayClient() {
return new DefaultAlipayClient(
serverUrl,
appId,
privateKey,
"json",
"UTF-8",
publicKey,
"RSA2"
);
}
}
# 4. 支付服务类
package com.example.demo.service;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AlipayService {
@Autowired
private AlipayClient alipayClient;
public String createOrder(String outTradeNo, String totalAmount, String subject) throws Exception {
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl("http://localhost:8080/alipay/return");
request.setNotifyUrl("http://localhost:8080/alipay/notify");
request.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," +
"\"total_amount\":\"" + totalAmount + "\"," +
"\"subject\":\"" + subject + "\"," +
"\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
return alipayClient.pageExecute(request).getBody();
}
}
# 5. 支付控制器
package com.example.demo.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.example.demo.service.AlipayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
@Controller
public class AlipayController {
@Autowired
private AlipayService alipayService;
@Value("${alipay.public-key}")
private String alipayPublicKey;
// 首页
@GetMapping("/")
public String index() {
return "index";
}
// 支付接口(接收前端表单参数)
@GetMapping("/pay")
public void pay(
@RequestParam(value = "outTradeNo", defaultValue = "202308130001") String outTradeNo,
@RequestParam(value = "amount", defaultValue = "0.01") String amount,
@RequestParam(value = "subject", defaultValue = "测试订单") String subject,
HttpServletResponse response
) throws Exception {
String form = alipayService.createOrder(outTradeNo, amount, subject);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();
}
// 支付宝异步回调
@PostMapping("/alipay/notify")
public String notify(@RequestParam Map<String, String> params) throws AlipayApiException {
boolean signVerified = AlipaySignature.rsaCheckV1(
params,
alipayPublicKey,
"UTF-8",
"RSA2"
);
if (signVerified) {
String outTradeNo = params.get("out_trade_no");
String tradeStatus = params.get("trade_status");
if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
System.out.println("订单支付成功: " + outTradeNo);
// TODO: 更新订单状态
}
return "success"; // 必须返回 success
} else {
return "fail";
}
}
// 支付宝同步回调
@GetMapping("/alipay/return")
public String returnUrl(@RequestParam Map<String, String> params, Map<String, Object> model) {
model.put("outTradeNo", params.get("out_trade_no"));
model.put("totalAmount", params.get("total_amount"));
return "result";
}
}
# 6. 前端页面
# index.html
放在 src/main/resources/templates
下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>支付宝沙箱支付测试</title>
</head>
<body>
<h1>支付宝沙箱支付测试</h1>
<form action="/pay" method="get">
<label>订单号:</label>
<input type="text" name="outTradeNo" value="202308130001"><br><br>
<label>支付金额:</label>
<input type="text" name="amount" value="0.01"><br><br>
<label>商品名称:</label>
<input type="text" name="subject" value="测试订单"><br><br>
<button type="submit">去支付</button>
</form>
</body>
</html>
# result.html
放在 src/main/resources/templates
下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>支付结果</title>
</head>
<body>
<h1>支付完成</h1>
<p>订单号: <span th:text="${outTradeNo}"></span></p>
<p>支付金额: <span th:text="${totalAmount}"></span></p>
<a href="/">返回首页</a>
</body>
</html>
# 7. 测试流程
启动 Spring Boot 项目
打开浏览器访问:
http://localhost:8080/
填写订单信息,点击 去支付
跳转到支付宝沙箱支付页面,登录沙箱买家账号付款
支付完成后:
- 浏览器访问
/alipay/return
→ 显示支付结果 - 支付宝服务器访问
/alipay/notify
→ 控制台打印支付成功信息
- 浏览器访问