Backend Development 11 min read

Integrating Alipay Sandbox Payment in Spring Boot: Configuration, SDK Setup, and Callback Handling

This article provides a step‑by‑step guide for integrating Alipay sandbox payment into a Spring Boot backend, covering sandbox configuration, network tunneling, Maven SDK dependency, application properties, payment request creation, callback processing, and common troubleshooting.

Architect's Guide
Architect's Guide
Architect's Guide
Integrating Alipay Sandbox Payment in Spring Boot: Configuration, SDK Setup, and Callback Handling

The guide begins with the prerequisite setup, requiring an Alipay sandbox account and a network tunneling tool to expose the local service to the public internet, enabling Alipay to send asynchronous callbacks.

It then shows how to configure the Alipay sandbox by visiting the sandbox portal and obtaining the public key, private key, gateway URL, APPID, and SDK information.

Next, the article explains the network tunneling process, recommending a free tunneling service, showing how to download the client, start a tunnel, and map the local 9090 port to a public address for testing.

For the actual development, the required Maven dependency is added:

<dependency>
  <groupId>com.alipay.sdk</groupId>
  <artifactId>alipay-sdk-java</artifactId>
  <version>4.9.28.ALL</version>
</dependency>

The application.yml (or equivalent) is configured with the Alipay credentials:

server:
  port: 9090
alipay:
  appId: 9021000135634074
  appPrivateKey: <your_private_key>
  alipayPublicKey: <alipay_public_key>
  notifyUrl: http://your-public-domain/notify

A Spring component reads these properties:

@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
    private String appId;
    private String appPrivateKey;
    private String alipayPublicKey;
    private String notifyUrl;
    @PostConstruct
    public void init() {
        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = "openapi-sandbox.dl.alipaydev.com";
        config.signType = "RSA2";
        config.appId = this.appId;
        config.merchantPrivateKey = this.appPrivateKey;
        config.alipayPublicKey = this.alipayPublicKey;
        config.notifyUrl = this.notifyUrl;
        Factory.setOptions(config);
        System.out.println("=======支付宝SDK初始化成功=======");
    }
}

The payment request object is defined:

@Data
public class PayVO {
    private String out_trade_no; // required
    private String subject;      // required
    private BigDecimal total_amount; // required
    private String body;        // optional
}

The controller creates an AlipayClient , builds a AlipayTradePagePayRequest , sets the business parameters as JSON, and returns the generated HTML form to the browser:

@RestController
@RequestMapping("/alipay")
public class AliPayController {
    @Resource AliPayConfig aliPayConfig;
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    // ... other constants ...
    @GetMapping("/pay")
    public void pay(PayVO aliPay, HttpServletResponse httpResponse) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(
            GATEWAY_URL, aliPayConfig.getAppId(), aliPayConfig.getAppPrivateKey(),
            "JSON", "utf-8", aliPayConfig.getAlipayPublicKey(), "RSA2");
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());
        aliPay.setOut_trade_no(UUID.randomUUID().toString());
        request.setBizContent("{\"out_trade_no\":\"" + aliPay.getOut_trade_no() + "\",\"total_amount\":\"" + aliPay.getTotal_amount() + "\",\"subject\":\"" + aliPay.getSubject() + "\",\"body\":\"" + aliPay.getBody() + "\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        request.setReturnUrl("http://localhost:9090/hello/pay");
        String form = alipayClient.pageExecute(request).getBody();
        httpResponse.setContentType("text/html;charset=utf-8");
        httpResponse.getWriter().write(form);
    }
}

The callback endpoint receives Alipay's asynchronous notification, verifies the signature, logs the transaction details, and updates the order status in the database:

@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));
        }
        if (Factory.Payment.Common().verifyNotify(params)) {
            // log details and update order
            ShopOrder order = new ShopOrder();
            order.setId(params.get("out_trade_no"));
            order.setStatus("1");
            order.setZhhifuTime(params.get("gmt_payment"));
            shopOrderMapper.save(order);
        }
    }
    return "success";
}

Common pitfalls such as a null Context during SDK initialization are addressed, with a solution that initializes the SDK in a @PostConstruct method of the configuration bean.

Finally, the article shows the expected result: a successful payment page in the Alipay sandbox, followed by the callback data and a confirmation that the order status has been updated.

backendJavaSDKSpring BootPayment IntegrationAlipay
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.