# Payment Element integration

> Follow the guide to integrate Antom Payment Element to build a seamless payment experience.

 Antom Payment Element is a payment component integrated via SDK, designed to provide a seamless payment experience and help increase conversion rates. For different client types, Antom offers the following solutions:

 - Web/WAP: Web Element for browser and mobile web environments
- App (Android & iOS & Flutter): Mobile Element designed for merchants' native mobile applications

 The capabilities supported by Payment Element on each platform are shown in the table below:

 | **Feature** | **Description** | **Web/WAP** | **Android** | **iOS** | **Flutter** |
| --- | --- | --- | --- | --- | --- |
| Payment Element-rendered payment method list | You can use the default payment method list rendered by Payment Element on the checkout page. You can also   [specify payment methods](#L9xOX)   to flexibly control which payment methods are displayed. | ✔️ | ✔️ | ✔️ | ✔️ |
| Merchant-rendered payment methods (single-payment-method integration) | You can   [specify individual payment methods](#L9xOX)   according to your business needs to display a customized payment method list. > **[INFO]** **Note**    : For   [certain payment methods](#Ygtd4X)   (e.g., card payments), you need to embed the payment details component rendered by Payment Element. | ✔️ | ✔️ | ✔️ | ✔️ |
| Embedded experience | The payment form is directly embedded on your merchant page, delivering a seamless integration experience. | ✔️ | ❌ | ❌ | ❌ |
| Pop-up experience | The buyer completes payment in a separate pop-up window after clicking, offering simple integration and secure experience. | ❌ | ✔️ | ✔️ | ✔️ |
| [Appearance customization](https://docs.antom.com/ac/cashierpay/appearance.md) | Use the     *appearance*     parameter to customize the visual style and layout of the payment interface, including theme selection, layout configuration, and CSS styling. | ✔️ | ✔️ | ✔️ | ✔️ |
| Custom p   ayment button | ​   You can customize the payment button. When the buyer clicks your custom payment button, you need to call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method to submit payment. | ✔️ | ❌ | ❌ | ❌ |

<!-- ToggleTab query="platform" -->

**Tab: Web/WAP**

# User experience {#BEWwv}

<!-- TabGroup -->

**Tab: Web**

The following figures demonstrate the user experience of using Payment Element in different scenarios:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

The following figure shows templates with embedded Payment Element-rendered payment method list:

 ![Web user experience templates with embedded Payment Element-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/654fb40d-fe90-4ae5-af47-d0d83fc3d93d.png) If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/61b582ba-39c9-4718-b6b3-6b850f78307c.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/7ca32450-68cd-474d-9d26-b645f6c98ef5.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/5dfc12e9-e7d1-4a44-98b9-cb5475f5d707.png)

**Tab: Stored card payments**

Payment Element handles the stored card payment scenario.

 ![User experience for stored card payments of Payment Element](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/fcb26e34-236b-454e-bcf0-c1a28eb63d52.png)

<!-- /TabGroup -->

**Tab: Merchant-rendered payment method list**

The following figure shows templates of merchant-rendered payment method list:

 ![Web user experience templates of merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f47c4812-dbc9-4c16-abda-b4c09b794db0.png) If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/c00c1697-c29e-416a-92aa-5c746b6128d2.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/dadc71af-863e-4fe8-9697-f6e03c5fd12a.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/6a1f3fa8-3b2e-4e10-9c37-610db8f7eb74.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

**Tab: WAP**

The following figures demonstrate the user experience of using Payment Element in different scenarios:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

The following figure shows templates with embedded Payment Element-rendered payment method list:

 ![WAP user experience templates with embedded Payment Element-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/c95557ec-7912-471e-b64c-0c3e049bf886.png)

 If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/49216072-a2d0-45d4-81b4-69087444d810.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/42c96cfe-dd03-463f-9c01-7dfdff4808ed.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f7016b1a-57d9-46bb-a0ec-7b7af2f4be7c.png)

**Tab: Stored card payments**

Payment Element handles the stored card payment scenario.

 ![User experience for stored card payments of Payment Element](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/67d151b4-08db-4f75-9831-4c407077f195.png)

<!-- /TabGroup -->

**Tab: Merchant-rendered payment method list**

The following figure shows templates of merchant-rendered payment method list:

 ![WAP user experience templates of merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/fa1dc44d-2bb0-44f8-89b2-0adcde44178b.png) If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/80081db0-5cc9-4865-bb47-79b7a6cf1414.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/0b6a633a-cfa7-40a9-a135-93580cf3df07.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/22162520-4054-4881-971f-ff4288b006f9.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

<!-- /TabGroup -->

# Order lifecycle {#iYCQo}

 Learn about the lifecycle of different payment methods:

<!-- TabGroup -->

**Tab: APM Payments**

For APM payments, such as  [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md)  and  [Touch'n Go eWallet](https://docs.antom.com/ac/antomop/touchngo.md) , funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can  [cancel](#Otb6j)  or  [refund](#kg4oU)  the order within the allowable period.

   ![Lifecycle diagram for APM payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/6da32eae-f8c2-495f-a6ce-c8a4f7b27c2e.png)

**Tab: Card payments, Apple Pay, Google Pay**

For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , the order lifecycle includes the following stages:

 1. Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can   [cancel](#Otb6j)   the order during the allowable period from when the order is placed until authorization is completed.
2. Capture   : You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  . After capture, you can initiate a   [refund](#kg4oU)   within the allowable period if needed.
3. Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to   [Dispute](#AoEw6)  .

   ![Lifecycle diagram for card payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/abc1f3bf-4223-4ed2-adc3-35862da1bfeb.png)

<!-- /TabGroup -->

# Payment flow {#nigJF}

 The following flow illustrates how to integrate One-time Payments using Payment Element:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

![Web/WAP payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using Payment Element-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/0530ab42-4989-4d17-b1f4-fbfbcfc0dc10.png)

**Tab: Merchant-rendered payment method list**

![Web/WAP payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/d550bd55-3f88-4045-bdff-182b889344a9.png)

<!-- /TabGroup -->
 1. **The buyer lands on the checkout page and submits payment.**
2. **Create a payment session request.**  
   You can obtain the payment session by calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API.
3. **Invoke Payment Element.**  
   On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the   `[submitPayment().then()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method, or the system will automatically return to your result page.
4. **Confirm the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)      to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   to send asynchronous notifications to you.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the payment status.

 > **[INFO]** **Note**    : For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.

 5. **Initiate capture and obtain the result.**  
   By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. The capture result can be obtained through one of the following methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)   to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the   [**notifyCapture (One-time Payments)**](https://docs.antom.com/ac/ams/notify_capture.md)   API.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the capture status.

# Integration preparations {#hKAW}

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

 - Obtained your client ID
- 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)  .
- Integrate the client-side SDK package by following the steps detailed in   [Integrate the SDK package for Web/WAP](https://docs.antom.com/ac/sdks/web.md)  , and ensure to use the latest SDK version or no lower than 1.46.0.

# Integration steps {#n1t0Y}

 Start your integration by taking the following steps:

 1. Create a payment session
2. Invoke Payment Element
3. Obtain    the payment result
4. Capture

## Step 1: Create a payment session   **[Server-side]** {#KuWal}

 Call the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API with order information to create a payment session and obtain the     *paymentSessionData*     required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list. Pass the corresponding parameters when calling the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can   [specify payment methods](#L9xOX)   to display only the options you need.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |
| *paymentRedirectUrl* | Yes | ​   The merchant page URL that the buyer is redirected to after the payment is completed. |
| *paymentNotifyUrl* | No | ​   The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |
| *settlementStrategy* | Yes | The settlement strategy for the payment request. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |
| *order.orderDescription* | Yes | Summary description of the order. |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)      and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  . |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)   scenarios. |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.WAP).osType(OsType.IOS).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
    } catch (AlipayApiException e) {
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
    }
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}
```

 If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "WAP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "IOS"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

**Tab: Merchant-rendered payment method list**

When rendering the payment method list yourself, you must pass the parameters for specifying payment methods listed in the table below. Note that for   [certain payment methods](#Ygtd4X)   (e.g., card payments), you need to embed the payment details component rendered by Payment Element. The optimal timing for calling the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API when offering card payment options is as follows:

 - If Payment Element needs to collect payment details: Call the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API after the buyer selects the payment method, and pass the card payment parameters listed in the table.
- If Payment Element does not need to collect payment details: Call the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API after the buyer selects the payment method and submits payment.

   | **Type** | **Parameter name** | **Required** | **Description** |
| --- | --- | --- | --- |
| Basic parameters | *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |  |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |  |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |  |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |  |
| *paymentNotifyUrl* | No | The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |  |
| *settlementStrategy.settlementCurrency* | Yes | The settlement currency of the payment. If you have signed multiple settlement currencies, you need to specify it in the API. |  |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |  |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |  |
| *order.orderDescription* | Yes | Summary description of the order. |  |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) . |  |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |  |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  scenarios. |  |
| Card payment parameters (Refer to   [Card payment features](#abqU1)  ) | *paymentFactor.captureMode* | No | Indicates the method for capturing funds after the user authorizes the payment. Valid values are: - `AUTOMATIC`  : indicates that Antom automatically captures the funds after the authorization. The same applies when the value is empty or you do not pass in this parameter. - `MANUAL`  : indicates that you manually capture the funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |  |
| *availablePaymentMethod.paymentMethodMetaData.is3DSAuthentication* | No | Determine whether to set the transaction authentication type to 3DS based on risk and dispute history. Valid values are: - `true`  : indicates that the transaction authentication type is 3DS authentication. - `false`  : indicates that the transaction authentication type is Non-3DS authentication. Default if empty or not provided. |  |
| *availablePaymentMethod.paymentMethodMetaData.tokenizeMode* | No | The tokenize mode. Indicates whether card information needs to be stored. When you opt to   [store card details](https://docs.antom.com/ac/cashierpay/tokenization.md)  , the actual information is replaced with a unique and secure token that can be used for future payments. Valid values are: - `ENABLED`  : indicates that you obtain card binding authorization and want to store card information for future payments. - `DISABLED`  : indicates that you don’t need to store card information. The same applies when the value is empty or you do not specify this parameter. - `ASKFORCONSENT`  : indicates that you present a button on the page, allowing the buyer to choose whether or not they want to store the card information. |  |
| *availablePaymentMethod.paymentMethodMetaData.isCardOnFile* | No | Indicates whether the card used in this transaction has been   [previously processed and stored](https://docs.antom.com/ac/cashierpay/cof.md)   by the merchant. Valid values are: - `true`  : The card used in the transaction has been previously processed and stored by the merchant. Set to   `true`   for stored card payments. - `false`  : Default. The card is new and has not been used previously on the merchant side. |  |
| *savedPaymentMethods.paymentMethodId* | No | Used for stored card payments.    The value of this parameter is that of     *cardToken*     obtained from the new card payment. |  |
| Parameters for specifying payment methods (Refer to   [Specify payment methods](#L9xOX)  ) | *availablePaymentMethod.paymentMethodTypeList.paymentMethodType* | No | Used to specify payment methods. You can specify one or multiple payment methods. Refer to   [Enumeration values of payment methods](https://docs.antom.com/ac/pm/enumeration_values.md)   for valid values. |
| *availablePaymentMethod.paymentMethodTypeList.paymentMethodOrder* | No | Set the priority order of payment methods. |  |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.WAP).osType(OsType.IOS).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    // replace with your specified payment method
    AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
    .paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
                                   .paymentMethodType("ALIPAY_CN")
                                   .build()))
    .build();
    alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
            System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
            System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
        } catch (AlipayApiException e) {
            return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
        }
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
    }
```

 If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "WAP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "IOS"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN" // Specify payment method
      }
    ]
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********u.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

<!-- /TabGroup -->
   The following code shows a sample of the response, which contains the following parameters:

 - *result.resultStatus*    : The result of the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API call.
- *paymentSessionData*    : The payment session data to be returned to the client.
- *paymentSessionExpiryTime*    : The expiration time of the payment session.

   ```json
 {
  "paymentSessionData": "gpZy************fQ==",
  "paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
  "paymentSessionId": "paymentSessionId****",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The table below shows the possible values of     *result.resultStatus*     in the response. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The payment session was successfully created, and     *paymentSessionData*     is returned. | Proceed to the next steps. |
| `U` | Unknown error. | Please use a new          *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | Failed to create the payment session. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

 > **[INFO]** **Note**    : If no response is received, it may indicate a network timeout. Please use a new     *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support.

 > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>  ​
>
>  **Q: How to set the address to receive payment notification?**
>
>  A: Specify     *paymentNotifyUrl*     in the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API to receive the asynchronous notification about the payment result (  [**notifyPayment**](https://docs.antom.com/docs/ac/ams/paymentrn_online.md)  ), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
>
>  ​
>
>  **Q: Does the returned**       ***paymentSessionData***       **require processing before passing it to the client?**
>
>  A: Do not process or modify     *paymentSessionData*     in any way, as this may cause the Payment Element invocation to fail.

## Step 2: Invoke Payment Element   **[Client-side]** {#FWfpW}

 Use     *paymentSessionData*     to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.

 Depending on the rendering method you chose in Step 1 (merchant-rendered or Payment Element-rendered payment method list), the following table compares how to invoke Payment Element in different scenarios:

 | **Method** | **Integration steps** |  |
| --- | --- | --- |
| Merchant-rendered payment method list       (Single payment method integration) | Payment Element collects payment details   ​ | 1. Call the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method to embed the payment details component rendered by Payment Element. 2. After the buyer clicks your custom payment button, call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method to submit payment. |
| Payment Element does not collect payment details   ​ | Call the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method without embedding the payment details component. After the buyer clicks your custom payment button, call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method to submit payment directly. |  |
| Payment Element-rendered payment method list | 1. Call the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method to embed the Payment Element-rendered payment method list. 2. After the buyer clicks your custom payment button, call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method to submit payment. |  |

 1. After obtaining     *paymentSessionData*     from the server, use the   `[AMSElement](https://docs.antom.com/ac/sdks/web_AMSElement.md)`   class to create a Payment Element instance. The following sample code how to instantiate the SDK using CDN or npm:

<!-- TabGroup -->

**Tab: CDN**

```javascript
// Get the browser language
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // Replace "-" with "_"

// Create Payment Element instance
const elementPayment = new window.AMSElement({
  environment: "sandbox",
  locale: "en_US",
  sessionData:sessionData
})
```

**Tab: npm**

```javascript
import { AMSElement, ThemeType, PaymentElementLayout } from '@alipay/ams-checkout' // Package management

// Get the browser language
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // Replace "-" with "_"

// Create Payment Element instance
const elementPayment = new AMSElement({
  environment: "sandbox",
  locale: "en_US",
  sessionData:sessionData
})
```

<!-- /TabGroup -->
   2. Use the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method from the instance object to create the payment component, and embed the component into the specified view if needed. Before calling the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method, you may add a     *loading*     indicator and close it when handling the callback in the   `.then()`   method. If the callback result contains error information, determine the specific error type via     *error?.code*    , and refer to the   [callback function event codes](https://docs.antom.com/ac/sdks/ref.md#M3TUS)   for detailed error causes and handling suggestions. If no error information is present, the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method rendering was successful.

 > **[INFO]** **Note**    :
>
>  - If you need to embed the payment details collection component (see   [Payment methods requiring embedding](#Ygtd4X)   for details), it is recommended that the container for the payment element have a minimum width of 375 px and no height restriction, allowing the Payment Element to automatically expand the container height.
> - The different configuration of   [*notRedirectAfterComplete*](https://docs.antom.com/ac/sdks/web_mount.md#Jmfs8)   in the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method handles the redirection of the merchant page differently. For details, refer to   [Redirect to the merchant page](https://docs.antom.com/ac/sdks/web_mount.md#gxPhN)  .
> - When Payment Element renders the payment method list, the   [*merchantAppointParam.singleOption*](https://docs.antom.com/ac/sdks/web_mount.md#KJPse)   parameter in the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method defaults to   `skip`  . When only one payment method is specified, it will skip the payment method list and enter the payment flow directly. If you need to display the payment method list, you can change the value of this parameter to   `list`  .

 The following sample code shows how to create a payment component using the      `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`      method:

 ```javascript
let loading = false;

// Customize appearance
const appearance = {
  theme: "default",
  layout: {
    type: "Accordion"
  },
  variables: {},
};

// Set the loading state of the external container before calling mount
loading = true;

// Mount to the document.querySelector("#payment-element") node
elementPayment.mount({
    type: 'payment',
    appearance: appearance,
    notRedirectAfterComplete: false,
    merchantAppointParam: {
      singleOption: 'skip'
    }
  },
  '#payment-element',
).then(({
  error
}) => {
  // Manually turn off the loading state of the external container
  loading = false;

  // Consume the error message and handle exceptions based on error.code
  if (error && error?.code) {
    // PARAM_INVALID: SDK parameter exception. Please check the integration code
    // UI_STATE_ERROR: Abnormal timing for the mount call. Please check the integration code
    console.log(error.message);

    if (error?.code === 'INITALIZE_API_TIMEOUT') {
      // The inquiryPayment API timed out, causing the checkout page to fail to render. Please guide the buyer to retry

    } else if (error?.code === 'INITALIZE_WEB_TIMEOUT') {
      // Timeout while loading static resources for the checkout page. Please guide the buyer to retry

    }...
    return;
  }
  // Mount rendered successfully, no action needed
})
```

 3. After the buyer clicks your custom payment button, call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`  method to submit payment.
   Before calling the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method, you may add a     *loading*     indicator and close it when handling the callback in the   `.then()`   method. It is recommended to display the *loading* state after the buyer clicks the payment button to prevent repeated submissions within a short period. After receiving the payment result returned by Payment Element, guide the buyer to either retry the payment or redirect to the payment result page based on the actual outcome.

   - If the callback result contains error information, you can simplify integration based on the     *status*     value. Refer to the sample code below for specific operations. You may also refer to     *error?.code*     for specific exception handling and refer to   [callback function event codes](https://docs.antom.com/ac/sdks/ref.md#heMi7)   for detailed error causes and handling suggestions.
  - If no error information exists, proceed with subsequent operations based on the     *status*     value.

 ```javascript
let loading = false;

function checkout() {
  loading = true;
  // When the buyer clicks the payment button:
  elementPayment.submitPayment().then(({ status, userCanceled3D, session, error }) => {
    // Manually turn off the loading state of the external container
    loading = false;

    if (error) { // Handle errors first
      const { code, message, traceId, context } = error;

      if (userCanceled3D) {
        // The buyer manually closed the 3D secure pop-up. Please poll for the result from the server
      }

      if (status === 'PROCESSING') {
        // The status is unknown due to network issues or channel instability. Please poll for the result from the server
      } else {
        // FAIL
        // Form validation failed. Payment Element has already prompted the buyer, so this can be ignored
        if (code === 'FORM_INVALID') {
          return;
        }

        toast(message);

        // Or customize the experience based on the code
        if (code) {
          // xxx
        }
      }
      return;
    }

    if (status === 'SUCCESS') {
      // SUCCESS. In some scenarios, Payment Element will show a toast notification. Please redirect directly to the result page

    } else if (status === 'CANCELLED') {
      // The order has been cancelled. This can be ignored if this scenario is not applicable

    } else {
      // Monitoring can be added here
    }
  })
}
```

 4. (Optional) You can call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method and pass the   [*handleActions*](https://docs.antom.com/ac/sdks/web_submitPayment.md#yVmLP)   parameter to control whether Payment Element handles automatic redirects:

 ```javascript
let loading = false;

function checkout() {
  loading = true;
  // When the buyer clicks the payment button:
  elementPayment.submitPayment({ handleActions: false }).then(({ status, userCanceled3D, session, error }) => {
    // Manually turn off the loading state of the external container
    loading = false;

    if (error) { // Handle errors first
      const { code, message, traceId, context } = error;

      if (userCanceled3D) {
        // The buyer manually closed the 3D secure pop-up. Please poll for the result from the server
      }

      if (status === 'PROCESSING') {
        // The status is unknown due to network issues or channel instability. Please poll for the result from the server
      } else {
        // FAIL
        // Form validation failed. Payment Element has already prompted the buyer, so this can be ignored
        if (code === 'FORM_INVALID') {
          return;
        }

        toast(message);

        // Or customize the experience based on the code
        if (code) {
          // xxx
        }
      }
      return;
    }

    if (status === 'SUCCESS') {
      // SUCCESS. In some scenarios, Payment Element will show a toast notification. Please redirect directly to the result page

    } else if (status === 'CANCELLED') {
      // The order has been cancelled. This can be ignored if this scenario is not applicable

    } else {
      // Monitoring can be added here
    }

    if (session && session.nextAction) {
      const { normalUrl, appLinkUrl, schemeUrl } = session.nextAction;

      const userAgent = navigator.userAgent || navigator.vendor || window.opera;
      if (/iphone|ipad|ipod/i.test(userAgent)) {
        // iOS browser
        if (appLinkUrl) {
          window.open(appLinkUrl, '_blank');
          return;
        } else if (schemeUrl) {
          window.open(schemeUrl, '_blank');
          return;
        }
      } else if (/android/i.test(userAgent)) {
        // Android browser
        if (appLinkUrl) {
          window.open(schemeUrl, '_blank');
          return;
        } else if (schemeUrl) {
          window.open(appLinkUrl, '_blank');
          return;
        }
      }

      // PC/Web/WAP
      window.open(normalUrl, '_blank');
    }

  })
}
```

 5. (Optional) You can call the   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`   method and pass the   [*shippingInfo*](https://docs.antom.com/ac/sdks/web_submitPayment.md#Am5lZ)   parameter to submit shipping address information:

 ```javascript
let loading = false;

const shippingInfo = {
  shippingAddress: {
    region: 'CN',
    state: 'SM',
    city: 'Shanghai',
    address1: '88 Century Avenue',
    address2: 'Floor 20, Tower A, Lujiazui',
    zipCode: '200120'
  },
  shippingPhoneNo: '+86 18200000000',
  shippingName: {
    firstName: 'Cui',
    lastName: 'Tom',
    middleName: '**',
    fullName: 'Tom ** Cui'
  }
}

function checkout() {
  loading = true;
  // When the buyer clicks the payment button:
  elementPayment.submitPayment({shippingInfo: shippingInfo, handleActions: true }).then(({ status, userCanceled3D, session, error }) => {
    // Manually turn off the loading state of the external container
    loading = false;

    if (error) { // Handle errors first
      const { code, message, traceId, context } = error;

      if (userCanceled3D) {
        // The buyer manually closed the 3D secure pop-up. Please poll for the result from the server
      }

      if (status === 'PROCESSING') {
        // The status is unknown due to network issues or channel instability. Please poll for the result from the server
      } else {
        // FAIL
        // Form validation failed. Payment Element has already prompted the buyer, so this can be ignored
        if (code === 'FORM_INVALID') {
          return;
        }

        toast(message);

        // Or customize the experience based on the code
        if (code) {
          // xxx
        }
      }
      return;
    }

    if (status === 'SUCCESS') {
      // SUCCESS. In some scenarios, Payment Element will show a toast notification. Please redirect directly to the result page

    } else if (status === 'CANCELLED') {
      // The order has been cancelled. This can be ignored if this scenario is not applicable

    } else {
      // Monitoring can be added here
    }

    if (session && session.nextAction) {
      const { normalUrl, appLinkUrl, schemeUrl } = session.nextAction;

      const userAgent = navigator.userAgent || navigator.vendor || window.opera;
      if (/iphone|ipad|ipod/i.test(userAgent)) {
        // iOS browser
        if (appLinkUrl) {
          window.open(appLinkUrl, '_blank');
          return;
        } else if (schemeUrl) {
          window.open(schemeUrl, '_blank');
          return;
        }
      } else if (/android/i.test(userAgent)) {
        // Android browser
        if (appLinkUrl) {
          window.open(schemeUrl, '_blank');
          return;
        } else if (schemeUrl) {
          window.open(appLinkUrl, '_blank');
          return;
        }
      }

      // PC/Web/WAP
      window.open(normalUrl, '_blank');
    }

  })
}
```

### Validate payment elements for the currently selected payment method {#t3KF6}

 The   `[validateFields()](https://docs.antom.com/ac/sdks/web_validateFields.md)`   method is used to verify whether the form fields under the currently selected payment method are complete and properly formatted. This method automatically identifies and validates the required parameters based on the selected payment method, eliminating the need for developers to manually maintain the parameter list. Even if   `[validateFields()](https://docs.antom.com/ac/sdks/web_validateFields.md)`   is not explicitly called, when executing   `[submitPayment()](https://docs.antom.com/ac/sdks/web_submitPayment.md)`  , the component will automatically display the corresponding error messages if any form issues are detected.

 ```javascript
let loading = false;

function checkout() {
  loading = true;

  // Validate the payment elements for the currently selected payment method
  elementPayment.validateFields().then(({isValid}) => {
    console.log(isValid);
    // Form validation failed
    if (!isValid) {
      console.log('Form validation failed');
      return;
    }
  });

  // After validation passes, you can initiate submitPayment()
  elementPayment.submitPayment().then(({ status, userCanceled3D, session, error }) => {
    ...
  })
}
```

### Configure CVV verification for stored card payment scenarios {#M2tfz}

 To enhance payment convenience and transaction success rates, the default value of the   [*merchantAppointParam.storedCard.needCVV*](https://docs.antom.com/ac/sdks/web_mount.md#NzA8o)   parameter in the   `[mount()](https://docs.antom.com/ac/sdks/web_mount.md)`   method is   `false`  , meaning CVV verification is not performed by default in stored card payment scenarios. If your business scenario has special requirements for payment security, you can set this parameter to   `true`   to enable CVV verification.

 > **[INFO]** **Note**    : Unless specifically required, it is recommended that you maintain the default value of   `false`  to avoid requiring buyers to re-enter the CVV code, thereby optimizing the payment experience and improving transaction success rates.

 The following is a sample code for enabling CVV verification in specified stored card payment scenarios:

 ```javascript
// Embed in document.querySelector("#payment-element")
elementPayment.mount({
    ...
    merchantAppointParam: {
      storedCard: {
          needCVV: false
      }
    }
  },
  '#payment-element',
).then(({
error
}) => {
  ...
})
```

### Listen for component events {#BXsGy}

 Call the   `[on()](https://docs.antom.com/ac/sdks/web_on.md)`   method to listen for component events, which includes the following event types:

 - `[paymentMethodChanged](https://docs.antom.com/ac/sdks/web_on.md#Vherk)`   event: Triggered when the buyer switches payment methods, the callback function receives a parameter     *payload*    , which contains data related to the payment method change.

 ```javascript
elementPayment.on('paymentMethodChanged', (({type, name}) => {
  console.log(type + name);
}));
```

 - `[billingAddressChanged](https://docs.antom.com/ac/sdks/web_on.md#c2hJp)`   event: Triggered when the buyer edits the billing address form data, the callback function receives a parameter payload, which contains the latest billing address form data.

 ```javascript
elementPayment.on('billingAddressChanged', (({sameAsShipping, billingAddress}) => {
   console.log(sameAsShipping + JSON.stringify(billingAddress));
}));
```

### Unmount Payment Element {#gn3NV8}

 Call the   `[destroy()](https://docs.antom.com/ac/sdks/web_destroy.md)`   method to release the resources occupied by the Payment Element component:

   ```typescript
elementPayment.destroy();
```

   > **[INFO]** **Common questions**
>
>  **Q: Can I integrate the Web Element using Webview in PC or mobile applications?**
>
>  A: Currently not supported.

## Step 3: Obtain the payment result   **[Server-side]** {#MxqX3}

 After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:

 - Receive asynchronous notifications from Antom
- Inquire about the payment result

<!-- TabGroup -->

**Tab: Receive asynchronous notifications**

**1\. Configure the webhook URL to receive asynchronous notifications**

 When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):

 - If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API.
- If all your orders share a unified notification URL, you can set the webhook URL on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   through     **Developer > Notification URL**    . For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

 The following code shows a sample of the asynchronous notification request:

<!-- TabGroup -->

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentMethodType": "CARD",
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe", // store cardToken for future card payments
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Authorization    was successful. | You may proceed to initiate a capture. |
| `F` | Authorization    failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

**Tab: APM payments**

```json
{
    "actualPaymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "paymentCreateTime": "2025-02-04T22:11:19-08:00",
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "ALIPAY_HK",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultInfo": {

    },
    "paymentTime": "2025-02-04T22:14:25-08:00",
    "pspCustomerInfo": {
        "pspCustomerId": "216022003753XXXX",
        "pspName": "ALIPAY_HK"
    },
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Payment was successful. | **​**    You may proceed to ship the goods. |
| `F` | Payment failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

<!-- /TabGroup -->
 **2\. Verify the asynchronous notification**

 When you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/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 Antom:

 ```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);
    }

}
```

   Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.

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

   > **[INFO]** **Common questions**
>
>  **Q: When will the notification be sent?**
>
>  A: It depends on whether the payment is completed:
>
>  - If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
> - If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
>
>  
>  **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 Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)      format.
>
>  The notification can be resent 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: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>  ​
>
>  **Q: What key parameters do I need to use in the notification?**  
>    A: Please note the following key parameters:
>
>  - *result*    : For APM payments, it represents the final payment result. For  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  ,   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , and card payments, it only represents the authorization result, and further capture is required.
> - *paymentRequestId*    : The payment request ID used for inquiries, cancellations, and reconciliation.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
> - *paymentAmount*    : The payment amount.

**Tab: Inquire about the result**

You can also inquire about the payment result by calling the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API using     *paymentRequestId*     from the payment request,    regardless of whether it is an APM payment, card payment,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , or   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) .

 The following sample code shows how to call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/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 sample code shows a request message:

   ```json
{
  "paymentRequestId": "paymentRequestId01"
}
```

   The following sample code shows a response message:

<!-- TabGroup -->

**Tab: APM payments**

```json
{
  "actualPaymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "TRUEMONEY",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentMethodType": "TRUEMONEY",
  "paymentTime": "2025-02-17T08:06:43-08:00",
  "pspCustomerInfo": {
    "pspName": "TRUEMONEY"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
    "actualPaymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "authExpiryTime": "2024-12-17T21:56:56-08:00",
    "cardInfo": {
        "cardBrand": "VISA",
        "funding": "CREDIT",
        "issuingCountry": "US"
    },
    "paymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "CARD",
    "paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultCode": "SUCCESS",
    "paymentResultInfo": {
        "avsResultRaw": "M",
        "cardBrand": "VISA",
        "cardNo": "************9954",
        "cvvResultRaw": "U",
        "funding": "CREDIT",
        "issuingCountry": "US",
        "networkTransactionId": "123qwe456rew",
        "paymentMethodRegion": "GLOBAL",
        "threeDSResult": {
            "cavv": "",
            "eci": ""
        }
    },
    "paymentResultMessage": "success.",
    "paymentStatus": "SUCCESS",
    "paymentTime": "2024-12-10T21:56:57-08:00",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

<!-- /TabGroup -->
   Please handle the result based on the value of the     *paymentStatus*     parameter in the response. For specific return values, refer to the   [API documentation](https://docs.antom.com/ac/ams/paymentri_online.md#Responseparameters-paymentStatus)  .

 > **[INFO]** **Common questions**
>
>  **Q: What key parameters should I pay attention to when using the**       [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)       **API to check the payment or authorization status?**
>
>  A: Please note the following key parameters:
>
>  - *result*    :    Only indicates the result of the API call. For APM payments, the final payment result should be determined based on     *paymentStatus*     (  `SUCCESS`  /  `FAIL`  /  `PROCESSING`  ). For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) ,     *paymentStatus*     only represents the authorization result, and the decision to ship goods should rely on the capture result.
> - *paymentAmount*    : Used to verify the payment amount.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
>
>  ​
>
>  **Q: How often should I call the inquiryPayment API?**
>
>  A: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.

<!-- /TabGroup -->

## Step 4: Capture   **[Server-side]** **[For card payments/Apple Pay/Google Pay only]** {#qu0V5}

 Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  .

**Tab: iOS**

# User experience {#2BEWwv}

 The following figures demonstrate the user experience of using Payment Element in different scenarios:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

 ![iOS user experience templates for invoking the Payment Element-rendered payment method list in a pop-up](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/83d1a1b7-e30b-40cc-8b72-bb350ba3c395.png) If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/4e0fd2d7-196e-4f0c-a424-35fd36883389.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/fa7d21a7-3bc9-4bb1-a334-5910f5c4cfad.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/054517ec-1b96-4e8b-a43d-0f8ebec53401.png)

**Tab: Stored card payments**

Payment Element handles the stored card payment scenario.

 ![User experience for stored card payments of Payment Element](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/48da6b02-d667-43af-9f45-ba17a6141a42.png)

<!-- /TabGroup -->

**Tab: Merchant-rendered payment method list**

The following figure shows templates of merchant-rendered payment method list:

 ![iOS user experience templates of merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/fe5b70f9-c2c0-41b6-8b76-c22ea5f5efbf.png) If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/5c280a88-d3fb-48d2-8fb7-0e9833d7d99d.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/34b1d2d5-2952-4c18-8941-67167652babf.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/7846ecfc-3a15-4175-a3d6-a4ccb31dfbf8.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

# Order lifecycle {#2iYCQo}

 Learn about the lifecycle of different payment methods:

<!-- TabGroup -->

**Tab: APM Payments**

For APM payments, such as  [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md)  and  [Touch'n Go eWallet](https://docs.antom.com/ac/antomop/touchngo.md) , funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can  [cancel](#Otb6j)  or  [refund](#kg4oU)  the order within the allowable period.

   ![Lifecycle diagram for APM payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/6da32eae-f8c2-495f-a6ce-c8a4f7b27c2e.png)

**Tab: Card payments, Apple Pay, Google Pay**

For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , the order lifecycle includes the following stages:

 1. Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can   [cancel](#Otb6j)   the order during the allowable period from when the order is placed until authorization is completed.
2. Capture   : You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  . After capture, you can initiate a   [refund](#kg4oU)   within the allowable period if needed.
3. Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to   [Dispute](#AoEw6)  .

   ![Lifecycle diagram for card payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/abc1f3bf-4223-4ed2-adc3-35862da1bfeb.png)

<!-- /TabGroup -->

# Payment flow {#n2igJF}

 The following flow illustrates how to integrate One-time Payments using Payment Element:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

![iOS payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using Payment Element-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/d1277b85-b45b-4105-b16c-9ba3654a994f.png)

**Tab: Merchant-rendered payment method list**

![iOS payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/1aed9cfb-7e26-4e0e-a0a7-2fd4b96fad0d.png)

<!-- /TabGroup -->
 1. **The buyer lands on the checkout page and submits payment.**
2. **Create a payment session request.**  
   You can obtain the payment session by calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API.
3. **Invoke Payment Element.**  
   On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the   `[onSubmitPayCallback()](https://docs.antom.com/ac/sdks/ios_AMSPaymentProtocol.md#b066eaf8)`   method, or the system will automatically return to your result page.
4. **Confirm the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)      to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   to send asynchronous notifications to you.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the payment status.

 > **[INFO]** **Note**    : For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.

 5. **Initiate capture and obtain the result.**  
   By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. The capture result can be obtained through one of the following methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)   to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the   [**notifyCapture (One-time Payments)**](https://docs.antom.com/ac/ams/notify_capture.md)   API.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the capture status.

# Integration preparations {#22KAW}

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

 - Obtained your client ID
- 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)  .
- Integrate the client-side SDK package by following the steps detailed in   [Integrate the SDK package for iOS](https://docs.antom.com/ac/sdks/ios.md)  , and ensure to use the latest SDK version or no lower than 1.46.0.

# Integration steps {#n22t0Y}

 Start your integration by taking the following steps:

 1. (Optional) Preload the SDK
2. Create a payment session
3. Invoke Payment Element
4. Obtain    the payment result
5. Capture

## (Optional) Step 1: Preload the SDK   **[Client-side]** {#c33hKYz}

 Before creating a payment session, it is highly recommended that you call the `[preload()](https://docs.antom.com/ac/sdks/ios_preload.md)` method to preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment. Follow the code example below to perform the preloading:

 ```objectivec
[AMSPaymentElement.shared preload];
```

## Step 2: Create a payment session   **[Server-side]** {#K22uWal}

 Call the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API with order information to create a payment session and obtain the     *paymentSessionData*     required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list. It is recommended that you create a payment session after the buyer clicks the payment button. Depending on the method you selected for rendering the payment method list at the checkout page, pass the corresponding parameters when calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API.

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can   [specify payment methods](#L9xOX)   to display only the options you need.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |
| *paymentRedirectUrl* | Yes | ​   The merchant page URL that the buyer is redirected to after the payment is completed. |
| *paymentNotifyUrl* | No | ​   The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |
| *settlementStrategy* | Yes | The settlement strategy for the payment request. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |
| *order.orderDescription* | Yes | Summary description of the order. |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)      and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  . |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)   scenarios. |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order Info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
    } catch (AlipayApiException e) {
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
    }
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}
```

 If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "APP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "IOS"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

**Tab: Merchant-rendered payment method list**

When rendering the payment method list yourself, you must pass the parameters for specifying payment methods listed in the table below. If Payment Element needs to collect payment details, pass the card payment parameters listed in the table below.

   | **Type** | **Parameter name** | **Required** | **Description** |
| --- | --- | --- | --- |
| Basic parameters | *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |  |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |  |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |  |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |  |
| *paymentNotifyUrl* | No | The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |  |
| *settlementStrategy.settlementCurrency* | Yes | The settlement currency of the payment. If you have signed multiple settlement currencies, you need to specify it in the API. |  |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |  |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |  |
| *order.orderDescription* | Yes | Summary description of the order. |  |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) . |  |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |  |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  scenarios. |  |
| Card payment parameters (Refer to   [Card payment features](#abqU1)  ) | *paymentFactor.captureMode* | No | Indicates the method for capturing funds after the user authorizes the payment. Valid values are: - `AUTOMATIC`  : indicates that Antom automatically captures the funds after the authorization. The same applies when the value is empty or you do not pass in this parameter. - `MANUAL`  : indicates that you manually capture the funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |  |
| *availablePaymentMethod.paymentMethodMetaData.is3DSAuthentication* | No | Determine whether to set the transaction authentication type to 3DS based on risk and dispute history. Valid values are: - `true`  : indicates that the transaction authentication type is 3DS authentication. - `false`  : indicates that the transaction authentication type is Non-3DS authentication. Default if empty or not provided. |  |
| *availablePaymentMethod.paymentMethodMetaData.tokenizeMode* | No | The tokenize mode. Indicates whether card information needs to be stored. When you opt to   [store card details](https://docs.antom.com/ac/cashierpay/tokenization.md)  , the actual information is replaced with a unique and secure token that can be used for future payments. Valid values are: - `ENABLED`  : indicates that you obtain card binding authorization and want to store card information for future payments. - `DISABLED`  : indicates that you don’t need to store card information. The same applies when the value is empty or you do not specify this parameter. - `ASKFORCONSENT`  : indicates that you present a button on the page, allowing the buyer to choose whether or not they want to store the card information. |  |
| *availablePaymentMethod.paymentMethodMetaData.isCardOnFile* | No | Indicates whether the card used in this transaction has been   [previously processed and stored](https://docs.antom.com/ac/cashierpay/cof.md)   by the merchant. Valid values are: - `true`  : The card used in the transaction has been previously processed and stored by the merchant. Set to   `true`   for stored card payments. - `false`  : Default. The card is new and has not been used previously on the merchant side. |  |
| *savedPaymentMethods.paymentMethodId* | No | Used for stored card payments.    The value of this parameter is that of     *cardToken*     obtained from the new card payment. |  |
| Parameters for specifying payment methods (Refer to   [Specify payment methods](#L9xOX)  ) | *availablePaymentMethod.paymentMethodTypeList.paymentMethodType* | No | Used to specify payment methods. You can specify one or multiple payment methods. Refer to   [Enumeration values of payment methods](https://docs.antom.com/ac/pm/enumeration_values.md)   for valid values. |
| *availablePaymentMethod.paymentMethodTypeList.paymentMethodOrder* | No | Set the priority order of payment methods. |  |
| *availablePaymentMethod.paymentMethodTypeList.expressCheckout* | No | Specifies whether to enable the express checkout option for a payment method. Currently, only   `ALIPAY_CN`  ,   `APPLEPAY`   and   `GOOGLEPAY`  can be set as express checkout methods. Valid values are: - `true`  : Enables express checkout for this payment method. - `false`  : Disables express checkout for this payment method.   > **[INFO]** **Note**    : This parameter is currently supported only on Android and iOS. |  |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    // replace with your specified payment method
    AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
    .paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
                                   .paymentMethodType("ALIPAY_CN")
                                   .build()))
    .build();
    alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
        } catch (AlipayApiException e) {
            return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
        }
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
    }
```

 If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "APP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "IOS"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN" // 指定支付方式
      }
    ]
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********u.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

<!-- /TabGroup -->
   The following code shows a sample of the response, which contains the following parameters:

 - *result.resultStatus*    :    The result of the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API call.
- *paymentSessionData*    : The payment session data to be returned to the client.
- *paymentSessionExpiryTime*    : The expiration time of the payment session.

   ```json
 {
  "paymentSessionData": "gpZy************fQ==",
  "paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
  "paymentSessionId": "paymentSessionId****",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The table below shows the possible values of     *result.resultStatus*     in the response. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The payment session was successfully created, and     *paymentSessionData*     is returned. | Proceed to the next steps. |
| `U` | Unknown error. | Please use a new          *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | Failed to create the payment session. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

 > **[INFO]** **Note**    : If no response is received, it may indicate a network timeout. Please use a new     *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support.

 > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>  ​
>
>  **Q: How to set the address to receive payment notification?**
>
>  A: Specify     *paymentNotifyUrl*     in the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API to receive the asynchronous notification about the payment result (  [**notifyPayment**](https://docs.antom.com/docs/ac/ams/paymentrn_online.md)  ), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
>
>  ​
>
>  **Q: Does the returned**       ***paymentSessionData***       **require processing before passing it to the client?**
>
>  A: Do not process or modify     *paymentSessionData*     in any way, as this may cause the Payment Element invocation to fail.

## Step 3: Invoke Payment Element   **[Client-side]** {#3WfpW}

 Use     *paymentSessionData*     to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.

 1. After obtaining     *paymentSessionData*     from the server, use the   `[AMSPaymentElement](https://docs.antom.com/ac/sdks/ios_AMSPaymentElement.md)`   class to create a Payment Element instance.

   1. Creating the   `[AMSPaymentElementConfiguration](https://docs.antom.com/ac/sdks/ios_AMSPaymentElementConfiguration.md)`   object and complete the SDK configuration.

   2. Implement   `[AMSPaymentProtocol](https://docs.antom.com/ac/sdks/ios_AMSPaymentProtocol.md)`   to handle corresponding events in subsequent processes.

   The following shows a sample code for creating the Payment Element instance using   `[AMSPaymentElement](https://docs.antom.com/ac/sdks/ios_AMSPaymentElement.md)`  :

   ```objectivec
#import <AMSComponent/AMSComponent-Swift.h>

// Create an AMSPaymentElementConfiguration object
AMSPaymentElementConfiguration *componentConfig = [AMSPaymentElementConfiguration new];
componentConfig.locale = @"en_US";

NSString *appearance = @"{\n  \"theme\": \"night\",\n  \"layout\": {\n    \"type\": \"Tabs\"\n  },\n  \"variables\": {\n    \"content-quaternary\": \"#FFFF00\"\n  }\n}";

// Set sandbox environment. If left empty, the online production environment will be used by default
NSDictionary *options = @{@"showLoading": @"true",
                          @"sandbox": @"true",
                          @"appearance": appearance
                          };
componentConfig.options = options;

// initConfiguration usage
[[AMSPaymentElement shared] initConfiguration:componentConfig completion:^(AMSStatusResult * _Nonnull result) {
    // Handle error events during the initConfiguration phase
    if (result.error) {
        // Handle failure
        if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
            NSLog(@"integration code error, please check the integration code");
        } else {
            NSLog(@"unknown error, please contact support");
        }
    } else {
        // Handle success
    }
}];

// Set callback to listen for payment events on the checkout page
[AMSPaymentElement shared].paymentDelegate = self;

// Server calls the Create Payment Session API to obtain paymentSessionData

#pragma AMSPaymentProtocol
// Handle submitPay phase event codes via callback
- (void)onSubmitPayCallback:(AMSStatusResult *)eventResult {
    AMSStatusResultType statusType = eventResult.status;
    AMSResultError *error = eventResult.error;

    switch (statusType) {
        case AMSStatusResultTypePROCESSING:
            if (error && error.code) {
                if ([@"PAYMENT_IN_PROCESS" isEqualToString:error.code]) {
                    NSLog(@"payment is in processing, please try polling the payment result from the server");
                } else if ([@"USER_CANCELED" isEqualToString:error.code]) {
                    NSLog(@"user cancelled the payment process, please try invoke createComponent again");
                } else if ([@"UNKNOWN_EXCEPTION" isEqualToString:error.code]) {
                    NSLog(@"unknown exception, please contact support");
                } else if ([@"PAYMENT_RESULT_TIMEOUT" isEqualToString:error.code]) {
                    NSLog(@"get payment result timeout, please try polling the payment result from the server");
                }
            }
            break;
        case AMSStatusResultTypeCANCELLED:
            // fall through
        case AMSStatusResultTypeSUCCESS:
            NSLog(@"payment cancelled or success, do nothing");
            break;
        case AMSStatusResultTypeFAIL:
            if (error && error.code) {
                if ([@"ORDER_IS_CANCELLED" isEqualToString:error.code]) {
                    NSLog(@"the merchant has proactively canceled the order, please check on your own.");
                } else if ([@"ORDER_IS_CLOSED" isEqualToString:error.code]) {
                    NSLog(@"the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
                } else {
                    NSLog(@"unknown error, please contact support");
                }
            }
            break;
        default:
            break;
    }
}
```

   2. Use the   `[createComponent()](https://docs.antom.com/ac/sdks/ios_createComponent.md)`   function from the instance object to invoke Payment Element:

     ```objectivec
// Callback event code method - createComponent usage
[[AMSPaymentElement shared] createComponent:paymentSessionData completion:^(AMSStatusResult * _Nonnull result) {
    if (result.error) {
        // Handle failure
        if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
            NSLog(@"integration code error, please check the integration code");
        } else if ([result.error.code isEqualToString:@"PARAM_INVALID"]) {
            NSLog(@"session data invalid, please check the session data");
        } else if ([result.error.code isEqualToString:@"INITIALIZE_WEB_TIMEOUT"]) {
            NSLog(@"web app timeout, please invoke component again");
        } else {
            NSLog(@"unknown error, please contact support");
        }
    } else {
        // Handle success
    }
}];

```

### Unmount Payment Element {#f31st}

 Call the   `[onDestory()](https://docs.antom.com/ac/sdks/ios_onDestory.md)`   method to release SDK component resources.

   ```objectivec
// Release SDK component resources
[[AMSPaymentElement shared] onDestroy];
```

  

## Step 4: Obtain the payment result   **[Server-side]** {#2MxqX3}

 After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:

 - Receive asynchronous notifications from Antom
- Inquire about the payment result

<!-- TabGroup -->

**Tab: Receive asynchronous notifications**

**1\. Configure the webhook URL to receive asynchronous notifications**

 When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):

 - If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API.
- If all your orders share a unified notification URL, you can set the webhook URL on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   through     **Developer > Notification URL**    . For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

 The following code shows a sample of the asynchronous notification request:

<!-- TabGroup -->

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentMethodType": "CARD",
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe", // store cardToken for future card payments
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Authorization    was successful. | You may proceed to initiate a capture. |
| `F` | Authorization    failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

**Tab: APM payments**

```json
{
    "actualPaymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "paymentCreateTime": "2025-02-04T22:11:19-08:00",
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "ALIPAY_HK",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultInfo": {

    },
    "paymentTime": "2025-02-04T22:14:25-08:00",
    "pspCustomerInfo": {
        "pspCustomerId": "216022003753XXXX",
        "pspName": "ALIPAY_HK"
    },
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Payment was successful. | **​**    You may proceed to ship the goods. |
| `F` | Payment failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

<!-- /TabGroup -->
 **2\. Verify the asynchronous notification**

 When you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/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 Antom:

 ```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);
    }

}
```

   Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.

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

   > **[INFO]** **Common questions**
>
>  **Q: When will the notification be sent?**
>
>  A: It depends on whether the payment is completed:
>
>  - If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
> - If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
>
>  
>  **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 Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)      format.
>
>  The notification can be resent 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: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>  ​
>
>  **Q: What key parameters do I need to use in the notification?**  
>    A: Please note the following key parameters:
>
>  - *result*    : For APM payments, it represents the final payment result. For  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  ,   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , and card payments, it only represents the authorization result, and further capture is required.
> - *paymentRequestId*    : The payment request ID used for inquiries, cancellations, and reconciliation.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
> - *paymentAmount*    : The payment amount.

**Tab: Inquire about the result**

You can also inquire about the payment result by calling the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API using     *paymentRequestId*     from the payment request,    regardless of whether it is an APM payment, card payment,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , or   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) .

 The following sample code shows how to call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/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 sample code shows a request message:

   ```json
{
  "paymentRequestId": "paymentRequestId01"
}
```

   The following sample code shows a response message:

<!-- TabGroup -->

**Tab: APM payments**

```json
{
  "actualPaymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "TRUEMONEY",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentMethodType": "TRUEMONEY",
  "paymentTime": "2025-02-17T08:06:43-08:00",
  "pspCustomerInfo": {
    "pspName": "TRUEMONEY"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
    "actualPaymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "authExpiryTime": "2024-12-17T21:56:56-08:00",
    "cardInfo": {
        "cardBrand": "VISA",
        "funding": "CREDIT",
        "issuingCountry": "US"
    },
    "paymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "CARD",
    "paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultCode": "SUCCESS",
    "paymentResultInfo": {
        "avsResultRaw": "M",
        "cardBrand": "VISA",
        "cardNo": "************9954",
        "cvvResultRaw": "U",
        "funding": "CREDIT",
        "issuingCountry": "US",
        "networkTransactionId": "123qwe456rew",
        "paymentMethodRegion": "GLOBAL",
        "threeDSResult": {
            "cavv": "",
            "eci": ""
        }
    },
    "paymentResultMessage": "success.",
    "paymentStatus": "SUCCESS",
    "paymentTime": "2024-12-10T21:56:57-08:00",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

<!-- /TabGroup -->
   Please handle the result based on the value of the     *paymentStatus*     parameter in the response. For specific return values, refer to the   [API documentation](https://docs.antom.com/ac/ams/paymentri_online.md#Responseparameters-paymentStatus)  .

 > **[INFO]** **Common questions**
>
>  **Q: What key parameters should I pay attention to when using the**       [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)       **API to check the payment or authorization status?**
>
>  A: Please note the following key parameters:
>
>  - *result*    :    Only indicates the result of the API call. For APM payments, the final payment result should be determined based on     *paymentStatus*     (  `SUCCESS`  /  `FAIL`  /  `PROCESSING`  ). For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) ,     *paymentStatus*     only represents the authorization result, and the decision to ship goods should rely on the capture result.
> - *paymentAmount*    : Used to verify the payment amount.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
>
>  ​
>
>  **Q: How often should I call the inquiryPayment API?**
>
>  A: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.

<!-- /TabGroup -->

## Step 5: Capture   **[Server-side]** **[For card payments or Apple Pay only]** {#2qu0V5}

 Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  .

**Tab: Android**

# User experience {#3BEWwv}

 The following figures demonstrate the user experience of using Payment Element in different scenarios:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

 ![Android user experience templates for invoking the Payment Element-rendered payment method list in a pop-up](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/215bbc78-aaa3-4365-850a-6cb27cc1b2c2.png) If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/6dbe8416-edfe-4f20-804b-f7838879ff33.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/ea2d06a7-3633-476c-b435-460d64564d3a.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/479e8477-f8e0-460d-80a4-b75e1fe22c7c.png)

**Tab: Stored card payments**

Payment Element handles the stored card payment scenario.

 ![User experience for stored card payments of Payment Element](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/1a14635b-5bfe-4516-b021-b56278006332.png)

<!-- /TabGroup -->

**Tab: Merchant-rendered payment method list**

The following figure shows templates of merchant-rendered payment method list:

 ![Android user experience templates of merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/6e4467c7-e119-4015-a971-1020b4ccf6ef.png) If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/e01386ff-3169-4ac0-8430-2edbfec9232a.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/a8dd6f19-f804-4cb2-9c26-21f9f4cd1c9f.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/c2777185-d07a-49b7-9bfb-6b2706aa8613.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

# Order lifecycle {#3iYCQo}

 Learn about the lifecycle of different payment methods:

<!-- TabGroup -->

**Tab: APM Payments**

For APM payments, such as  [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md)  and  [Touch'n Go eWallet](https://docs.antom.com/ac/antomop/touchngo.md) , funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can  [cancel](#Otb6j)  or  [refund](#kg4oU)  the order within the allowable period.

   ![Lifecycle diagram for APM payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/6da32eae-f8c2-495f-a6ce-c8a4f7b27c2e.png)

**Tab: Card payments, Apple Pay, Google Pay**

For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , the order lifecycle includes the following stages:

 1. Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can   [cancel](#Otb6j)   the order during the allowable period from when the order is placed until authorization is completed.
2. Capture   : You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  . After capture, you can initiate a   [refund](#kg4oU)   within the allowable period if needed.
3. Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to   [Dispute](#AoEw6)  .

   ![Lifecycle diagram for card payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/abc1f3bf-4223-4ed2-adc3-35862da1bfeb.png)

<!-- /TabGroup -->

# Payment flow {#3nigJF}

 The following flow illustrates how to integrate One-time Payments using Payment Element:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

![Android payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using Payment Element-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/d1277b85-b45b-4105-b16c-9ba3654a994f.png)

**Tab: Merchant-rendered payment method list**

![Android payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/1aed9cfb-7e26-4e0e-a0a7-2fd4b96fad0d.png)

<!-- /TabGroup -->
 1. **The buyer lands on the checkout page and submits payment.**
2. **Create a payment session request.**  
   You can obtain the payment session by calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API.
3. **Invoke Payment Element.**  
   On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the   `[onSubmitPayCallback()](https://docs.antom.com/ac/sdks/android_OnSubmitPayListener.md#C2RMs)`   method, or the system will automatically return to your result page.
4. **Confirm the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)      to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   to send asynchronous notifications to you.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the payment status.

 > **[INFO]** **Note**    : For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.

 5. **Initiate capture and obtain the result.**  
   By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. The capture result can be obtained through one of the following methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)   to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the   [**notifyCapture (One-time Payments)**](https://docs.antom.com/ac/ams/notify_capture.md)   API.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the capture status.

# Integration preparations {#h33KAW}

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

 - Obtained your client ID
- 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)  .
- Integrate the client-side SDK package by following the steps detailed in   [Integrate the SDK package for Android](https://docs.antom.com/ac/sdks/android.md)  , and ensure to use the latest SDK version or no lower than 1.46.0.

# Integration steps {#33t0Y}

 Start your integration by taking the following steps:

 1. (Optional) Preload the SDK
2. Create a payment session
3. Invoke Payment Element
4. Obtain    the payment result
5. Capture

## (Optional) Step 1: Preload the SDK   **[Client-side]** {#chKYz}

 Before creating a payment session, it is highly recommended that you call the `[preload()](https://docs.antom.com/ac/sdks/android_preload.md)` method to preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment. Follow the code example below to perform the preloading:

 ```java
 AMSPaymentElement.preload(getApplicationContext());
```

## Step 2: Create a payment session   **[Server-side]** {#K3Wal}

 Call the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API with order information to create a payment session and obtain the     *paymentSessionData*     required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list. It is recommended that you create a payment session after the buyer clicks the payment button. Depending on the method you selected for rendering the payment method list at the checkout page, pass the corresponding parameters when calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API.

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can   [specify payment methods](#L9xOX)   to display only the options you need.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |
| *paymentRedirectUrl* | Yes | ​   The merchant page URL that the buyer is redirected to after the payment is completed. |
| *paymentNotifyUrl* | No | ​   The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |
| *settlementStrategy* | Yes | The settlement strategy for the payment request. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |
| *order.orderDescription* | Yes | Summary description of the order. |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)      and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  . |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)   scenarios. |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.ANDROID).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
    } catch (AlipayApiException e) {
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
    }
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}
```

 If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "APP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "ANDROID"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

**Tab: Merchant-rendered payment method list**

When rendering the payment method list yourself, you must pass the parameters for specifying payment methods listed in the table below. If Payment Element needs to collect payment details, pass the card payment parameters listed in the table below.

   | **Type** | **Parameter name** | **Required** | **Description** |
| --- | --- | --- | --- |
| Basic parameters | *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |  |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |  |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |  |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |  |
| *paymentNotifyUrl* | No | The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |  |
| *settlementStrategy.settlementCurrency* | Yes | The settlement currency of the payment. If you have signed multiple settlement currencies, you need to specify it in the API. |  |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |  |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |  |
| *order.orderDescription* | Yes | Summary description of the order. |  |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) . |  |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |  |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  scenarios. |  |
| Card payment parameters (Refer to   [Card payment features](#abqU1)  ) | *paymentFactor.captureMode* | No | Indicates the method for capturing funds after the user authorizes the payment. Valid values are: - `AUTOMATIC`  : indicates that Antom automatically captures the funds after the authorization. The same applies when the value is empty or you do not pass in this parameter. - `MANUAL`  : indicates that you manually capture the funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |  |
| *availablePaymentMethod.paymentMethodMetaData.is3DSAuthentication* | No | Determine whether to set the transaction authentication type to 3DS based on risk and dispute history. Valid values are: - `true`  : indicates that the transaction authentication type is 3DS authentication. - `false`  : indicates that the transaction authentication type is Non-3DS authentication. Default if empty or not provided. |  |
| *availablePaymentMethod.paymentMethodMetaData.tokenizeMode* | No | The tokenize mode. Indicates whether card information needs to be stored. When you opt to   [store card details](https://docs.antom.com/ac/cashierpay/tokenization.md)  , the actual information is replaced with a unique and secure token that can be used for future payments. Valid values are: - `ENABLED`  : indicates that you obtain card binding authorization and want to store card information for future payments. - `DISABLED`  : indicates that you don’t need to store card information. The same applies when the value is empty or you do not specify this parameter. - `ASKFORCONSENT`  : indicates that you present a button on the page, allowing the buyer to choose whether or not they want to store the card information. |  |
| *availablePaymentMethod.paymentMethodMetaData.isCardOnFile* | No | Indicates whether the card used in this transaction has been   [previously processed and stored](https://docs.antom.com/ac/cashierpay/cof.md)   by the merchant. Valid values are: - `true`  : The card used in the transaction has been previously processed and stored by the merchant. Set to   `true`   for stored card payments. - `false`  : Default. The card is new and has not been used previously on the merchant side. |  |
| *savedPaymentMethods.paymentMethodId* | No | Used for stored card payments.    The value of this parameter is that of     *cardToken*     obtained from the new card payment. |  |
| Parameters for specifying payment methods (Refer to   [Specify payment methods](#L9xOX)  ) | *availablePaymentMethod.paymentMethodTypeList.paymentMethodType* | No | Used to specify payment methods. You can specify one or multiple payment methods. Refer to   [Enumeration values of payment methods](https://docs.antom.com/ac/pm/enumeration_values.md)   for valid values. |
| *availablePaymentMethod.paymentMethodTypeList.paymentMethodOrder* | No | Set the priority order of payment methods. |  |
| *availablePaymentMethod.paymentMethodTypeList.expressCheckout* | No | Specifies whether to enable the express checkout option for a payment method. Currently, only   `ALIPAY_CN`  ,   `APPLEPAY`   and   `GOOGLEPAY`  can be set as express checkout methods. Valid values are: - `true`  : Enables express checkout for this payment method. - `false`  : Disables express checkout for this payment method.   > **[INFO]** **Note**    : This parameter is currently supported only on Android and iOS. |  |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.ANDROID).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order Info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    // replace with your specified payment method
    AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
    .paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
                                   .paymentMethodType("ALIPAY_CN")
                                   .build()))
    .build();
    alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
    } catch (AlipayApiException e) {
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
        }
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
    }
```

 If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "APP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "ANDROID"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN" // Specify payment method
      }
    ]
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********u.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

<!-- /TabGroup -->
   The following code shows a sample of the response, which contains the following parameters:

 - *result.resultStatus*    :    The result of the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API call.
- *paymentSessionData*    : The payment session data to be returned to the client.
- *paymentSessionExpiryTime*    : The expiration time of the payment session.

   ```json
 {
  "paymentSessionData": "gpZy************fQ==",
  "paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
  "paymentSessionId": "paymentSessionId****",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The table below shows the possible values of     *result.resultStatus*     in the response. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The payment session was successfully created, and     *paymentSessionData*     is returned. | Proceed to the next steps. |
| `U` | Unknown error. | Please use a new          *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | Failed to create the payment session. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

 > **[INFO]** **Note**    : If no response is received, it may indicate a network timeout. Please use a new     *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support.

 > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>  ​
>
>  **Q: How to set the address to receive payment notification?**
>
>  A: Specify     *paymentNotifyUrl*     in the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API to receive the asynchronous notification about the payment result (  [**notifyPayment**](https://docs.antom.com/docs/ac/ams/paymentrn_online.md)  ), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
>
>  ​
>
>  **Q: Does the returned**       ***paymentSessionData***       **require processing before passing it to the client?**
>
>  A: Do not process or modify     *paymentSessionData*     in any way, as this may cause the Payment Element invocation to fail.

## Step 3: Invoke Payment Element   **[Client-side]** {#FW22fpW}

 Use     *paymentSessionData*     to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.

 1. After obtaining     *paymentSessionData*     from the server, use the   `[AMSPaymentElement](https://docs.antom.com/ac/sdks/android_AMSPaymentElement.md)`   class to create SDK instance.

   1. Creating the   `[AMSBaseConfiguration](https://docs.antom.com/ac/sdksn/android_AMSBaseConfiguration.md)`  object and complete the SDK configuration.

   2. Implement   `[OnCreateComponentListener()](https://docs.antom.com/ac/sdks/android_OnCreateComponentListener.md)`  to handle events in the process of invoking the payment component and launching the payment page.

   3. Implement   `[OnSubmitPayListener()](https://docs.antom.com/ac/sdks/android_OnSubmitPayListener.md)`  to handle events related to the payment initiation process.

 The following shows a sample code for creating the SDK instance using   `[AMSPaymentElement](https://docs.antom.com/ac/sdks/android_AMSPaymentElement.md)`   :

   ```java
AMSPaymentElementConfiguration configuration = new AMSPaymentElementConfiguration();
configuration.setLocale(new Locale("en", "US"));
configuration.setOption("showLoading", "true");
configuration.setOption("sandbox", "true");
configuration.setOption("notRedirectAfterComplete", "false");
String appearance = "{\"theme\":\"night\",\"layout\":{\"type\":\"accordion\"},\"variables\":{\"content-primary\":\"#ff5b4d\"}}";
configuration.setOption("appearance", appearance);

configuration.setOnCreateComponentListener(new OnCreateComponentListener() {
    @Override
    public void onCreateComponentCallback(AMSStatusResult statusResult) {
        if (statusResult.getError() != null) {
            switch (statusResult.getError().getCode()) {
                case "UI_STATE_ERROR":
                    System.out.println("integration code error, please check the integration code");
                    break;
                case "PARAM_INVALID":
                    System.out.println("session data invalid, please check the session data");
                    break;
                case "INITIALIZE_WEB_TIMEOUT":
                    System.out.println("web app timeout, please invoke component again");
                    break;
                default:
                    System.out.println("unknown error, please contact support");
                break;
            }
        }
    }
});

configuration.setOnSubmitPayListener(new OnSubmitPayListener() {
    @Override
    public void onSubmitPayCallback(AMSStatusResult statusResult) {
        AMSStatus status = statusResult.getStatus();
        AMSResultError error = statusResult.getError();
        if (status ==  AMSStatus.PROCESSING) {
           if (error != null && error.getCode() != null) {
               if ("PAYMENT_IN_PROCESS".equals(error.getCode())) {
                   System.out.println("payment is in processing, please try polling the payment result from the server");
               } else if ("USER_CANCELED".equals(error.getCode())){
                   System.out.println("user cancelled the payment process, please try invoke createComponent again");
               } else if ("UNKNOWN_EXCEPTION".equals(error.getCode())) {
                   System.out.println("unknown exception, please contact support");
               } else if ("PAYMENT_RESULT_TIMEOUT".equals(error.getCode())){
                   System.out.println("get payment result timeout, please try polling the payment result from the server");
               }
           }
        } else if (status == AMSStatus.CANCELLED || status == AMSStatus.SUCCESS) {
            System.out.println("payment cancelled or success, do nothing");
        } else if (status == AMSStatus.FAIL) {
            if (error != null && error.getCode() != null) {
                if ("ORDER_IS_CANCELLED".equals(error.getCode())) {
                    System.out.println("the merchant has proactively canceled the order, please check on your own.");
                } else if ("ORDER_IS_CLOSED".equals(error.getCode()) || "INQUIRY_PAYMENT_SESSION_FAILED".equals(error.getCode())){
                    System.out.println("the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
                } else {
                    System.out.println("unknown error, please contact support");
                }
            }
        }
    }
});

AMSPaymentElement amsPaymentElement = new AMSPaymentElement.Builder(this, (AMSPaymentElementConfiguration) configuration).build();

```

   2. Use the   `[createComponent()](https://docs.antom.com/ac/sdks/android_createComponent.md)`      function from the instance object to invoke Payment Element:

   ```java
// paymentSessionData obtained when creating a payment session
String paymentSessionData = "exxxxe";

amsPaymentElement.createComponent(this, paymentSessionData);
```

### Unmount Payment Element {#1xGNou}

 Call the   `[onDestory()](https://docs.antom.com/ac/sdks/android_onDestory.md)`   method to release SDK component resources in the following scenarios:

   ```java
// release SDK component resources
amsPaymentElement.onDestroy();
```

  

## Step 4: Obtain the payment result   **[Server-side]** {#3xqX3}

 After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:

 - Receive asynchronous notifications from Antom
- Inquire about the payment result

<!-- TabGroup -->

**Tab: Receive asynchronous notifications**

**1\. Configure the webhook URL to receive asynchronous notifications**

 When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):

 - If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API.
- If all your orders share a unified notification URL, you can set the webhook URL on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   through     **Developer > Notification URL**    . For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

 The following code shows a sample of the asynchronous notification request:

<!-- TabGroup -->

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentMethodType": "CARD",
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe", // store cardToken for future card payments
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Authorization    was successful. | You may proceed to initiate a capture. |
| `F` | Authorization    failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

**Tab: APM payments**

```json
{
    "actualPaymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "paymentCreateTime": "2025-02-04T22:11:19-08:00",
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "ALIPAY_HK",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultInfo": {

    },
    "paymentTime": "2025-02-04T22:14:25-08:00",
    "pspCustomerInfo": {
        "pspCustomerId": "216022003753XXXX",
        "pspName": "ALIPAY_HK"
    },
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Payment was successful. | **​**    You may proceed to ship the goods. |
| `F` | Payment failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

<!-- /TabGroup -->
 **2\. Verify the asynchronous notification**

 When you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/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 Antom:

 ```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);
    }

}
```

   Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.

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

   > **[INFO]** **Common questions**
>
>  **Q: When will the notification be sent?**
>
>  A: It depends on whether the payment is completed:
>
>  - If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
> - If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
>
>  
>  **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 Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)      format.
>
>  The notification can be resent 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: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>  ​
>
>  **Q: What key parameters do I need to use in the notification?**  
>    A: Please note the following key parameters:
>
>  - *result*    : For APM payments, it represents the final payment result. For  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  ,   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , and card payments, it only represents the authorization result, and further capture is required.
> - *paymentRequestId*    : The payment request ID used for inquiries, cancellations, and reconciliation.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
> - *paymentAmount*    : The payment amount.

**Tab: Inquire about the result**

You can also inquire about the payment result by calling the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API using     *paymentRequestId*     from the payment request,    regardless of whether it is an APM payment, card payment,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , or   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) .

 The following sample code shows how to call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/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 sample code shows a request message:

   ```json
{
  "paymentRequestId": "paymentRequestId01"
}
```

   The following sample code shows a response message:

<!-- TabGroup -->

**Tab: APM payments**

```json
{
  "actualPaymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "TRUEMONEY",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentMethodType": "TRUEMONEY",
  "paymentTime": "2025-02-17T08:06:43-08:00",
  "pspCustomerInfo": {
    "pspName": "TRUEMONEY"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
    "actualPaymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "authExpiryTime": "2024-12-17T21:56:56-08:00",
    "cardInfo": {
        "cardBrand": "VISA",
        "funding": "CREDIT",
        "issuingCountry": "US"
    },
    "paymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "CARD",
    "paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultCode": "SUCCESS",
    "paymentResultInfo": {
        "avsResultRaw": "M",
        "cardBrand": "VISA",
        "cardNo": "************9954",
        "cvvResultRaw": "U",
        "funding": "CREDIT",
        "issuingCountry": "US",
        "networkTransactionId": "123qwe456rew",
        "paymentMethodRegion": "GLOBAL",
        "threeDSResult": {
            "cavv": "",
            "eci": ""
        }
    },
    "paymentResultMessage": "success.",
    "paymentStatus": "SUCCESS",
    "paymentTime": "2024-12-10T21:56:57-08:00",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

<!-- /TabGroup -->
   Please handle the result based on the value of the     *paymentStatus*     parameter in the response. For specific return values, refer to the   [API documentation](https://docs.antom.com/ac/ams/paymentri_online.md#Responseparameters-paymentStatus)  .

 > **[INFO]** **Common questions**
>
>  **Q: What key parameters should I pay attention to when using the**       [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)       **API to check the payment or authorization status?**
>
>  A: Please note the following key parameters:
>
>  - *result*    :    Only indicates the result of the API call. For APM payments, the final payment result should be determined based on     *paymentStatus*     (  `SUCCESS`  /  `FAIL`  /  `PROCESSING`  ). For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) ,     *paymentStatus*     only represents the authorization result, and the decision to ship goods should rely on the capture result.
> - *paymentAmount*    : Used to verify the payment amount.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
>
>  ​
>
>  **Q: How often should I call the inquiryPayment API?**
>
>  A: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.

<!-- /TabGroup -->

## Step 5: Capture   **[Server-side]** **[For card payments or Google Pay only]** {#3u0V5}

 Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  .

**Tab: Flutter**

# User experience {#4BEWwv}

 The following figures demonstrate the user experience of using Payment Element in different scenarios:

<!-- TabGroup -->

**Tab: iOS**

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

 ![iOS user experience templates for invoking the Payment Element-rendered payment method list in a pop-up](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/83d1a1b7-e30b-40cc-8b72-bb350ba3c395.png) If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/4e0fd2d7-196e-4f0c-a424-35fd36883389.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/fa7d21a7-3bc9-4bb1-a334-5910f5c4cfad.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/054517ec-1b96-4e8b-a43d-0f8ebec53401.png)

**Tab: Stored card payments**

Payment Element handles the stored card payment scenario.

 ![User experience for stored card payments of Payment Element](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/48da6b02-d667-43af-9f45-ba17a6141a42.png)

<!-- /TabGroup -->

**Tab: Merchant-rendered payment method list**

The following figure shows templates of merchant-rendered payment method list:

 ![iOS user experience templates of merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/fe5b70f9-c2c0-41b6-8b76-c22ea5f5efbf.png) If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/5c280a88-d3fb-48d2-8fb7-0e9833d7d99d.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/34b1d2d5-2952-4c18-8941-67167652babf.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/7846ecfc-3a15-4175-a3d6-a4ccb31dfbf8.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

**Tab: Android**

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

 ![Android user experience templates for invoking the Payment Element-rendered payment method list in a pop-up](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/215bbc78-aaa3-4365-850a-6cb27cc1b2c2.png) If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/6dbe8416-edfe-4f20-804b-f7838879ff33.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/ea2d06a7-3633-476c-b435-460d64564d3a.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/479e8477-f8e0-460d-80a4-b75e1fe22c7c.png)

**Tab: Stored card payments**

Payment Element handles the stored card payment scenario.

 ![User experience for stored card payments of Payment Element](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/1a14635b-5bfe-4516-b021-b56278006332.png)

<!-- /TabGroup -->

**Tab: Merchant-rendered payment method list**

The following figure shows templates of merchant-rendered payment method list:

 ![Android user experience templates of merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/6e4467c7-e119-4015-a971-1020b4ccf6ef.png) If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:

<!-- TabGroup -->

**Tab: Scan to pay**

Payment Element displays a QR code for buyers to complete the payment.

 ![Payment Element displays a QR code for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/e01386ff-3169-4ac0-8430-2edbfec9232a.png)

**Tab: Redirect to payment page**

Payment Element redirects to the payment method page for buyers to complete the payment.

 ![Payment Element redirects to the payment method page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/a8dd6f19-f804-4cb2-9c26-21f9f4cd1c9f.png)

**Tab: New card payment**

Payment Element displays the card detail collection page for buyers to complete the payment.

 ![Payment Element displays the card detail collection page for buyers to complete the payment](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/c2777185-d07a-49b7-9bfb-6b2706aa8613.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

<!-- /TabGroup -->

# Order lifecycle {#4iYCQo}

 Learn about the lifecycle of different payment methods:

<!-- TabGroup -->

**Tab: APM Payments**

For APM payments, such as  [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md)  and  [Touch'n Go eWallet](https://docs.antom.com/ac/antomop/touchngo.md) , funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can  [cancel](#Otb6j)  or  [refund](#kg4oU)  the order within the allowable period.

   ![Lifecycle diagram for APM payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/6da32eae-f8c2-495f-a6ce-c8a4f7b27c2e.png)

**Tab: Card payments, Apple Pay, Google Pay**

For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , the order lifecycle includes the following stages:

 1. Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can   [cancel](#Otb6j)   the order during the allowable period from when the order is placed until authorization is completed.
2. Capture   : You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  . After capture, you can initiate a   [refund](#kg4oU)   within the allowable period if needed.
3. Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to   [Dispute](#AoEw6)  .

   ![Lifecycle diagram for card payments](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/abc1f3bf-4223-4ed2-adc3-35862da1bfeb.png)

<!-- /TabGroup -->

# Payment flow {#4nigJF}

 The following flow illustrates how to integrate One-time Payments using Payment Element:

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

![Flutter payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using Payment Element-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/d1277b85-b45b-4105-b16c-9ba3654a994f.png)

**Tab: Merchant-rendered payment method list**

![Flutter payment flow sequence diagram showing the integration flow across Buyer, Merchant client, Payment Element, Payment method, Merchant server and Antom when using merchant-rendered payment method list](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/1aed9cfb-7e26-4e0e-a0a7-2fd4b96fad0d.png)

<!-- /TabGroup -->
 1. **The buyer lands on the checkout page and submits payment.**
2. **Create a payment session request.**  
   You can obtain the payment session by calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API.
3. **Invoke Payment Element.**  
   On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the   `[onSubmitPayCallback()](https://docs.antom.com/ac/sdks/flutter_setOnSubmitPayListener.md#e76Rw)`   method, or the system will automatically return to your result page.
4. **Confirm the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)      to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   to send asynchronous notifications to you.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the payment status.

 > **[INFO]** **Note**    : For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.

 5. **Initiate capture and obtain the result.**  
   By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. The capture result can be obtained through one of the following methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API or configure on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/account/login?goto=https%3A%2F%2Fdashboard.alipay.com%2Fglobal-payments%2Fhome)   to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the   [**notifyCapture (One-time Payments)**](https://docs.antom.com/ac/ams/notify_capture.md)   API.
  - Synchronous inquiry: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API to check the capture status.

# Integration preparations {#h41KAW}

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

 - Obtained your client ID
- 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)  .
- Integrate the client-side SDK package by following the steps detailed in   [Integrate the SDK package for Flutter](https://docs.antom.com/ac/sdks/flutter.md)  .

# Integration steps {#33t0Y}

 Start your integration by taking the following steps:

 1. (Optional) Preload the SDK
2. Create a payment session
3. Invoke Payment Element
4. Obtain    the payment result
5. Capture

## (Optional) Step 1: Preload the SDK   **[Client-side]** {#c4hKYz}

 Before creating a payment session, it is highly recommended that you call the `[preload()](https://docs.antom.com/ac/sdks/flutter_preload.md)` method to preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment. Follow the code example below to perform the preloading:

 ```dart
// Preload Payment Element SDK
AMSPaymentElement.preload();
```

## Step 2: Create a payment session   **[Server-side]** {#K4Wal}

 Call the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API with order information to create a payment session and obtain the     *paymentSessionData*     required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list. It is recommended that you create a payment session after the buyer clicks the payment button. Depending on the method you selected for rendering the payment method list at the checkout page, pass the corresponding parameters when calling the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API.

<!-- TabGroup -->

**Tab: Payment Element-rendered payment method list**

When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can   [specify payment methods](#L9xOX)   to display only the options you need.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |
| *paymentRedirectUrl* | Yes | ​   The merchant page URL that the buyer is redirected to after the payment is completed. |
| *paymentNotifyUrl* | No | ​   The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |
| *settlementStrategy* | Yes | The settlement strategy for the payment request. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |
| *order.orderDescription* | Yes | Summary description of the order. |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)      and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  . |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)   scenarios. |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

    // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
    } catch (AlipayApiException e) {
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
    }
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}
```

 If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "APP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "IOS"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

**Tab: Merchant-rendered payment method list**

When rendering the payment method list by yourself, you must pass the parameters for specifying payment methods listed in the table below. If Payment Element needs to collect payment details, pass the card payment parameters listed in the table below.

   | **Type** | **Parameter name** | **Required** | **Description** |
| --- | --- | --- | --- |
| Basic parameters | *productCode* | Yes | For Payment Element, the value is fixed as      `CASHIER_PAYMENT`  . |
| *productScene* | Yes | For Payment Element, the value is fixed as      `ELEMENT_PAYMENT`  . |  |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |  |
| *paymentAmount* | Yes | The payment amount that the merchant requests to receive in the order currency. |  |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |  |
| *paymentNotifyUrl* | No | The payment result notification URL, which can be passed in through the API or set as a fixed value through Antom Dashboard. If both are set, the value in the API takes precedence. |  |
| *settlementStrategy.settlementCurrency* | Yes | The settlement currency of the payment. If you have signed multiple settlement currencies, you need to specify it in the API. |  |
| *order.referenceOrderId* | Yes | The unique ID to identify the order on the merchant side. |  |
| *order.orderAmount* | Yes | The order amount on the merchant side for the services or products provided to the buyer. This parameter is used to display the buyer’s consumption record or payment result page. It includes the following parameters: - *currency*    : The transaction currency that is specified in the contract. A 3-letter currency code that follows the      [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)      standard. - *value*    : The amount to charge as a positive integer in the smallest currency unit.   > **[INFO]** **Note**    : If goods information is specified, the value of     *order.orderAmount.value*     must exactly match the total amount calculated from the goods details. Otherwise, the API will return a parameter validation error. Calculation logic: Σ(    *goods[i].goodsUnitAmount.value*     ×     *goods[i].goodsQuantity*    ) =     *order.orderAmount.value* |  |
| *order.orderDescription* | Yes | Summary description of the order. |  |
| *env.terminalType* | No | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application.   > **[INFO]** **Note**    : This parameter is required for  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) . |  |
| *env.osType* | No | The operating system type from which the buyer initiated the transaction. Valid values: - `IOS`  : Apple's iOS. - `ANDROID`  : Google's Android.   > **[INFO]** **Note**    : Specify this parameter when     *env.terminalType*     is   `WAP`   or   `APP`  . |  |
| *env.clientIp* | No | The IP address of the client device. > **[INFO]** **Note**    : This parameter is required for card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  scenarios. |  |
| Card payment parameters (Refer to   [Card payment features](#abqU1)  ) | *paymentFactor.captureMode* | No | Indicates the method for capturing funds after the user authorizes the payment. Valid values are: - `AUTOMATIC`  : indicates that Antom automatically captures the funds after the authorization. The same applies when the value is empty or you do not pass in this parameter. - `MANUAL`  : indicates that you manually capture the funds by calling the   [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)   API. |
| *order.buyer* | Yes | Buyer information. At least one of the following must be provided: - *order.buyer.referenceBuyerId* - *order.buyer.buyerPhoneNo* - *order.buyer.buyerEmail* |  |
| *availablePaymentMethod.paymentMethodMetaData.is3DSAuthentication* | No | Determine whether to set the transaction authentication type to 3DS based on risk and dispute history. Valid values are: - `true`  : indicates that the transaction authentication type is 3DS authentication. - `false`  : indicates that the transaction authentication type is Non-3DS authentication. Default if empty or not provided. |  |
| *availablePaymentMethod.paymentMethodMetaData.tokenizeMode* | No | The tokenize mode. Indicates whether card information needs to be stored. When you opt to   [store card details](https://docs.antom.com/ac/cashierpay/tokenization.md)  , the actual information is replaced with a unique and secure token that can be used for future payments. Valid values are: - `ENABLED`  : indicates that you obtain card binding authorization and want to store card information for future payments. - `DISABLED`  : indicates that you don’t need to store card information. The same applies when the value is empty or you do not specify this parameter. - `ASKFORCONSENT`  : indicates that you present a button on the page, allowing the buyer to choose whether or not they want to store the card information. |  |
| *availablePaymentMethod.paymentMethodMetaData.isCardOnFile* | No | Indicates whether the card used in this transaction has been   [previously processed and stored](https://docs.antom.com/ac/cashierpay/cof.md)   by the merchant. Valid values are: - `true`  : The card used in the transaction has been previously processed and stored by the merchant. Set to   `true`   for stored card payments. - `false`  : Default. The card is new and has not been used previously on the merchant side. |  |
| *savedPaymentMethods.paymentMethodId* | No | Used for stored card payments.    The value of this parameter is that of     *cardToken*     obtained from the new card payment. |  |
| Parameters for specifying payment methods (Refer to   [Specify payment methods](#L9xOX)  ) | *availablePaymentMethod.paymentMethodTypeList.paymentMethodType* | No | Used to specify payment methods. You can specify one or multiple payment methods. Refer to   [Enumeration values of payment methods](https://docs.antom.com/ac/pm/enumeration_values.md)   for valid values. |
| *availablePaymentMethod.paymentMethodTypeList.paymentMethodOrder* | No | Set the priority order of payment methods. |  |
| *availablePaymentMethod.paymentMethodTypeList.expressCheckout* | No | Specifies whether to enable the express checkout option for a payment method. Currently, only   `ALIPAY_CN`  ,   `APPLEPAY`   and   `GOOGLEPAY`  can be set as express checkout methods. Valid values are: - `true`  : Enables express checkout for this payment method. - `false`  : Disables express checkout for this payment method.   > **[INFO]** **Note**    : This parameter is currently supported only on Android and iOS. |  |

 The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   **.**

 The following sample code shows how to call the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API:

 ```java
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);

     // replace with your environment info
    Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
    alipayPaymentSessionRequest.setEnv(env);

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

    // convert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();

    // set amount
    Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // set settlement strategy
    // replace with your existing settlement currency
    SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
    alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();
    // set order info
    Order order = Order.builder().referenceOrderId(orderId).
    orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");

    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    // replace with your specified payment method
    AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
    .paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
                                   .paymentMethodType("ALIPAY_CN")
                                   .build()))
    .build();
    alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
        System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
    } catch (AlipayApiException e) {
        return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
    }
    return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}
```

 If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:

   ```json
{
  "env": {
    "terminalType": "APP",
    "clientIp": "***.***.***.***", // The buyer's IP adress
    "osType": "IOS"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "HKD",
      "value": "300"
    },
    "orderDescription": "AMSDM_GIFT",
    "referenceOrderId": "PAYMENT_2025*********138_AUTO"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "300"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN" // Specify payment method
      }
    ]
  },
  "paymentNotifyUrl": "https://www.*********.com",
  "paymentRedirectUrl": "https://www.*********u.com",
  "paymentRequestId": "PAYMENT_2025*********201_AUTO",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "ELEMENT_PAYMENT"
}
```

<!-- /TabGroup -->
   The following code shows a sample of the response, which contains the following parameters:

 - *result.resultStatus*    :    The result of the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API call.
- *paymentSessionData*    : The payment session data to be returned to the client.
- *paymentSessionExpiryTime*    : The expiration time of the payment session.

   ```json
 {
  "paymentSessionData": "gpZy************fQ==",
  "paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
  "paymentSessionId": "paymentSessionId****",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The table below shows the possible values of     *result.resultStatus*     in the response. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The payment session was successfully created, and     *paymentSessionData*     is returned. | Proceed to the next steps. |
| `U` | Unknown error. | Please use a new          *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | Failed to create the payment session. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

 > **[INFO]** **Note**    : If no response is received, it may indicate a network timeout. Please use a new     *paymentRequestId*     and call the API again. If the issue persists, contact Antom Technical Support.

 > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>  ​
>
>  **Q: How to set the address to receive payment notification?**
>
>  A: Specify     *paymentNotifyUrl*     in the      [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)      API to receive the asynchronous notification about the payment result (  [**notifyPayment**](https://docs.antom.com/docs/ac/ams/paymentrn_online.md)  ), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
>
>  ​
>
>  **Q: Does the returned**       ***paymentSessionData***       **require processing before passing it to the client?**
>
>  A: Do not process or modify     *paymentSessionData*     in any way, as this may cause the Payment Element invocation to fail.

## Step 3: Invoke Payment Element   **[Client-side]** {#FW24fpW}

 Use     *paymentSessionData*     to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.

 1. After obtaining     *paymentSessionData*     from the server, use the   `[AMSPaymentElement](https://docs.antom.com/ac/sdks/flutter_AMSPaymentElement.md)`   method to create Payment Element instance and initialize.

   1. Implement the   `[init()](https://docs.antom.com/ac/sdks/flutter_init.md)`   method for initialization, and pass the relevant configuration items in the     *configurations*     object:

 ```dart
final element = AMSPaymentElement();

element.init(
  {
    "locale": "en_US",
    "showLoading": "true",
    "sandbox": "true",
    "notRedirectAfterComplete": "false",
    "appearance":
    "{"theme":"default","layout":{"type":"accordion"},"variables":{}}",
  },
  (result) {
    if (result.getStatus() == AMSStatus.SUCCESS) {
      // Initialization succeeded, continue calling createComponent()
      print('Initialization succeeded');
    } else {
      // Initialization failed, check result.getError()
      final error = result.getError();
      print('Initialization failed: ${error?.getCode()} - ${error?.getMessage()}');
    }
  },
);
```

 > **[INFO]** **Note**    :    Different configurations of   ["notRedirectAfterComplete"](https://docs.antom.com/ac/sdks/flutter_init.md#pzkkr)   in the   `[init()](https://docs.antom.com/ac/sdks/flutter_init.md)`   method will affect the merchant page's redirection behavior. For details, please refer to   [Redirect to the merchant page](https://docs.antom.com/ac/sdks/flutter_init.md#gxPhN)  .

   2. Implement the   `[onResult](https://docs.antom.com/ac/sdks/flutter_init.md#wQBq3)`   callback function in the   `[init()](https://docs.antom.com/ac/sdks/flutter_init.md)`      method    to monitor exception events during the payment component initialization process. Please refer to the error     *code*     and     *message*     in the callback parameters for handling.
  3. (Optional)    Implement the      `[onSubmitPayCallback()](https://docs.antom.com/ac/sdks/flutter_setOnSubmitPayListener.md#e76Rw)`      callback function in the   `[setOnSubmitPayListener()](https://docs.antom.com/ac/sdks/flutter_setOnSubmitPayListener.md)`      method to monitor events during the payment process. Please refer to the error     *code*     and     *message*     in the callback parameters for handling.

 > **[INFO]** **Note**    :    It is strongly recommended that you use the   `[setOnSubmitPayListener()](https://docs.antom.com/ac/sdks/flutter_setOnSubmitPayListener.md)`   method to monitor payment events in order to enhance user experience.

   4. Implement the   `[createComponent()](https://docs.antom.com/ac/sdks/flutter_createComponent.md)`   method    to create and display the payment component UI, and implement the   `[onResult](https://docs.antom.com/ac/sdks/flutter_createComponent.md#HgPUP)`   callback function to monitor exception events during the payment component creation process. Please refer to the error     *code*     and     *message*     in the callback parameters for handling.

 The following shows a sample code for creating the SDK instance using   `[AMSPaymentElement](https://docs.antom.com/ac/sdks/flutter_AMSPaymentElement.md)`  :

 ```dart
AMSPaymentElement.preload();

// Create AMSPaymentElement instance
AMSPaymentElement amsPaymentElement = AMSPaymentElement();

// Set configuration items, parameter settings can be referenced below
Map<String, dynamic> amsPaymentElementConfiguration = {
  "locale": "en_US",
  "showLoading": "true",
  "sandbox": "true",
  "notRedirectAfterComplete": "false",
  "appearance":
  "{"theme":"default","layout":{"type":"accordion"},"variables":{}}",
};

// Initialize and listen to initialization results
amsPaymentElement?.init(config, (result) {
  if (result.getError() != null && result.getError()?.getCode() != null) {
    print(
      "code: ${result.getError()?.getCode()}, message: ${result.getError()?.getMessage()}",
    );
  }
});

// Optional, but strongly recommended to set payment status listener, handle according to error codes and messages, for specific handling recommendations please refer to the event code list
amsPaymentElement?.setOnSubmitPayListener((result) {
  AMSStatus? status = result.getStatus();
  if (status != AMSStatus.SUCCESS) {
    AMSResultError? error = result.getError();
    String code = error?.getCode() ?? "";
    String message = error?.getMessage() ?? "";
    print("code: $code, message: $message");
  }
});

// paymentSessionData obtained when creating payment session
String paymentSessionData = "exxxxe";

// Use the createComponent() method in the instance object to call Payment Element, and set call result listener, if error code is not empty, refer to the event code list for handling
amsPaymentElement.createComponent(sessionData, (result) {
  if (result.getError() != null && result.getError()?.getCode() != null) {
    print(
      "code: ${result.getError()?.getCode()}, message: ${result.getError()?.getMessage()}",
    );
  }
});
```

### Unmount Payment Element {#oztYd}

 Call the   `[destory()](https://docs.antom.com/ac/sdks/flutter_destroy.md)`   method to release SDK component resources:

 ```dart
// release SDK component resources
amsPaymentElement.destroy();
```

## Step 4: Obtain the payment result   **[Server-side]** {#4xqX3}

 After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:

 - Receive asynchronous notifications from Antom
- Inquire about the payment result

<!-- TabGroup -->

**Tab: Receive asynchronous notifications**

**1\. Configure the webhook URL to receive asynchronous notifications**

 When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):

 - If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through     *paymentNotifyUrl*     in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API.
- If all your orders share a unified notification URL, you can set the webhook URL on   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   through     **Developer > Notification URL**    . For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

 The following code shows a sample of the asynchronous notification request:

<!-- TabGroup -->

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentMethodType": "CARD",
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cardToken":"exxxxe", // store cardToken for future card payments
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Authorization    was successful. | You may proceed to initiate a capture. |
| `F` | Authorization    failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

**Tab: APM payments**

```json
{
    "actualPaymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "HKD",
        "value": "100"
    },
    "paymentCreateTime": "2025-02-04T22:11:19-08:00",
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "ALIPAY_HK",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultInfo": {

    },
    "paymentTime": "2025-02-04T22:14:25-08:00",
    "pspCustomerInfo": {
        "pspCustomerId": "216022003753XXXX",
        "pspName": "ALIPAY_HK"
    },
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

   The following table shows the possible values of     *result.resultStatus*     in the notification request of payment result. Please handle the result according to the guidance provided:

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Payment was successful. | **​**    You may proceed to ship the goods. |
| `F` | Payment failed. | Please use a new     *paymentRequestId*        and initiate the payment again. |

<!-- /TabGroup -->
 **2\. Verify the asynchronous notification**

 When you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/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 Antom:

 ```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);
    }

}
```

   Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.

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

   > **[INFO]** **Common questions**
>
>  **Q: When will the notification be sent?**
>
>  A: It depends on whether the payment is completed:
>
>  - If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
> - If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
>
>  
>  **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 Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)      format.
>
>  The notification can be resent 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: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>  ​
>
>  **Q: What key parameters do I need to use in the notification?**  
>    A: Please note the following key parameters:
>
>  - *result*    : For APM payments, it represents the final payment result. For  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  ,   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) , and card payments, it only represents the authorization result, and further capture is required.
> - *paymentRequestId*    : The payment request ID used for inquiries, cancellations, and reconciliation.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
> - *paymentAmount*    : The payment amount.

**Tab: Inquire about the result**

You can also inquire about the payment result by calling the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API using     *paymentRequestId*     from the payment request,    regardless of whether it is an APM payment, card payment,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , or   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) .

 The following sample code shows how to call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/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 sample code shows a request message:

   ```json
{
  "paymentRequestId": "paymentRequestId01"
}
```

   The following sample code shows a response message:

<!-- TabGroup -->

**Tab: APM payments**

```json
{
  "actualPaymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "TRUEMONEY",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentMethodType": "TRUEMONEY",
  "paymentTime": "2025-02-17T08:06:43-08:00",
  "pspCustomerInfo": {
    "pspName": "TRUEMONEY"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

**Tab: Card payments, Apple Pay, Google Pay**

```json
{
    "actualPaymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "authExpiryTime": "2024-12-17T21:56:56-08:00",
    "cardInfo": {
        "cardBrand": "VISA",
        "funding": "CREDIT",
        "issuingCountry": "US"
    },
    "paymentAmount": {
        "currency": "USD",
        "value": "5000"
    },
    "paymentId": "20240101123456789XXXX",
    "paymentMethodType": "CARD",
    "paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
    "paymentRequestId": "paymentRequestId01",
    "paymentResultCode": "SUCCESS",
    "paymentResultInfo": {
        "avsResultRaw": "M",
        "cardBrand": "VISA",
        "cardNo": "************9954",
        "cvvResultRaw": "U",
        "funding": "CREDIT",
        "issuingCountry": "US",
        "networkTransactionId": "123qwe456rew",
        "paymentMethodRegion": "GLOBAL",
        "threeDSResult": {
            "cavv": "",
            "eci": ""
        }
    },
    "paymentResultMessage": "success.",
    "paymentStatus": "SUCCESS",
    "paymentTime": "2024-12-10T21:56:57-08:00",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

<!-- /TabGroup -->
   Please handle the result based on the value of the     *paymentStatus*     parameter in the response. For specific return values, refer to the   [API documentation](https://docs.antom.com/ac/ams/paymentri_online.md#Responseparameters-paymentStatus)  .

 > **[INFO]** **Common questions**
>
>  **Q: What key parameters should I pay attention to when using the**       [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)       **API to check the payment or authorization status?**
>
>  A: Please note the following key parameters:
>
>  - *result*    :    Only indicates the result of the API call. For APM payments, the final payment result should be determined based on     *paymentStatus*     (  `SUCCESS`  /  `FAIL`  /  `PROCESSING`  ). For card payments,  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  , and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) ,     *paymentStatus*     only represents the authorization result, and the decision to ship goods should rely on the capture result.
> - *paymentAmount*    : Used to verify the payment amount.
> - *paymentId*    : The payment order ID generated by Antom, used for refunds and reconciliation.
>
>  ​
>
>  **Q: How often should I call the inquiryPayment API?**
>
>  A: Call the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.

<!-- /TabGroup -->

## Step 5: Capture   **[Server-side]** **[For card payments or Google Pay only]** {#4u0V5}

 Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to   [Capture](https://docs.antom.com/ac/cashierpay/capture.md)  .

<!-- /ToggleTab -->

# After payments {#BJbEu}

 After completing the payment, you can perform the following actions:

## Cancellation   **[Server-side]** {#Otb6j}

 For successful payments, if the buyer requests cancellation or a refund on the same day, you can use Antom’s cancellation capability to cancel the order or release funds. Orders not yet completed can also be cancelled directly. For details, refer to   [Cancel](https://docs.antom.com/ac/cashierpay/cancel.md)  .

## Refund   **[Server-side]** {#kg4oU}

 Different payment methods have varying refund capabilities. To learn about Antom refund rules and how to initiate a refund for a successful transaction, refer to   [Refund](https://docs.antom.com/ac/cashierpay/refund.md)  .

## Dispute   **[Server-side]** {#AoEw6}

 Antom provides dispute resolution services for contested transactions. For more information, refer to [Dispute Guidance](https://docs.antom.com/ac/dispute/overview.md) and [Dispute resolution](https://docs.antom.com/ac/dispute/dispute_resolution.md).

# Payment method features {#RvQap}

 This section explains differences in supported features across payment methods.

## Default timeout {#v6YBS}

 The default order closing time varies for different payment methods. For specific information, refer to   [Payment method default timeout](https://docs.antom.com/ac/pm/default_timeout.md)  .

 > **[INFO]** **Note**    : Since Payment Element orders have a default validity period of 1 hour, the actual timeout period is extended by 1 hour beyond the payment method’s default timeout. For example, if a payment method’s default timeout is 14 minutes, the actual timeout period for a Payment Element order will be 1 hour and 14 minutes.

## Integration key points {#l5xra}

 Refer to   [Integration key considerations](https://docs.antom.com/ac/pm/apm_integration.md?locale=en-us#key_considerations)   to learn about the integration key points and recommended solutions for different payment methods.

## Card payment features {#abqU1}

 Payment Element supports the following card payment features.    Click to get    detailed information and usage instructions:

 - [3D Secure 2](https://docs.antom.com/ac/pm/3ds.md)
- [Antom 3DS-Retry](https://docs.antom.com/ac/pm/3ds_retry.md)
- [MIT (Merchant-Initiated Transaction)](https://docs.antom.com/ac/pm/mit.md)
- [Antom Tokenization](https://docs.antom.com/ac/pm/tokenization.md)
- [COF (Card-on-File)](https://docs.antom.com/ac/pm/cof.md)

# Additional content {#GBkuL}

 Antom also offers the following customization options:

 - [**Appearance customization**](https://docs.antom.com/ac/cashierpay/appearance.md)  : Antom provides extensive styling options, including theme, layout, and CSS customization.
- [**Google Pay**](https://docs.antom.com/ac/cashierpay/gpay_element.md)  : Buyers can pay using credit or debit cards stored in their Google account. With Payment Element, no additional  [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  SDK integration is needed—it loads  [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md)  automatically.
- [**Apple Pay**](https://docs.antom.com/ac/cashierpay/apay_element.md)  : Buyers can pay using credit or debit cards stored in their Apple account. With Payment Element, no additional  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  SDK integration is needed—it loads  [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)  automatically.

## Specify a payment method {#L9xOX}

 You can pass the parameters in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API to specify the display of payment methods on Payment Element, the order of the payment method list, and the display of quick payments. This feature offers you the following benefits:

 - Filter local payment methods based on your business region.
- Sort your preferred payment methods.
- Display the mainstream quick payments, such as  [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md)  ,   [Apple Pay](https://docs.antom.com/ac/antomop/applepay.md)   and   [Google Pay](https://docs.antom.com/ac/antomop/googlepay.md) .

 For specific steps, refer to   [Specify a payment method](https://docs.antom.com/ac/pm/specify_pm.md)  .

## Payment methods requiring embedding {#Ygtd4X}

 The following payment methods require you to embed the payment details collection component:

 | **Payment method category** | **Payment method** | **Enum value** |
| --- | --- | --- |
| Card | [Mastercard](https://docs.antom.com/ac/antomop/mastercard_mdx.md) | `CARD` |
| [Visa](https://docs.antom.com/ac/antomop/visa_mdx.md) | `CARD` |  |
| [American Express](https://docs.antom.com/ac/antomop/amex_mdx.md) | `CARD` |  |
| [Brazilian cards](https://docs.antom.com/ac/antomop/brazilian_mdx.md) | `CARD` |  |
| [Chilean cards](https://docs.antom.com/ac/antomop/chilean_mdx.md) | `CARD` |  |
| [Diners](https://docs.antom.com/ac/antomop/diners_mdx.md) | `CARD` |  |
| [Discover](https://docs.antom.com/ac/antomop/discover_mdx.md) | `CARD` |  |
| [South Korean Cards (Local cards)](https://docs.antom.com/ac/antomop/south_korean_mdx.md) | `CARD` |  |
| [Mexican cards](https://docs.antom.com/ac/antomop/mexican_mdx.md) | `CARD` |  |
| [Peruvian cards](https://docs.antom.com/ac/antomop/peruvian_mdx.md) | `CARD` |  |
| [UnionPay](https://docs.antom.com/ac/antomop/unionpay_mdx.md) | `CARD` |  |
| Digital wallet | [OVO](https://docs.antom.com/ac/antomop/ovo.md) | `OVO` |
| [Mercado Pago](https://docs.antom.com/ac/antomop/mp_mdx.md)   (Mexico) | `MERCADOPAGO_MX` |  |
| [Mercado Pago](https://docs.antom.com/ac/antomop/mp_mdx.md)   (Brazil) | `MERCADOPAGO_BR` |  |
| [Mercado Pago](https://docs.antom.com/ac/antomop/mp_mdx.md)   (Peru) | `MERCADOPAGO_PE` |  |
| [Mercado Pago](https://docs.antom.com/ac/antomop/mp_mdx.md)   (Chile) | `MERCADOPAGO_CL` |  |
| Cash payment | [Konbini (7-Eleven)](https://docs.antom.com/ac/antomop/Konbini_711_mdx.md) | `SEVENELEVEN` |
| [Konbini](https://docs.antom.com/ac/antomop/konbini_mdx.md) | `KONBINI` |  |
| Online banking | [BANCOMAT Pay](https://docs.antom.com/ac/antomop/bancomatpay.md) | `BANCOMATPAY` |
| [BLIK](https://docs.antom.com/ac/antomop/blik.md) | `BLIK` |  |
| [Pay-easy](https://docs.antom.com/ac/antomop/payeasy.md) | `ONLINEBANKING_PAYEASY` |  |
| [FPX](https://docs.antom.com/ac/antomop/fpx.md) | `ONLINEBANKING_FPX` |  |

## Payment retry mechanism {#Aohu2}

 Antom provides a payment retry mechanism. For payment sessions created via the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API, buyers can make multiple payment attempts and freely switch payment methods within the validity period of the payment session, without requiring the merchant server to re-invoke the API. For more information, refer to   [Payment retry mechanism](https://docs.antom.com/ac/cashierpay/payment_retry.md)  .