# Card payments

> Learn how to accept card payments through SDK integration.

 export const AlertDeprecate = () => (  <svg aria-hidden="true" focusable="false" width="32" height="32" style={{
  marginRight: 16,
  marginTop: 2,
  flexShrink: 0
}} fill="#d97706" // Darker yellow icon
viewBox="0 0 24 24">
      <circle cx="12" cy="12" r="12" fill="#ffe066" /> {/* Lighter yellow circle */}
      <path d="M12 8v4" stroke="#d97706" strokeWidth="2" strokeLinecap="round" />
      <circle cx="12" cy="16" r="1" fill="#d97706" />
    </svg>   Deprecation Notice:       ); <AlertDeprecate>
  The content of this guide has been deprecated.<br />
  We recommend you adopt the <Link href="https://docs.antom.com/ac/cashierpay/element?platform=web-wap">Payment Element integration</Link> for improved experience.
</AlertDeprecate> Antom SDK is a pre-built UI component designed to collect card information and manage 3D authentication processes for you. Integration of this component does not require you have a PCI qualification, making it ideal for those who prefer to entrust Antom to collect card information.

  

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

**Tab: Web/WAP**

# User experience {#BkD7y1}

 The following figures show the user journey of paying on a shopping website or mobile web app:

<!-- TabGroup -->

**Tab: Web**

![Web user experience showing card payment flow via Antom SDK on a shopping website](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/187d55cd-53da-4732-a667-1701ab11ae42.png)

**Tab: WAP**

![WAP user experience showing card payment flow via Antom SDK on a mobile web app](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/e7b3209b-dfcf-4c5a-b45f-eeb689cb3e72.png)

<!-- /TabGroup -->

# Payment flow {#d2DKE1}

 The following process shows how to integrate One-time Payments via Antom SDKs:

 ![Card payment flow showing the interaction across buyer, merchant client, Antom SDK, merchant server, and Antom server](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/4f9ca083-fb5b-4ed2-9b54-09b0bebd94c7.png)

 1. **The user lands on the checkout page.**
2. **Create a payment session request.**  
   After the buyer selects a payment method and submits the order, 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 the client SDK.**  
   On the client side, invoke the SDK through the payment session. The SDK will handle information collection, redirection, app invocation, QR code display, verification, and other processes based on the payment method's characteristics. Then the SDK will callback the payment result via   `onEventCallback`  .
4. **Confirm the payment result.**  
   Obtain the payment result by using 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 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.
5. **Get the capture result.**  
   For card payments, you need to obtain the capture result by using 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 to set the address for receiving asynchronous notifications. When the payment request is successful or expires, Antom will use  [**notifyCapture**](https://docs.antom.com/ac/ams/notify_capture.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 request status.

# Integration preparations {#uEXVe}

 Before you start integrating, read the   [Integration guide](https://docs.antom.com/integration_guide_en.md)   and   [API overview](https://docs.antom.com/ac/ams/api_fund.md)   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 of   [Integrate the SDK package for Web/WAP](https://docs.antom.com/ac/sdks/web.md)  .

# Integration steps {#XkD7wT1}

 Start your integration by taking the following steps:

 1. Create a payment session
2. Create and invoke the SDK
3. Obtain payment result
4. Obtain capture result

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

 When a buyer selects a payment method provided by Antom, you need to collect key information such as payment request ID, order amount, payment method, order description, payment redirect URL, and payment result notification URL, call the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  API to create a payment session, and return the payment session to the client.

 Creating a payment session includes the following parameters:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | Represents the payment product that is being used, which is stipulated in the contract. For One-time Payments, the value is fixed as   `CASHIER_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that you request to receive in the order currency. |
| *paymentMethod* | Yes | The payment method that is used to collect the payment by the merchant or acquirer. |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |
| *order* | Yes | The order information, such as buyer, merchant, goods, amount, shipping information, and purchase environment. |
| *paymentNotifyUrl* | No | Payment result notification address, which can be passed in through the API or set as a fixed value through Antom Dashboard. |
| *settlementStrategy* | No | The settlement strategy for the payment request. |
| *paymentFactor.isAuthorization* | No | Indicates whether the payment scenario requires authorization. Set this parameter to   `true`   when the value of     *paymentMethodType*     is   `CARD`  , which indicates that the payment scenario requires authorization. > **[INFO]** **Note**    : When this parameter is set to   `true`  , the payment funds are guaranteed and held on the payment method side. You can use the        [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)        API to deduct the payment funds. |

 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
public static void createCardPaymentSession() {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

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

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

    // set paymentMethod
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("CARD").build();
    alipayPaymentSessionRequest.setPaymentMethod(paymentMethod);

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

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

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

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

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

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

    AlipayPaymentSessionResponse alipayPaymentSessionResponse = null;
    try {
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

```

   The following code shows a sample of the request message:

   ```json
{
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "SGD",
      "value": "4200"
    },
    "orderDescription": "antom testing order",
    "referenceOrderId": "referenceOrderId01"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentFactor": {
    "isAuthorization": true
  },
  "paymentMethod": {
    "paymentMethodType": "CARD"
  },
  "paymentNotifyUrl": "https://www.yourNotifyUrl.com",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "productCode": "CASHIER_PAYMENT"
}

```

   The following code shows a sample of the response, which contains the following parameters:

 - *paymentSessionData*    : the payment session data to be returned to the frontend.
- *paymentSessionExpiryTime*    : the expiration time of the payment session.

   ```json
{
  "paymentSessionData": "UNvjVWnWPXJA4BgW+vfjsQj7PbOraafHY19X+6EqMz6Kvvmsdk+akdLvoShW5avHX8e8J15P8uNVEf/PcCMyXg==&&SG&&111",
  "paymentSessionExpiryTime": "2024-01-01T00:00:00+08:00",
  "paymentSessionId": "UNvjVWnWPXJA4BgW+vfjsQj7PbOraafHY19X+6EqMz6Ikyj9FPVUOpv+DjiIZqMe",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

```

   > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of a certain payment method, do not use Chinese characters for fields in the request.
>
>   **Q: How to set the URL to receive the 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/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.

## Step 2: Create and invoke the SDK   **[Client-side]** {#oDqHQJ1}

 The Antom SDK is a component used for handling payment processes. You initiate the SDK by creating a payment session to collect information and switch between apps based on the payment method specified in the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  API.

### 1\. (Optional) Preload the SDK {#Yhdg56}

 Before creating a payment session, it is highly recommended that you 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:

 ```javascript
// import { AMSCashierPayment } from '@alipay/ams-checkout';

AMSCashierPayment.preload();
```

### 2\. Instantiate the SDK {#KQO5Xq1}

 Create the SDK instance by using the   `AMSCashierPayment`  . Configuration objects includes the following parameters:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *environment* | Yes | It is used to pass in environmental information. Valid values are: - `sandbox`  : Sandbox environment - `prod`  : Production environment |
| *locale* | No | It is used to pass in language information. Valid values are listed as follows. You can choose the value to pass based on the region of the payment method. If other values are passed, English is used by default: - `en_US`  : English - `es_ES`  : Spanish - `fr_FR`  : French - `nl_NL`  : Dutch - `it_IT`  : Italian - `de_DE`  : German - `zh_CN`  : Simplified Chinese - `zh_HK`  : Traditional Chinese - `pt_PT`  : Portuguese (Portugal) - `ro`  : Romanian - `pl_PL`  : Polish |
| *analytics* | No | It is used to configure and analyze data. It contains a value below: - *enabled*    : Optional Boolean. It defaults to   `true`  , which indicates that you allow the SDK to upload and analyze operational data to deliver a better service. If you do not allow the data to be uploaded and analyzed, specify it as   `false`  . |
| *onLog* | No | It is a callback method that is used to generate the error information about logs and API exceptions during the execution of the SDK. |
| *onEventCallback* | No | A callback function returns a specific event code when a payment event happens during SDK runtime, like payment result or a form submission error. For further information, refer to   [event codes](https://docs.antom.com/ac/sdks/ref.md)  . |

 The following sample code shows how to instantiate the SDK:

   ```javascript
// Import { AMSCashierPayment } from '@alipay/ams-checkout'

const checkoutApp = new window.AMSCashierPayment({
  environment: "sandbox",
  locale: "en_US",
  onLog: ({code, message}) => {},
  onEventCallback: ({code, message}) => {},
});

// Request the server to get paymentSessionData
```

   > **[INFO]** **Note**    : Each instance can handle only one payment session. It is recommended to create the instance before calling   `createComponent`   each time.

### 3\. Invoke the SDK {#iVDpGq1}

 After the buyer selects a payment method on the page, you need to create the SDK and initiate it with a payment session.

 Use the   `createComponent`   or   `mountComponent`   function in the instance object to create a payment component:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *sessionData* | Yes | Create a configuration object by using the     *sessionData*     parameter: Pass the complete data in the     *paymentSessionData*     parameter obtained in the response through the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API to the     *sessionData*     parameter. |
| *appearance* | No | Customized appearance theme configuration, and it contains the following child parameters: - *showSubmitButton*    : Optional. Boolean type. The default value is   `false`  , which indicates that the submit button provided by the SDK component is not enabled.   `true`   indicates that the SDK component renders the submit button. If set to   `false`  , you need to call the   `submit()`   function of the instance object to initiate the payment flow. This parameter is only applicable to the embedded experience. |
| *notRedirectAfterComplete* | No | Boolean type. The default value is   `false`  , which means it will redirect back to your page after the payment is completed. The same applies when the value is empty.    If this value is set to   `true`  , it means that there will be no redirection after the payment is completed. You need to use the customer event code to control the card binding to complete the subsequent process. Note that the payment result event code returned by the client is only used as a reference for the redirect operation of the client page. For transaction status updates, refer to the results returned by the server's   [**notifyPayment**](https://docs.antom.com/ac/apo/paymentrn_online.md)        or   [**inquiryPayment**](https://docs.antom.com/ac/apo_zh-cn/paymentri_online.md)        API. |
| *merchantAppointParam* | No | Object type. It is used to set up custom functions, including the following parameters: - *storedCard*    : Optional. Object type. It is used to set up custom functions with a stored card and contains the following parameters:     - *needCVV*    : Optional. Boolean type. The default value is   `false`  . It indicates that the buyer does not need to do CVV verification during the payment process, and the same applies when the value is null. If this value is set to   `true`  , it indicates that CVV verification is required during the payment process. |

#### Popup experience vs. Embedded experience {#qtdbk}

 There are different ways in which you can make the SDK display on a page through a pop-up window or embedded on a page.

<!-- TabGroup -->

**Tab: Popup experience**

![Antom SDK card payment popup experience showing the payment element displayed as a modal overlay on the merchant page](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/e3bb255d-38ee-4365-9763-87133720156f.png)

   Popup experience offers the advantage of low impact on page style and relatively independent flow.

 After the buyer selects a payment method on the page and clicks submit, you need to inevoke the SDK and pop up the window.

 ```javascript
async function create(sessionData) {
  await checkoutApp.createComponent({
    sessionData: sessionData,
    notRedirectAfterComplete: true,
  });
}
```

**Tab: Embedded experience**

![Antom SDK card payment embedded experience showing the payment element rendered inline within a designated container on the merchant page](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/55e5bef2-a09e-4293-97e4-f47434ecf782.png)

   The embedded experience embeds payment element within the designated view. You need to focus on styling adjustments for the payment list. The embedded content's width adjusts automatically to fit the parent container, while the height dynamically updates with view changes.

 ```javascript
async function create(sessionData) {
  await checkoutApp.mountComponent({
    sessionData: sessionData,
    appearance:{
      showSubmitButton: false, // Configure whether the payment button is rendered by the component.
    },
    notRedirectAfterComplete: true,
  },'#ContainerNodeId');
}
```

##### Embedded submit payment {#UPr55g}

 If you need to pass the collected billing address information for AVS verification, you can configure the following parameters through the   `submit`   function.

 - *billingAddress*    : Required. Object type. Used to identify the billing address information of the payment user. It includes the following parameters:

   - *region*    : Required. String (2). Complies with   [ISO 3166](https://www.iso.org/obp/ui/#search)   standard two-letter country or region code.
  - *address1*    : Optional. String (256). Line 1 of the address, for example, the street address, P.O. box, and company name.
  - *address2*    : Optional. String (256). Line 2 of the address, such as apartment, suite, unit, building, or similar information.
  - *city*    : Optional. String (32). The city, district, suburb, town, or village name.
  - *state*    : Optional. String (8). The state, country, or province name.
  - *zipCode*    : Optional. String (32). Postal code.

 ```javascript
// The user inputs the billing address information and stores it in the billingAddress object for subsequent submission.
const billingAddress = {
  region: '',
  address1: '',
  address2: '',
  city: '',
  state: '',
  zipCode: ''
}

// Execute when the user completes the form and clicks the submit button.
checkoutApp.submit({billingAddress}).then(({code, message})=>{})
```

<!-- /TabGroup -->

##### Destroy the component {#vpOFdL1}

 Call the   `unmount`   method to free SDK component resources in the following situations:

 - When the buyer switches views to exit the checkout page, free the component resources created in the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  .
- When the buyer initiates multiple payments, free the component resources created in the previous  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  .
- When the buyer completes the payment and sets     *notRedirectAfterComplete*     to   `true`  , free the component resources after obtaining specific payment result codes.

 ```javascript
// Free SDK component resources
checkoutApp.unmount();
```

   > **[INFO]** **Common questions**
>
>  **Q: What can I do when I receive SDK_CREATEPAYMENT_PARAMETER_ERROR?**
>
>  A: When you receive this event code, check if the     *sessionData*     passed in is correct and complete.
>
>  ​
>
>  **Q: What can I do when I receive SDK_PAYMENT_ERROR or a rendering view error occurred?**
>
>  A: Check the network request for any exceptions during API initialization, such as network timeouts. Ensure that the environment for creating payment session request is consistent with the environment used for SDK instantiation. Check whether the parameters in the        [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API are passed correctly. If the API exceptions persist, feel free to contact us for further troubleshooting.
>
>  ​
>
>  **Q: What can I do when I receive**      **SDK_FORM_VERIFICATION_FAILED**     **?**
>
>  A: The reason could be that the buyer did not fill in all the required elements. Upon submission, an error code indicating form verification failure may be returned. It is recommended to guide the buyer on enhancing the form content.

### 4\. Display payment results {#Go6NwO5}

 If you set     *notRedirectAfterComplete*     to   `false`  , the buyer will be redirected to the     *paymentRedirectUrl*     that you provided in        [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)        API after completing the payment. You can obtain the payment result by active query in that URL and show it to the buyer.

 If     *notRedirectAfterComplete*     is   `true`  ,    the payment result will be given through the   `onEventCallback`   function. The payment result here is only for front-end display, and the final order status is subject to the server side.

 You need to customize the processing flow you want for each payment result through the data in the result of   `onEventCallback`  .

 The following are the possible event codes of the payment result returned by   `onEventCallback`  :

   | **Event code** | **Message** | **Solution** |
| --- | --- | --- |
| SDK_PAYMENT_SUCCESSFUL | Payment was successful. | Redirect the buyer to the payment result page, then confirm the payment result with the server. |
| SDK_PAYMENT_PROCESSING | Payment is being processed. | Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment. |
| SDK_PAYMENT_FAIL | Payment failed. | Check the value of          *result.paymentResultCode*     in the   `onEventCallback`   result data for details. Guide the buyer to retry payment based on the obtained information. > **[INFO]** **Note**    : For the meaning of     *result.paymentResultCode*    , refer to   [Description of payment failure or abnormal payment status](https://docs.antom.com/ac/sdks/ref.md?locale=en-us#nuduf)  . |
| SDK_PAYMENT_CANCEL | Payment was canceled. | The SDK can be re-invoked with a     *paymentSessionData*     within the validity period; if it has expired, the     *paymentSessionData*     needs to be re-requested. |
| SDK_PAYMENT_ERROR | The payment status was abnormal. | Confirm the payment result with the server.    If it is confirmed that the payment has failed, guide the buyer to    retry payment   . |

 The following sample code shows how to process the   `onEventCallback`  :

 ```javascript
function onEventCallback({ code, result }) {
  switch (code) {
    case 'SDK_PAYMENT_SUCCESSFUL':
      // Payment was successful. Redirect the buyer to the payment result page, then confirm the payment result with the server.
      break;
    case 'SDK_PAYMENT_PROCESSING':
      console.log('Check the payment result data', result);
      // Payment is being processed. Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment.
      break;
    case 'SDK_PAYMENT_FAIL':
      console.log('Check the payment result data', result);
      // Payment failed. Check the value of result.paymentResultCode in the onEventCallback result data for details. Guide the buyer to retry payment based on the obtained information.
      break;
    case 'SDK_PAYMENT_CANCEL':
      // Payment was canceled. The SDK can be re-invoked with a paymentSessionData within the validity period; if it has expired, the paymentSessionData needs to be re-requested.
      break;
    case 'SDK_PAYMENT_ERROR':
      console.log('Check the payment result data', result);
      // The payment status was abnormal. Confirm the payment result with the server. If it is confirmed that the payment has failed, guide the buyer to retry payment.
      break;
    default:
      break;
  }
}
```

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

 After the buyer completes the payment or the payment times out, Antom sends the corresponding payment results to the you through server interactions, you can obtain the payment result by one of the following methods:

 - Receive the asynchronous notification
- Inquire about the result

### Receive the asynchronous notification {#WDVw7j7}

 When the payment reaches a final status of success or failure, Antom sends an asynchronous notification to the     *paymentNotifyUrl*     specified in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API. When you receive the notification from Antom, you are required to return a response as instructed in   [Return a receipt acknowledgment message](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)  .

 Antom    allows you to specify the URL in the     *paymentNotifyUrl*     parameter within the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API. If the URL for each payment is the same, you can also configure it in the    Antom    Dashboard.

 The following code shows a sample of the notification request:

   ```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "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"
  }
}

```

   How to verify the signature of the notification and make a response to the notification, see  [Sign a request and verify the signature](https://docs.antom.com/ac/ams/digital_signature.md)  .

   > **[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 usually send you an asynchronous notification within 3 to 5 seconds. For some payment methods like cash payment, 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 didn't make a response 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 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 are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to the following key parameters:
>
>  - *result*    : indicates the payment result of the order.
> - *paymentRequestId*    : indicates the payment request number you generated for consult, cancel, and reconciliation.
> - *paymentId*    : indicates the payment order number generated by Antom used for refund and reconciliation.
> - *paymentAmount*    : indicates the payment amount.

### Inquire about the result {#wlAb8q1}

 You can call the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API to initiate a query on the result of an order.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *paymentRequestId* | No | The payment request ID generated by the merchant. |

 The parameter is not a full set of parameters, refer to the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API for full set of parameters and additional requirements for certain payment methods.

   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 code shows a sample of the request message:

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

```

   The following code shows a sample of the response message:

   ```json
{
  "authExpiryTime": "2024-01-08T00:01:00+08:00",
  "cardInfo": {
    "cardBrand": "MASTERCARD",
    "funding": "DEBIT",
    "issuingCountry": "US"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "CARD",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "networkTransIdXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentResultMessage": "success",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

```

   > **[INFO]** **Common questions**
>
>  **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.
>
>  
>  **Q: What are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to these key parameters:
>
>  - *result*    : represents the result of this   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)        API call, the result of the order needs to be judged according to     *paymentStatus*    :
>
>    - `SUCCESS`      and      `FAIL`      represent the final result.
>   - `PROCESSING`      represents the processing.
>
>  - *paymentAmount*    : indicates the payment amount.

## Step 4: Obtain capture result  **[Server-side]** {#g1Ow5F}

 After the merchant completes the capture or the capture times out, Antom sends the corresponding capture results to you through server interactions, you can obtain the capture result by one of the following methods:

 - Receive the asynchronous notification
- Inquire about the result

### Receive the asynchronous notification {#nnwrAd}

 When the capture reaches a final status of success or failure, Antom sends an asynchronous notification to the     *paymentNotifyUrl*     specified in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API. When you receive the notification from Antom, you are required to return a response as instructed in   [Return a receipt acknowledgment message](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)  .

 Antom    allows you to specify the URL in the     *paymentNotifyUrl*     parameter within the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API. If the URL for each payment is the same, you can also configure it in the Antom Dashboard.

 The following code shows a sample of successful capture:

 ```json
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101987654321XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The following code shows a sample of failed capture:

 ```json
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101123456789XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "PROCESS_FAIL",
    "resultMessage": "fail.",
    "resultStatus": "F"
  }
}
```

 How to verify the signature of the notification and make a response to the notification, see  [Sign a request and verify the signature](https://docs.antom.com/ac/ams/digital_signature.md)  .

 > **[INFO]** **Common questions**    ​
>
>  **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 didn't make a response 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 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 are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to the following key parameters:
>
>  - *result*    : represents the capture result of the order.
> - *notifyType*    : the value of        *notifyType*     is      `CAPTURE_RESULT`  .
> - *paymentRequestId*    : the payment request number you generated, used for querying, canceling, and reconciliation.
> - *paymentId*    : the payment order ID generated by Antom used for refund and reconciliation.
> - *acquirerReferenceNo*    : merchants integrating with in-card payment services in Singapore and Hong Kong will receive specific acquirer numbers in the notification.

### Inquire about the result {#NrYhdL}

 You can call the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API to initiate a query on the result of an order.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *paymentRequestId* | No | The payment request ID generated by the merchant. |

 The parameter is not a full set of parameters, refer to the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API for full set of parameters and additional requirements for certain payment methods.

 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 code shows a sample of the request message:

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

#### Value of capture status {#q3e0qA}

 The value of the     *transactions*     in the response of the API is the capture status:

 | **Parameter name** | **Description** |
| --- | --- |
| *transactions.transactionType* | The value is   `CAPTURE`  , meaning the capture status. |
| *transactions.transactionResult* | Capture status. |

 The following code shows a sample of successful capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "S",
        "resultCode": "SUCCESS",
        "resultMessage": "success"
      }
    }
  ]
}
```

 The following code shows a sample of failed capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "F",
        "resultCode": "PROCESS_FAIL",
        "resultMessage": "General business failure. No retry."
      }
    }
  ]
}
```

 The following code shows a sample of processing capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "U",
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process"
      }
    }
  ]
}
```

   > **[INFO]** **Common questions**
>
>  **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.

# Sample codes {#xjYwO01}

 Full sample codes for front-end:

 ```javascript
import { AMSCashierPayment } from '@alipay/ams-checkout'

// (Optional) Preload the SDK. Before creating a payment session, preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment.
AMSCashierPayment.preload();

// Listen for the submit event on your web checkout counter.
document
  .querySelector("button#submit")
  .addEventListener("click", handleSubmit);

async function handleSubmit() {

  // Step 1: Get a payment session from YOUR server.
  const paymentSessionData = await getPaymentSessionData();

  // Step 2: Create and invoke the SDK.
  // Create an AMSCashierPayment instance.
  const checkoutApp = new window.AMSCashierPayment({
    environment: "sandbox",
    locale: "en_US",
    onLog: ({code, message}) => {},
    onEventCallback: onEventCallback,
  });

  // Show the checkout ui by invoking createComponent method.
  await checkoutApp.createComponent({
    sessionData: paymentSessionData,
    // Set no redirection after payment completion, with the merchant controlling subsequent process.
    notRedirectAfterComplete: true,
    merchantAppointParam: {
        storedCard: {
          needCVV: true, // Set as false by default, indicating that CVV verificationn is not required.
        },
    },
  });
}

// Handle payment results
const onEventCallback = function({ code, result }) {
  switch (code) {
    case 'SDK_PAYMENT_SUCCESSFUL':
      // Payment was successful. Redirect the buyer to the payment result page, then confirm the payment result with the server.
      break;
    case 'SDK_PAYMENT_PROCESSING':
      console.log('Check the payment result data', result);
      // Payment is being processed. Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment.
      break;
    case 'SDK_PAYMENT_FAIL':
      console.log('Check the payment result data', result);
      // Payment failed. Check the value of result.paymentResultCode in the onEventCallback result data for details. Guide the buyer to retry payment based on the obtained information.
      break;
    case 'SDK_PAYMENT_CANCEL':
      // Payment was canceled. The SDK can be re-invoked with a paymentSessionData within the validity period; if it has expired, the paymentSessionData needs to be re-requested.
      break;
    case 'SDK_PAYMENT_ERROR':
      console.log('Check the payment result data', result);
      // The payment status was abnormal. Confirm the payment result with the server. If it is confirmed that the payment has failed, guide the buyer to retry payment.
      break;
    case 'SDK_FORM_VERIFICATION_FAILED':
      // Verification failed after form submission. Guide the buyer to confirm the input and retry payment.
      break;
    default:
      break;
  }
}

```

# Event codes {#ZdcfdB}

 Status codes: Returned by   `onEventCallback`   during the component's runtime lifecycle.

   | **Type** | **Code** | **Description** | **Further action** |
| --- | --- | --- | --- |
| Status codes | SDK_FORM_VERIFICATION_FAILED | Verification failed after form submission. | Guide the buyer to confirm the input and retry payment. |

**Tab: iOS**

# User experience {#BkDw7T1}

 The following figure shows the user journey of paying on an app:

 ![iOS user experience showing card payment flow via Antom SDK on a shopping app](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/ddd9b6cf-ffa6-4b66-b719-e2bee24a8f22.png)

# Payment flow {#d2DKE2}

 The following process shows how to integrate One-time Payments via Antom SDKs:

 ![Card payment flow showing the interaction across buyer, merchant client, Antom SDK, merchant server, and Antom server](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/4f9ca083-fb5b-4ed2-9b54-09b0bebd94c7.png)

 1. **The user lands on the checkout page.**
2. **Create a payment session request.**  
   After the buyer selects a payment method and submits the order, 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 the client SDK.**  
   On the client side, invoke the SDK through the payment session. The SDK will handle information collection, redirection, app invocation, QR code display, verification, and other processes based on the payment method's characteristics. Then the SDK will callback the payment result via   `onEventCallback`  .
4. **Confirm the payment result.**  
   Obtain the payment result by using 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 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.
5. **Get the capture result.**  
   For card payments, you need to obtain the capture result by using 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 to set the address for receiving asynchronous notifications. When the payment request is successful or expires, Antom will use  [**notifyCapture**](https://docs.antom.com/ac/ams/notify_capture.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 request status.

# Integration preparations {#g7B00}

 Before you start integrating, read the   [Integration guide](https://docs.antom.com/integration_guide_en.md)   and   [API overview](https://docs.antom.com/ac/ams/api_fund.md)   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 of   [Integrate the SDK package for iOS](https://docs.antom.com/ac/sdks/ios.md)  .

 > **[INFO]** **Note**    : Currently, Flutter and React Native (RN) development frameworks are not supported.

# Integration steps {#XkD7Tw1}

 Start your integration by taking the following steps:

 1. Create a payment session
2. Create and invoke the SDK
3. Obtain payment result
4. Obtain capture result

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

 When a buyer selects a payment method provided by Antom, you need to collect key information such as the payment request ID, order amount, payment method, order description, payment redirect URL, and payment result notification URL, call the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  API to create a payment session, and return the payment session to the client.

 Creating a payment session includes the following parameters:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | Represents the payment product that is being used, which is stipulated in the contract. For One-time Payments, the value is fixed as   `CASHIER_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that you request to receive in the order currency. |
| *paymentMethod* | Yes | The payment method that is used to collect the payment by the merchant or acquirer. |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |
| *order* | Yes | The order information, such as buyer, merchant, goods, amount, shipping information, and purchase environment. |
| *paymentNotifyUrl* | No | Payment result notification address, which can be passed in through the API or set as a fixed value through Antom Dashboard. |
| *settlementStrategy* | No | The settlement strategy for the payment request. |
| *paymentFactor.isAuthorization* | No | Indicates whether the payment scenario requires authorization. Set this parameter to   `true`   when the value of     *paymentMethodType*     is   `CARD`  , which indicates that the payment scenario requires authorization. > **[INFO]** **Note**    : When this parameter is set to   `true`  , the payment funds are guaranteed and held on the payment method side. You can use the        [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)        API to deduct the payment funds. |

 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
public static void createCardPaymentSession() {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

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

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

    // set paymentMethod
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("CARD").build();
    alipayPaymentSessionRequest.setPaymentMethod(paymentMethod);

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

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

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

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

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

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

    AlipayPaymentSessionResponse alipayPaymentSessionResponse = null;
    try {
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

```

   The following code shows a sample of the request message:

   ```json
{
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "SGD",
      "value": "4200"
    },
    "orderDescription": "antom testing order",
    "referenceOrderId": "referenceOrderId01"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentFactor": {
    "isAuthorization": true
  },
  "paymentMethod": {
    "paymentMethodType": "CARD"
  },
  "paymentNotifyUrl": "https://www.yourNotifyUrl.com",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "productCode": "CASHIER_PAYMENT"
}

```

   The following code shows a sample of the response, which contains the following parameters:

 - *paymentSessionData*    : the payment session data to be returned to the frontend.
- *paymentSessionExpiryTime*    : the expiration time of the payment session.

   ```json
{
  "paymentSessionData": "UNvjVWnWPXJA4BgW+vfjsQj7PbOraafHY19X+6EqMz6Kvvmsdk+akdLvoShW5avHX8e8J15P8uNVEf/PcCMyXg==&&SG&&111",
  "paymentSessionExpiryTime": "2024-01-01T00:00:00+08:00",
  "paymentSessionId": "UNvjVWnWPXJA4BgW+vfjsQj7PbOraafHY19X+6EqMz6Ikyj9FPVUOpv+DjiIZqMe",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

```

   > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of a certain payment method, do not use Chinese characters for fields in the request.
>
>  ​
>
>  **Q: How to set the URL to receive the 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/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.

## Step 2: Create and invoke the SDK  **[Client-side]** {#oDwHQJ1}

 The Antom SDK is a component used for handling payment processes. You initiate the SDK by creating a payment session to collect information, switch between apps, and display QR codes based on the payment method specified in the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  API.

 After the buyer selects a payment method on the page, you need to create the SDK and initiate it with a payment session.

### 1\. (Optional) Preload the SDK {#Gtdrg6}

 Before creating a payment session, it is highly recommended that you 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
[[AMSCashierPayment shared] preload];

```

### 2\. Instantiate the SDK {#KQO5Xq2}

 Create the SDK instance by using the   `AMSCashierPayment`   and specify basic configurations. Creating an     *AMSCashierPaymentConfiguration*     object includes the following parameters:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *locale* | No | It is used to pass in language information. Valid values are listed as follows. You can choose the value to pass based on the region of the payment method. If other values are passed, English is used by default: - `en_US`  : English - `es_ES`  : Spanish - `fr_FR`  : French - `nl_NL`  : Dutch - `it_IT`  : Italian - `de_DE`  : German - `zh_CN`  : Simplified Chinese - `zh_HK`  : Traditional Chinese - `pt_PT`  : Portuguese (Portugal) - `ro`  : Romanian - `pl_PL`  : Polish |
| *options* | No | It is used to customize themes and features and whether to use the sandbox environment. Valid values are: - `"showSubmitButton"`  : Optional. Boolean type. The default value is   `false`  , which indicates that the submit button provided by the SDK component is not enabled.   `true`   indicates that the SDK component renders the submit button. If set to   `false`  , you need to call the   `submit()`   function of the instance object to initiate the payment flow. This parameter is only applicable to the embedded experience. - `"sandbox", "true"`  : Sandbox environment - `"sandbox", "false"`  : Production environment - `"notRedirectAfterComplete"`  : Optional, Boolean type. The default value is false, which means it will redirect back to your page after the payment is completed. The same applies when the value is empty. true value means there will be no redirect after the payment is completed. You need to use the customer event code to control the card binding to complete the subsequent process. Note that the payment result event code returned by the client is only used as a reference for the redirect operation of the client page. For transaction status updates, refer to the results returned by the server's        **notifyPayment**        or        **inquiryPayment**        API. - `"merchantAppointParam"`  : JSONString type. It is used to set up custom functions, including the following parameters:     - *storedCard*    : Optional. Object type. It is used to set up custom functions with a stored card and contains the following parameters:       - *needCVV*    : Optional. Boolean type. The default value is   `false`  . It indicates that the buyer does not need to do CVV verification during the payment process, and the same applies when the value is null. If this value is set to   `true`  , it indicates that CVV verification is required during the payment process. |
| *setOnCheckoutListener* | No | Create an instance of the     **OnCheckoutListener**     API, which is used for event handling in the subsequent process. The API includes the following method: - onEventCallback   : Required. A callback function that monitors payment events on the checkout page, returning     *eventCode*     and     *eventResult*    . |

 Implementing the   `AMSPaymentProtocol`   used for handling corresponding events in subsequent processes. It contains the following method:

 | **Method** | **Required** | **Description** |
| --- | --- | --- |
| *onEventCallback* | No | A callback function that monitors payment events on the checkout page, returning     *eventCode*     and     *eventResult*    . |

 > **[INFO]** **Note**    : Each instance can handle only one payment session. It is recommended to create the instance before calling   `createComponent`   each time.

 The following sample code shows how to instantiate the SDK:

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

AMSCashierPaymentConfiguration *componentConfig = [AMSCashierPaymentConfiguration new];
componentConfig.locale = @"en_US";
// Card payment scenarios require CVV verification.
NSString *merchantAppointParam = @"{ \"storedCard\": { \"needCVV\": true } }";

NSDictionary *options = @{
    @"showSubmitButton": @"false", // Only applicable to the embedded experience. Configure whether the payment button is rendered by the SDK component. The default value is false.
    @"sandbox": @"true", // Set the sandbox environment. If you leave it empty, the production environment is used by default.
    @"merchantAppointParam": merchantAppointParam,
    @"notRedirectAfterComplete": @"true"  // Set no redirection after payment completion, with the merchant controlling the subsequent process.
    };
componentConfig.options = options;

[[AMSCashierPayment shared] initConfiguration:componentConfig];

// Set the callback to monitor events on the checkout page.
[AMSCashierPayment shared].paymentDelegate = self;
[AMSCashierPayment shared].loggerDelegate = self;
```

### 3\. Invoke the SDK {#iVDpwG1}

 Call the   `createComponent`   method:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *sessionData* | Yes | Create a configuration object by using the     *sessionData*     parameter: Pass the complete data in the     *paymentSessionData*     parameter obtained in the response through the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API to the     *sessionData*     parameter. |

 Call the   `onDestroy`   method to free SDK component resources in the following situations:

 - When the buyer exits the checkout page, free the component resources created in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  .
- When the buyer initiates multiple payments, free the component resources created in the previous   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  .

 The following sample code shows how to invoke the SDK:

 ```objectivec
[[AMSCashierPayment shared] createComponent:sessionData];

//Free SDK component resources
[[AMSCashierPayment shared] onDestroy];
```

#### Popup experience vs. Embedded experience {#Ydtge999}

 There are different ways in which you can make the SDK display on a page through a pop-up window or embedded on a page.

<!-- TabGroup -->

**Tab: Popup experience**

![Antom SDK card payment popup experience showing the payment element displayed as a modal overlay on the merchant page](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f216f987-d0db-45cc-9328-f13c9010ecc5.png)

   Popup experience offers the advantage of low impact on page style and relatively independent flow.

 After the buyer selects a payment method on the page and clicks submit, you need to inevoke the SDK and pop up the window.

 ```javascript
[[AMSCashierPayment shared] createComponent:sessionData];
```

**Tab: Embedded experience**

![Antom SDK card payment embedded experience showing the payment element rendered inline within a designated container on the merchant page](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f843e99e-58c3-44d2-8dcb-3f4f6c322604.png)

   The embedded experience embeds payment element within the designated view. You need to focus on styling adjustments for the payment list. The embedded content's width adjusts automatically to fit the parent container, while the height dynamically updates with view changes.

 ```javascript
self.checkoutView = [[AMSCashierPayment shared] mountComponent:paymentSessionData];
```

##### Embedded submit payment {#Cysthf5g}

 Call the   `submit()`   function in the instance object:

 - This function can initiate the payment submission process and return specific event codes. These event codes can also be returned via   `onError`   or   `onEventCallback`   functions.

 - If you need to pass the collected billing address information for AVS verification, you can configure the following parameters through the   `submit`   function.

   - *billingAddress*    : Required. Object type. Used to identify the billing address information of the payment user. It includes the following parameters:

     - *region*    : Required. String (2). Complies with   [ISO 3166](https://www.iso.org/obp/ui/#search)   standard two-letter country or region code.
    - *address1*    : Optional. String (256). Line 1 of the address, for example, the street address, P.O. box, and company name.
    - *address2*    : Optional. String (256). Line 2 of the address, such as apartment, suite, unit, building, or similar information.
    - *city*    : Optional. String (32). The city, district, suburb, town, or village name.
    - *state*    : Optional. String (8). The state, country, or province name.
    - *zipCode*    : Optional. String (32). Postal code.

 ```objectivec
// The buyer inputs to complete payment
NSString *dataString = @"{"billingAddress":{"zipCode":"310000","region":"CN"}}";

[[AMSCashierPayment shared] submit: dataString];
```

<!-- /TabGroup -->

### 4\. Display payment results {#Go6dNO1}

 The payment result will be returned through the   `onEventCallback`   function. The payment result here is only for front-end display, and the final order status is subject to the server side. You need to customize the processing flow you want for each payment result through the data in the result of   `onEventCallback`  .

 The following are the possible event codes of the payment result returned by   `onEventCallback`  :

   | **Event code** | **Message** | **Solution** |
| --- | --- | --- |
| SDK_PAYMENT_SUCCESSFUL | Payment was successful. | Redirect the buyer to the payment result page, then confirm the payment result with the server. |
| SDK_PAYMENT_PROCESSING | Payment is being processed. | Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment. |
| SDK_PAYMENT_FAIL | Payment failed. | Check the value of          *result.paymentResultCode*     in the   `onEventCallback`   result data for details. Guide the buyer to retry payment based on the obtained information. > **[INFO]** **Note**    : For the meaning of     *result.paymentResultCode*    , refer to   [Description of payment failure or abnormal payment status](https://docs.antom.com/ac/sdks/ref.md?locale=en-us#nuduf)  . |
| SDK_PAYMENT_CANCEL | Payment was canceled. | The SDK can be re-invoked with a     *paymentSessionData*     within the validity period; if it has expired, the     *paymentSessionData*     needs to be re-requested. |
| SDK_PAYMENT_ERROR | The payment status was abnormal. | Confirm the payment result with the server.    If it is confirmed that the payment has failed, guide the buyer to    retry payment   . |

 The following sample code shows how to process the   `onEventCallback`  :

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

#pragma AMSPaymentProtocol
- (void)onEventCallback:(NSString *)eventCode eventResult:(AMSEventResult *)eventResult
{
    if ([eventCode isEqualToString:@"SDK_PAYMENT_SUCCESSFUL"]) {
        // Payment was successful. Redirect the buyer to the payment result page, then confirm the payment result with the server.
    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_PROCESSING"]) {
        // Payment is being processed. Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment.

    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_FAIL"]) {
        // Payment failed. Check the value of result.paymentResultCode in the onEventCallback result data for details. Guide the buyer to retry payment based on the obtained information.

    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_CANCEL"]) {
        // Payment was canceled. The SDK can be re-invoked with a paymentSessionData within the validity period; if it has expired, the paymentSessionData needs to be re-requested.

    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_ERROR"]) {
        // The payment status was abnormal. Confirm the payment result with the server. If it is confirmed that the payment has failed, guide the buyer to retry payment.
    }
    NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}
```

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

 After the buyer completes the payment or the payment times out, Antom sends the corresponding payment results to you through server interactions, you can obtain the payment result by one of the following methods:

 - Receive the asynchronous notification
- Inquire about the result

### Receive the asynchronous notification {#WDV7jq1}

 When the payment reaches a final status of success or failure, Antom sends an asynchronous notification to the     *paymentNotifyUrl*     specified in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API. When you receive the notification from Antom, you are required to return a response as instructed in   [Return a receipt acknowledgment message](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)  .

 Antom allows you to specify the URL in the     *paymentNotifyUrl*     parameter within the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API. If the URL for each payment is the same, you can also configure it in the Antom Dashboard.

 The following code shows a sample of the notification request:

   ```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "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"
  }
}

```

   How to verify the signature of the notification and make a response to the notification, see  [Sign a request and verify the signature](https://docs.antom.com/ac/ams/digital_signature.md)  .

   > **[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 usually send you an asynchronous notification within 3 to 5 seconds. For some payment methods like cash payment, 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 didn't make a response 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 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 are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to the following key parameters:
>
>  - *result*    : indicates the payment result of the order.
> - *paymentRequestId*    : indicates the payment request number you generated for consult, cancel, and reconciliation.
> - *paymentId*    : indicates the payment order number generated by Antom used for refund and reconciliation.
> - *paymentAmount*    : indicates the payment amount.

### Inquire about the result {#wlAwb81}

 You can call the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API to initiate a query on the result of an order.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *paymentRequestId* | No | The payment request ID generated by the merchant. |

 The parameter is not a full set of parameters, refer to the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API for full set of parameters and additional requirements for certain payment methods.

   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 code shows a sample of the request message:

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

```

   The following code shows a sample of the response message:

   ```json
{
  "authExpiryTime": "2024-01-08T00:01:00+08:00",
  "cardInfo": {
    "cardBrand": "MASTERCARD",
    "funding": "DEBIT",
    "issuingCountry": "US"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "CARD",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "networkTransIdXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentResultMessage": "success",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

```

   > **[INFO]** **Common questions**
>
>  **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.
>
>  
>  **Q: What are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to these key parameters:
>
>  - *result*    : represents the result of this   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)        API call, the result of the order needs to be judged according to     *paymentStatus*    :
>
>    - `SUCCESS`      and      `FAIL`      represent the final result.
>   - `PROCESSING`      represents the processing.
>
>  - *paymentAmount*    : indicates the payment amount.

## Step 4: Obtain capture result  **[Server-side]** {#gq1O5F}

 After the merchant completes the capture or the capture times out, Antom sends the corresponding capture results to you through server interactions, you can obtain the capture result by one of the following methods:

 - Receive the asynchronous notification
- Inquire about the result

### Receive the asynchronous notification {#nnwrAd66}

 When the capture reaches a final status of success or failure, Antom sends an asynchronous notification to the     *paymentNotifyUrl*     specified in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API. When you receive the notification from Antom, you are required to return a response as instructed in   [Return a receipt acknowledgment message](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)  .

 Antom    allows you to specify the URL in the     *paymentNotifyUrl*     parameter within the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API. If the URL for each payment is the same, you can also configure it in the Antom Dashboard.

 The following code shows a sample of successful capture:

 ```json
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101987654321XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The following code shows a sample of failed capture:

 ```json
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101123456789XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "PROCESS_FAIL",
    "resultMessage": "fail.",
    "resultStatus": "F"
  }
}
```

 How to verify the signature of the notification and make a response to the notification, see  [Sign a request and verify the signature](https://docs.antom.com/ac/ams/digital_signature.md)  .

 > **[INFO]** **Common questions**    ​
>
>  **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 didn't make a response 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 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 are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to the following key parameters:
>
>  - *result*    : represents the capture result of the order.
> - *notifyType*    : the value of        *notifyType*     is      `CAPTURE_RESULT`  .
> - *paymentRequestId*    : the payment request number you generated, used for querying, canceling, and reconciliation.
> - *paymentId*    : the payment order ID generated by Antom used for refund and reconciliation.
> - *acquirerReferenceNo*    : merchants integrating with in-card payment services in Singapore and Hong Kong will receive specific acquirer numbers in the notification.

### Inquire about the result {#NrYdhL}

 You can call the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API to initiate a query on the result of an order.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *paymentRequestId* | No | The payment request ID generated by the merchant. |

 The parameter is not a full set of parameters, refer to the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API for full set of parameters and additional requirements for certain payment methods.

   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 code shows a sample of the request message:

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

#### Value of capture status {#q3eq0A}

 The value of the     *transactions*     in the response of the API is the capture status:

 | **Parameter name** | **Description** |
| --- | --- |
| *transactions.transactionType* | The value is   `CAPTURE`  , meaning the capture status. |
| *transactions.transactionResult* | Capture status. |

 The following code shows a sample of successful capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "S",
        "resultCode": "SUCCESS",
        "resultMessage": "success"
      }
    }
  ]
}
```

 The following code shows a sample of failed capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "F",
        "resultCode": "PROCESS_FAIL",
        "resultMessage": "General business failure. No retry."
      }
    }
  ]
}
```

 The following code shows a sample of processing capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "U",
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process"
      }
    }
  ]
}
```

   > **[INFO]** **Common questions**
>
>  **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.

# Sample codes {#xjYOw01}

 Full sample codes for front-end:

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

// (Optional) Preload the SDK. Before creating a payment session, preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment.
[[AMSCashierPayment shared] preload];

// Step 1: Get Antom PaymentSessionData from your server.
NSString *paymentSessionData = "YOUR_PAYMENT_SESSIONDATA";

// Step 2: Create an AMSConfiguration object.
AMSCashierPaymentConfiguration *componentConfig = [AMSCashierPaymentConfiguration new];
componentConfig.locale = @"en_US";
NSString *merchantAppointParam = @"{ \"storedCard\": { \"needCVV\": true } }";
NSDictionary *options = @{
    // Set the sandbox environment. If you leave it empty, the production environment is used by default.
    @"sandbox": @"true",
    // Card payment scenarios require CVV verification.
    @"merchantAppointParam": merchantAppointParam,
    // Set no redirection after payment completion, with the merchant controlling the subsequent process.
    @"notRedirectAfterComplete": @"true"  
};
componentConfig.options = options;
[[AMSCashierPayment shared] initConfiguration:componentConfig];

// Set the callback to monitor payment events on the checkout page.
[AMSCashierPayment shared].paymentDelegate = self;

// Create and render the card component.
[[AMSCashierPayment shared] createComponent:paymentSessionData];

#pragma AMSPaymentProtocol
- (void)onEventCallback:(NSString *)eventCode eventResult:(AMSEventResult *)eventResult
{
    if ([eventCode isEqualToString:@"SDK_PAYMENT_SUCCESSFUL"]) {
        // Payment was successful. Redirect the buyer to the payment result page, then confirm the payment result with the server.
    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_PROCESSING"]) {
        // Payment is being processed. Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment.
    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_FAIL"]) {
        // Payment failed. Check the value of result.paymentResultCode in the onEventCallback result data for details. Guide the buyer to retry payment based on the obtained information.
    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_CANCEL"]) {
        // Payment was canceled. The SDK can be re-invoked with a paymentSessionData within the validity period; if it has expired, the paymentSessionData needs to be re-requested.
    } else if ([eventCode isEqualToString:@"SDK_PAYMENT_ERROR"]) {
        // The payment status was abnormal. Confirm the payment result with the server. If it is confirmed that the payment has failed, guide the buyer to retry payment.
    } else if ([eventCode isEqualToString:@"SDK_FORM_VERIFICATION_FAILED"]) {
       // Verification failed after form submission. Guide the buyer to confirm the input and retry payment.
    }
    NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}

// After the payment is completed or when the buyer exits the checkout page, free SDK component resources.
[[AMSCashierPayment shared] onDestroy];
```

# Event codes {#Yhdttv}

 Status codes: Returned by   `onEventCallback`   during the component's runtime lifecycle.

   | **Type** | **Code** | **Description** | **Further action** |
| --- | --- | --- | --- |
| Status codes | SDK_FORM_VERIFICATION_FAILED | Verification failed after form submission. | Guide the buyer to confirm the input and retry payment. |

**Tab: Android**

# User experience {#BkDw7T2}

 The following figure shows the user journey of paying on an app:

 ![Android user experience showing card payment flow via Antom SDK on a shopping app](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/ddd9b6cf-ffa6-4b66-b719-e2bee24a8f22.png)

# Payment flow {#d2DKE3}

 The following process shows how to integrate One-time Payments via Antom SDKs:

 ![Card payment flow showing the interaction across buyer, merchant client, Antom SDK, merchant server, and Antom server](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/4f9ca083-fb5b-4ed2-9b54-09b0bebd94c7.png)

 1. **The user lands on the checkout page.**
2. **Create a payment session request.**  
   After the buyer selects a payment method and submits the order, 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 the client SDK.**  
   On the client side, invoke the SDK through the payment session. The SDK will handle information collection, redirection, app invocation, QR code display, verification, and other processes based on the payment method's characteristics. Then the SDK will callback the payment result via   `OnCheckoutListener`  .
4. **Confirm the payment result.**  
   Obtain the payment result by using 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 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.
5. **Get the capture result.**  
   For card payments, you need to obtain the capture result by using 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 to set the address for receiving asynchronous notifications. When the payment request is successful or expires, Antom will use  [**notifyCapture**](https://docs.antom.com/ac/ams/notify_capture.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 request status.

# Integration preparations {#s1IDK}

 Before you start integrating, read the   [Integration guide](https://docs.antom.com/integration_guide_en.md)   and   [API overview](https://docs.antom.com/ac/ams/api_fund.md)   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 of   [Integrate the SDK package for Android](https://docs.antom.com/ac/sdks/android.md)  .

 > **[INFO]** **Note**    : Currently, Flutter and React Native (RN) development frameworks are not supported.

# Integration steps {#XkD7Tw5}

 Start your integration by taking the following steps:

 1. Create a payment session
2. Create and invoke the SDK
3. Obtain payment result
4. Obtain capture result

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

 When a buyer selects a payment method provided by Antom, you need to collect key information such as the payment request ID, order amount, payment method, order description, payment redirect URL, and payment result notification URL, call the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  API to create a payment session, and return the payment session to the client.

 Creating a payment session includes the following parameters:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | Represents the payment product that is being used, which is stipulated in the contract. For One-time Payments, the value is fixed as   `CASHIER_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID assigned by the merchant to identify a payment request. |
| *paymentAmount* | Yes | The payment amount that you request to receive in the order currency. |
| *paymentMethod* | Yes | The payment method that is used to collect the payment by the merchant or acquirer. |
| *paymentRedirectUrl* | Yes | The merchant page URL that the buyer is redirected to after the payment is completed. |
| *order* | Yes | The order information, such as buyer, merchant, goods, amount, shipping information, and purchase environment. |
| *paymentNotifyUrl* | No | Payment result notification address, which can be passed in through the API or set as a fixed value through Antom Dashboard. |
| *settlementStrategy* | No | The settlement strategy for the payment request. |
| *paymentFactor.isAuthorization* | No | Indicates whether the payment scenario requires authorization. Set this parameter to   `true`   when the value of     *paymentMethodType*     is   `CARD`  , which indicates that the payment scenario requires authorization. > **[INFO]** **Note**    : When this parameter is set to   `true`  , the payment funds are guaranteed and held on the payment method side. You can use the        [**capture (One-time Payments)**](https://docs.antom.com/ac/ams/capture.md)        API to deduct the payment funds. |

 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**](https://docs.antom.com/ac/ams/session_cashier.md)  API:

   ```java
public static void createCardPaymentSession() {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

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

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

    // set paymentMethod
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("CARD").build();
    alipayPaymentSessionRequest.setPaymentMethod(paymentMethod);

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

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

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

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

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

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

    AlipayPaymentSessionResponse alipayPaymentSessionResponse = null;
    try {
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

```

   The following code shows a sample of the request message:

   ```json
{
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "SGD",
      "value": "4200"
    },
    "orderDescription": "antom testing order",
    "referenceOrderId": "referenceOrderId01"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentFactor": {
    "isAuthorization": true
  },
  "paymentMethod": {
    "paymentMethodType": "CARD"
  },
  "paymentNotifyUrl": "https://www.yourNotifyUrl.com",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "productCode": "CASHIER_PAYMENT"
}

```

   The following code shows a sample of the response, which contains the following parameters:

 - *paymentSessionData*    : the payment session data to be returned to the frontend.
- *paymentSessionExpiryTime*    : the expiration time of the payment session.

   ```json
{
  "paymentSessionData": "UNvjVWnWPXJA4BgW+vfjsQj7PbOraafHY19X+6EqMz6Kvvmsdk+akdLvoShW5avHX8e8J15P8uNVEf/PcCMyXg==&&SG&&111",
  "paymentSessionExpiryTime": "2024-01-01T00:00:00+08:00",
  "paymentSessionId": "UNvjVWnWPXJA4BgW+vfjsQj7PbOraafHY19X+6EqMz6Ikyj9FPVUOpv+DjiIZqMe",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

```

   > **[INFO]** **Common questions**
>
>  **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of a certain payment method, do not use Chinese characters for fields in the request.
>
>   **Q: How to set the URL to receive the 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/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.

## Step 2: Create and invoke the SDK  **[Client-side]** {#oDwHQJ12}

 The Antom SDK is a component used for handling payment processes. You initiate the SDK by creating a payment session to collect information, switch between apps, and display QR codes based on the payment method specified in the  [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  API.

 After the buyer selects a payment method on the page, you need to create the SDK and initiate it with a payment session.

### 1\. (Optional) Preload the SDK {#ygdteb8}

 Before creating a payment session, it is highly recommended that you preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment.

 Call the   `createComponent`   method:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *context* | Yes | The Android context object. |

 Follow the code example below to perform the preloading:

 ```java
AMSCashierPayment.preload(context.getApplicationContext());

```

### 2\. Instantiate the SDK {#KQO5Xq3}

 Create the SDK instance by using the   `AMSCashierPayment`   and specify basic configurations. Creating a configuration object includes the following methods:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *setLocale* | No | It is used to pass in language information. Valid values are listed as follows. You can choose the value to pass based on the region of the payment method. If other values are passed, English is used by default: - `"en", "US"`  : English - `"es", "ES"`  : Spanish - `"fr", "FR"`  : French - `"nl", "NL"`  : Dutch - `"it", "IT"`  : Italian - `"de", "DE"`  : German - `"zh", "CN"`  : Simplified Chinese - `"zh", "HK"`  : Traditional Chinese - `"pt", "PT"`  : Portuguese (Portugal) - `"ro"`  : Romanian - `"pl", "PL"`  : Polish |
| *setOption* | No | It is used to customize themes and features and whether to use the sandbox environment. Valid values are: - `"showSubmitButton"`  : Optional. Boolean type. The default value is   `false`  , which indicates that the submit button provided by the SDK component is not enabled.   `true`   indicates that the SDK component renders the submit button. If set to   `false`  , you need to call the   `submit()`   function of the instance object to initiate the payment flow. This parameter is only applicable to the embedded experience. - `"sandbox", "true"`  : Sandbox environment - `"sandbox", "false"`  : Production environment   - `"notRedirectAfterComplete", "true"`  :    Optional, Boolean type. The default value is   `false`  , which means it will redirect back to your page after the payment is completed. The same applies when the value is empty.    If this value is set to   `true`  , it means that there will be no redirection after the payment is completed. You need to use the customer event code to control the card binding to complete the subsequent process. Note that the payment result event code returned by the client is only used as a reference for the redirect operation of the client page. For transaction status updates, refer to the results returned by the server's   [**notifyPayment**](https://docs.antom.com/ac/apo/paymentrn_online.md)        or   [**inquiryPayment**](https://docs.antom.com/ac/apo_zh-cn/paymentri_online.md)        API. - `"merchantAppointParam"`  : JSONString type. It is used to set up custom functions, including the following parameters:     - *storedCard*    : Optional. Object type. It is used to set up custom functions with a stored card and contains the following parameters:       - *needCVV*    : Optional. Boolean type. The default value is   `false`  . It indicates that the buyer does not need to do CVV verification during the payment process, and the same applies when the value is null. If this value is set to   `true`  , it indicates that CVV verification is required during the payment process. |
| *setOnCheckoutListener* | No | Create an instance of the     **OnCheckoutListener**     API, which is used for event handling in the subsequent process. The API includes the following method: - onEventCallback   : Required. A callback function that monitors payment events on the checkout page, returning     *eventCode*     and     *eventResult*    . |

 > **[INFO]** **Note**    : Each instance can handle only one payment session. It is recommended to create the instance before calling   `createComponent`   each time.

 The following sample code shows how to instantiate the SDK:

   ```java
AMSCashierPaymentConfiguration configuration = new AMSCashierPaymentConfiguration();
configuration.setLocale(new Locale("en", "US"));
// Set the sandbox environment. If you leave it empty, the production environment is used by default.
configuration.setOption("sandbox", "true");
// Set mandatory CVV verification for buyers.
configuration.setOption("merchantAppointParam", "{ \"storedCard\": { \"needCVV\": true } }");
// Set the callback to monitor payment events on the checkout page.
configuration.setOnCheckoutListener(new OnCheckoutListener() {
    @Override
    public void onEventCallback(String eventCode, AMSEventResult eventResult) {
        Log.e(TAG, "onEventCallback eventCode=" + eventCode + " eventResult=" + eventResult.toString());
    }
});
// Instantiate AMSCashierPayment.
AMSCashierPayment checkout = new AMSCashierPayment.Builder(activity, configuration).build();
```

### 3\. Invoke the SDK {#iVDpwG12}

 Call the   `createComponent`   method:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *sessionData* | Yes | Create a configuration object by using the     *sessionData*     parameter: Pass the complete data in the     *paymentSessionData*     parameter obtained in the response through the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API to the     *sessionData*     parameter. |

 Call the   `onDestroy`   method to free SDK component resources in the following situations:

 - When the buyer exits the checkout page, free the component resources created in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  .
- When the buyer initiates multiple payments, free the component resources created in the previous   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)  .

 The following sample code shows how to invoke the SDK:

 ```java
checkout.createComponent(activity, sessionData);

//Free SDK component resources
checkout.onDestroy();
```

#### Popup experience vs. Embedded experience {#tdstttb6}

 There are different ways in which you can make the SDK display on a page through a pop-up window or embedded on a page.

<!-- TabGroup -->

**Tab: Popup experience**

![Antom SDK card payment popup experience showing the payment element displayed as a modal overlay on the merchant page](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f216f987-d0db-45cc-9328-f13c9010ecc5.png)

   Popup experience offers the advantage of low impact on page style and relatively independent flow.

 After the buyer selects a payment method on the page and clicks submit, you need to inevoke the SDK and pop up the window.

 ```javascript
checkout.createComponent(activity, sessionData);
```

**Tab: Embedded experience**

![Antom SDK card payment embedded experience showing the payment element rendered inline within a designated container on the merchant page](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f843e99e-58c3-44d2-8dcb-3f4f6c322604.png)

   The embedded experience embeds payment element within the designated view. You need to focus on styling adjustments for the payment list. The embedded content's width adjusts automatically to fit the parent container, while the height dynamically updates with view changes.

 ```javascript
Map<String, Object> appearanceConfig = new HashMap<>();
appearanceConfig.put("showSubmitButton", false);
AMSPaymentAppearance appearance = AMSPaymentAppearance.create(appearanceConfig);
checkout.mountComponent(activity, appearance, sessionData, parentViewGroup);
```

##### Embedded submit payment {#Cysthf5g}

 Call the   `submit()`   function in the instance object:

 - This function can initiate the payment submission process and return specific event codes. These event codes can also be returned via the   `onEventCallback`   function.

 - If you need to pass the collected billing address information for AVS verification, you can configure the following parameters through the   `submit`   function.

   - *billingAddress*    : Required. Object type. Used to identify the billing address information of the payment user. It includes the following parameters:

     - *region*    : Required. String (2). Complies with   [ISO 3166](https://www.iso.org/obp/ui/#search)   standard two-letter country or region code.
    - *address1*    : Optional. String (256). Line 1 of the address, for example, the street address, P.O. box, and company name.
    - *address2*    : Optional. String (256). Line 2 of the address, such as apartment, suite, unit, building, or similar information.
    - *city*    : Optional. String (32). The city, district, suburb, town, or village name.
    - *state*    : Optional. String (8). The state, country, or province name.
    - *zipCode*    : Optional. String (32). Postal code.

 ```java
let dataString = '{"billingAddress":{"zipCode":"310000","region":"CN"}}';

// The buyer inputs and submits the binding
checkout.submit(dataString);
```

<!-- /TabGroup -->

### 4\. Display payment results {#Go6dNO12}

 The payment result will be returned through the   `onEventCallback`   function. The payment result here is only for front-end display, and the final order status is subject to the server side. You need to customize the processing flow you want for each payment result through the data in the result of   `onEventCallback`  .

 The following are the possible event codes of the payment result returned by   `onEventCallback`  :

   | **Event code** | **Message** | **Solution** |
| --- | --- | --- |
| SDK_PAYMENT_SUCCESSFUL | Payment was successful. | Redirect the buyer to the payment result page, then confirm the payment result with the server. |
| SDK_PAYMENT_PROCESSING | Payment is being processed. | Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment. |
| SDK_PAYMENT_FAIL | Payment failed. | Check the value of          *result.paymentResultCode*     in the   `onEventCallback`   result data for details. Guide the buyer to retry payment based on the obtained information. > **[INFO]** **Note**    : For the meaning of     *result.paymentResultCode*    , refer to   [Description of payment failure or abnormal payment status](https://docs.antom.com/ac/sdks/ref.md?locale=en-us#nuduf)  . |
| SDK_PAYMENT_CANCEL | Payment was canceled. | The SDK can be re-invoked with a     *paymentSessionData*     within the validity period; if it has expired, the     *paymentSessionData*     needs to be re-requested. |
| SDK_PAYMENT_ERROR | The payment status was abnormal. | Confirm the payment result with the server.    If it is confirmed that the payment has failed, guide the buyer to    retry payment   . |

 The following sample code shows how to process the   `onEventCallback`   :

 ```java
AMSCashierPaymentConfiguration configuration = new AMSCashierPaymentConfiguration();
configuration.setLocale(new Locale("en", "US"));
// Set the sandbox environment. If you leave it empty, the production environment is used by default.
configuration.setOption("sandbox", "true");
// Configure whether the payment button is rendered by the SDK component.
configuration.setOption("showSubmitButton", "true");
// Set the callback to monitor payment events on the checkout page.
configuration.setOnCheckoutListener(new OnCheckoutListener() {
    @Override
    public void onEventCallback(String eventCode, AMSEventResult eventResult) {
        Log.e(TAG, "onEventCallback eventCode=" + eventCode + " eventResult=" + eventResult.toString());

        if (!TextUtils.isEmpty(eventCode)) {
            if ("SDK_PAYMENT_SUCCESSFUL".equals(eventCode)) {
                // Payment was successful. Redirect the buyer to the payment result page, then confirm the payment result with the server.
            } else if ("SDK_PAYMENT_PROCESSING".equals(eventCode)) {
                // Payment is being processed. Confirm the payment result with the server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment.
            } else if ("SDK_PAYMENT_FAIL".equals(eventCode)) {
                // Payment failed. Check the value of result.paymentResultCode in the onEventCallback result data for details. Guide the buyer to retry payment based on the obtained information.
            } else if ("SDK_PAYMENT_CANCEL".equals(eventCode)) {
                // Payment was canceled. The SDK can be re-invoked with a paymentSessionData within the validity period; if it has expired, the paymentSessionData needs to be re-requested.
            } else if ("SDK_PAYMENT_ERROR".equals(eventCode)) {
                // The payment status was abnormal. Confirm the payment result with the server. If it is confirmed that the payment has failed, guide the buyer to retry payment.
            }
        }
    }
});
// Instantiate AMSCashierPayment.
AMSCashierPayment checkout = new AMSCashierPayment.Builder(activity, configuration).build();

```

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

 After the buyer completes the payment or the payment times out, Antom sends the corresponding payment results to the you through server interactions, you can obtain the payment result by one of the following methods:

 - Receive the asynchronous notification
- Inquire about the result

### Receive the asynchronous notification {#WDVw7j8}

 When the payment reaches a final status of success or failure, Antom sends an asynchronous notification to the     *paymentNotifyUrl*     specified in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API. When you receive the notification from Antom, you are required to return a response as instructed in   [Return a receipt acknowledgment message](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)  .

 Antom    allows you to specify the URL in the     *paymentNotifyUrl*     parameter within the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API. If the URL for each payment is the same, you can also configure it in the    Antom    Dashboard.

 The following code shows a sample of the notification request:

   ```json
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "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"
  }
}

```

   How to verify the signature of the notification and make a response to the notification, see  [Sign a request and verify the signature](https://docs.antom.com/ac/ams/digital_signature.md)  .

   > **[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 usually send you an asynchronous notification within 3 to 5 seconds. For some payment methods like cash payment, 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 didn't make a response 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 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 are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to the following key parameters:
>
>  - *result*    : indicates the payment result of the order.
> - *paymentRequestId*    : indicates the payment request number you generated for consult, cancel, and reconciliation.
> - *paymentId*    : indicates the payment order number generated by Antom used for refund and reconciliation.
> - *paymentAmount*    : indicates the payment amount.

### Inquire about the result {#wlAwb812}

 You can call the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API to initiate a query on the result of an order.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *paymentRequestId* | No | The payment request ID generated by the merchant. |

 The parameter is not a full set of parameters, refer to the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API for full set of parameters and additional requirements for certain payment methods.

   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 code shows a sample of the request message:

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

```

   The following code shows a sample of the response message:

   ```json
{
  "authExpiryTime": "2024-01-08T00:01:00+08:00",
  "cardInfo": {
    "cardBrand": "MASTERCARD",
    "funding": "DEBIT",
    "issuingCountry": "US"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "CARD",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "networkTransIdXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentResultMessage": "success",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

```

   > **[INFO]** **Common questions**
>
>  **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.
>
>  
>  **Q: What are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to these key parameters:
>
>  - *result*    : represents the result of this   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)        API call, the result of the order needs to be judged according to     *paymentStatus*    :
>
>    - `SUCCESS`      and      `FAIL`      represent the final result.
>   - `PROCESSING`      represents the processing.
>
>  - *paymentAmount*    : indicates the payment amount.

## Step 4: Obtain capture result  **[Server-side]** {#gq1O5F2}

 After the merchant completes the capture or the capture times out, Antom sends the corresponding capture results to you through server interactions, you can obtain the capture result by one of the following methods:

 - Receive the asynchronous notification
- Inquire about the result

### Receive the asynchronous notification {#nnwrAd3}

 When the capture reaches a final status of success or failure, Antom sends an asynchronous notification to the     *paymentNotifyUrl*     specified in the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API. When you receive the notification from Antom, you are required to return a response as instructed in   [Return a receipt acknowledgment message](https://docs.antom.com/ac/cashierpay/notifications.md#vQK5A)  .

 Antom    allows you to specify the URL in the     *paymentNotifyUrl*     parameter within the   [**createPaymentSession (One-time Payments)**](https://docs.antom.com/ac/ams/session_cashier.md)   API. If the URL for each payment is the same, you can also configure it in the Antom Dashboard.

 The following code shows a sample of successful capture:

 ```json
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101987654321XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

 The following code shows a sample of failed capture:

 ```json
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101123456789XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "PROCESS_FAIL",
    "resultMessage": "fail.",
    "resultStatus": "F"
  }
}
```

 How to verify the signature of the notification and make a response to the notification, see  [Sign a request and verify the signature](https://docs.antom.com/ac/ams/digital_signature.md)  .

 > **[INFO]** **Common questions**    ​
>
>  **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 didn't make a response 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 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 are the key parameters in the notification that I need to use?**
>
>  A: Pay attention to the following key parameters:
>
>  - *result*    : represents the capture result of the order.
> - *notifyType*    : the value of        *notifyType*     is      `CAPTURE_RESULT`  .
> - *paymentRequestId*    : the payment request number you generated, used for querying, canceling, and reconciliation.
> - *paymentId*    : the payment order ID generated by Antom used for refund and reconciliation.
> - *acquirerReferenceNo*    : merchants integrating with in-card payment services in Singapore and Hong Kong will receive specific acquirer numbers in the notification.

### Inquire about the result {#NrYdhL2}

 You can call the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API to initiate a query on the result of an order.

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *paymentRequestId* | No | The payment request ID generated by the merchant. |

 The parameter is not a full set of parameters, refer to the  [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  API for full set of parameters and additional requirements for certain payment methods.

   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 code shows a sample of the request message:

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

#### Value of capture status {#q3eq0A2}

 The value of the     *transactions*     in the response of the API is the capture status:

 | **Parameter name** | **Description** |
| --- | --- |
| *transactions.transactionType* | The value is   `CAPTURE`  , meaning the capture status. |
| *transactions.transactionResult* | Capture status. |

 The following code shows a sample of successful capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "S",
        "resultCode": "SUCCESS",
        "resultMessage": "success"
      }
    }
  ]
}
```

 The following code shows a sample of failed capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "F",
        "resultCode": "PROCESS_FAIL",
        "resultMessage": "General business failure. No retry."
      }
    }
  ]
}
```

 The following code shows a sample of processing capture:

 ```json
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "U",
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process"
      }
    }
  ]
}
```

   > **[INFO]** **Common questions**
>
>  **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.

# Sample codes {#xjYOw012}

 Full sample codes for front-end:

 ```java
// (Optional) Preload the SDK. Before creating a payment session, preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment.
AMSCashierPayment.preload(context);

// Step 1: Get Antom PaymentSessionData from your server.
String paymentSessionData = "YOUR_PAYMENT_SESSIONDATA";

// Step 2: Create the AMSCashierPaymentConfiguration type.
AMSCashierPaymentConfiguration configuration = new AMSCashierPaymentConfiguration();
configuration.setLocale(new Locale("en", "US"));
// Set the sandbox environment. If you leave it empty, the production environment is used by default.
configuration.setOption("sandbox", "true");
// Set no redirection after payment completion, with the merchant controlling subsequent process.
configuration.setOption("notRedirectAfterComplete", "true");
// Set mandatory CVV verification for users.
configuration.setOption("merchantAppointParam", "{ \"storedCard\": { \"needCVV\": true } }");
// Configure whether the payment button is rendered by the SDK component.
configuration.setOnCheckoutListener(new OnCheckoutListener() {
    @Override
    public void onEventCallback(String eventCode, AMSEventResult eventResult) {
        AlipayLog.e(TAG, "onEventCallback eventCode=" + eventCode + " eventResult=" + eventResult.toString());

        if (!TextUtils.isEmpty(eventCode)) {
            if ("SDK_PAYMENT_SUCCESSFUL".equals(eventCode)) {
                // Payment was successful. Redirect the buyer to the payment result page, then confirm the payment result with the server.
            } else if ("SDK_PAYMENT_PROCESSING".equals(eventCode)) {
                // Payment is being processed. Confirm the payment result with server. If the payment is successful, redirect the buyer to the payment result page. If the payment fails, guide the buyer to retry payment.
            } else if ("SDK_PAYMENT_FAIL".equals(eventCode)) {
                // Payment failed. Check the value of result.paymentResultCode in the onEventCallback result data for details. Guide the buyer to retry payment based on the obtained information.
            } else if ("SDK_PAYMENT_CANCEL".equals(eventCode)) {
                // Payment was canceled. The SDK can be re-invoked with a paymentSessionData within the validity period; if it has expired, the paymentSessionData needs to be re-requested.
            } else if ("SDK_PAYMENT_ERROR".equals(eventCode)) {
                // The payment status was abnormal. Confirm the payment result with the server. If it is confirmed that the payment has failed, guide the buyer to retry payment.
            } else if ("SDK_FORM_VERIFICATION_FAILED".equals(eventCode)) {
                // Verification failed after form submission. Guide the buyer to confirm the input and retry payment.
            }
        }
    }
});

// Instantiate AMSCashierPayment.
AMSCashierPayment checkout = new AMSCashierPayment.Builder(activity, configuration).build();

// Create and render the component.
checkout.createComponent(activity, paymentSessionData);

// After the payment is completed or when the buyer exits the checkout page, free SDK component resources.
checkout.onDestroy();
```

# Event codes {#Raydnjd}

 Status codes: Returned by   `onEventCallback`   during the component's runtime lifecycle.

   | **Type** | **Code** | **Description** | **Further action** |
| --- | --- | --- | --- |
| Status codes | SDK_FORM_VERIFICATION_FAILED | Verification failed after form submission. | Guide the buyer to confirm the input and retry payment. |

<!-- /ToggleTab -->