# How to Integrate Third-Party Payment Like Alipay in the Mall Project

> Learn how to integrate Alipay into your Mall project. Follow this guide to add the SDK, configure credentials, and implement payment logic for seamless transactions.

- Repository: [macro/mall](https://github.com/macrozheng/mall)
- Tags: how-to-guide
- Published: 2026-02-28

---

**To integrate Alipay into the Mall project, add the Alipay SDK dependency in [`mall-portal/pom.xml`](https://github.com/macrozheng/mall/blob/main/mall-portal/pom.xml), configure credentials via `AlipayConfig`, implement the payment logic in `AlipayServiceImpl`, and expose REST endpoints through `AlipayController` to handle desktop payments, mobile wallets, asynchronous notifications, and transaction queries.**

The Mall repository by macrozheng provides a production-ready reference implementation for integrating third-party payment like Alipay into a Spring Boot e-commerce platform. The implementation follows a clean layered architecture that isolates payment concerns within the `mall-portal` module, making it straightforward to swap providers or add additional gateways such as WeChat Pay.

## Architecture Overview

The Alipay integration spans four distinct layers within the `mall-portal` module. The **configuration layer** (`AlipayConfig`) externalizes credentials and URLs. The **domain layer** (`AliPayParam`) defines the contract for payment requests. The **service layer** (`AlipayServiceImpl`) encapsulates SDK interactions, signature verification, and order state management. Finally, the **controller layer** (`AlipayController`) exposes HTTP endpoints that return HTML forms for browser redirection and handle server-to-server callbacks.

## Step-by-Step Integration Guide

Follow these steps to activate Alipay payments in your Mall instance:

1. **Add the SDK dependency** in [`mall-portal/pom.xml`](https://github.com/macrozheng/mall/blob/main/mall-portal/pom.xml) using the `${alipay-sdk.version}` property.

2. **Configure Alipay properties** in [`application.yml`](https://github.com/macrozheng/mall/blob/main/application.yml) (gateway URL, App ID, private/public keys, charset, sign type, and callback URLs).

3. **Enable configuration binding** by ensuring `AlipayConfig` is annotated with `@Component` and `@ConfigurationProperties(prefix = "alipay")`.

4. **Define the request DTO** (`AliPayParam`) to capture `outTradeNo`, `subject`, and `totalAmount`.

5. **Implement the service contract** in `AlipayServiceImpl`, injecting `AlipayConfig`, `AlipayClient`, and `OmsPortalOrderService`.

6. **Create the controller** (`AlipayController`) mapping `/alipay/pay`, `/alipay/webPay`, `/alipay/notify`, and `/alipay/query`.

7. **Ensure order service integration** by verifying that `OmsPortalOrderService.paySuccessByOrderSn` is available to update order status upon successful payment.

8. **Test the flow** by triggering a payment, validating the asynchronous notification signature, and querying the trade status.

## Core Implementation Components

### Adding the Alipay SDK Dependency

Declare the Alipay SDK in the `mall-portal` module’s Maven configuration. The project manages the version through a property to ensure consistency across environments.

```xml
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>${alipay-sdk.version}</version>
</dependency>

```

Source: [`mall-portal/pom.xml`](https://github.com/macrozheng/mall/blob/main/mall-portal/pom.xml)

### Configuring Alipay Credentials

Externalize all sensitive parameters and endpoint URLs in [`application.yml`](https://github.com/macrozheng/mall/blob/main/application.yml). The `AlipayConfig` class maps these properties to a Spring bean using `@ConfigurationProperties`.

```yaml
alipay:
  gatewayUrl: https://openapi.alipay.com/gateway.do
  appId: your_app_id
  appPrivateKey: |
    -----BEGIN PRIVATE KEY-----
    ...
    -----END PRIVATE KEY-----
  alipayPublicKey: |
    -----BEGIN PUBLIC KEY-----
    ...
    -----END PUBLIC KEY-----
  returnUrl: http://yourdomain.com/alipay/return
  notifyUrl: http://yourdomain.com/alipay/notify
  charset: UTF-8
  signType: RSA2

```

Source: [`AlipayConfig.java`](https://github.com/macrozheng/mall/blob/main/AlipayConfig.java)

### Implementing the Payment Service

The `AlipayServiceImpl` class implements the `AlipayService` interface, providing methods for `pay`, `webPay`, `notify`, and `query`. It constructs SDK requests and returns HTML forms for client-side redirection.

**Desktop Payment Generation:**

```java
@Override
public String pay(AliPayParam param) {
    AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
    request.setReturnUrl(alipayConfig.getReturnUrl());
    request.setNotifyUrl(alipayConfig.getNotifyUrl());
    
    JSONObject bizContent = new JSONObject();
    bizContent.put("out_trade_no", param.getOutTradeNo());
    bizContent.put("subject", param.getSubject());
    bizContent.put("total_amount", param.getTotalAmount());
    bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
    
    request.setBizContent(bizContent.toString());
    return alipayClient.pageExecute(request).getBody();
}

```

**Asynchronous Notification Handling:**

The `notify` method validates the callback signature using `AlipaySignature.rsaCheckV1` and updates the order status only when `trade_status` equals `TRADE_SUCCESS`.

```java
@Override
public String notify(Map<String, String> params) {
    try {
        boolean verified = AlipaySignature.rsaCheckV1(
                params,
                alipayConfig.getAlipayPublicKey(),
                alipayConfig.getCharset(),
                alipayConfig.getSignType());
        
        if (verified && "TRADE_SUCCESS".equals(params.get("trade_status"))) {
            portalOrderService.paySuccessByOrderSn(
                params.get("out_trade_no"), 1);
            return "success";
        }
    } catch (AlipayApiException e) {
        log.error("Alipay notify verification error", e);
    }
    return "failure";
}

```

**Transaction Status Query:**

The `query` method allows synchronous verification of a payment state by calling the Alipay query API and updating the local order record when the remote status confirms success.

```java
@Override
public String query(String outTradeNo, String tradeNo) {
    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
    JSONObject biz = new JSONObject();
    if (StringUtils.isNotEmpty(outTradeNo)) 
        biz.put("out_trade_no", outTradeNo);
    if (StringUtils.isNotEmpty(tradeNo)) 
        biz.put("trade_no", tradeNo);
    
    request.setBizContent(biz.toString());
    AlipayTradeQueryResponse resp = alipayClient.execute(request);
    
    if (resp.isSuccess() && "TRADE_SUCCESS".equals(resp.getTradeStatus())) {
        portalOrderService.paySuccessByOrderSn(outTradeNo, 1);
    }
    return resp.getTradeStatus();
}

```

Source: [`AlipayServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/AlipayServiceImpl.java)

### Exposing REST Endpoints

The `AlipayController` routes HTTP requests to the service layer. For payment endpoints, it sets the response content type to `text/html` and writes the generated Alipay form directly to the output stream, triggering an immediate browser redirect to the Alipay gateway.

```java
@Autowired
private AlipayService alipayService;

@Autowired
private AlipayConfig alipayConfig;

@ApiOperation("Alipay desktop payment")
@RequestMapping(value = "/pay", method = RequestMethod.GET)
public void pay(AliPayParam param, HttpServletResponse resp) throws IOException {
    resp.setContentType("text/html;charset=" + alipayConfig.getCharset());
    resp.getWriter().write(alipayService.pay(param));
}

@ApiOperation("Alipay async notification")
@RequestMapping(value = "/notify", method = RequestMethod.POST)
public String notify(HttpServletRequest request) {
    Map<String, String> params = new HashMap<>();
    // extract params from request...
    return alipayService.notify(params);
}

```

Source: [`AlipayController.java`](https://github.com/macrozheng/mall/blob/main/AlipayController.java)

## Summary

- The Alipay integration resides entirely within the `mall-portal` module, avoiding coupling with core domain logic.
- **AlipayConfig** externalizes all credentials and URLs, enabling environment-specific configurations without code changes.
- **AlipayServiceImpl** handles three critical flows: generating payment forms (`pay`/`webPay`), verifying callback signatures (`notify`), and synchronizing transaction states (`query`).
- The controller returns raw HTML forms to facilitate immediate browser redirection to Alipay’s sandbox or production environment.
- Signature verification via `AlipaySignature.rsaCheckV1` is mandatory in the notification handler to prevent spoofing attacks before calling `paySuccessByOrderSn`.

## Frequently Asked Questions

### How does the Mall project secure Alipay callback notifications?

The `notify` method in `AlipayServiceImpl` validates every incoming request using `AlipaySignature.rsaCheckV1`, which checks the RSA signature against the configured `alipayPublicKey`. Only after verification succeeds and the `trade_status` equals `TRADE_SUCCESS` does the service invoke `portalOrderService.paySuccessByOrderSn` to update the order. This prevents fraudulent status updates from unauthorized sources.

### What is the difference between `pay` and `webPay` methods in the Mall Alipay integration?

The `pay` method generates a form for **desktop web** payments using `AlipayTradePagePayRequest`, while `webPay` (if implemented similarly) targets **mobile web** or WAP clients using `AlipayTradeWapPayRequest`. Both methods construct a BizContent JSON object containing `out_trade_no`, `subject`, and `total_amount`, but they specify different product codes to optimize the checkout experience for the respective device type.

### How do I test Alipay integration without real transactions?

Configure the `gatewayUrl` in `AlipayConfig` to point to the Alipay sandbox environment (`https://openapi.alipaydev.com/gateway.do`) instead of the production URL. Obtain sandbox credentials (App ID, private key, and Alipay public key) from the Alipay Open Platform console, then set the `notifyUrl` to an accessible endpoint (via ngrok or similar) to receive test callbacks locally.

### Can I adapt this architecture to integrate WeChat Pay or other providers?

Yes. The Mall project’s layered design allows you to implement a new `WechatPayConfig`, `WechatPayServiceImpl`, and `WechatPayController` following the same pattern: externalize credentials, implement a service interface with `pay`, `notify`, and `query` methods, and expose corresponding REST endpoints. The existing `OmsPortalOrderService.paySuccessByOrderSn` method can be reused to finalize orders regardless of the payment provider.