# Spring Boot 3.x 支付宝沙箱支付完整示例

# 预备

登录支付宝开放平台 (opens new window)

获取沙箱应用相关参数

# 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. 测试流程

  1. 启动 Spring Boot 项目

  2. 打开浏览器访问:http://localhost:8080/

  3. 填写订单信息,点击 去支付

  4. 跳转到支付宝沙箱支付页面,登录沙箱买家账号付款

  5. 支付完成后:

    • 浏览器访问 /alipay/return → 显示支付结果
    • 支付宝服务器访问 /alipay/notify → 控制台打印支付成功信息
Last Updated: 8/13/2025, 9:30:19 AM