# Hosted mode

> Learn how to integrate card payment methods through the hosted mode using API.

This article describes how to integrate card payment methods through the hosted mode. The hosted mode protects you from the requirements of PCI-DSS compliance by ensuring that sensitive buyer payment data does not pass through or get stored on your servers. This eliminates security risks and data breach concerns. Additionally, you do not need to undergo separate PCI compliance certification, reducing operational and technical costs while improving deployment efficiency for your payment system.

In the hosted mode, APO generates and provides you with a user-friendly payment information collection page. During the payment process, buyers are securely redirected to this page to input their payment details. Once the information is submitted, APO processes it securely and converts it into an encrypted card token (_cardToken_). This card token acts as a secure reference to the payment card information and can be used in subsequent payment processes. With the hosted mode, you avoid direct contact with buyers' payment data while delivering a seamless and reliable payment experience that ensures both security and compliance.

## User experience

The following figures show the user experience in the first-time and saved card payments.

### First-time payments

#### Tab: Web

#### Web user experience

![2.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/92499ebf-6e6f-4372-9719-b44818da9a09.png)

#### Tab: App

#### App user experience

![3.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/7a37f790-8ee6-4803-afad-89d29f5cfd7e.png)

### Saved card payments

#### Tab: Web

#### Web user experience

![1.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/1f9348b4-d36d-412b-8f82-9b5f34fa9355.png)

#### Tab: App

#### App user experience

![4.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/8632c242-c6cb-4b44-ab54-f9fc5e198e1e.png)

## Payment flow

For card payments with the hosted mode, the payment flow is composed of the following steps.

#### Tab: First-time payments

![首次支付时序图更新-英.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/b5e32a28-086b-4e46-b53a-95b743442102.png)

1.  **The buyer enters the page to select a payment method.**
2.  **Create a payment request.**
    After the buyer selects a payment method and submits the order, the merchant server-side calls the [**pay**](https://docs.antom.com/ac/apo/pay.md) API based on the payment information to create a payment request.
3.  **Redirect to the payment URL.**
    The merchant client-side redirects to the URL returned by the payment request to complete the payment.
4.  **Obtain the authorized payment result.**
    The merchant server-side receives the payment result notification returned by the payment method and processes based on the result.
5.  **Capture and obtain the capture result.**
    You must intiate capture after the authorized payment is successful. You can obtain the capture result using one of the following methods:

-   Asynchronous notification: Specify _paymentNotifyUrl_ in the [**pay**](https://docs.antom.com/ac/apo/pay.md) API to set the address for receiving asynchronous notifications. When the payment request is successful or expires, APO uses the [**notifyCapture**](https://docs.antom.com/ac/apo/notify_capture.md) API to send asynchronous notifications to you.
-   Synchronous inquiry: Call the [**inquiryPayment**](https://docs.antom.com/ac/apo/paymentri_online.md) API to check the payment request status.

#### Tab: Saved card payments

![已存卡支付时序图-英.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/2f374498-bbc9-4025-9c53-f0be403324b0.png)

1.  **The buyer enters the checkout page to select a payment method.**
2.  **Create a payment request.**
    The merchant server creates a payment request by calling the [**pay**](https://docs.antom.com/ac/apo/pay.md) API using the payment information associated with _cardToken_.
3.  **Process the payment** **continuation** **URL.**
    Return the the payment continuation URL to the client. You need to redirect the buyer to the payment continuation URL and continue the payment process.
4.  **Obtain the authorized payment result.**
    After the buyer authorizes and completes the payment, they are redirected to the merchant's page. You can obtain the authorized payment result through asynchronous notifications or inquiring about the payment result using the [**inquiryPayment**](https://docs.antom.com/ac/apo/paymentri_online.md) API.
5.  **Capture and obtain the capture result.**
    You must initiate capture after the authorized payment is successful. You can obtain the capture result using one of the following methods:

-   Asynchronous notification: Specify _paymentNotifyUrl_ in the [**pay**](https://docs.antom.com/ac/apo/pay.md) API to set the address for receiving asynchronous notifications. When the payment request is successful or expires, APO uses the [**notifyCapture**](https://docs.antom.com/ac/apo/notify_capture.md) API to send asynchronous notifications to you.
-   Synchronous inquiry: Call the [**inquiryPayment**](https://docs.antom.com/ac/apo/paymentri_online.md) API to check the payment request status.

> **Note:** If you activated the same payment method with multiple acquirers, you can configure payment routing rules on [APO Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify). If no payment routing rules are set, APO will use random routing rules.

## Integration preparations

Before you start integrating, read the [Integration Guide](https://docs.antom.com/integration_guide_en.md) and [API Overview](https://docs.antom.com/ac/ams/api_fund.md) documents to understand the integration steps of the server-side API and the precautions for calling the API. Furthermore, ensure that the following prerequisites are met:

-   Obtain a client ID and an agent token (applicable to ISV model)
-   Complete the key configuration
-   Complete the configuration of _paymentNotifyUrl_ to receive the asynchronous notification
-   Integrate the server-side SDK package, install the server-side library, and initialize a request instance. For more details, refer to [Server-side SDKs](https://docs.antom.com/ac/sdks/server_sdks.md).

## Integration steps

Most card payments follow the general payment flow and integration process provided by APO. Start your integration by taking the following steps.

1.  Display the payment methods
2.  Authorize a payment
3.  (Optional) Redirect to the payment continuation URL
4.  Obtain the authorized payment result
5.  Capture and obtain the capture result

> **Not****e**: For South Korean cards, issuer-authentication and non-authentication payment types exist. Non-authentication payments of South Korean cards follow the general card payment process. However, issuer-authentication payments of South Korean cards involve additional actions.

### Step 1: Display payment methods Client-side

#### Tab: First-time payments

#### First-time payments

Add the logos and names of the payment methods you plan to integrate. This allows buyers to easily choose their preferred method of payment. You can contact APO Technical Support to source the logos and names.

The following figure shows the page effect after adding a payment method:

![5.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/6c017402-0e68-4852-8ab3-47a2f095d020.png)

#### Tab: Saved card payments

#### Saved card payments

You can display the card brand names, logos, and masked card number for buyers to select and proceed with saved card payments.

![6.png](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/e674ca53-ae33-4ab8-ad9f-ca3dc7956dfd.png)

### Step 2: Authorize a payment Server-side

When the buyer selects a payment method, you need to collect the key order information, such as the buyer's payment method information, order information, device information, and payment amount. Call the [**pay**](https://docs.antom.com/ac/apo/pay.md) API, and submit an authorization request for payment.

Initiating a payment request involves the following key parameters:

| **Parameter name** | **Whether** **required during** **first-time payments** | **Whether required during saved card payments** | **Description** |
| --- | --- | --- | --- |
| _productCode_ | Yes | Yes | The value of this field in this scenario is fixed as `CASHIER_PAYMENT`. |
| _paymentRequestId_ | Yes | Yes | The request ID of the authorized payment, which must be unique each time. |
| _paymentAmount.value_ | Yes | Yes | The payment amount. |
| _paymentAmount.currency_ | Yes | Yes | The currency of the payment amount. |
| _settlementStrategy.settlementCurrency_ | No | No | The currency of the settlement strategy for the payment request. |
| _paymentMethodMetaData_ | No | No | The additional information that certain payment methods required. |
| _paymentMethodMetaData.__tokenizeMode_ | No | No | Card information storage mode. When you need to store buyer's card information, specify this parameter. - `ENABLED`: Indicates that you need to store card information for subsequent payments. - `DISABLED`: Indicates that you do not need store card information. The same applies when the value is empty or when this parameter is not specified. - `ASKFORCONSENT` : Indicates that a "save card" button is displayed on the intermediate page, allowing buyers to choose whether to save their card information. |
| _paymentMethod.paymentMethodType_ | Yes | Yes | The payment method that is used to collect the payment by the merchant or acquirer. The value is fixed as `CARD`. |
| _paymentMethod.paymentMethodId_ | No | Yes | The ID of payment methods provided to the buyer by the merchant or acquirer. The _cardToken_ value returned from the initial payment must be passed in during subsequent payments. > **Note**: The payment method ID is non-applicable during the first payment. Hence, you do not need to pass this parameter for the first payment. |
| _paymentFactor.isAuthorization_ | Yes | Yes | The payment mode. This parameter must be set as `true`, which indicates that the payment scenario is authorization. |
| _paymentFactor.captureMode_ | No | No | The capture mode. If this parameter is not specified, the default value is `AUTOMATIC`, which means automatic capture. |
| _productCode_ | Yes | Yes | The product code. In this scenario, the value is fixed as `CASHIER_PAYMENT`. |
| _paymentExpiryTime_ | No | No | The payment expiration time. |
| _paymentRedirectUrl_ | Yes | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. This URL must be an HTTPS address and should render content corresponding to the payment result. |
| _paymentNotify__Url_ | No | No | The URL that is used to receive the payment result notification. This URL must be an HTTPS address and if the address is configured on [APO Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify), this parameter can be omitted. |
| _env.__terminalType_ | Yes | Yes | The terminal type from which the buyer initiates the payment. Valid values are: - `WEB`: Merchant's PC website. - `WAP`: Merchant's H5 website. - `APP`: Merchant's mobile application (app). |
| _env.clientIp_ | Yes | Yes | The buyer's current IP. |
| _order.orderAmount_ | Yes | Yes | The order amount of the merchant side. |
| _order.referenceOrderId_ | Yes | Yes | The order ID of the merchant side. |
| _order.orderDescription_ | Yes | Yes | The order description of the merchant side. |
| _order.buyer_ | Yes | Yes | The buyer information of the merchant side. At least one of the following information must be provided: - _order.buyer.referenceBuyerId_ - _order.buyer.buyerPhoneNo_ - _order.buyer.buyerEmail_ |
| _paymentMethod.paymentMethodMetaData.is3DSAuthentication_ | No | No | Indicates that whether the transaction authentication type is 3D Secure. Valid values are: - `true`: When set to `true`, APO will mark the transaction as 3D Secure and pass it to the corresponding acquirers. - `false`: If the parameter is not set or set it to `false`, APO will mark the transaction as non-3D Secure, and pass it to the corresponding acquirers. However, the final processing decision depends on the acquirer. |

For more information about all parameters, refer to the **[pay](https://docs.antom.com/ac/apo/pay.md)** API.

The following sample code shows how to call the [**pay**](https://docs.antom.com/ac/apo/pay.md) API:

```json
public static void payByCard() {
    AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
    alipayPayRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

    // replace with your paymentRequestId
    String paymentRequestId = UUID.randomUUID().toString();
    alipayPayRequest.setPaymentRequestId(paymentRequestId);

    // set amount
    Amount amount = Amount.builder().currency("SGD").value("4200").build();
    alipayPayRequest.setPaymentAmount(amount);

    // set payment methods
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("CARD").build();
    alipayPayRequest.setPaymentMethod(paymentMethod);

    // card info
    Map<String, Object> paymentMethodMetaData = new HashMap<String, Object>();
     paymentMethodMetaData.put("tokenizeMode", ASKFORCONSENT);
     paymentMethod.setPaymentMethodMetaData(paymentMethodMetaData);

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();

    // set buyer info
    Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();

    // set order info
    Order order = Order.builder().referenceOrderId(orderId)
        .orderDescription("antom testing order").orderAmount(amount).buyer(buyer).build();
    alipayPayRequest.setOrder(order);

    // set env info
    Env env = Env.builder().terminalType(TerminalType.WEB).clientIp("1.2.3.4").build();
    alipayPayRequest.setEnv(env);

    // set auth capture payment mode
    PaymentFactor paymentFactor = PaymentFactor.builder().isAuthorization(true).build();
    alipayPayRequest.setPaymentFactor(paymentFactor);

    // replace with your notify url
    alipayPayRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com");

    // replace with your redirect url
    alipayPayRequest.setPaymentRedirectUrl("https://www.yourMerchantWeb.com");

    // do payment
    AlipayPayResponse alipayPayResponse = null;
    try {
        alipayPayResponse = CLIENT.execute(alipayPayRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}
```

The following shows the sample code of a payment request:

#### Tab: First-time payments

```json
{
  "env": {
    "clientIp": "112.80.248.78",
    "deviceId": "eYOIkvFpZzztgO0Yu6USdprBQZCWxDhiUAHCiK8K/cH9mT6wMaMO****",
    "deviceLanguage": "zh_CN",
    "terminalType": "WEB"
  },
  "order": {
    "buyer": {
      "buyerEmail": "alipay@alipay.com",
      "buyerName": {
        "firstName": "Dehua",
        "fullName": "Dehua Skr Liu",
        "lastName": "Liu",
        "middleName": "Skr"
      },
      "buyerPhoneNo": "1234567****",
      "referenceBuyerId": "test1234****"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "30000"
    },
    "orderDescription": "Cappuccino #grande (Mika's coffee shop)",
    "referenceOrderId": "ORDER_2022111414171****"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "30000"
  },
  "paymentFactor": {
    "isAuthorization": true
  },
  "paymentMethod": {
    "paymentMethodType": "CARD"
  },
  "paymentNotifyUrl": "https://www.alipay.com/notify",
  "paymentRedirectUrl": "https://www.alipay.com",
  "paymentRequestId": "13eIlShXoOg0S9jd3pMWzg3iOBwoXCv1YuEUy****",
  "productCode": "CASHIER_PAYMENT",
  "settlementStrategy": {
    "settlementCurrency": "EUR"
  }
}
```

#### Tab: Saved card payments

```json
{
  "order": {
    "orderAmount": {
      "currency": "HKD",
      "value": "30000"
    },
    "orderDescription": "《Bad Romance》-Lady Gaga",
    "referenceOrderId": "ORDER_2025051514581****",
    "goods": [
      {
        "goodsCategory": "Digital Goods",
        "goodsName": "《Bad Romance》",
        "goodsQuantity": "1",
        "goodsUnitAmount": {
          "currency": "HKD",
          "value": "30000"
        },
        "goodsUrl": "https://www.youtube.com/watch?v=QdaG6pDOz5A",
        "referenceGoodsId": "GOODS_2025051514581****"
      }
    ],
    "shipping": {
      "shippingName": {
        "firstName": "lady",
        "fullName": "lady gaga",
        "lastName": "gaga"
      },
      "shippingPhoneNo": "123456789"
    },
    "buyer": {
      "buyerEmail": "gaga@gaga.com",
      "buyerName": {
        "firstName": "lady",
        "fullName": "lady gaga",
        "lastName": "gaga"
      },
      "buyerPhoneNo": "123456789",
      "referenceBuyerId": "88888888"
    }
  },
  "env": {
    "terminalType": "WAP",
    "osType": "ANDROID",
    "clientIp": "112.80.248.78",
    "deviceId": "eYOIkvFpZzztgO0Yu6USdprBQZCWxDhiUAHCiK8K/cH9mT6wMaMO****",
    "deviceLanguage": "zh_CN"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "30000"
  },
  "paymentMethod": {
    "paymentMethodType": "CARD",
    "paymentMethodMetaData": {
      "isCardOnFile": true
    },
    "paymentMethodId": "cardToken  XXXXXXXXXXXXXXXXXXXXXX"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentNotifyUrl": "https://kademo.intlalipay.cn/payments/notifySuccess",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "PAY_2025051514581****",
  "productCode": "CASHIER_PAYMENT",
  "paymentFactor": {
    "isAuthorization": true
  }
}
```

The following shows the sample codes of a response for partial scenarios:

#### Tab: First authorized payments

```json
{
  "authExpiryTime": "2025-02-27T15:15:57+08:00",
  "normalUrl": "https://ac.alipay.com/page/sandbox/stone-infostaging.html?paymentId=20250220194010800190188000014991264&code=golcashier99ed8d93-efcf-4fe7-b9a1-4bb1152d6ad4sandbox&golSandbox=true&pspName=CARD&county=SG",
  "paymentActionForm": "{\"method\":\"GET\",\"paymentActionFormType\":\"RedirectActionForm\",\"redirectUrl\":\"https://ac.alipay.com/page/sandbox/stone-infostaging.html?paymentId=20250220194010800190188000014991264&code=golcashier99ed8d93-efcf-4fe7-b9a1-4bb1152d6ad4sandbox&golSandbox=true&pspName=CARD&county=SG\"}",
  "paymentAmount": {
    "currency": "HKD",
    "value": "30000"
  },
  "paymentCreateTime": "2025-02-20T15:15:57+08:00",
  "paymentId": "2025022019401080019018800001499****",
  "paymentRequestId": "13eIlShnRH5mKYtqFa2kvfht2IXdx1XoOg0S9jd3pMWzg3iOBwoXCv1YuEUy****",
  "redirectActionForm": {
    "method": "GET",
    "redirectUrl": "https://ac.alipay.com/page/sandbox/stone-infostaging.html?paymentId=20250220194010800190188000014991264&code=golcashier99ed8d93-efcf-4fe7-b9a1-4bb1152d6ad4sandbox&golSandbox=true&pspName=CARD&county=SG"
  },
  "result": {
    "resultCode": "PAYMENT_IN_PROCESS",
    "resultMessage": "Payment is processing.",
    "resultStatus": "U"
  }
}
```

#### Tab: Failed authorized payments

```json
{
  "result": {
    "resultCode": "RISK_REJECT",
    "resultMessage": "The transaction cannot be further processed because of security reasons. If the user has already paid for the transaction, the transaction will be refunded.",
    "resultStatus": "F"
  }
}
```

#### Tab: Authorized payment in process

```json
{
    "result": {
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process",
        "resultStatus": "U"
    }
}
```

The table shows the possible values that the _result.resultStatus_ parameter in the response message may return. Please handle the result according to the guidances:

| **_result.resultStatus_** | **Message** | **Further actions** |
| --- | --- | --- |
| `S` | Indicates that the authorized payment is successful. | You may proceed with initiating capture. |
| `F` | Indicates the authorized payment failed. | Please close the current transaction or replace _paymentRequestId_ to place the order again. |
| `U` | Indicates that the authorized payment is being processed. | - If _normalUrl_ is returned, the merchant frontend should redirect to _normalUrl_. - If _normalUrl_ is not returned, it indicates that the transaction is being processed. You can call the **[inquiryPayment](https://docs.antom.com/ac/apo/paymentri_online.md)** API to retrieve the payment result, or wait for the asynchronous payment result notifications. |

> **Note**: If you did not receive a response message, it might be due to a network timeout. You can call the **[inquiryPayment](https://docs.antom.com/ac/apo/paymentri_online.md)** API to retrieve the payment result, or wait for the asynchronous payment result notifications.

### Step 3: (Optional) Redirect to the payment continuation URL Client-side

After the merchant server obtains _normalUrl_ and passes it to the frontend, it will redirect from the merchant frontend to the APO _normalUrl_. 

#### Tab: WEB

After obtaining _normalUrl,_ you need to redirect the page to the APO _normalUrl_ in the browser, or open it in a new tab.

```javascript
if (serverResponse.normalUrl != null) {
    window.open(serverResponse.normalUrl, '_blank');
}
```

#### Tab: WAP

After obtaining _normalUrl,_ you need to redirect the page to the APO _normalUrl_ in the browser, or open it in a new tab.

```javascript
window.location.href = URL;
```

#### Tab: iOS

After receiving _normalUrl_ from APO, the merchant app redirects to the system default browser to load the APO _normalUrl_ page. The buyer submits payments on this page.

```objectivec
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:Url] options:@{} completionHandler:nil];
}else{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:Url]];
}
```

#### Tab: Android

After receiving _normalUrl_ from APO, the merchant app redirects to the system default browser to load the APO _normalUrl_ page. The buyer submits payments on this page.

```java
try {
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Url));
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // use the startActivity function to redirect to the wallet app
    startActivity(intent);
} catch (Exception e) {
    e.printStackTrace();
}
```

### Step 4: Obtain the authorized payment result Server-side

#### 1\. Set the webhook URL to receive notifications

You can choose one of following methods to set the webhook URL to receive notifications:

-   If each of your order has a unique notification URL, we recommend to set the webhook URL in each individual request. You can pass the asynchronous notification receiving URL for the specific order through the _paymentNotifyUrl_ parameter in the [**pay**](https://docs.antom.com/docs/ac/apo/pay.md) API.
-   If all your orders share a unified notification URL, you can set the webhook URL on [APO Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify) through **Developer > Notification Address**.

> **Note**:
>
> -   If you set the webhook URL both in the API and APO Dashboard, the one set in the [**pay**](https://docs.antom.com/docs/ac/apo/pay.md) API takes precedence.
> -   If the buyer fails to verify their identity after being redirected to the 3D URL, APO will only send an asynchronous notification after the order is closed. The default payment expiration time depends on the acquirer.

The following is the notification request sample code:

```json
{
  "acquirerReferenceNo":"pay_6tmvamfcxp5ujbbfjeopyz****",
  "result":{
    "resultStatus":"S",
    "resultCode":"SUCCESS",
    "resultMessage":"success."
  },
  "notifyType":"PAYMENT_RESULT",
  "paymentId":"2025031719401089010011160025568****",
  "paymentRequestId":"G15320250317102252****",
  "paymentResultInfo":{
    "lastFour":"1358",
    "funding":"CREDIT",
    "issuerName":"ORIENT CORPORATION",
    "expiryMonth":"**",
    "threeDSResult":{
      "cavv":"",
      "xid":"649335d6-1858-4532-8a6e-0579e1b7****",
      "threeDSType":"INTERNAL",
      "eci":"05",
      "threeDSVersion":"2.2.0"
    },
    "expiryYear":"**",
    "cardNo":"************1358",
    "cardBin":"4280**",
    "holdName":"NIHEI SHUNSUKE",
    "issuingCountry":"JP",
    "avsResultRaw":"I",
    "fingerprint":"a28f7dd0713e2f1d4e9ccae8853f5c0abca5154a03a6559cd985eb409857****",
    "networkTransactionId":"46507608833****",
    "cardBrand":"VISA",
    "cvvResultRaw":""
  },
  "paymentTime":"2025-03-16T19:27:17-07:00",
  "acquirerInfo":{
    "referenceRequestId":"202503171903130000060027882****",
    "acquirerTransactionId":"pay_6tmvamfcxp5ujbbfjeopyz****",
    "acquirerMerchantId":"pc_6cpbmm5qderubjraxrygje****",
    "acquirerName":"CHECKOUT"
  },
  "paymentAmount":{
    "currency":"JPY",
    "value":"120"
  },
  "paymentCreateTime":"2025-03-16T19:26:42-07:00"
}

```

The table shows the possible values that the _result.resultStatus_ parameter in the request message may return. Please handle the result according to the guidances:

| **_result.resultStatus_** | **Message** | **Further actions** |
| --- | --- | --- |
| `S` | Indicates that the authorized payment is successful. | You can proceed with initiating capture, and ensure to save _paymentId_ for capture and future refunds. |
| `F` | Indicates the authorized payment failed. | Please close the current transaction or replace _paymentRequestId_ to place the order again. > **Note**: In certain failure scenarios, for example, if there are parameter exceptions, the **[pay](https://docs.antom.com/ac/apo/pay.md)** API will synchronously return `F` and will not send any asynchronous notification. You can directly close the order based on the `F` status. |

> **Common Questions**
>
> **Q: When will the notification be sent?**
>
> A: The sending time depends on whether the payment is completed: if the payment is completed, APO will send an asynchronous notification immediately after receiving notification from the acquirers.
>
> **Q: Will the asynchronous notification be re-sent?**
>
> A: Yes, the asynchronous notification will be re-sent automatically within 24 hours for the following cases:
>
> -   If you didn't receive the asynchronous notification due to network reasons.
> -   If you receive an asynchronous notification from APO, but you didn't make a response to the notification in the [Sample code](https://docs.antom.com/ac/apo/notifications.md#wkNv0) format.
>
> The notification can be re-sent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
>
> **Q:** **What are the key parameters in the notification that I need to use?**
>
> A: Pay attention to the following key parameters:
>
> -   _result_: indicates the payment result of the order.
> -   _paymentRequestId_: indicates the payment request number you generated for consult, cancel, and reconciliation.
> -   _paymentId_: indicates the payment order number generated by APO, used for refund and reconciliation.
> -   _paymentAmount_: indicates the payment amount. Pass this parameter if payment amount verification is required.
> -   _acquirerInfo_: indicates the information about the acquirers.
>
> **Q:** **Do** **I need to save** **the information on acquirers****?**
>
> A: It is recommended to save the information on acquirers (_acquirerInfo_), refer to [Order number management](https://docs.antom.com/ac/apo_zh-cn/iddemon.md) for specific reasons.

#### 2\. Verify asynchronous notifications

If you receive an asynchronous notification from APO, you are required to return the response in the [Sample code](https://docs.antom.com/ac/apo/notifications.md#vQK5A) format, but you do not need to countersign the response.

You need to verify the signature of the payment notification sent by APO.

```java
import javax.servlet.http.HttpServletRequest;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;

@RestController
public class PaymentNotifyHandleBySDK {

    /**
     * alipay public key, used to verify signature
     */
    private static final String SERVER_PUBLIC_KEY = "";

    /**
     * payment result notify processor
     * using <a href="https://spring.io">Spring Framework</a>
     *
     * @param request    HttpServletRequest
     * @param notifyBody notify body
     * @return
     */
    @PostMapping("/payNotify")
    public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {

        // retrieve the required parameters from http request.
        String requestUri = request.getRequestURI();
        String requestMethod = request.getMethod();

        // retrieve the required parameters from request header.
        String requestTime = request.getHeader("request-time");
        String clientId = request.getHeader("client-id");
        String signature = request.getHeader("signature");

        Result result;
        AlipayResponse response = new AlipayResponse();

        try {
            // verify the signature of notification
            boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
            if (!verifyResult) {
                throw new RuntimeException("Invalid notify signature");
            }

            // deserialize the notification body

            // update the order status with notify result

            // respond the server that the notification is received
            result = new Result("SUCCESS", "success", ResultStatusType.S);

        } catch (Exception e) {
            String errorMsg = e.getMessage();
            // handle error condition
            result = new Result("ERROR", errorMsg, ResultStatusType.F);
        }
        response.setResult(result);
        return ResponseEntity.ok().body(response);
    }

}
```

You do not need to countersign the response of the result notification. However, you must respond to each notification request in the following fixed format, regardless of whether the payment is successful or not.

```json
{
    "result": {
        "resultCode": "SUCCESS",
        "resultStatus": "S",
        "resultMessage": "success"
    }
}
```

### Step 5: Capture and obtain the capture result

You can configure the _paymentFactor.captureMode_ parameter in the [**pay**](https://docs.antom.com/ac/apo/pay.md) API to opt for automatic capture or manual capture. You can obtain the capture result through an asynchronous notification or inquire about the capture result by calling the [**inquiryPayment**](https://docs.antom.com/ac/apo/paymentri_online.md) API. For more information, see [Capture](https://docs.antom.com/ac/apo/capture.md).

It is recommended to save the information of the acquirers (_acquirerInfo_), refer to [Order number management](https://docs.antom.com/ac/apo_zh-cn/iddemon.md) for specific reasons. The following code shows an example of a capture result response when inquiring about the capture result:

```json
{
  "paymentResultCode":"SUCCESS",
  "paymentRequestId":"G15320250317102252****",
  "paymentResultInfo":{
    "lastFour":"1358",
    "funding":"CREDIT",
    "issuerName":"ORIENT CORPORATION",
    "expiryMonth":"**",
    "threeDSResult":{
      "cavv":"",
      "xid":"649335d6-1858-4532-8a6e-0579e1b7****",
      "threeDSType":"INTERNAL",
      "eci":"05",
      "threeDSVersion":"2.2.0"
    },
    "expiryYear":"**",
    "cardNo":"************1358",
    "cardBin":"428067",
    "holdName":"NIHEI SHUNSUKE",
    "issuingCountry":"JP",
    "avsResultRaw":"I",
    "fingerprint":"a28f7dd0713e2f1d4e9ccae8853f5c0abca5154a03a6559cd985eb409857****",
    "networkTransactionId":"46507608833****",
    "cardBrand":"VISA",
    "cvvResultRaw":""
  },
  "transactions":[
    {
      "transactionType":"CAPTURE",
      "transactionStatus":"SUCCESS",
      "transactionRequestId":"G15320250317102252****",
      "transactionAmount":{
        "currency":"JPY",
        "value":"120"
      },
      "transactionTime":"2025-03-16T19:27:17-07:00",
      "acquirerInfo":{
        "referenceRequestId":"202503171903130100060027884****",
        "acquirerTransactionId":"act_yv3fchmu3bre3l3tui5y35****",
        "acquirerMerchantId":"pc_6cpbmm5qderubjraxrygje****",
        "acquirerName":"CHECKOUT"
      },
      "transactionId":"2025031719401089010011160025567****",
      "transactionResult":{
        "resultStatus":"S",
        "resultCode":"SUCCESS",
        "resultMessage":"success"
      }
    }
  ],
  "paymentAmount":{
    "currency":"JPY",
    "value":"120"
  },
  "acquirerReferenceNo":"pay_6tmvamfcxp5ujbbfjeopyz****",
  "result":{
    "resultStatus":"S",
    "resultCode":"SUCCESS",
    "resultMessage":"success."
  },
  "paymentId":"2025031719401089010011160025568****",
  "paymentResultMessage":"success.",
  "paymentTime":"2025-03-16T19:27:17-07:00",
  "acquirerInfo":{
    "referenceRequestId":"202503171903130000060027882****",
    "acquirerTransactionId":"pay_6tmvamfcxp5ujbbfjeopyz****",
    "acquirerMerchantId":"pc_6cpbmm5qderubjraxrygje****",
    "acquirerName":"CHECKOUT"
  },
  "paymentStatus":"SUCCESS",
  "paymentCreateTime":"2025-03-16T19:26:42-07:00"
}
```

## After payment

### Inquire about the authorized payment result

In addition to obtaining the buyer's payment result through the asynchronous notification, you can retrieve the corresponding payment result through the payments inquiry service. You can call the [**inquiryPayment**](https://docs.antom.com/ac/apo/paymentri_online.md) API and use the _paymentRequestId_ value of the payment to check the payment status.

The following code shows how to call the [**inquiryPayment**](https://docs.antom.com/ac/apo/paymentri_online.md) API:

```java
public static void inquiryPayment() {
    AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();

    // replace with your paymentRequestId
    alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");

    AlipayPayQueryResponse alipayPayQueryResponse = null;
    try {
        alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}
```

The following code shows an example of a request:

```json
{
    "paymentRequestId": "REQUEST_2024100821261****"
}
```

It is recommended to save the information on acquirers (_acquirerInfo_), refer to [Order number management](https://docs.antom.com/ac/apo_zh-cn/iddemon.md) for specific reasons. The following code shows an example of a response:

#### Tab: 3D-authenticated payments

```json
{
  "paymentResultCode": "SUCCESS",
  "paymentRequestId": "G15320250317102252****",
  "paymentResultInfo": {
    "lastFour": "1358",
    "funding": "CREDIT",
    "issuerName": "ORIENT CORPORATION",
    "expiryMonth": "**",
    "threeDSResult": {
      "cavv": "",
      "xid": "649335d6-1858-4532-8a6e-0579e1b7****",
      "threeDSType": "INTERNAL",
      "eci": "05",
      "threeDSVersion": "2.2.0"
    },
    "expiryYear": "**",
    "cardNo": "************1358",
    "cardBin": "428067",
    "holdName": "NIHEI SHUNSUKE",
    "issuingCountry": "JP",
    "avsResultRaw": "I",
    "fingerprint": "a28f7dd0713e2f1d4e9ccae8853f5c0abca5154a03a6559cd985eb409857****",
    "networkTransactionId": "46507608833****",
    "cardBrand": "VISA",
    "cvvResultRaw": ""
  },
  "paymentAmount": {
    "currency": "JPY",
    "value": "120"
  },
  "acquirerReferenceNo": "pay_6tmvamfcxp5ujbbfjeopyz****",
  "result": {
    "resultStatus": "S",
    "resultCode": "SUCCESS",
    "resultMessage": "success."
  },
  "paymentId": "2025031719401089010011160025568****",
  "paymentResultMessage": "success.",
  "paymentTime": "2025-03-16T19:27:17-07:00",
  "acquirerInfo": {
    "referenceRequestId": "202503171903130000060027882****",
    "acquirerTransactionId": "pay_6tmvamfcxp5ujbbfjeopyz****",
    "acquirerMerchantId": "pc_6cpbmm5qderubjraxrygje****",
    "acquirerName": "CHECKOUT"
  },
  "paymentStatus": "SUCCESS",
  "paymentCreateTime": "2025-03-16T19:26:42-07:00"
}
```

#### Tab: Non 3D-authenticated payments

```json
{
  "acquirerInfo": {
    "acquirerMerchantId": "2188120229218367",
    "acquirerName": "ALIPAY",
    "acquirerResultCode": "SUCCESS",
    "acquirerResultMessage": "success",
    "acquirerTransactionId": "20250724194010800100188730206132981",
    "referenceRequestId": "PAY_10040954202507241753320589210"
  },
  "authExpiryTime": "2025-07-30T18:29:57-07:00",
  "paymentAmount": {
    "currency": "SGD",
    "value": "1"
  },
  "paymentId": "20250724194010800100188730206132981",
  "paymentMethodType": "CARD",
  "paymentRedirectUrl": "https://ac.alipay.com/page/antom-web-checkout/src/component-app/threedPage/index.html?scene=callbackPage",
  "paymentRequestId": "PAY_10040954202507241753320589210",
  "paymentResultCode": "SUCCESS",
  "paymentResultInfo": {
    "avsResultRaw": "I",
    "cardBrand": "VISA",
    "cardCategory": "CONSUMER",
    "cardNo": "************6338",
    "credentialTypeUsed": "PAN",
    "cvvResultRaw": "P",
    "funding": "DEBIT",
    "issuingCountry": "HK",
    "networkTransactionId": "385205053951842",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "challengeCancel": "",
      "eci": "",
      "threeDSOffered": false,
      "threeDStransactionStatusReason": ""
    }
  },
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2025-07-23T18:29:57-07:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

The table shows the possible values of _paymentStatus_ returned in the response. Please handle the result according to the guidances: 

| **_paymentStatus_** | **Message** | **Further actions** |
| --- | --- | --- |
| `SUCCESS` | Indicates that the authorized payment is successful. | You may proceed with initiating capture. |
| `FAIL` | Indicates that the authorized payment failed. | Please close the current transaction or replace _paymentRequestId_ to place the order again. |
| `PROCESSING` | Indicates that the authorized payment is being processed. | You can continue to inquire about the payment result or inquire after the payment expiration time. |

> **Common Questions**
>
> **Q: How often should I call the** **[inquiryPayment](https://docs.antom.com/ac/apo/paymentri_online.md)** **API****?**
>
> A: Please continuously call the **[inquiryPayment](https://docs.antom.com/ac/apo/paymentri_online.md)** API at 2-second intervals, and make the inquiry after placing the order via the [**pay**](https://docs.antom.com/ac/apo/pay.md) API until the final payment result is obtained or the payment result asynchronous notification is received.
>
> **Q:** **What are t****he key parameters in the inquiry that I need to use?**
>
> A: Pay attention to the following key parameters:
>
> -   _paymentStatus_: You need to determine the payment result based on _paymentStatus_.
> -   _paymentAmo__unt_: indicates the payment amount.

### Cancel Server-side

If you need to cancel a transaction, you can use the **[cancel](http://docs.antom.com/ac/apo/paymentc_online)** API. For more information, see [Cancel](https://docs.antom.com/ac/apo/cancel.md).

### Refund Server-side

To learn about APO refund rules and how to initiate a refund for a successful transaction, see [Refund](https://docs.antom.com/ac/apo/refund.md) for more information.

### Dispute

When a buyer chooses to pay with a card, a dispute may occur. To learn more, see [Dispute](https://docs.antom.com/ac/apo/dispute.md).

### Reconciliation

After the transaction is completed, use the financial reports provided by APO for reconciliation. For more information on how to reconcile and the settlement rules of APO, please refer to [Reconciliation](https://docs.antom.com/ac/apo/reconcile.md).