# Accept payments

> Learn how to integrate Tokenized Payment to enable seamless, one-click, and automatic recurring payments for your buyers.

 Tokenized Payment enables you to build an online automatic deduction feature on your website or application. After the buyer completes authorization during the first payment, subsequent payments can be made with just one click or directly deducted by your system without buyer's action. It is suitable for the following business scenarios:

 - **Recurring payments**    : For example, subscription or membership services, where the payment deduction cycle is managed by you.
- **Small-amount, high-frequency payments or high repurchase-rate scenarios**    : For example, gaming and e-commerce, where you can provide your buyers with a convenient and seamless payment experience.

 The Tokenized Payment product supports integration on various terminal types (Web/WAP/App), and requires only a single integration to connect with multiple payment methods, such as e-wallets and bank transfers.

  

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

**Tab: Web/WAP**

# User experience {#ecwGW}

 The following figures show the buyer's experience during the authorization and payment process:

## Authorization {#zRPua}

<!-- TabGroup -->

**Tab: Web**

Antom provides two authorization methods: QR code authorization and login authorization. The experience may vary depending on the payment method.

<!-- TabGroup -->

**Tab: QR code authorization**

The buyer is redirected to the payment method webpage, where they complete authorization by scanning the QR code displayed on the page.

   ![Web user experience flow diagram showing the QR code authorization process for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/8244e3e1-6e01-44eb-af3a-7db6dbd03870.png)

**Tab: Login authorization**

The buyer is redirected to the payment method webpage, where they complete authorization by entering their account credentials.

   ![Web user experience flow diagram showing the login authorization process for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/c18f54f2-d8ef-4a7a-9d1b-b7056d0520da.png)

<!-- /TabGroup -->

**Tab: WAP**

Antom provides two authorization methods: App authorization and login authorization. The experience may vary depending on the payment method.

<!-- TabGroup -->

**Tab: App authorization**

The buyer is redirected to the payment method app to complete the authorization process.

 ![WAP user experience flow diagram showing the App authorization process for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/af61d55a-4824-4f4c-8637-f19a1c08f724.png)

**Tab: Login authorization**

The buyer is redirected to the payment method's H5 page, where they complete authorization by entering their account credentials.

 ![WAP user experience flow diagram showing the login authorization process for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/389da86d-74af-4122-ad87-44b99dad98e7.png)

<!-- /TabGroup -->

<!-- /TabGroup -->

## Payment {#izwOX}

 After the buyer clicks to pay, the user experience for initiating the deduction is shown as below:

 ![Mobile user experience screenshot showing the Tokenized Payment checkout experience flow.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/e23661d2-5537-49c5-bb71-1aa1e44ee1a0.png)

 Subsequent recurring payments do not require any buyer actions and can be directly deducted by your system.

# Payment flow {#eLZVd}

 Before the first tokenized payment, you need to obtain the buyer's authorization. After the buyer authorizes, you can use the authorization code (    *authCode*    ) to obtain the payment token (    *accessToken*    ) and directly initiate the tokenization service. Authorization is not required for subsequent payments. The authorization and payment flow is outlined below:

 ![Sequence diagram illustrating the end-to-end Tokenized Payment authorization and payment flow.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f294780e-aaff-4cb1-bfa9-f4b433fb04f0.png)

 1. **The buyer lands on the checkout page.**
2. **Obtain the authorization URL.**  
   After the buyer selects a payment method, call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API to obtain the authorization URL.

 3. **Obtain the authorization result.**  
   You can obtain the authorization result through the reconstructed URL returned by the payment method or through asynchronous notification.

 4. **Apply for the payment token.**  
   Call the   [**applyToken**](https://docs.antom.com/ac/ams/accesstokenapp.md)   API to apply for the payment token (    *accessToken*    ), and store the corresponding token after obtaining it.

 5. **Initiate a payment.**  
   After obtaining the buyer's authorization, you can directly call the   [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)   API to initiate the tokenization service.

 6. **Obtain the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the      [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)      API to set the address for receiving asynchronous notifications. When the payment is successful or failed, 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.

# Integration steps {#QLFGi}

 To obtain the buyer's authorization and perform tokenized payment, please complete the following integration steps:

 1. Obtain the authorization URL
2. Redirect to the payment method page for authorization
3. Obtain the authorization result
4. Apply for payment token
5. Initiate a payment

## Step 1: Obtain the authorization URL   **[Server-side]** {#YYhhf}

 You need to first obtain the authorization URL and then redirect the buyer to the authorization URL to complete authorization. For web integration, the authorization URL can be obtained from     *normalUrl*     in the response of the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API.

 Antom provides server-side API libraries for multiple languages. The following Java code examples require Java 6 or later:

### 1\. Install an API library {#kAXZM}

 You can find the latest version on   [GitHub](https://github.com/alipay/global-open-sdk-java)  .

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

### 2\. Initialize the request instance {#kqv7c}

  Create a singleton resource to make a request to Antom.  ```java
import com.alipay.global.api.AlipayClient;
import com.alipay.global.api.DefaultAlipayClient;
import com.alipay.global.api.model.constants.EndPointConstants;

public class Sample {
    public static final String        CLIENT_ID            = "";
    public static final String        ANTOM_PUBLIC_KEY     = "";
    public static final String        MERCHANT_PRIVATE_KEY = "";

    private final static AlipayClient CLIENT               = new DefaultAlipayClient(
        EndPointConstants.SG, MERCHANT_PRIVATE_KEY, ANTOM_PUBLIC_KEY, CLIENT_ID);

}
```

### 3\. Initiate a recurring payment authorization request {#Y8R4k}

 Pass the following parameters in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   request:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *authRedirectUrl* | Yes | URL used to redirect the buyer back to the merchant's page after the authorization is completed. |
| *authState* | Yes | A string passed to identify the authorization request. |
| *customerBelongsTo* | Yes | The target payment method for the authorization request. |
| *scopes* | Yes | Fixed as   `AGREEMENT_PAY`   for recurring payment authorization. |
| *terminalType* | Yes | Terminal type of which the merchant service applies to. Valid values are: - `WEB`  : The buyer initiates the transaction on the merchant's web browser page. - `WAP`  : The buyer initiates the transaction on the merchant's HTML page on mobile devices. |
| *osType* | No | The operating system type. Valid values are: - `IOS`  : Indicates the operation system is Apple's iOS. - `ANDROID`  : Indicates the operation system is Google's Android.   > **[INFO]** **Note**    : This field is required when     *terminalType*     is   `WAP`  . |

 The following code shows how to call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API to obtain the authorization URL:

   ```java
public static void authorizationConsult() {
    AlipayAuthConsultRequest alipayAuthConsultRequest = new AlipayAuthConsultRequest();

    // replace with your authState
    String authState = UUID.randomUUID().toString();
    alipayAuthConsultRequest.setAuthState(authState);

    // set the target payment method for which you are requesting authorization
    alipayAuthConsultRequest.setCustomerBelongsTo(CustomerBelongsTo.TOSSPAY);

    // set the authorization scope
    alipayAuthConsultRequest.setScopes(new ScopeType[]{ScopeType.AGREEMENT_PAY});

    // set terminalType
    alipayAuthConsultRequest.setTerminalType(TerminalType.WEB);

    // replace with your authRedirectUrl
    alipayAuthConsultRequest.setAuthRedirectUrl("http://www.yourRedirectUrl.com");

    // consult authorization
    AlipayAuthConsultResponse alipayAuthConsultResponse;
    try {
        alipayAuthConsultResponse = CLIENT.execute(alipayAuthConsultRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}
```

   The following code shows a sample of the request message:

<!-- TabGroup -->

**Tab: Web**

```json
{
    "authRedirectUrl": "http://www.yourRedirectUrl.com",
    "authState": "556c1e32-3723-4b02-88ed-8c46087540ca",
    "customerBelongsTo": "TOSSPAY",
    "scopes": [
        "AGREEMENT_PAY"
    ],
    "terminalType": "WEB"
}
```

**Tab: WAP**

```json
{
    "authRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_113.html",
    "authState": "STATE_20250325101650291",
    "customerBelongsTo": "TOSSPAY",
    "scopes": [
        "AGREEMENT_PAY"
    ],
    "terminalType": "WAP",
    "osType": "ANDROID"
}
```

<!-- /TabGroup -->

### 4\. Receive the consult response {#S8SJo}

 The response from the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API contains the authorization URL to redirect the buyer to proceed with authorization:

<!-- TabGroup -->

**Tab: Web**

```json
{
    "authUrl": "https://pay.toss.im/payfront/web/billing?billingKey=5RMRHqdZPPaSr5AP4wkw43&source=AlipayConnect&needCallback=false",
    "normalUrl": "https://pay.toss.im/payfront/web/billing?billingKey=5RMRHqdZPPaSr5AP4wkw43&source=AlipayConnect&needCallback=false",
    "webRequestMethod": "GET",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

**Tab: WAP**

```json
{
    "appIdentifier": "viva.republica.toss",
    "authUrl": "https://pay.toss.im/payfront/web/billing?billingKey=moeoiG8rm2PUPawM3ZrXde&source=AlipayConnect&needCallback=false",
    "normalUrl": "https://pay.toss.im/payfront/web/billing?billingKey=moeoiG8rm2PUPawM3ZrXde&source=AlipayConnect&needCallback=false",
    "webRequestMethod": "GET",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

<!-- /TabGroup -->
   The table below shows the possible values of     *result.resultStatus*     in the consult response. Please handle the result according to the guidance provided:

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The request was successful. | Successfully obtained the authorization URL (one or more of     *applinkUrl*    /    *normalUrl*    /    *schemeUrl*    ). For detailed information of each URL, refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)  . |
| `U` | Unknown error. | Please use a new     *authState*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | The request failed. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

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

   > **[INFO]** **Common questions**
>
>  **Q: Multiple URLs are returned in the response of the**       [**consult**](https://docs.antom.com/ac/ams/authconsult.md)       **API. Which one should I use?**
>
>  A: For different payment methods and terminal types, Antom may return one or more of the following links:     *normalUrl*    ,     *applinkUrl*    , or     *schemeUrl*    . The merchant server needs to pass these URLs to the merchant front-end for redirection. For detailed information of each URL, refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)  .
>
>   **Q: How to set**       ***terminalType***      **?**
>
>  A: The valid values of     *terminalType*     are:
>
>  - If the buyer initiates a transaction from a PC browser, the     *terminalType*     needs to be specified as   `WEB`  .
> - If the buyer initiates a transaction from the mobile browser, the     *terminalType*     needs to be specified as   `WAP`  . Add the     *osType*     parameter and fill in the corresponding system parameters   `ANDROID`   or   `IOS`   according to the buyer's device.
>
>  You must pass the correct     *terminalType*     to obtain the correct redirect URL. Passing an incorrect value may impact the authorization success rate.
>
>   **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>   **Q: What should I do after receiving the returned**       ***normalUrl***      **?**
>
>  A: For transactions performed in PC browsers, Antom returns the     *normalUrl*     parameter in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   response. Your server needs to pass this URL to the client for redirection. Do not cache the returned     *normalUrl*    . When re-initiating authorization, you need to obtain a new     *normalUrl*     for redirection.

## Step 2: Redirect to the payment method page for authorization   **[Client-side]** {#NLJtb}

 After the server obtains the authorization URL, it needs to pass this URL to the client. Your client will redirect the buyer to the recurring payment authorization page. The code below shows an example of loading the URL in the client (the URL refers to     *applinkUrl*    ,     *schemeUrl*    , or     *normalUrl*     returned by the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   response):

<!-- TabGroup -->

**Tab: Web**

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

**Tab: WAP**

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

<!-- /TabGroup -->
   For more information on the URLs returned by different payment methods, see   [URLs returned for some payment methods](https://docs.antom.com/ac/auto_debit/redirection_details.md)   and refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)   to learn how to use these URLs.

 > **[INFO]** **Common questions**
>
>  **Q: How to handle different payment experiences?**
>
>  A: Authorization experiences vary by the URL type. Some URLs redirect buyers to the payment method's native app, while others complete authorization within an H5 page. For details, see   [URLs returned for some payment methods](https://docs.antom.com/ac/auto_debit/redirection_details.md)  .

 The following figure shows the rendering effect of the payment method authorization page:

 ![Mobile user experience screenshot showing the rendering effect of the payment method authorization page for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/0775fe7f-e7d9-48c7-ba26-239d88eb976e.png)

## Step 3: Obtain the authorization result {#gUxG0}

### 1\. Redirect to the merchant page {#NYcbU}

 When the buyer performs authorization on the relevant payment method authorization page, the authorization may be successful or fail. In the event of authorization success or failure, the following describes the subsequent redirects:

 - **Authorization success**    : If the authorization is successful, the buyer will be redirected back to the merchant page. The merchant page address is a reconstructed URL consisting of     *authRediectUrl*    ,     *authCode*    , and     *authState*    . However, the redirection may fail due to network issues or buyer actions.
- **Authorization failure**    :

   - If the buyer cancels the authorization or exits the authorization page, some payment methods will redirect the buyer back to the merchant page. The merchant page address is determined by     *authRediectUrl*    .
  - If the buyer does not authorize before the timeout or authorization fails, the buyer will not be redirected back to the merchant page.

 > **[INFO]** **Note**    :
>
>  - The authorization URL can only be used once. If the authorization fails, you need to call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API again and provide a new     *authState*     value.
> - For Boost, if redirection to the merchant page is required, contact Antom Technical Support for configuration.

### 2\. Obtain the authorization code {#nscrb}

 After the buyer completes authorization in Step 2, you can obtain the authorization code (    *authCode*    ) through one of the following methods:

 - Obtain     *authCode*     from the reconstructed URL returned by the payment method.
- Obtain     *authCode*     from the asynchronous notification of authorization sent by Antom.

<!-- TabGroup -->

**Tab: Obtain authCode from the reconstructed URL**

**Obtain**       ***authCode***       **from the reconstructed URL**       **[Client-side]**

   After successful authorization, the buyer will be redirected to the reconstructed URL returned by the payment method. This URL consists of three parts:

 - The value of     *authRedirectUrl*     passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, for example,   `https://www.alipay.com/`  .
- The value of     *authState*     passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, for example,   `663A8FA9-D836-48EE-8AA1-1FF682989DC7`  .
- The     *authCode*     returned by the payment method, for example,   `281004138596827069301079`  .

   The code below shows an example of a reconstructed URL:

   ```plain
https://www.alipay.com/&authState=663A8FA9-D836-48EE-8AA1-1FF682989DC7&authCode=281004138596827069301079
```

   You can obtain the     *authCode*     value from the reconstructed URL. Before using the     *authCode*    , please verify that the     *authState*     value in the reconstructed URL matches the     *authState*     value passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, and do one of the following:

 - If the     *authState*     values do not match, the reconstructed URL is considered untrustworthy, as malicious events such as attacks may have occurred during the redirection process. In this case, the     *authCode*     value in the URL cannot be used.
- If the     *authState*     values match, use the     *authCode*     value to apply for the payment token using the   [**applyToken**](https://docs.antom.com/ac/ams/accesstokenapp.md)   API.

**Tab: Obtain authCode from the asynchronous notification**

**Obtain**       ***authCode***       **from the asynchronous notification**    **[Server-side]**

   If you cannot get the reconstructed URL due to network issues or other reasons, you can follow the steps below to obtain the authorization code (    *authCode*    ) from the asynchronous notification of authorization sent by Antom:

 1. Configure the webhook URL to receive the asynchronous notification of authorization. Go to   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   >     **Developer**     >     **Notification URL**    , and add the notification address for the     **alipay.ams.authorizations.notify**     API. For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

   2. After the buyer completes authorization, Antom sends you an asynchronous notification through the        [**notifyAuthorization**](https://docs.antom.com/docs/ac/ams/notifyauth.md)   API. When you receive the asyncrhonous notification, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.  The following code shows an example of the asynchronous notification request:

   ```json
{
  "authCode": "28100113_1631148338197000019ba74",
  "authState": "489767958497",
  "authorizationNotifyType": "AUTHCODE_CREATED",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success",
    "resultStatus": "S"
  }
}
```

   Obtain the authorization code (    *authCode*    ) based on the value of     *result.resultStatus*     (only returns   `S`  ) in the authorization notification request:

   - `S`  : Indicates the authorization was successful and returns the following fields:

     - *authState*    : The unique ID generated for the authorization request. Verify that this value matches the     *authState*     specified in the   [**consult**](https://docs.antom.com/docs/ac/ams/authconsult.md)   request.
    - *authorizationNotifyType*    : Only returns   `AUTHCODE_CREATED`   in this scenario, indicating the buyer successfully initiated authorization for the tokenized payment on the merchant's client.
    - *authCode*    : The authorization code generated after successful authorization. Use this code to request a payment token.

 3. You need to verify the signature of the authorization notification sent by Antom:

   ```java
@PostMapping("/receiveAuthNotify")
@ResponseBody
public Result receiveAuthNotify(HttpServletRequest request, @RequestBody String notifyBody) {
    // retrieve the required parameters from http request
    String requestUri = request.getRequestURI();
    String requestMethod = request.getMethod();

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

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

        // deserialize the notification body
        AlipayAuthNotify authNotify = JSON.parseObject(notifyBody, AlipayAuthNotify.class);

        if (authNotify != null && "SUCCESS".equals(authNotify.getResult().getResultCode())) {
            // get authCode for applyToken
            return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
        }

    } catch (Exception e) {
        return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
    }

    return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}

```

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

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

   > **[INFO]** **Common questions**
>
>  **Q: Can both methods (reconstructed URL and asynchronous notification) be used to obtain**       ***authCode***      **?**
>
>  A: Yes. If multiple     *authCode*     values are received, use the first one received. Do not reuse the same     *authCode*     when requesting a payment token.
>
>   **Q: When will the notification be sent?**
>
>  A: After the buyer's authorization is completed, Antom sends an asynchronous notification to you.
>
>   **Q: Will the asynchronous notification be re-sent?**
>
>  A: Yes, the asynchronous notification will be re-sent    automatically within 24 hours for the following cases:
>
>  - If you didn't receive the asynchronous notification due to network reasons.
> - If you receive an asynchronous notification from Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format.
>
>  The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
>
>   **Q: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>   **Q: How to determine authorization failure?**
>
>  A: If you do not receive     *authCode*     within 15 minutes, the authorization can be considered failed. You can guide the buyer to re-initiate authorization.

<!-- /TabGroup -->

**Tab: iOS**

# User experience {#e2cwGW}

 The following figures show the buyer's experience during the authorization and payment process:

## Authorization {#zRPu2a}

 Antom provides two authorization methods: App authorization and login authorization. The experience may vary depending on the payment method.

<!-- TabGroup -->

**Tab: App authorization**

The buyer is redirected to the payment method app to complete the authorization process.

   ![Mobile user experience flow diagram showing the App authorization process for Tokenized Payment on iOS.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/150b6174-f667-4da8-8fb9-2aae942629ae.png)

**Tab: Login authorization**

The buyer is redirected to the payment method's H5 page, where they complete authorization by entering their account credentials.

   ![Mobile user experience flow diagram showing the login authorization process for Tokenized Payment on iOS.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/118fa68c-8259-429f-83d2-7e9c5f206ee7.png)

<!-- /TabGroup -->

## Payment {#izw22OX}

 After the buyer clicks to pay, the user experience for initiating the deduction is shown as below:

 ![Mobile user experience screenshot showing the Tokenized Payment checkout experience flow.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/e23661d2-5537-49c5-bb71-1aa1e44ee1a0.png)

 Subsequent recurring payments do not require any buyer actions and can be directly deducted by your system.

# Payment flow {#eL2ZVd}

 Before the first tokenized payment, you need to obtain the buyer's authorization. After the buyer authorizes, you can use the authorization code (    *authCode*    ) to obtain the payment token (    *accessToken*    ) and directly initiate the tokenization service. Authorization is not required for subsequent payments. The authorization and payment flow is outlined below:

 ![Sequence diagram illustrating the end-to-end Tokenized Payment authorization and payment flow.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f294780e-aaff-4cb1-bfa9-f4b433fb04f0.png)

 1. **The buyer lands on the checkout page.**
2. **Obtain the authorization URL.**  
   After the buyer selects a payment method, call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API to obtain the authorization URL.

 3. **Obtain the authorization result.**  
   You can obtain the authorization result through the reconstructed URL returned by the payment method or through asynchronous notification.

 4. **Apply for the payment token.**  
   Call the   [**applyToken**](https://docs.antom.com/ac/ams/accesstokenapp.md)   API to apply for the payment token (    *accessToken*    ), and store the corresponding token after obtaining it.

 5. **Initiate a payment.**  
   After obtaining the buyer's authorization, you can directly call the   [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)   API to initiate the tokenization service.

 6. **Obtain the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the      [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)      API to set the address for receiving asynchronous notifications. When the payment is successful or failed, 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.

# Integration steps {#QL2FGi}

 To obtain the buyer's authorization and perform tokenized payment, please complete the following integration steps:

 1. Obtain the authorization URL
2. Redirect to the payment method page for authorization
3. Obtain the authorization result
4. Apply for payment token
5. Initiate a payment

## Step 1: Obtain the authorization URL   **[Server-side]** {#Y2hhf}

 You need to first obtain the authorization URL and then redirect the buyer to the authorization URL to complete authorization. For web integration, the authorization URL can be obtained from     *normalUrl*     in the response of the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API.

 Antom provides server-side API libraries for multiple languages. The following Java code examples require Java 6 or later:

### 1\. Install an API library {#kA2XZM}

 You can find the latest version on   [GitHub](https://github.com/alipay/global-open-sdk-java)  .

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

### 2\. Initialize the request instance {#kqv2c}

  Create a singleton resource to make a request to Antom.  ```java
import com.alipay.global.api.AlipayClient;
import com.alipay.global.api.DefaultAlipayClient;
import com.alipay.global.api.model.constants.EndPointConstants;

public class Sample {
    public static final String        CLIENT_ID            = "";
    public static final String        ANTOM_PUBLIC_KEY     = "";
    public static final String        MERCHANT_PRIVATE_KEY = "";

    private final static AlipayClient CLIENT               = new DefaultAlipayClient(
        EndPointConstants.SG, MERCHANT_PRIVATE_KEY, ANTOM_PUBLIC_KEY, CLIENT_ID);

}
```

### 3\. Initiate a recurring payment authorization request {#Y2R4k}

 Pass the following parameters in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   request:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *authRedirectUrl* | Yes | URL used to redirect the buyer back to the merchant's page after the authorization is completed. |
| *authState* | Yes | A string passed to identify the authorization request. |
| *customerBelongsTo* | Yes | The target payment method for the authorization request. |
| *scopes* | Yes | Fixed as   `AGREEMENT_PAY`   for recurring payment authorization. |
| *terminalType* | Yes | Terminal type of which the merchant service applies to. Valid values are: - `APP`  : The buyer initiates the transaction on the merchant's mobile application. |
| *osType* | No | The operating system type. Valid values are: - `IOS`  : Indicates the operation system is Apple's iOS. - `ANDROID`  : Indicates the operation system is Google's Android.   > **[INFO]** **Note**    : This field is required when     *terminalType*     is   `APP`  . |

 The following code shows how to call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API to obtain the authorization URL:

   ```java
public static void authorizationConsult() {
    AlipayAuthConsultRequest alipayAuthConsultRequest = new AlipayAuthConsultRequest();

    // replace with your authState
    String authState = UUID.randomUUID().toString();
    alipayAuthConsultRequest.setAuthState(authState);

    // set the target payment method for which you are requesting authorization
    alipayAuthConsultRequest.setCustomerBelongsTo(CustomerBelongsTo.TOSSPAY);

    // set the authorization scope
    alipayAuthConsultRequest.setScopes(new ScopeType[]{ScopeType.AGREEMENT_PAY});

    // set terminalType
    alipayAuthConsultRequest.setTerminalType(TerminalType.WEB);

    // replace with your authRedirectUrl
    alipayAuthConsultRequest.setAuthRedirectUrl("http://www.yourRedirectUrl.com");

    // consult authorization
    AlipayAuthConsultResponse alipayAuthConsultResponse;
    try {
        alipayAuthConsultResponse = CLIENT.execute(alipayAuthConsultRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}
```

   The following code shows a sample of the request message:

   ```json
{
    "authRedirectUrl": "kademo://auth",
    "authState": "STATE_20250325101702257",
    "customerBelongsTo": "TOSSPAY",
    "scopes": [
        "AGREEMENT_PAY"
    ],
    "terminalType": "APP",
    "osType": "IOS"
}
```

### 4\. Receive the consult response {#S22SJo}

 The response from the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API contains the authorization URL to redirect the buyer to proceed with authorization:

   ```json
{
    "appIdentifier": "viva.republica.toss",
    "applinkUrl": "https://toss.onelink.me/3563614660?pid=referral&af_force_deeplink=true&af_dp=supertoss%3A%2F%2Fpay%2FbillingKey%3FbillingKey%3D0a5acO7999DSjKgJM8Kxf9%26skipResult%3Dfalse%26shouldAutoClose%3Dfalse&source=AlipayConnect&needCallback=false",
    "authUrl": "https://toss.onelink.me/3563614660?pid=referral&af_force_deeplink=true&af_dp=supertoss%3A%2F%2Fpay%2FbillingKey%3FbillingKey%3D0a5acO7999DSjKgJM8Kxf9%26skipResult%3Dfalse%26shouldAutoClose%3Dfalse&source=AlipayConnect&needCallback=false",
    "normalUrl": "https://pay.toss.im/payfront/web/billing?billingKey=0a5acO7999DSjKgJM8Kxf9&source=AlipayConnect&needCallback=false",
    "schemeUrl": "supertoss://pay/billingKey?billingKey=0a5acO7999DSjKgJM8Kxf9&source=AlipayConnect&needCallback=false",
    "webRequestMethod": "GET",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

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

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The request was successful. | Successfully obtained the authorization URL (one or more of     *applinkUrl*    /    *normalUrl*    /    *schemeUrl*    ). For detailed information of each URL, refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)  . |
| `U` | Unknown error. | Please use a new     *authState*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | The request failed. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

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

   > **[INFO]** **Common questions**
>
>  **Q: Multiple URLs are returned in the response of the**       [**consult**](https://docs.antom.com/ac/ams/authconsult.md)       **API. Which one should I use?**
>
>  A: For different payment methods and terminal types, Antom may return one or more of the following links:     *normalUrl*    ,     *applinkUrl*    , or     *schemeUrl*    . The merchant server needs to pass these URLs to the merchant front-end for redirection. For detailed information of each URL, refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)  .
>
>   **Q: How to set**       ***terminalType***      **?**
>
>  A: The valid values of     *terminalType*     are:
>
>  - If the buyer initiates a transaction from a mobile app, the     *terminalType*     needs to be specified as   `APP`  . Add the     *osType*     parameter and fill in the corresponding system parameters   `ANDROID`   or   `IOS`   according to the buyer's mobile device.
>
>  You must pass the correct     *terminalType*     to obtain the correct redirect URL. Passing an incorrect value may impact the authorization success rate.
>
>   **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>   **Q: What should I do after receiving the returned**       ***normalUrl***      **?**
>
>  A: For transactions performed in PC browsers, Antom returns the     *normalUrl*     parameter in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   response. Your server needs to pass this URL to the client for redirection. Do not cache the returned     *normalUrl*    . When re-initiating authorization, you need to obtain a new     *normalUrl*     for redirection.

## Step 2: Redirect to the payment method page for authorization   **[Client-side]** {#N22LJtb}

 After the server obtains the authorization URL, it needs to pass this URL to the client. Your client will redirect the buyer to the recurring payment authorization page. The code below shows an example of loading the URL in the client (the URL refers to     *applinkUrl*    ,     *schemeUrl*    , or     *normalUrl*     returned by the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   response):

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

   For more information on the URLs returned by different payment methods, see   [URLs returned for some payment methods](https://docs.antom.com/ac/auto_debit/redirection_details.md)   and refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)   to learn how to use these URLs.

 > **[INFO]** **Common questions**
>
>  **Q: How to handle different payment experiences?**
>
>  A: Authorization experiences vary by the URL type. Some URLs redirect buyers to the payment method's native app, while others complete authorization within an H5 page. For details, see   [URLs returned for some payment methods](https://docs.antom.com/ac/auto_debit/redirection_details.md)  .

 The following figure shows the rendering effect of the payment method authorization page:

 ![Mobile user experience screenshot showing the rendering effect of the payment method authorization page for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/0775fe7f-e7d9-48c7-ba26-239d88eb976e.png)

## Step 3: Obtain the authorization result {#2UxG0}

### 1\. Redirect to the merchant page {#N2YcbU}

 When the buyer performs authorization on the relevant payment method authorization page, the authorization may be successful or fail. In the event of authorization success or failure, the following describes the subsequent redirects:

 - **Authorization success**    : If the authorization is successful, the buyer will be redirected back to the merchant page. The merchant page address is a reconstructed URL consisting of     *authRediectUrl*    ,     *authCode*    , and     *authState*    . However, the redirection may fail due to network issues or buyer actions.
- **Authorization failure**    :

   - If the buyer cancels the authorization or exits the authorization page, some payment methods will redirect the buyer back to the merchant page. The merchant page address is determined by     *authRediectUrl*    .
  - If the buyer does not authorize before the timeout or authorization fails, the buyer will not be redirected back to the merchant page.

 > **[INFO]** **Note**    :
>
>  - The authorization URL can only be used once. If the authorization fails, you need to call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API again and provide a new     *authState*     value.
> - For Boost, if redirection to the merchant page is required, contact Antom Technical Support for configuration.

### 2\. Obtain the authorization code {#n2scrb}

 After the buyer completes authorization in Step 2, you can obtain the authorization code (    *authCode*    ) through one of the following methods:

 - Obtain     *authCode*     from the reconstructed URL returned by the payment method.
- Obtain     *authCode*     from the asynchronous notification of authorization sent by Antom.

<!-- TabGroup -->

**Tab: Obtain authCode from the reconstructed URL**

**Obtain**       ***authCode***       **from the reconstructed URL**       **[Client-side]**

   After successful authorization, the buyer will be redirected to the reconstructed URL returned by the payment method. This URL consists of three parts:

 - The value of     *authRedirectUrl*     passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, for example,   `https://www.alipay.com/`  .
- The value of     *authState*     passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, for example,   `663A8FA9-D836-48EE-8AA1-1FF682989DC7`  .
- The     *authCode*     returned by the payment method, for example,   `281004138596827069301079`  .

   The code below shows an example of a reconstructed URL:

   ```plain
https://www.alipay.com/&authState=663A8FA9-D836-48EE-8AA1-1FF682989DC7&authCode=281004138596827069301079
```

   You can obtain the     *authCode*     value from the reconstructed URL. Before using the     *authCode*    , please verify that the     *authState*     value in the reconstructed URL matches the     *authState*     value passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, and do one of the following:

 - If the     *authState*     values do not match, the reconstructed URL is considered untrustworthy, as malicious events such as attacks may have occurred during the redirection process. In this case, the     *authCode*     value in the URL cannot be used.
- If the     *authState*     values match, use the     *authCode*     value to apply for the payment token using the   [**applyToken**](https://docs.antom.com/ac/ams/accesstokenapp.md)   API.

**Tab: Obtain authCode from the asynchronous notification**

**Obtain**       ***authCode***       **from the asynchronous notification**    **[Server-side]**

   If you cannot get the reconstructed URL due to network issues or other reasons, you can follow the steps below to obtain the authorization code (    *authCode*    ) from the asynchronous notification of authorization sent by Antom:

 1. Configure the webhook URL to receive the asynchronous notification of authorization. Go to   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   >     **Developer**     >     **Notification URL**    , and add the notification address for the     **alipay.ams.authorizations.notify**     API. For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

   2. After the buyer completes authorization, Antom sends you an asynchronous notification through the        [**notifyAuthorization**](https://docs.antom.com/docs/ac/ams/notifyauth.md)   API. When you receive the asyncrhonous notification, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.  The following code shows an example of the asynchronous notification request:

   ```json
{
  "authCode": "28100113_1631148338197000019ba74",
  "authState": "489767958497",
  "authorizationNotifyType": "AUTHCODE_CREATED",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success",
    "resultStatus": "S"
  }
}
```

   Obtain the authorization code (    *authCode*    ) based on the value of     *result.resultStatus*     (only returns   `S`  ) in the authorization notification request:

   - `S`  : Indicates the authorization was successful and returns the following fields:

     - *authState*    : The unique ID generated for the authorization request. Verify that this value matches the     *authState*     specified in the   [**consult**](https://docs.antom.com/docs/ac/ams/authconsult.md)   request.
    - *authorizationNotifyType*    : Only returns   `AUTHCODE_CREATED`   in this scenario, indicating the buyer successfully initiated authorization for the tokenized payment on the merchant's client.
    - *authCode*    : The authorization code generated after successful authorization. Use this code to request a payment token.

 3. You need to verify the signature of the authorization notification sent by Antom:

   ```java
@PostMapping("/receiveAuthNotify")
@ResponseBody
public Result receiveAuthNotify(HttpServletRequest request, @RequestBody String notifyBody) {
    // retrieve the required parameters from http request
    String requestUri = request.getRequestURI();
    String requestMethod = request.getMethod();

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

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

        // deserialize the notification body
        AlipayAuthNotify authNotify = JSON.parseObject(notifyBody, AlipayAuthNotify.class);

        if (authNotify != null && "SUCCESS".equals(authNotify.getResult().getResultCode())) {
            // get authCode for applyToken
            return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
        }

    } catch (Exception e) {
        return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
    }

    return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}

```

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

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

   > **[INFO]** **Common questions**
>
>  **Q: Can both methods (reconstructed URL and asynchronous notification) be used to obtain**       ***authCode***      **?**
>
>  A: Yes. If multiple     *authCode*     values are received, use the first one received. Do not reuse the same     *authCode*     when requesting a payment token.
>
>   **Q: When will the notification be sent?**
>
>  A: After the buyer's authorization is completed, Antom sends an asynchronous notification to you.
>
>   **Q: Will the asynchronous notification be re-sent?**
>
>  A: Yes, the asynchronous notification will be re-sent    automatically within 24 hours for the following cases:
>
>  - If you didn't receive the asynchronous notification due to network reasons.
> - If you receive an asynchronous notification from Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format.
>
>  The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
>
>   **Q: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>   **Q: How to determine authorization failure?**
>
>  A: If you do not receive     *authCode*     within 15 minutes, the authorization can be considered failed. You can guide the buyer to re-initiate authorization.

<!-- /TabGroup -->

**Tab: Android**

# User experience {#e3cwGW}

 The following figures show the buyer's experience during the authorization and payment process:

## Authorization {#3RPu2a}

 Antom provides two authorization methods: App authorization and login authorization. The experience may vary depending on the payment method.

<!-- TabGroup -->

**Tab: App authorization**

The buyer is redirected to the payment method app to complete the authorization process.

   ![Mobile user experience flow diagram showing the App authorization process for Tokenized Payment on Android.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f283eb0d-29c9-4f39-ab84-d550ac352961.png)

**Tab: Login authorization**

The buyer is redirected to the payment method's H5 page, where they complete authorization by entering their account credentials.

   ![Mobile user experience flow diagram showing the login authorization process for Tokenized Payment on Android.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/118fa68c-8259-429f-83d2-7e9c5f206ee7.png)

<!-- /TabGroup -->

## Payment {#342OX}

 After the buyer clicks to pay, the user experience for initiating the deduction is shown as below:

 ![Mobile user experience screenshot showing the Tokenized Payment checkout experience flow.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/e23661d2-5537-49c5-bb71-1aa1e44ee1a0.png)

 Subsequent recurring payments do not require any buyer actions and can be directly deducted by your system.

# Payment flow {#e3LZVd}

 Before the first tokenized payment, you need to obtain the buyer's authorization. After the buyer authorizes, you can use the authorization code (    *authCode*    ) to obtain the payment token (    *accessToken*    ) and directly initiate the tokenization service. Authorization is not required for subsequent payments. The authorization and payment flow is outlined below:

 ![Sequence diagram illustrating the end-to-end Tokenized Payment authorization and payment flow.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/f294780e-aaff-4cb1-bfa9-f4b433fb04f0.png)

 1. **The buyer lands on the checkout page.**
2. **Obtain the authorization URL.**  
   After the buyer selects a payment method, call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API to obtain the authorization URL.

 3. **Obtain the authorization result.**  
   You can obtain the authorization result through the reconstructed URL returned by the payment method or through asynchronous notification.

 4. **Apply for the payment token.**  
   Call the   [**applyToken**](https://docs.antom.com/ac/ams/accesstokenapp.md)   API to apply for the payment token (    *accessToken*    ), and store the corresponding token after obtaining it.

 5. **Initiate a payment.**  
   After obtaining the buyer's authorization, you can directly call the   [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)   API to initiate the tokenization service.

 6. **Obtain the payment result.**  
   Obtain the payment result by using one of the following two methods:

   - Asynchronous notification: Specify     *paymentNotifyUrl*     in the      [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)      API to set the address for receiving asynchronous notifications. When the payment is successful or failed, 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.

# Integration steps {#Q3LFGi}

 To obtain the buyer's authorization and perform tokenized payment, please complete the following integration steps:

 1. Obtain the authorization URL
2. Redirect to the payment method page for authorization
3. Obtain the authorization result
4. Apply for payment token
5. Initiate a payment

## Step 1: Obtain the authorization URL   **[Server-side]** {#Y3hhf}

 You need to first obtain the authorization URL and then redirect the buyer to the authorization URL to complete authorization. For web integration, the authorization URL can be obtained from     *normalUrl*     in the response of the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API.

 Antom provides server-side API libraries for multiple languages. The following Java code examples require Java 6 or later:

### 1\. Install an API library {#kA3ZM}

 You can find the latest version on   [GitHub](https://github.com/alipay/global-open-sdk-java)  .

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

### 2\. Initialize the request instance {#k2qv2c}

  Create a singleton resource to make a request to Antom.  ```java
import com.alipay.global.api.AlipayClient;
import com.alipay.global.api.DefaultAlipayClient;
import com.alipay.global.api.model.constants.EndPointConstants;

public class Sample {
    public static final String        CLIENT_ID            = "";
    public static final String        ANTOM_PUBLIC_KEY     = "";
    public static final String        MERCHANT_PRIVATE_KEY = "";

    private final static AlipayClient CLIENT               = new DefaultAlipayClient(
        EndPointConstants.SG, MERCHANT_PRIVATE_KEY, ANTOM_PUBLIC_KEY, CLIENT_ID);

}
```

### 3\. Initiate a recurring payment authorization request {#Y334k}

 Pass the following parameters in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   request:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *authRedirectUrl* | Yes | URL used to redirect the buyer back to the merchant's page after the authorization is completed. |
| *authState* | Yes | A string passed to identify the authorization request. |
| *customerBelongsTo* | Yes | The target payment method for the authorization request. |
| *scopes* | Yes | Fixed as   `AGREEMENT_PAY`   for recurring payment authorization. |
| *terminalType* | Yes | Terminal type of which the merchant service applies to. Valid values are: - `APP`  : The buyer initiates the transaction on the merchant's mobile application. |
| *osType* | No | The operating system type. Valid values are: - `IOS`  : Indicates the operation system is Apple's iOS. - `ANDROID`  : Indicates the operation system is Google's Android.   > **[INFO]** **Note**    : This field is required when     *terminalType*     is   `APP`  . |

 The following code shows how to call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API to obtain the authorization URL:

   ```java
public static void authorizationConsult() {
    AlipayAuthConsultRequest alipayAuthConsultRequest = new AlipayAuthConsultRequest();

    // replace with your authState
    String authState = UUID.randomUUID().toString();
    alipayAuthConsultRequest.setAuthState(authState);

    // set the target payment method for which you are requesting authorization
    alipayAuthConsultRequest.setCustomerBelongsTo(CustomerBelongsTo.TOSSPAY);

    // set the authorization scope
    alipayAuthConsultRequest.setScopes(new ScopeType[]{ScopeType.AGREEMENT_PAY});

    // set terminalType
    alipayAuthConsultRequest.setTerminalType(TerminalType.WEB);

    // replace with your authRedirectUrl
    alipayAuthConsultRequest.setAuthRedirectUrl("http://www.yourRedirectUrl.com");

    // consult authorization
    AlipayAuthConsultResponse alipayAuthConsultResponse;
    try {
        alipayAuthConsultResponse = CLIENT.execute(alipayAuthConsultRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}
```

   The following code shows a sample of the request message:

   ```json
{
    "authRedirectUrl": "kademo://auth",
    "authState": "STATE_20250325101702257",
    "customerBelongsTo": "TOSSPAY",
    "scopes": [
        "AGREEMENT_PAY"
    ],
    "terminalType": "APP",
    "osType": "ANDROID"
}
```

### 4\. Receive the consult response {#S33SJo}

 The response from the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API contains the authorization URL to redirect the buyer to proceed with authorization:

   ```json
{
    "appIdentifier": "viva.republica.toss",
    "applinkUrl": "https://toss.onelink.me/3563614660?pid=referral&af_force_deeplink=true&af_dp=supertoss%3A%2F%2Fpay%2FbillingKey%3FbillingKey%3D0a5acO7999DSjKgJM8Kxf9%26skipResult%3Dfalse%26shouldAutoClose%3Dfalse&source=AlipayConnect&needCallback=false",
    "authUrl": "https://toss.onelink.me/3563614660?pid=referral&af_force_deeplink=true&af_dp=supertoss%3A%2F%2Fpay%2FbillingKey%3FbillingKey%3D0a5acO7999DSjKgJM8Kxf9%26skipResult%3Dfalse%26shouldAutoClose%3Dfalse&source=AlipayConnect&needCallback=false",
    "normalUrl": "https://pay.toss.im/payfront/web/billing?billingKey=0a5acO7999DSjKgJM8Kxf9&source=AlipayConnect&needCallback=false",
    "schemeUrl": "supertoss://pay/billingKey?billingKey=0a5acO7999DSjKgJM8Kxf9&source=AlipayConnect&needCallback=false",
    "webRequestMethod": "GET",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

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

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The request was successful. | Successfully obtained the authorization URL (one or more of     *applinkUrl*    /    *normalUrl*    /    *schemeUrl*    ). For detailed information of each URL, refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)  . |
| `U` | Unknown error. | Please use a new     *authState*     and call the API again. If the issue persists, contact Antom Technical Support. |
| `F` | The request failed. | Please check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid. |

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

   > **[INFO]** **Common questions**
>
>  **Q: Multiple URLs are returned in the response of the**       [**consult**](https://docs.antom.com/ac/ams/authconsult.md)       **API. Which one should I use?**
>
>  A: For different payment methods and terminal types, Antom may return one or more of the following links:     *normalUrl*    ,     *applinkUrl*    , or     *schemeUrl*    . The merchant server needs to pass these URLs to the merchant front-end for redirection. For detailed information of each URL, refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)  .
>
>   **Q: How to set**       ***terminalType***      **?**
>
>  A: The valid values of     *terminalType*     are:
>
>  - If the buyer initiates a transaction from a mobile app, the     *terminalType*     needs to be specified as   `APP`  . Add the     *osType*     parameter and fill in the corresponding system parameters   `ANDROID`   or   `IOS`   according to the buyer's mobile device.
>
>  You must pass the correct     *terminalType*     to obtain the correct redirect URL. Passing an incorrect value may impact the authorization success rate.
>
>   **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>   **Q: What should I do after receiving the returned**       ***normalUrl***      **?**
>
>  A: For transactions performed in PC browsers, Antom returns the     *normalUrl*     parameter in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   response. Your server needs to pass this URL to the client for redirection. Do not cache the returned     *normalUrl*    . When re-initiating authorization, you need to obtain a new     *normalUrl*     for redirection.

## Step 2: Redirect to the payment method page for authorization   **[Client-side]** {#N33Jtb}

 After the server obtains the authorization URL, it needs to pass this URL to the client. Your client will redirect the buyer to the recurring payment authorization page. The code below shows an example of loading the URL in the client (the URL refers to     *applinkUrl*    ,     *schemeUrl*    , or     *normalUrl*     returned by the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   response):

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

   For more information on the URLs returned by different payment methods, see   [URLs returned for some payment methods](https://docs.antom.com/ac/auto_debit/redirection_details.md)   and refer to   [Best practices for configuring the authorization URL](https://docs.antom.com/ac/auto_debit/best_practice.md)   to learn how to use these URLs.

 > **[INFO]** **Common questions**
>
>  **Q: How to handle different payment experiences?**
>
>  A: Authorization experiences vary by the URL type. Some URLs redirect buyers to the payment method's native app, while others complete authorization within an H5 page. For details, see   [URLs returned for some payment methods](https://docs.antom.com/ac/auto_debit/redirection_details.md)  .

 The following figure shows the rendering effect of the payment method authorization page:

 ![Mobile user experience screenshot showing the rendering effect of the payment method authorization page for Tokenized Payment.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/0775fe7f-e7d9-48c7-ba26-239d88eb976e.png)

## Step 3: Obtain the authorization result {#3UxG0}

### 1\. Redirect to the merchant page {#N3YcbU}

 When the buyer performs authorization on the relevant payment method authorization page, the authorization may be successful or fail. In the event of authorization success or failure, the following describes the subsequent redirects:

 - **Authorization success**    : If the authorization is successful, the buyer will be redirected back to the merchant page. The merchant page address is a reconstructed URL consisting of     *authRediectUrl*    ,     *authCode*    , and     *authState*    . However, the redirection may fail due to network issues or buyer actions.
- **Authorization failure**    :

   - If the buyer cancels the authorization or exits the authorization page, some payment methods will redirect the buyer back to the merchant page. The merchant page address is determined by     *authRediectUrl*    .
  - If the buyer does not authorize before the timeout or authorization fails, the buyer will not be redirected back to the merchant page.

 > **[INFO]** **Note**    :
>
>  - The authorization URL can only be used once. If the authorization fails, you need to call the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API again and provide a new     *authState*     value.
> - For Boost, if redirection to the merchant page is required, contact Antom Technical Support for configuration.

### 2\. Obtain the authorization code {#n33crb}

 After the buyer completes authorization in Step 2, you can obtain the authorization code (    *authCode*    ) through one of the following methods:

 - Obtain     *authCode*     from the reconstructed URL returned by the payment method.
- Obtain     *authCode*     from the asynchronous notification of authorization sent by Antom.

<!-- TabGroup -->

**Tab: Obtain authCode from the reconstructed URL**

**Obtain**       ***authCode***       **from the reconstructed URL**       **[Client-side]**

   After successful authorization, the buyer will be redirected to the reconstructed URL returned by the payment method. This URL consists of three parts:

 - The value of     *authRedirectUrl*     passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, for example,   `https://www.alipay.com/`  .
- The value of     *authState*     passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, for example,   `663A8FA9-D836-48EE-8AA1-1FF682989DC7`  .
- The     *authCode*     returned by the payment method, for example,   `281004138596827069301079`  .

   The code below shows an example of a reconstructed URL:

   ```plain
https://www.alipay.com/&authState=663A8FA9-D836-48EE-8AA1-1FF682989DC7&authCode=281004138596827069301079
```

   You can obtain the     *authCode*     value from the reconstructed URL. Before using the     *authCode*    , please verify that the     *authState*     value in the reconstructed URL matches the     *authState*     value passed in the   [**consult**](https://docs.antom.com/ac/ams/authconsult.md)   API, and do one of the following:

 - If the     *authState*     values do not match, the reconstructed URL is considered untrustworthy, as malicious events such as attacks may have occurred during the redirection process. In this case, the     *authCode*     value in the URL cannot be used.
- If the     *authState*     values match, use the     *authCode*     value to apply for the payment token using the   [**applyToken**](https://docs.antom.com/ac/ams/accesstokenapp.md)   API.

**Tab: Obtain authCode from the asynchronous notification**

**Obtain**       ***authCode***       **from the asynchronous notification**    **[Server-side]**

   If you cannot get the reconstructed URL due to network issues or other reasons, you can follow the steps below to obtain the authorization code (    *authCode*    ) from the asynchronous notification of authorization sent by Antom:

 1. Configure the webhook URL to receive the asynchronous notification of authorization. Go to   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)   >     **Developer**     >     **Notification URL**    , and add the notification address for the     **alipay.ams.authorizations.notify**     API. For detailed steps, refer to   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .

   2. After the buyer completes authorization, Antom sends you an asynchronous notification through the        [**notifyAuthorization**](https://docs.antom.com/docs/ac/ams/notifyauth.md)   API. When you receive the asyncrhonous notification, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.  The following code shows an example of the asynchronous notification request:

   ```json
{
  "authCode": "28100113_1631148338197000019ba74",
  "authState": "489767958497",
  "authorizationNotifyType": "AUTHCODE_CREATED",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success",
    "resultStatus": "S"
  }
}
```

   Obtain the authorization code (    *authCode*    ) based on the value of     *result.resultStatus*     (only returns   `S`  ) in the authorization notification request:

   - `S`  : Indicates the authorization was successful and returns the following fields:

     - *authState*    : The unique ID generated for the authorization request. Verify that this value matches the     *authState*     specified in the   [**consult**](https://docs.antom.com/docs/ac/ams/authconsult.md)   request.
    - *authorizationNotifyType*    : Only returns   `AUTHCODE_CREATED`   in this scenario, indicating the buyer successfully initiated authorization for the tokenized payment on the merchant's client.
    - *authCode*    : The authorization code generated after successful authorization. Use this code to request a payment token.

 3. You need to verify the signature of the authorization notification sent by Antom:

   ```java
@PostMapping("/receiveAuthNotify")
@ResponseBody
public Result receiveAuthNotify(HttpServletRequest request, @RequestBody String notifyBody) {
    // retrieve the required parameters from http request
    String requestUri = request.getRequestURI();
    String requestMethod = request.getMethod();

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

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

        // deserialize the notification body
        AlipayAuthNotify authNotify = JSON.parseObject(notifyBody, AlipayAuthNotify.class);

        if (authNotify != null && "SUCCESS".equals(authNotify.getResult().getResultCode())) {
            // get authCode for applyToken
            return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
        }

    } catch (Exception e) {
        return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
    }

    return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}

```

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

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

   > **[INFO]** **Common questions**
>
>  **Q: Can both methods (reconstructed URL and asynchronous notification) be used to obtain**       ***authCode***      **?**
>
>  A: Yes. If multiple     *authCode*     values are received, use the first one received. Do not reuse the same     *authCode*     when requesting a payment token.
>
>   **Q: When will the notification be sent?**
>
>  A: After the buyer's authorization is completed, Antom sends an asynchronous notification to you.
>
>   **Q: Will the asynchronous notification be re-sent?**
>
>  A: Yes, the asynchronous notification will be re-sent    automatically within 24 hours for the following cases:
>
>  - If you didn't receive the asynchronous notification due to network reasons.
> - If you receive an asynchronous notification from Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format.
>
>  The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
>
>   **Q: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.
>
>   **Q: How to determine authorization failure?**
>
>  A: If you do not receive     *authCode*     within 15 minutes, the authorization can be considered failed. You can guide the buyer to re-initiate authorization.

<!-- /TabGroup -->

<!-- /ToggleTab -->

## Step 4: Apply for payment token   **[Server-side]** {#lJsTn}

 After obtaining the authorization code (    *authCode*    ), you must call the   [**applyToken**](https://docs.antom.com/docs/ac/ams/accesstokenapp.md)   API within one minute to request a payment token (    *accessToken*    ). Otherwise, the     *authCode*     will expire and become invalid. Only after obtaining     *accessToken*     can subsequent tokenized payments be made from the buyer's account.

 When calling the   [**applyToken**](https://docs.antom.com/docs/ac/ams/accesstokenapp.md)   API, ensure the following parameters are correctly passed in the request:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *grantType* | Yes | Pass in the fixed value   `AUTHORIZATION_CODE`  . |
| *customerBelongsTo* | Yes | Specify the target payment method for which you are requesting authorization. |
| *authCode* | Yes | Pass in the value of     *authcode*     that you obtained in Step 3. |

 The following code is a sample of calling the   [**applyToken**](https://docs.antom.com/docs/ac/ams/accesstokenapp.md)   API:

 ```java
public static void applyToken() {
    String authCode = "yourAuthCode";
    AlipayAuthApplyTokenRequest alipayPayRequest = new AlipayAuthApplyTokenRequest();

    // set grantType
    alipayPayRequest.setGrantType(GrantType.AUTHORIZATION_CODE);
    // set the target payment method for which you are requesting authorization
    alipayPayRequest.setCustomerBelongsTo(CustomerBelongsTo.GCASH);
    // set authCode
    alipayPayRequest.setAuthCode(authCode);

    // apply for the token
    AlipayAuthApplyTokenResponse authApplyTokenResponse;
    try {
        authApplyTokenResponse = CLIENT.execute(alipayPayRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}
```

   The following sample code shows a request message of applying for the payment token:

 ```json
{
  "authCode": "663A8FA9D83648EE8AA11FF68298XXXX",
  "customerBelongsTo": "GCASH",
  "grantType": "AUTHORIZATION_CODE"
}
```

   The following sample code shows a response message of applying for the payment token:

 ```json
{
  "accessToken": "281011030220200914TLsu9RhgUv87Lf1111****",
  "accessTokenExpiryTime": "2022-09-14T17:14:16+08:00",
  "extendInfo": "{"userId":"100000111111****","userLoginId":"6017271****"}",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "Success",
    "resultStatus": "S"
  },
  "userLoginId": "6017271****"
}
```

   The following table shows the possible values of     *result.resultStatus*     in the response message for applying for the payment token. Please handle the result according to the guidance provided:

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | The request was successful. | Successfully obtained     *accessToken*    , and the following fields are returned: - *accessToken*    : The tokenized payment ID generated by Antom for subsequent payments. - *accessTokenExpiryTime*    : For the specific expiry time of     *accessToken*    , refer to   [Validity period of     *accessToken*](#YgXVq)  . If the     *accessToken*     expires, you need to guide the buyer to authorize again. - *userLoginId*    : The login ID used by the buyer when registering for the payment method. You can store this account information for display during subsequent payments. Note that not all payment methods will return this information, refer to   [Features of payment methods](#qkEDC)   for details. |
| `U`  ​ | Unknown error. | Please call the API again with the same parameters. If the issue persists, contact Antom Technical Support. |
| `F` | The request failed. | Please handle the relevant issues based on     *result.resultCode*     message. |

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

   > **[INFO]** **Common questions**
>
>  **Q: Can**       ***authCode***       **be reused?**  
>    A: No.     *authCode*     can only be used once.
>
>  ​
>
>  **Q: How long is the validity period of**       ***authCode***      **?**
>
>  A: 1 minute for common scenarios. Ensure the payment token is requested within 1 minute.
>
>  ​
>
>  **Q: Can I obtain the payment token through asynchronous notifications?**  
>    A: No. The payment token can only be applied for by calling the   [**applyToken**](https://docs.antom.com/docs/ac/ams/accesstokenapp.md)   API.

### Validity period of payment token {#YgXVq}

 Regarding the payment methods supported by Tokenized Payment, the validity period of payment token (    *accessToken*    ) is shown in the following table:

 | **Payment method** | **Validity period of**       ***accessToken*** |
| --- | --- |
| [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md) | 92 years |
| [Kakao Pay](https://docs.antom.com/ac/antomop/kakaopay.md) | 100 years |
| [AlipayHK](https://docs.antom.com/ac/antomop/aplusalipayhk.md) | 100 years |
| [GCash](https://docs.antom.com/ac/antomop/gcash.md) | 100 years |
| [DANA](https://docs.antom.com/ac/antomop/DANA.md) | 100 years |
| [Touch'n Go eWallet](https://docs.antom.com/ac/antomop/touchngo.md) | 100 years |
| [TrueMoney](https://docs.antom.com/ac/antomop/truemoney.md) | 100 years |
| [PayPay](https://docs.antom.com/ac/antomop/paypay_mdx.md) | 1 year    <sup>Note</sup> |
| [NAVER Pay](https://docs.antom.com/ac/antomop/naverpay.md) | 2 years |
| [Boost](https://docs.antom.com/ac/antomop/boost.md) | 100 years |
| [KrungThai Bank](https://docs.antom.com/ac/antomop/kyb.md) | 76 years |
| [Siam Commercial Bank](https://docs.antom.com/ac/antomop/scb.md) | 76 years |
| [Grabpay SG](https://docs.antom.com/ac/antomop/grabpay_sg.md) | 10 years |
| [Grabpay MY/PH](https://docs.antom.com/ac/antomop/grabpay_.md) | 10 years |
| [K PLUS](https://docs.antom.com/ac/antomop/kplus.md) | 100 years |
| [Maya](https://docs.antom.com/ac/antomop/maya.md) | 100 years |
| [LINE Pay](https://docs.antom.com/ac/antomop/rabbitlinepay.md) | 100 years |
| [Toss Pay](https://docs.antom.com/ac/antomop/tosspay.md) | 14 years |
| [ZaloPay](https://docs.antom.com/ac/antomop/zalopay.md) | 10 years |

 > **[INFO]** **Note**    : After successfully completing the initial authorization with PayPay, the token is valid for one year. If any successful transaction occurs within the validity period, the token's validity will automatically extend by an additional year, starting from the date of the successful transaction.

## Step 5: Initiate a payment   **[Server-side]** {#Vl7Ta}

 With a successful authorization, you can provide the buyer with tokenization services. Funds will be automatically deducted for subsequent purchases without requiring the buyer to re-enter payment information.

 Specify the following parameters when initiating a payment:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *productCode* | Yes | The payment product that is being used. For Tokenized Payment, the value is fixed as   `AGREEMENT_PAYMENT`  . |
| *paymentRequestId* | Yes | The unique ID generated by the merchant for each payment request. |
| *paymentAmount* | Yes | The payment amount in the smallest currency unit. For example,   `CNY`   in cents,   `KRW`   in won. |
| *paymentMethod* | Yes | The payment method that is used. |
| *paymentMethod.paymentMethodId* | Yes | The payment token (    *accessToken*    ) obtained from the   [**applyToken**](https://docs.antom.com/docs/ac/ams/accesstokenapp.md)   API. |
| *paymentNotifyUrl* | No | The address for receiving payment result notifications. It can be set through the API or or   [set as a fixed value through Antom Dashboard](https://docs.antom.com/ac/merchant_service/notification.md)  . |
| *settlementStrategy* | No | The settlement strategy for the payment request. |
| *order* | Yes | Order information, including order amount, order ID, and order description. |
| *env* | Yes | Terminal type where the transaction was initiated. For example, when the transaction is initiated from the merchant's PC browser, the value of     *env.terminalType*     is   `WEB`  . |

 The above parameters are the basic parameters for initiating a payment, refer to   [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)   for full parameters and additional requirements for certain payment methods.

 The following code is a sample of calling the   [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)   API:

 ```java
public static void pay() {
    AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
    alipayPayRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);

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

    // set amount
    // you should convert amount unit(in practice, amount should be calculated on your serverside)
    Amount amount = Amount.builder().currency("SGD").value("550000").build();
    alipayPayRequest.setPaymentAmount(amount);

    // set paymentMethod
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("GCASH").
    paymentMethodId("2828XXX77801726307481000Iba1Pm20IU171000179").build();
    alipayPayRequest.setPaymentMethod(paymentMethod);

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

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

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

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

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

 The following code shows a sample of the request message:

 ```json
{
  "env": {
    "clientIp": "114.121.121.01",
    "terminalType": "WEB"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "SGD",
      "value": "550000"
    },
    "orderDescription": "antom api testing order",
    "referenceOrderId": "f69cb774-8d47-4da9-bf91-08c656581cdf"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "550000"
  },
  "paymentMethod": {
    "paymentMethodId": "2828XXX77801726307481000Iba1Pm20IU171000179",
    "paymentMethodType": "GCASH"
  },
  "paymentNotifyUrl": "http://www.yourNotifyUrl.com",
  "paymentRequestId": "AGREEMENT_PAYMENT_REQUEST_2020070316170XXXX",
  "productCode": "AGREEMENT_PAYMENT"
}
```

 The following code shows a sample of the response message:

 ```json
{
  "paymentAmount": {
    "currency": "SGD",
    "value": "550000"
  },
  "paymentCreateTime": "2020-07-03T01:17:50-07:00",
  "paymentId": "2020070311401080010018840027964XXXX",
  "paymentRequestId": "AGREEMENT_PAYMENT_REQUEST_2020070316170XXXX",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "Success",
    "resultStatus": "S"
  }
}
```

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

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Payment was successful. | No further action is needed. |
| `U`  ​ | Payment is being processed. | Please poll the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API or wait for the asynchronous notification from   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)        for the payment result. |
| `F` | Payment failed. | - In the scenario where the buyer clicks to pay, handle the relevant issues based on the message from     *result.resultCode*    . - In the scenario of recurring payments, if the deduction initiated from the merchant side fails, handle it based on the return value of     *result.resultCode*    :     - `USER_BALANCE_NOT_ENOUGH`  : If you need to call the API again, please note that you can retry up to 2 times within 24 hours. Frequent retries may result in rate limiting on the Antom side.   - `INVALID_ACCESS_TOKEN`  : Please guide the buyer to re-authorize.   - `USER_NOT_EXIST`  : Please guide the buyer to re-authorize.   - Other error codes: Please handle or retry after confirming the specific reason. |

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

 > **[INFO]** **Common questions**
>
>  **Q: How to set**       ***terminalType***      **?**
>
>  A: The valid values of     *terminalType*     are:
>
>  - If the buyer initiates a transaction from a PC browser, the     *terminalType*     needs to be specified as   `WEB`  .
> - If the buyer initiates a transaction from the mobile browser, the     *terminalType*     needs to be specified as   `WAP`  . Add the     *osType*     parameter and fill in the corresponding system parameters   `ANDROID`   or   `IOS`   according to the buyer's mobile device.
>
>   **Q: Can I use Chinese characters in the value of the request parameters?**
>
>  A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
>
>   **Q: How to set the address to receive payment notification?**
>
>  A: Specify     *paymentNotifyUrl*     in the   [**pay (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md)   API to receive the asynchronous notification about the payment result (  [**notifyPayment**](https://docs.antom.com/docs/ac/ams/paymentrn_online.md)  ), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.

### Obtain payment result {#WgF7V}

 You can obtain the payment result using one of the following methods:

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

<!-- TabGroup -->

**Tab: Receive asynchronous notifications**

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

 When the payment reaches a final status of success or failure, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications:

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

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

   ```json
{
  "actualPaymentAmount": {
    "currency": "HKD",
    "value": "98080"
  },
  "customsDeclarationAmount": {},
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "HKD",
    "value": "98080"
  },
  "paymentCreateTime": "2024-09-27T00:23:36-07:00",
  "paymentId": "202409271940108001001881E0211235544",
  "paymentRequestId": "bc93d19e-e1f6-4b68-b6b1-3d6ddc2a792a",
  "paymentTime": "2024-09-27T00:23:46-07:00",
  "pspCustomerInfo": {
    "pspCustomerId": "20881221121****",
    "pspName": "ALIPAY_HK"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

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

   | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | Payment was successful. | You can obtain the following field information: - *paymentRequestId*    : The payment request ID used for consult, cancellation, and reconciliation. - *paymentId*    : The payment order ID generated by Antom, used for refund and reconciliation. - *paymentAmount*    : The payment amount. |
| `F` | Payment failed. | Please guide the buyer to retry payment. |

 **2\. Verify the asynchronous notification**

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

   You need to verify the signature of the payment notification sent by Antom:

   ```java
/**
 * receive notify
 *
 * @param request    request
 * @param notifyBody notify body
 * @return Result
 */
@PostMapping("/receiveNotify")
@ResponseBody
public Result receiveNotify(HttpServletRequest request, @RequestBody String notifyBody) {
    // retrieve the required parameters from http request
    String requestUri = request.getRequestURI();
    String requestMethod = request.getMethod();

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

    try {
        // verify the signature of notification
        boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId,
                                                          requestTime, signature, notifyBody, ANTOM_PUBLIC_KEY);
        if (!verifyResult) {
            throw new RuntimeException("Invalid notify signature");
        }
        // deserialize the notification body
        JSONObject jsonObject = JSON.parseObject(notifyBody);
        String notifyType = (String)jsonObject.get("notifyType");
        if("PAYMENT_RESULT".equals(notifyType)){
            AlipayPayResultNotify paymentNotify = jsonObject.toJavaObject(AlipayPayResultNotify.class);
            if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
                // handle your own business logic
                // e.g. The relationship between payment information and users is kept in the database
                System.out.println("receive payment notify: " + JSON.toJSONString(paymentNotify));
                return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
            }
        }

    } catch (Exception e) {
        return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
    }

    return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}
```

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

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

   > **[INFO]** **Common questions**
>
>  **Q: When will the notification be sent?**
>
>  A: It depends on whether the payment is completed:
>
>  - If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
> - If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
>
>   **Q: Will the asynchronous notification be re-sent?**
>
>  A: Yes, the asynchronous notification will be re-sent    automatically within 24 hours for the following cases:
>
>  - If you didn't receive the asynchronous notification due to network reasons.
> - If you receive an asynchronous notification from Antom, but you did not respond to the notification in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format.
>
>  The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
>
>   **Q: When responding to an asynchronous notification, do I need to add a digital signature?**
>
>  A: If you receive an asynchronous notification from Antom, you are required to return the response in the   [Sample code](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A)   format, but you do not need to countersign the response.

**Tab: Inquire about the result**

You can also inquire about the payment result by calling the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API using     *paymentRequestId*     from the payment request.

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

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

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

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

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

   The following sample code shows a response message of   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)  :

   ```json
{
  "actualPaymentAmount": {
    "currency": "USD",
    "value": "1"
  },
  "customsDeclarationAmount": {
    "currency": "CNY",
    "value": "7"
  },
  "paymentAmount": {
    "currency": "USD",
    "value": "1"
  },
  "paymentId": "20250305194010800100188690281017336",
  "paymentMethodType": "ALIPAY_CN",
  "paymentRedirectUrl": "https://checkout.antom.com/checkout-page/pages/payment/index.html?sessionData=%2BCUim8L0KviXagaygm9xBL5jZ%2F75w6gAX1nn8pcuFuGkIsMoHtD6U88YSyMrMJvorbwnBg5uQv8e6pyvIpjDQQ%3D%3D%26%26SG%26%26188%26%26eyJleHRlbmRJbmZvIjoie1wiT1BFTl9NVUxUSV9QQVlNRU5UX0FCSUxJVFlcIjpcInRydWVcIixcImxvY2FsZVwiOlwiZW5fVVNcIixcImRpc3BsYXlBbnRvbUxvZ29cIjpcInRydWVcIn0iLCJwYXltZW50U2Vzc2lvbkNvbmZpZyI6eyJwYXltZW50TWV0aG9kQ2F0ZWdvcnlUeXBlIjoiQUxMIiwicHJvZHVjdFNjZW5lIjoiQ0hFQ0tPVVRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifSwic2VjdXJpdHlDb25maWciOnsiYXBwSWQiOiIiLCJhcHBOYW1lIjoiT25lQWNjb3VudCIsImJpelRva2VuIjoiNlRjZGJyMnJGM3JQWXg0aGtWckhxYnZqIiwiZ2F0ZXdheSI6Imh0dHBzOi8vaW1ncy1zZWEuYWxpcGF5LmNvbS9tZ3cuaHRtIiwiaDVnYXRld2F5IjoiaHR0cHM6Ly9vcGVuLXNlYS1nbG9iYWwuYWxpcGF5LmNvbS9hcGkvb3Blbi9yaXNrX2NsaWVudCIsIndvcmtTcGFjZUlkIjoiIn0sInNraXBSZW5kZXJQYXltZW50TWV0aG9kIjpmYWxzZX0%3D",
  "paymentRequestId": "PAYMENT_20250305220039086_AUTO",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2025-03-05T06:02:34-08:00",
  "pspCustomerInfo": {
    "pspName": "ALIPAY_CN"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}
```

   Obtain the payment status based on the value of     *paymentStatus*     in the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   response:

 - `SUCCESS`  : Payment was successful.
- `FAIL`  : Payment failed.
- `PROCESSING`  : Payment is being processed.
- `CANCELLED`  : Payment was canceled.

 > **[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*    : Indicates the result of the   [**inquiryPayment**](https://docs.antom.com/ac/ams/paymentri_online.md)   API call, the payment result needs to be confirmed through the value of     *paymentStatus*    :
>
>    - `SUCCESS`  : Payment was successful.
>   - `FAIL`  : Payment failed.
>   - `PROCESSING`  : Payment is being processed.
>   - `CANCELLED`  : Payment was canceled.
>
>  - *paymentAmount*    : The payment amount.

<!-- /TabGroup -->

# After payments {#BJbEu}

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

## Cancel a transaction {#Otb6j}

 After the buyer places an order, you can close the transaction within a certain period by using the   [**cancel**](https://docs.antom.com/ac/ams/paymentc_online.md)   API. For detailed instructions, refer to   [Cancel](https://docs.antom.com/ac/auto_debit/cancel.md)  .

## Revoke authorization {#Ht5HC}

 Once the buyer completes the authorization process, you are required to grant your buyer the ability to revoke authorization for the following reasons:

 - To empower the buyer with full control over their authorized agreements, enabling them to terminate the authorization relationship at any time based on their account security strategy or service usage requirements.
- Certain payment methods impose system-level restrictions, which may limit a single e-wallet account to only one or a small number of valid authorization credentials with the same merchant.

 For detailed instructions on implementing the authorization revocation, refer to   [Revoke authorization](https://docs.antom.com/ac/auto_debit/revoke_auth.md)  .

## Refund {#kg4oU}

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

## Reconciliation {#AoEw6}

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

# Best practices {#x29yr}

 Antom provides you with best practice solutions such as agreement-signing QR code optimization, client experience optimization, the display of payment results, payment-retry solution, and API timeout settings. For more details, refer to   [Best practices](https://docs.antom.com/ac/auto_debit/practice.md)  .

# Features of payment methods {#qkEDC}

 The table below shows which payment method returns the buyer login ID (    *userLoginId*    ) after buyer authorization, and the example returned ID:

 | **Payment method** | **Whether**       ***userLoginID***       **is returned** | **Example** |
| --- | --- | --- |
| [Alipay](https://docs.antom.com/ac/antomop/alipay_cn.md) | Yes | `n_c***@hotmail.com` `186XXXXXX21` |
| [AlipayHK](https://docs.antom.com/ac/antomop/aplusalipayhk.md) | Yes | `852-66****37` |
| [GCash](https://docs.antom.com/ac/antomop/gcash.md) | Yes | `63-********90` |
| [DANA](https://docs.antom.com/ac/antomop/DANA.md) | Yes | `62-**********06` |
| [Touch'n Go eWallet](https://docs.antom.com/ac/antomop/touchngo.md) | Yes | `601*******32` |
| [Kakao Pay](https://docs.antom.com/ac/antomop/kakaopay.md) | Yes | `gm****ina@naver.com` |
| [TrueMoney](https://docs.antom.com/ac/antomop/truemoney.md) | Yes | `+66*****4713` |
| [PayPay](https://docs.antom.com/ac/antomop/paypay_mdx.md) | Yes | `T1mNO****yDYJf` |
| [NAVER Pay](https://docs.antom.com/ac/antomop/naverpay.md) | Yes | `gksd******@naver.com` |
| [Boost](https://docs.antom.com/ac/antomop/boost.md) | Yes | `+4420****5666` |
| [Maya](https://docs.antom.com/ac/antomop/maya.md) | Yes | `+6394******9412` |
| [LINE Pay](https://docs.antom.com/ac/antomop/rabbitlinepay.md) | Yes | `***ันทร์` |
| [Toss Pay](https://docs.antom.com/ac/antomop/tosspay.md) | No | `TOSS` |
| [ZaloPay](https://docs.antom.com/ac/antomop/zalopay.md) | Yes | `****7396` |
