# APM recurring payments

> Learn how to accept APM recurring payments through API-only subscription integration.

 Subscription payment is an automatic recurring payment solution that helps you collect payments on a periodic basis. With a single authorization, the buyer can link their payment accounts to enjoy ongoing subscription services. It also supports dynamic adjustments to subscription settings such as modifying the billing cycle or amount, canceling renewals, or terminating services. The entire process is both convenient and secure.

 This document focuses on API-based integration for APM. Different payment methods require different integration strategies, each with its own advantages and disadvantages that affect development costs and user experience. To make the best technical decision for your business, please refer to   [Choose your integration path](https://docs.antom.com/ac/subscriptionpay/use_cases.md)   for a detailed comparison of integration options and their applicable use cases.

## User experience {#ToetX}

<!-- TabGroup -->

**Tab: First-time binding**

Before starting a subscription payment, you need to link your account and authorize the payment first.

 ![APM first-time binding and subscription authorization flow via API-only integration for mobile terminal](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/4d0a7546-ae04-49d1-a0c4-e56d8fbf797b.png)

**Tab: Subsequent payments**

Antom's server initiates subsequent recurring payments. Upon receiving the asynchronous renewal notification, the merchant’s server renews the buyer’s subscription service. No user interaction is required.

<!-- /TabGroup -->

## Workflow {#JGrYi}

 The following diagram illustrates the process of subscription cycle, creating subscription, and receiving payment notifications.

<!-- TabGroup -->

**Tab: Subscription cycle**

The following diagram illustrates the entire subscription cycle, including subscription creation, payment method binding and contract signing, completion of the first payment, and refund processing when necessary. The process ensures the valid activation of subscriptions and the security and transparency of all payment transactions.

 ![Subscription lifecycle diagram of subscription creation phase for APM API-only integration](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/16096160-81da-487d-8f04-a63fae658ef6.png) ![Subscription lifecycle diagram of the first payment completion for APM API-only integration](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/f2808015-81db-41df-bac5-faf71eebbc3d.png)

**Tab: Create subscription**

![Sequence diagram of APM subscription creation via API-only integration](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/8b2e294b-6647-48a0-ac2d-f14032442732.png) Please follow the steps below to create a subscription relationship:

 1. The buyer enters the checkout page and selects a payment method.
2. The merchant server initiates a subscription creation request based on the payment method, subscription cycle, periodic amount, product, and other transaction information.
3. The merchant client redirects to the URL returned by the subscription creation request or invokes the corresponding application to complete the authorization.
4. The merchant server receives the subscription creation result notification and payment result notification from the payment platform, and carries out the corresponding business processing based on the results.

**Tab: Receive payment notification**

After the subscription relationship is created, Antom will initiate charges to the buyer according to the specified cycle and amount, and return the charge results to the merchant server. Upon receiving the subscription payment result notification, the merchant server can perform corresponding business processing based on the result.

 ![Sequence diagram of receiving APM subscription renewal payment notifications via API-only integration](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2026/png/5a0052ce-7eba-49e4-be79-37d9073cdf29.png)

<!-- /TabGroup -->

## Integration preparations {#zmnOh}

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

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

## Integration steps {#CnuPc}

 Start your integration by taking the following steps:

 1. Add a list of payment methods
2. Create a subscription
3. Redirect authorization binding link
4. Receive asynchronous notification of subscription result
5. Receive asynchronous notification of subscription renewal

### Step 1: Add a list of payment methods  **[Client-side]** {#gjPpX}

 In a subscription scenario, when the buyer enters the payment method selection page, the payment method identifiers and names to be integrated for this transaction should be displayed, allowing the buyer to choose according to their needs and preferences. Please contact Antom technical support to obtain the identifiers and names of each payment method.

 > **[INFO]** **Note**    : The payment method list page needs to be implemented by you.

### Step 2: Create a subscription  **[Server-side]** {#uyxKl}

 Call the   [**create**](https://docs.antom.com/ac/ams/create_sub.md)        API, you need to collect the user’s payment method, subscription cycle, periodic amount, order information, and other details to submit the subscription creation request.
 The subscription creation process includes the following key parameters:

 | **Parameter name** | **Required** | **Description** |
| --- | --- | --- |
| *periodRule.periodType* | Yes | The subscription period type   , supporting four types of cycles:   `YEAR`  ,   `MONTH`  ,   `WEEK`  , and   `DAY`  . |
| *subscriptionNotificationUrl* | Yes | The URL that is used to receive the subscription result notification. |
| *subscriptionRequestId* | Yes | The unique ID assigned by a merchant to identify a subscription request.    Each time a subscription creation is initiated, a new ID must be generated. |
| *subscriptionDescription* | Yes | The description of the subscription. |
| *subscriptionStartTime* | Yes | The date and time when the subscription becomes active. |
| *subscriptionExpiryTime* | No | A specific date and time after which the created subscription expires. |
| *subscriptionRedirectUrl* | Yes | The merchant page URL that the user is redirected to after authorizing the subscription.    The page to be displayed should be based on the server-side result and is not fixed as a success page. |
| *paymentAmount* | Yes | The payment amount charged to the user per subscription period. |
| *paymentMethod.paymentMethodType* | Yes | The payment method that is used to accept the subscription payment. |
| *paymentNotificationUrl* | No | The URL that is used to receive the payment result notification for each subscription period. You can also configure the subscription notification URL in   [Antom Dashboard](https://global.alipay.com/ilogin/account_login.htm?goto=https%3A%2F%2Fglobal.alipay.com%2Fopen%2Fconsole%2Fdeveloper%2Fapp%2Flist&from_site=MERCHANT&terminal_type=pc&loginScene=MERCHANT&locale=cn&loginId=&_route=QK)  . If you specify this URL in both this API and Antom Dashboard, the URL configured in the API takes precedence. |
| *settlementStrategy.currency* | Yes | The ISO currency code of the currency that the merchant wants to be settled against.       If multiple settlement currencies are contracted for the business, they need to be specified in the API. |
| *orderInfo* | Yes | The order information for the subscription. |
| *env.TerminalType* | Yes | The terminal type the merchant service applies to. Valid values are: - `WEB`  : The client-side terminal type is a website, which is opened via a PC browser. - `WAP`  : The client-side terminal type is an H5 page, which is opened via a mobile browser. - `APP`  : The client-side terminal type is a mobile application. |
| *env.osType* | No | The OS type. Valid values are: - `IOS`  : indicates the operation system is Apple's iOS. - `ANDROID`  : indicates the operation system is Google's Android. |

 The following code is an example of initiating a request by calling the   [**create**](https://docs.antom.com/ac/ams/create_sub.md)   API:

 ```java
public static void createSubscription() {
    AlipaySubscriptionCreateRequest alipaySubscriptionCreateRequest = new AlipaySubscriptionCreateRequest();

    // replace with your subscriptionRequestId.
    // You can save the relationship between the subscriptionRequestId and the user ID for later information retrieval.
    String subscriptionRequestId = UUID.randomUUID().toString();
    alipaySubscriptionCreateRequest.setSubscriptionRequestId(subscriptionRequestId);
    alipaySubscriptionCreateRequest.setSubscriptionDescription("Subscription Description");

    // set subscription start time and end time. you might want to consider time zones
    // If the start time is earlier than the authorization time, the subscription is successful.
    // If the start time is later than the authorization time, the payment is made after the successful authorization, which is the pre-sale.
    // For details, please refer to:：<a href="https://docs.antom.com/ac/subscriptionpay/activation#uiqBb">Samples</a>
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
    alipaySubscriptionCreateRequest.setSubscriptionStartTime(ZonedDateTime.now().format(formatter));
    alipaySubscriptionCreateRequest.setSubscriptionEndTime(ZonedDateTime.now().plusYears(3).format(formatter));

    // set periodRule
    PeriodRule periodRule = PeriodRule.builder().periodCount(1).periodType("MONTH").build();
    alipaySubscriptionCreateRequest.setPeriodRule(periodRule);

    // set paymentMethod
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("ALIPAY_HK").build();
    alipaySubscriptionCreateRequest.setPaymentMethod(paymentMethod);

    // onvert amount unit(in practice, amount should be calculated on your serverside)
    // For details, please refer to:<a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
    Amount amount = Amount.builder().currency("HKD").value("1688").build();

    // set payment amount
    alipaySubscriptionCreateRequest.setPaymentAmount(amount);

    // set order info
    OrderInfo orderInfo = OrderInfo.builder().orderAmount(amount).build();
    alipaySubscriptionCreateRequest.setOrderInfo(orderInfo);

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

    // set env info
    Env env = Env.builder().terminalType(TerminalType.APP).build();
    env.setOsType(OsType.ANDROID);

    alipaySubscriptionCreateRequest.setEnv(env);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipaySubscriptionCreateRequest.setPaymentNotificationUrl("http://www.yourNotifyUrl.com/subscriptions/receivePaymentNotify");
    alipaySubscriptionCreateRequest.setSubscriptionNotificationUrl("http://www.yourNotifyUrl.com/subscriptions/receiveSubscriptionNotify");

    // replace with your subscription redirect url
    alipaySubscriptionCreateRequest.setSubscriptionRedirectUrl("http://www.yourRedirectUrl.com?subscriptionRequestId=" + subscriptionRequestId);

    AlipaySubscriptionCreateResponse alipaySubscriptionCreateResponse;
        try {
            alipaySubscriptionCreateResponse = CLIENT.execute(alipaySubscriptionCreateRequest);
        } catch (AlipayApiException e) {
            String errorMsg = e.getMessage();
            // handle error condition
        }
    }
```

 The following code shows a sample of the request message:

 ```json
{
  "env": {
    "osType": "ANDROID",
    "terminalType": "APP"
  },
  "orderInfo": {
    "orderAmount": {
      "currency": "HKD",
      "value": "1688"
    }
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "1688"
  },
  "paymentMethod": {
    "paymentMethodType": "ALIPAY_HK"
  },
  "paymentNotificationUrl": "http://www.yourNotifyUrl.com/subscriptions/receivePaymentNotify",
  "periodRule": {
    "periodCount": 1,
    "periodType": "MONTH"
  },
  "settlementStrategy": {
    "settlementCurrency": "USD"
  },
  "subscriptionDescription": "Subscription Description",
  "subscriptionEndTime": "2029-03-11T17:48:07+08:00",
  "subscriptionNotificationUrl": "http://www.yourNotifyUrl.com/subscriptions/receiveSubscriptionNotify",
  "subscriptionRedirectUrl": "http://www.yourRedirectUrl.com?subscriptionRequestId=5e5932ac-ed92-461a-9e3f-e1b4ac08fb0e",
  "subscriptionRequestId": "5e5932ac-ed92-461a-9e3f-e1b4ac08fb0e",
  "subscriptionStartTime": "2026-03-11T17:48:07+08:00"
}
```

 The response code involves the following key parameters:

 | **Parameter name** | **Description** |
| --- | --- |
| *result.resultStatus* | Determine the subscription creation status. |
| *normalUrl* | Redirect to the    H5    payment link.   ​ |
| *applinkUrl* | Redirect to the    deeplink    payment link.   ​ |
| *schemeUrl* | Redirect to the    scheme    payment link. |

 The following code shows a sample of the response message:

 ```json
{
    "appIdentifier": "com.iap.linker_portal",
    "applinkUrl": "https://psp.ac.alipay.com/page/simulation-wallet/acwallet/signContract.html?scopes=AGREEMENT_PAY%2CUSER_LOGIN_ID&bizContent=%7B%22acquirerId%22%3A%22102218800000000000A%22%2C%22authClientDisplayName%22%3A%222188120314639523%40alitest.com%22%2C%22authClientId%22%3A%2221881200300645I9%22%2C%22authClientName%22%3A%222188120314639523%40alitest.com%22%2C%22authRedirectUrl%22%3A%22https%3A%2F%2Fg.alipayplus.com%2Fpage%2Fac-auth-payment%2Fresult%2Fmobile%2Findex.html%3FloadMode%3D2%26callbackType%3DCommon%26terminalType%3DAPP%26referenceAgreementId%3D2026031119214000100500031242021%26authRequestId%3D2026031119091305000370002050791%26pspId%3D102216000000000000A%26clientId%3DT_4GGO000000000001%22%2C%22authState%22%3A%22188bmljL2ZDWEZ4MnowK3dYVVdQVElPS0lpSFQ0b21xRkdSVWxkTStlaXAzOEh1VEVpaFRJS3M3Y290T0Zma0h6Ng%22%2C%22customerBelongsTo%22%3A%22ALIPAY_HK%22%2C%22osType%22%3A%22ANDROID%22%2C%22passThroughInfo%22%3A%22%7B%5C%22referenceMerchantId%5C%22%3A%5C%2221881200300645I9%5C%22%7D%22%2C%22pspId%22%3A%22102216000000000000A%22%2C%22referenceAgreementId%22%3A%222026031119214000100500031242021%22%2C%22referenceMerchantId%22%3A%2221881200300645I9%22%2C%22scopes%22%3A%5B%22AGREEMENT_PAY%22%2C%22USER_LOGIN_ID%22%5D%2C%22terminalType%22%3A%22APP%22%7D&source=AlipayConnect&needCallback=false",
    "normalUrl": "https://g.alipayplus.com/page/aplus-linker/acwallet/authorization.html?url=alipayconnect%3A%2F%2Fplatformapi%2Facwallet%2FsignContract&scopes=AGREEMENT_PAY%2CUSER_LOGIN_ID&bizContent=%7B%22acquirerId%22%3A%22102218800000000000A%22%2C%22authClientDisplayName%22%3A%222188120314639523%40alitest.com%22%2C%22authClientId%22%3A%2221881200300645I9%22%2C%22authClientName%22%3A%222188120314639523%40alitest.com%22%2C%22authRedirectUrl%22%3A%22https%3A%2F%2Fg.alipayplus.com%2Fpage%2Fac-auth-payment%2Fresult%2Fmobile%2Findex.html%3FloadMode%3D2%26callbackType%3DCommon%26terminalType%3DAPP%26referenceAgreementId%3D2026031119214000100500031242021%26authRequestId%3D2026031119091305000370002050791%26pspId%3D102216000000000000A%26clientId%3DT_4GGO000000000001%22%2C%22authState%22%3A%22188bmljL2ZDWEZ4MnowK3dYVVdQVElPS0lpSFQ0b21xRkdSVWxkTStlaXAzOEh1VEVpaFRJS3M3Y290T0Zma0h6Ng%22%2C%22customerBelongsTo%22%3A%22ALIPAY_HK%22%2C%22osType%22%3A%22ANDROID%22%2C%22passThroughInfo%22%3A%22%7B%5C%22referenceMerchantId%5C%22%3A%5C%2221881200300645I9%5C%22%7D%22%2C%22pspId%22%3A%22102216000000000000A%22%2C%22referenceAgreementId%22%3A%222026031119214000100500031242021%22%2C%22referenceMerchantId%22%3A%2221881200300645I9%22%2C%22scopes%22%3A%5B%22AGREEMENT_PAY%22%2C%22USER_LOGIN_ID%22%5D%2C%22terminalType%22%3A%22APP%22%7D&source=AlipayConnect&needCallback=false",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
```

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

 | ***result.resultStatus*** | **Message** | **Further action** |
| --- | --- | --- |
| `S` | API call succeeded. | Guide the buyer to redirect to the URL for authorization. |
| `F` | Subscription creation failed. | Retry by replacing the     *subscriptionRequestId*    . |
| `U` | Subscription creation processing delayed. | Close the subscription or initiate a retry of the original order. |

 > **[INFO]** **Note**    : If no response is received, it may indicate a network timeout. You can close the subscription or initiate a retry of the original order.

 **​**

 > **[INFO]** **Common questions**
>
>  **Q: How can I determine which type of URL needs to be consumed in the response?**  
>  A: Depending on the payment method and terminal type, Antom may return one or more of the following URLs:    *normalUrl*    ,     *applinkUrl*    , and     *schemeUrl*    . The merchant server should pass these URLs to the merchant frontend, and any one of them can be selected for redirection.
>
>  ​
>
>  **Q: How do I set the**       ***terminalType***      **?**
>
>  A: Valid values for    terminalType    are as follows:
>
>  - If the buyer initiates the transaction on a PC, set     *terminalType*     to   `WEB`  .
> - If the buyer initiates the transaction on a mobile browser, set     *terminalType*     to   `WAP`  . Specify the     *osType*     parameter and set the corresponding system based on the buyer's phone:   `ANDROID`   or   `IOS`  .
> - If the buyer initiates the transaction within an application, set     *terminalType*     to   `APP`  .

  

### Step 3: Redirect to the authorization binding link  **[Client-side]** {#JGwTC}

 After obtaining the authorization binding link returned by Antom, the merchant server passes the address to the frontend, which then redirects the buyer to the payment method page. The different types of payment progress links are shown in the table below:

 | **Type** | **Description** | **Example** |
| --- | --- | --- |
| *normalUrl* | The URL of an HTTPS address, used to redirect to the website page of the payment method on the same browser page. | https://render.alipay.com/p/s/i/?scheme=alipays%3A%2F%2Fplatformapi%2FstartApp%3FappId%3D10000007%26actionType%3Droute%26qrcode%3Dhttps%3A%2F%2Fglobal.alipay.com%2F281002040099gUtj0amuJ48dt49hKJX1jA94%26externalThrough%3D%257B%2522acTerminalType%2522%253A%2522WAP%2522%257D |
| *applinkUrl* | The Android App Link or iOS Universal Link that is used for redirection in the payment process. | https://payments.gcash.com/gcash-ac-cashier-intermediate-web/h5.html?acCodeValue=https%3A%2F%2Fglobal.alipay.com%2F2810020400948dtv5AptV1kpaQ48dyD2r72r&acFlag=true |
| *schemeUrl* | The scheme URL that is used to open a payment method app. | alipays://platformapi/startApp?appId=10000007&actionType=route&qrcode=https%3A%2F%2Fglobal.alipay.com%2F281002040099gUtj0amuJ48dt49hKJX1jA94&externalThrough=%7B%22acTerminalType%22%3A%22WAP%22%7D |

 Refer to   [How to properly use the payment continuation URL](https://docs.antom.com/ac/cashierpay/config.md)   for more details.

 The following is the sample codes for loading payment continuation URL on the merchant front end:

<!-- TabGroup -->

**Tab: Web**

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

**Tab: WAP**

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

**Tab: iOS**

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

**Tab: Android**

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

<!-- /TabGroup -->
 The following figure shows the effect of the payment method checkout page:

 ![Screenshot of APM payment method checkout page shows the payment method interface for completing the binding](https://intranetproxy.alipay.com/skylark/lark/0/2025/png/12191/1758197171259-7be0541b-1d41-43ad-8a68-25263661279c.png)

 Different payment methods return different payment continuation URLs at different terminals. Antom returns different payment continuation URLs based on the     *paymentMethod*     and     *terminalType*     values you specified. The following table lists the types of returned payment continuation URLs and user experience on different terminals. Refer to   [URLs returned for payment methods](https://docs.antom.com/ac/cashierpay/urls.md)   for more details.

 | **Type** | **Return scenarios** | **Description** | **User experience** |
| --- | --- | --- | --- |
| *applinkUrl* | This URL is typically returned when a buyer initiates a payment from a merchant's app or mobile website, depending on whether the payment method is supported. | Automatically determine whether the buyer has installed the payment method app. - If the buyer has installed the payment method app, launch the payment method app. - If the buyer does not have the payment method app installed, launch the mobile browser page. | - When the buyer has the payment method app installed   :   ![App Link redirection experience when the buyer has the payment method app installed](https://intranetproxy.alipay.com/skylark/lark/0/2026/png/119656509/1770792656303-80eb5a78-a7ec-42c8-bd3e-76480893c1e0.png) - When the buyer does not have the payment method app installed:   ![App Link redirection experience when the buyer does not have the payment method app installed](https://intranetproxy.alipay.com/skylark/lark/0/2026/png/119656509/1770792662975-70e8572f-2e27-43d8-8022-3db3b09e5c5a.png) |
| *schemeUrl* | This URL is typically returned when a buyer initiates a payment from a merchant's app or mobile website, depending on whether the payment method is supported. | - Launch the payment method app directly via the app scheme. - If the buyer does not have the payment method app installed, the app cannot be launched, and an exception will be displayed. Refer to   [Best practices](https://docs.antom.com/ac/cashierpay/config.md#eK0wp)   for more details. | - When the buyer has the payment method app installed   :   ![Scheme URL redirection experience when the buyer has the payment method app installed](https://intranetproxy.alipay.com/skylark/lark/0/2026/png/119656509/1770792655614-4712418a-747d-433c-97a2-0d5e25f8021b.png) - Not supported if the buyer does not have the payment method app installed |
| *normalUrl* | This URL is returned when the buyer initiates a payment from the merchant's webpage, depending on whether the payment method is supported. | - The H5 page of the payment method   . - The H5 page experience for each payment method varies. For example, certain payment methods support direct payment after login, while others require an intermediate page to invoke the payment method app for payment. | - Payment made on a web page   :   ![Normal URL payment experience on a desktop web page](https://intranetproxy.alipay.com/skylark/lark/0/2026/png/119656509/1770792653901-6aeb4690-6689-4f19-8629-72ffdf212891.png) - Payment made on an H5 page:   ![Normal URL payment experience on an H5 mobile page](https://intranetproxy.alipay.com/skylark/lark/0/2026/png/119656509/1770792663691-cdf9452f-c56f-4fee-acb2-43c3e22e9c21.png) - When the intermediate page invokes the payment method app for payment   :   ![Normal URL intermediate page that invokes the payment method app](https://intranetproxy.alipay.com/skylark/lark/0/2026/png/119656509/1770792657978-e71306d1-9eca-4d6b-b860-b5d556c39589.png) |

 > **[INFO]** **Common questions**
>
>  **Q: What should I pay attention to when passing the parameter**       ***paymentRedirectUrl***      **?**  
>  A: It should be set to an HTTPS address by default, and special characters in the URL must not be encoded; otherwise, it may cause payment exceptions.
>
>  ​
>
>  **Q: How should the payment result page be displayed?**
>
>  A: You need to specify the     *subscriptionRedirectUrl*     parameter in the   [**create**](https://docs.antom.com/ac/ams/create_sub.md)   API to provide an HTTPS address. This address is used to display the payment result on the merchant side.
>
>  - Both successful and failed authorizations may have an entry for returning from the payment method page to the merchant page. Therefore, do not hardcode     *subscriptionRedirectUrl*     as a success page; instead, display content based on the server-side result to avoid user misunderstanding.
> - If the transaction is initiated from a merchant application,     *subscriptionRedirectUrl*     must be set to the scheme address of the merchant app.
>
>  ​
>
>  **Q: Does returning to the merchant result page mean the subscription relationship has taken effect?**
>
>  A: No, the redirect to the merchant page alone does not indicate successful authorization. There are three possible situations:
>
>  - The buyer may have successfully authorized but failed to return to the merchant page due to network issues.
> - The buyer may return to the merchant page through a payment method entry even without completing authorization.
> - The buyer may complete authorization, but the subscription relationship might still fail to take effect if the initial payment is unsuccessful.

### Step 4: Receive asynchronous notification of subscription result  **[Server-side]** {#dWsxe}

 Antom will push asynchronous notifications based on the authorization result and payment result status of the APM transaction:

<!-- TabGroup -->

**Tab: Subscription status notification**

A subscription status notification is triggered whether the buyer authorization succeeds or fails. Antom will return the subscription status through the subscription result notification (  [**notifySubscription**](https://docs.antom.com/ac/ams/notify_sub.md)  ). Please follow the steps below:

 1. Set the webhook URL to receive notifications. This is configured through the     *subscriptionNotificationUrl*     parameter in the   [**create**](https://docs.antom.com/ac/ams/create_sub.md)   API request.The following are examples of two types of subscription status notifications:

   - When the value of     *subscriptionNotificationType*     is   `CREATE`  , determine the subscription relationship based on the value of     *subscriptionStatus*    :

     - `ACTIVE`  : Indicates that the subscription relationship has taken effect.
    - `TERMINATED`  : Indicates that the subscription relationship has been terminated.

 ```json
{
	"periodRule": {
		"periodCount": 1,
		"periodType": "MONTH"
	},
	"subscriptionEndTime": "2074-02-20T01:16:17-08:00",
	"subscriptionId": "20240914190000****00000050000010226",
	"subscriptionNotificationType": "CREATE",
	"subscriptionRequestId": "SUBSCRIPTION_20244409****165oo009851_AUTO",
	"subscriptionStartTime": "2024-09-13T19:30:17-07:00",
	"subscriptionStatus": "ACTIVE"
}
```

   - When the value of     *subscriptionNotificationType*     is   `TERMINATE`  , the subscription relationship becomes invalid.

 ```json
{
  "periodRule": {
    "periodCount": 1,
    "periodType": "WEEK"
  },
  "subscriptionId": "2025102619******00000160000671943",
  "subscriptionLastUpdateTime": "2025-10-26T09:51:13-07:00",
  "subscriptionNotificationType": "TERMINATE",
  "subscriptionRequestId": "PR_en_****176",
  "subscriptionStartTime": "2025-10-26T10:01:13-07:00",
  "subscriptionStatus": "TERMINATED"
}
```

 2. Verify the signature of the received notification. Follow the steps below to verify the signature of the payment notification sent by Antom:

 ```java
/**
     * receive subscription notify
     *
     * @param request    request
     * @param notifyBody notify body
     * @return Result
     */
    @PostMapping("/receiveSubscriptionNotify")
    @ResponseBody
    public Result receiveSubscriptionNotify(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
            AlipaySubscriptionNotify subscriptionNotify = JSON.parseObject(notifyBody, AlipaySubscriptionNotify.class);

            if (subscriptionNotify != null && SubscriptionNotificationType.CREATE.equals(subscriptionNotify.getSubscriptionNotificationType())) {
                // handle your own business logic.
                // e.g. The subscription information of the user is saved through the relationship between the subscriptionRequestId and the user ID.
                System.out.println("receive subscription notify: " + JSON.toJSONString(subscriptionNotify));
                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();
    }
```

**Tab: Current period payment result notification**

After the subscription is successfully activated, a subscription payment notification for the current period will be triggered. Antom will return the deduction result through the   [**notifyPayment (Subscription)**](https://docs.antom.com/ac/ams/notify_subpayment.md)   API. Please follow the steps below:

 1. Set the webhook URL to receive the notification. You can configure this through the     *paymentNotificationUrl*     parameter in the   [**create**](https://docs.antom.com/ac/ams/create_sub.md)   API request or via the   [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify)  . For detailed steps, please refer to the   [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md)  .The following is an example of a payment result notification:

 ```json
{
	"paymentAmount": {
		"currency": "PHP",
		"value": "100"
	},
  "notifyType": "PAYMENT_RESULT",
	"paymentCreateTime": "2024-09-13T19:28:41-07:00",
	"paymentId": "20240914194010****00188400245315817",
	"paymentTime": "2024-09-13T19:28:43-07:00",
	"periodEndTime": "2024-10-13T19:30:17-07:00",
	"periodStartTime": "2024-09-13T19:30:17-07:00",
	"phaseNo": "1",
	"result": {
		"resultCode": "SUCCESS",
		"resultMessage": "success",
		"resultStatus": "S"
	},
	"subscriptionId": "20240914190000****00000050000010226",
	"subscriptionRequestId": "SUBSCRIPTION_2024440****0165oo009851_AUTO"
}
```

 Description of key parameters:

 - *notifyType*    : Notification type; the value is   `PAYMENT_RESULT`  .
- *phaseNo*    : The sequence number of the current subscription period.
- *periodStartTime*    : The start time of the current subscription period.
- *periodEndTime*    : The end time of the current subscription period.
- *paymentAmount*    : The charged amount for each subscription period.

 2. Verify the signature of the received notification. Follow the steps below to verify the signature of the payment notification sent by Antom:

 ```java
 /**
     * receive payment notify
     *
     * @param request    request
     * @param notifyBody notify body
     * @return Result
     */
    @PostMapping("/receivePaymentNotify")
    @ResponseBody
    public Result receivePaymentNotify(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
            AlipaySubscriptionPayNotify paymentNotify = JSON.parseObject(notifyBody, AlipaySubscriptionPayNotify.class);

            if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
                // handle your own business logic.
                // e.g. The payment information of the user is saved through the relationship between the subscriptionRequestId and the user ID.
                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();
    }
```

<!-- /TabGroup -->
 3. Respond to the notification result. When responding to the notification, you must follow the fixed format below regardless of whether the payment transaction succeeds or fails, and no signature processing is required.

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

 > **[INFO]** **Common questions**
>
>  **Q: Will the asynchronous notification be re-sent?**
>
>  A: Yes, the asynchronous notification will be re-sent automatically within 24 hours for the following cases:
>
>  - If you didn't receive the asynchronous notification due to network reasons.
> - If you receive an asynchronous notification from Antom, but you didn't make a response to the notification in the sample code format of   [Process the notification](https://docs.antom.com/ac/cashierpay/notifications.md#JtjSl)  .
>
>  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: No. If you receive an asynchronous notification from Antom, you are required to return the response in the sample code format of   [Process the notification](https://docs.antom.com/ac/cashierpay/notifications.md#JtjSl)  , but you do not need to countersign the response.
>
>  **​**
>
>  **Q: Do I need to verify the signature after receiving the payment result notification?**
>
>  A: Yes. To ensure that the callback request is indeed sent by Antom, verification is required during signature verification. When assembling messages to be verified, you are required to process in the following standard order:   `<http-method> <http-uri> <client-id>.<request-time>.<request-body>`  . Note that   `request-body`   should be assembled directly from the original value, rather than parsed into JSON and then assembled.
>
>  **​**
>
>  **Q: If the first payment fails, will the subscription take effect?**  
>  A: When the first deduction during subscription activation fails, the subscription will not take effect. Antom will push a webhook notification with    *subscriptionStatus*     =   `TERMINATED`   to the merchant, indicating that the subscription activation has failed.
>
>   **Q: What is the subscription timeout period?**  
>  A: For APM, the default timeout period is 80 minutes. You can also specify a custom timeout period using the    *subscriptionExpiryTime*     parameter.
>
>   **Q: If the subscription creation fails, will there be a first payment result notification?**  
>  There are two possible situations:
>
>  - If the buyer authorization is successful but the first payment fails, both a subscription creation failure notification and a first payment failure notification will be sent.
> - If the buyer authorization fails, only a subscription creation failure notification will be sent.

### Step 5: Receive asynchronous notification of subscription renewal  **[Server-side]** {#g3QVV}

 After the subscription is successfully created and a valid relationship is established, the Antom system will automatically initiate renewal payments according to your configured subscription rules and send the corresponding payment result notification through the   [**notifyPayment**](https://docs.antom.com/ac/ams/paymentrn_online.md)   API, enabling periodic billing.

 - Trigger timing: The renewal deduction will be automatically triggered 24 hours before the start date of the next subscription cycle. You can determine the initiation time of the next cycle’s payment by subtracting 24 hours from the     *periodEndTime*     parameter in the previous cycle’s payment result notification.
- Cycle rule: The renewal period and deduction frequency will follow the     *periodRule*     defined during subscription creation, for example, daily, monthly, quarterly, or yearly billing. The explanation is as follows:

 | **First payment deduction time** **(**      ***paymentTime***       **=**       ***periodStartTime***      **)** | **Subscription cycle** | **Next payment deduction time**      **(**      ***paymentTime***      **)** | **Next Period Effective Time**      **(**      ***periodStartTime***      **)** |
| --- | --- | --- | --- |
| 2024-09-25T20:10:17+08:00 | Set the subscription cycle to 3 days, you need to pass in the following parameters: - *periodRule.periodCount*     =      `3` - *periodRule.periodType*     =  `DAY` | 2024-09-27T20:20:04+08:00 | 2024-09-28T20:10:17+08:00 |
| 2024-09-25T20:10:17+08:00 | Set the subscription cycle to one week, you need to pass in the following parameters: - *periodRule.periodCount*     =      `1` - *periodRule.periodType*     =  `WEEK` | 2024-10-01T20:10:17+08:00 | 2024-10-02T20:10:17+08:00 |
| 2024-09-25T20:10:17+08:00 | Set the subscription cycle to one month, you need to pass in the following parameters: - *periodRule.periodCount*     =      `1` - *periodRule.periodType*     =  `MONTH` | 2024-10-24T20:10:17+08:00 | 2024-10-25T20:10:17+08:00 |
| 2024-09-25T20:10:17+08:00 | Set the subscription cycle to one year, you need to pass in the following parameters: - *periodRule.periodCount*     =      `1` - *periodRule.periodType*     =  `YEAR` | 2025-09-24T20:10:17+08:00 | 2025-09-25T20:10:17+08:00 |

 Asynchronous notifications are generally divided into the following scenarios:

 | **Common scenarios** | **First-time payment binding** | **Subsequent cycle payments** |
| --- | --- | --- |
| Subscription result notification | Sent the subscription creation result. | Not sent. |
| Current payment result notification | Sent the payment status, amount, and validity period of the current cycle. | Sent the payment status, amount, and validity period of each cycle. |

 Example of current period payment result notification:

 ```json
{
	"paymentAmount": {
		"currency": "PHP",
		"value": "100"
	},
  "notifyType": "PAYMENT_RESULT",
	"paymentCreateTime": "2024-09-17T23:10:48-07:00",
	"paymentId": "20240918194010****00188060246428030",
	"paymentTime": "2024-09-17T23:10:50-07:00",
	"periodEndTime": "2024-10-19T22:15:17-07:00",
	"periodStartTime": "2024-09-19T22:15:17-07:00",
	"phaseNo": "2",
	"result": {
		"resultCode": "SUCCESS",
		"resultMessage": "success",
		"resultStatus": "S"
	},
	"subscriptionId": "2024091819000000****000050000010807",
	"subscriptionRequestId": "SUBSCRIPTION_20244****yyy5oo0hhh1_AUTO"
}
```

 Description of key parameters:

 - *notifyType*    :    Notification type; the value is   `PAYMENT_RESULT`  .
- *phaseNo*    :    The sequence number of the current subscription period.

 > **[INFO]** **Common questions**
>
>  **Q: If a payment deduction fails, will it cause the subscription to become invalid?**  
>  A: If the first deduction when creating a subscription fails, the subscription relationship will not take effect. However, if the subscription has already taken effect and subsequent cycle deductions fail (for example, due to insufficient balance), the subscription will remain valid. If the subscription is not actively canceled, Antom will retry the deduction in the next billing cycle.
>
>  ​
>
>  **Q: Will a payment failure trigger a deduction notification, and will it be retried?**  
>  A: Yes, a failed deduction will trigger a payment failure notification. In the APM subscription payment scenario, Antom will perform multiple retry attempts.
>
>  ​
>
>  **Q: If the first deduction occurs on dates such as February 28, March 31, or April 30 (the end of the month), how is the next deduction date determined?**  
>  A: The subscription cycle logic is based on the selected date. If the next cycle does not have that same date, the deduction will occur one day earlier. For example:
>
>  - First period: 1.28, Second period: 2.28, Third period: 3.28, Fourth period: 4.28.
> - First period: 1.31, Second period: 2.28, Third period: 3.31, Fourth period: 4.30.
> - First period: 1.30, Second period: 2.28, Third period: 3.30, Fourth period: 4.30.
>
>  ​
>
>  **Q: How are subsequent recurring deductions associated with the initial subscription contract?**  
>  A: For recurring deduction notifications, the association can be made using the    *subscriptionRequestId*     or     *subscriptionId*     included in the notification request to link back to the initial contract.

## After subscription {#S8eHQ}

### Subscription trial {#Rue5J}

 Antom provides a subscription trial feature that allows buyers to experience a product or service for a limited time at no cost or at a discounted rate before officially purchasing a subscription plan.  
   For more details, please refer to the   [Subscription trial](https://docs.antom.com/ac/subscriptionpay/subscription_trial.md)  .

### Subscription cancellation {#jcX2m}

 The subscription cancellation feature allows buyers to cancel their current subscription at any time when they no longer need to use the associated service.       For more details, please refer to the   [Subscription cancellation](https://docs.antom.com/ac/subscriptionpay/subscription_cancellation.md)  .

### Cancel {#Otb6j}

 For orders with successful payments, if a buyer requests to cancel or refund on the same day, you can use Antom’s order cancellation capability to cancel or unfreeze the order status.  
   In addition, for orders that have not yet been paid, you can also cancel them directly. For detailed integration instructions, please    refer to   [Cancel](https://docs.antom.com/ac/easypay/cancel.md)  .   ​

### Refund {#kg4oU}

 For successfully paid orders, if you need to issue a refund to the buyer, Antom provides two methods:

 - Your operations staff can manually process refunds directly through the      [Antom Dashboard](https://dashboard.alipay.com/)  ​   .
- Call refund API to initiate a refund.    Refer to   [Refund](https://docs.antom.com/ac/easypay/refund.md)   to learn about Antom refund rules and operation process.

## Best practices {#O7DPd}

 An   tom provides you with the following best practice solutions:

 - [Client-side optimization](https://docs.antom.com/ac/subscriptionpay/best_practice.md#da4f92cb)
- [Payment result display](https://docs.antom.com/ac/subscriptionpay/best_practice.md#BH52r)
- [API timeout settings](https://docs.antom.com/ac/subscriptionpay/best_practice.md#NXXk4)