Accept payments with EasySafePay (SDK)
Antom EasySafePay is a minimalist payment solution focused on small-amount, high-frequency payment scenarios. With its innovative "bind payment method upon first payment" design and one-click payment feature, it significantly simplifies the payment process. Buyers can choose to pay directly or perform payment method binding during the first transaction, and subsequent payments can be processed instantly without repeated verification.
This solution leverages industry-leading intelligent risk control systems, dynamic polling technology, and payment failure recovery strategies to ensure transaction security while achieving top-tier payment success rates in the industry. It creates a win-win-win scenario for buyer payment experience, merchant conversion rates, and platform ecosystem value.
Web/WAP
iOS
Android
WebView
User experience
Through simple browser integration, you can quickly enable digital wallet and online banking payment functionalities.



Different payment methods vary in their browser-side user experience. For specific interaction differences, refer to the table below:
Digital wallet
Online banking
In the digital wallet payment scenario, the system will guide the buyer to complete the transaction on the merchant's page or within the payment method app after the buyer confirms the payment. The first payment verification and subsequent simplified payment process are illustrated as follows:
First payment
Subsequent payments
The first payment requires security authentication. Once authorized, the buyer will be enabled for password-free payments on subsequent transactions.

Subsequent payments will be processed automatically upon order submission, without requiring password entry.

The online banking process is illustrated as follows, including first payment authentication and subsequent simplified payment flows.
First payment
Subsequent payments
The first payment requires security authentication. Once authorized, the buyer will be enabled for password-free payments on subsequent transactions.

Subsequent payments will be processed automatically upon order submission, without requiring password entry.

Payment flow
First payment
Subsequent payments
The first payment flow chart:

- The buyer enters the checkout page.
- Create a payment session request.
After the buyer selects a payment method and submits the order, you can obtain the payment session by calling the createPaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session and the SDK will automatically collect payment elements, render the payment interface, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. For detailed interaction differences across payment methods, refer to the User experience table. - Obtain the authorization result.
When the authorization is successful, Antom sends you the asynchronous notification through the notifyAuthorization API. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
The subsequent payment flow chart:

- The buyer enters the checkout page.
- Create a payment session request.
After the buyer selects a payment method and submits the order, you can obtain the payment session by calling the createPaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session and the SDK will automatically collect payment elements, render the payment interface, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. For detailed interaction differences across payment methods, refer to the User experience table. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
Integration preparations
Before you start integrating, read the Integration Guide and API Overview 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.
- If you need to conduct joint debugging by connecting the sandbox with the production environment, please contact Antom technical support at least two business days in advance to request configuration. The sandbox environment and production environment require separate configuration.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke the SDK
- Obtain the authorization and payment result
(Optional) Step 1: Preload the SDK Client-side
Preloading the SDK during the checkout page initialization significantly improves the rendering performance with no negative impact. It is recommended to trigger preloading of the SDK when the buyer selects a payment method.
Follow the code example below to perform the preloading:
Preload SDK
AMSEasyPay.preload();
Step 2: Create a payment session Server-side
When a buyer selects a payment method provided by Antom, you need to collect essential information including the payment request ID, order amount, payment method, order description, payment redirect page URL, and payment result notification URL.
Call the createPaymentSession (EasySafePay) API to create a payment session and initialize the Antom SDK using the paymentSessionData value returned in the response.
The table below lists the parameter specifications for calling the createPaymentSession (EasySafePay) API during the first and subsequent payments:
Note: For subsequent payments with Express Bank Transfer, simply keep the parameters consistent with the first payment. The buyer can open the Express Bank Transfer webpage and enter the phone number to proceed directly with the payment.
The parameter format for the buyer's payment account for each payment method is as follows:
During the first-time payment, passing the buyer's payment account will auto-fill the buyer's account on the payment page, eliminating manual input. Below is a comparison of the user experience with and without these fields:
With account parameter passed
Without account parameter passed
Login account input is not required.

Manual input of login account is required.

Below are code examples for first and subsequent payments.
First payment
Subsequent payments
@@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
User loginUser = users.get(payment.getUserId());
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType(payment.paymentMethodType).build();
if (loginUser.getPaymentMethodTypeAccessToken().containsKey(payment.getPaymentMethodType())) {
// buyer has authorized
String accessToken = loginUser.getPaymentMethodTypeAccessToken().get(payment.getPaymentMethodType());
paymentMethod.setPaymentMethodId(accessToken);
} else {
// set agreementInfo
// replace with your authState
String authState = UUID.randomUUID().toString();
AgreementInfo agreementInfo = AgreementInfo.builder().authState(authState).build();
alipayPaymentSessionRequest.setAgreementInfo(agreementInfo);
// save the paymentMethodType corresponding to the authState
authStatePayment.put(authState, payment);
// The login ID that the user used to register in the payment method client. The login ID can be the user's email address or phone number.
// Specify this parameter to free users from manually entering their login IDs.
if(StringUtil.isNotBlank(loginUser.getPhoneNumber()){
buyer.setBuyerPhoneNo(loginUser.getPhoneNumber());
}
if(StringUtil.isNotBlank(loginUser.getEmail() && "ALIPAY_HK".equals(payment.getPaymentMethodType())){
buyer.setBuyerPhoneNo(loginUser.getPhoneNumber());
}
}
alipayPaymentSessionRequest.setPaymentMethod(paymentMethod);
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId)
.orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect URL
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}The following code shows a sample of the request message:
{
"agreementInfo": {
"authState": "authState001",
"userLoginId": "userLoginId001"
},
"order": {
"buyer": {
"referenceBuyerId": "referenceBuyerId001"
},
"orderAmount": {
"currency": "CNY",
"value": "100"
},
"orderDescription": "orderDescription001",
"referenceOrderId": "referenceOrderId001"
},
"paymentAmount": {
"currency": "CNY",
"value": "100"
},
"paymentMethod": {
"paymentMethodType": "ALIPAY_CN"
},
"paymentNotifyUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/record/notify?env=main_online&paymentMethodType=ALIPAY_CN",
"paymentRedirectUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/result",
"paymentRequestId": "paymentRequestId001",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message:
{
"paymentSessionData": "ZqeGpu7pbMb/I3dNWTTEL3o4w5mXh20j13VnmsE1p3cjK3CVpnMXY7BfQlIvwNqQWtXHEMUo0R5pQwnSyNtxTA==&&SG&&188&&eyJh***",
"paymentSessionExpiryTime": "2024-09-27T15:57:30+08:00",
"paymentSessionId": "ZqeGpu7pbMb/I3dNWTTEL3o4w5mXh20j13VnmsE1p3fI21eGbgq240lFVquZsLrM",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId and authstate value.
public static void createPaymentSession() {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// set amount
// you should convert amount unit(in practice, amount should be calculated on your server side)
Amount amount = Amount.builder().currency("HKD").value("98080").build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
//set settlement currency
SettlementStrategy settlementStrategy = new SettlementStrategy();
settlementStrategy.setSettlementCurrency("USD");
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("ALIPAY_HK")
.paymentMethodId("28288803001319861727421828000Cv96OFlYoi17100****").build();
alipayPaymentSessionRequest.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();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl("http://www.yourRedirectUrl.com");
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}
The following code shows a sample of the request message:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "98080"
},
"orderDescription": "antom api testing order",
"referenceOrderId": "5e445b58-49ad-4552-a36d-d38f311a090d"
},
"paymentAmount": {
"currency": "HKD",
"value": "98080"
},
"paymentMethod": {
"paymentMethodId": "28288803001319861727421828000Cv96OFlYoi17100****",
"paymentMethodType": "ALIPAY_HK"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com",
"paymentRedirectUrl": "http://www.yourRedirectUrl.com",
"paymentRequestId": "5810a84e-3a3e-4e47-bbac-9dfe3f2dd2b3",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message:
{
"paymentSessionData": "paymentSessionData****",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId value.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of a certain payment method, do not use Chinese characters for parameters in the request.
Q: How to set the URL to receive the payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to receive the asynchronous notification about the payment result (notifyPayment), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
Q: What is the difference between paymentAmount and orderAmount?
A: paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
A: paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
Q: What does paymentSessionExpiryTime specifically refer to in payment requests?
A: paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
A: paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
Q: Which parameters should be prioritized in the response message?
A: Pay attention to the following key parameters:
A: Pay attention to the following key parameters:
- result.resultStatus: Indicates the result of the API call.
- paymentSessionData: Encrypted payment session data, which is passed to the frontend for initializing the Antom SDK.
- paymentSessionExpiryTime: Expiration timestamp of the payment session.
Step 3: Invoke the SDK Client-side
After obtaining the paymentSessionData value on the merchant server side, the merchant client can invoke the SDK to redirect the checkout page to the payment method authorization page. When the buyer submits a payment request, the SDK will automatically handle encrypted communication, risk control verification, page redirection, and payment instruction execution, enabling an end-to-end payment authorization process.
1. Instantiate the SDK
- Use AMSEasyPayto create the SDK instance. The configuration object includes the following parameters:
The following sample code shows how to instantiate the SDK using npm or CDN:
npm
CDN
npm
import { AMSEasyPay } from '@alipay/ams-checkout' // Manage the package
const checkoutApp = new AMSEasyPay({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({code, message})=>{},
});
CDN
const checkoutApp = new window.AMSEasyPay({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({code, message})=>{},
});
- Use createComponentin the instance object to create a payment component. The parameters involved are as follows:
The following sample code shows how to create the component:
async function create(sessionData) {
await checkoutApp.createComponent({
sessionData: sessionData,
notRedirectAfterComplete: false // Set as false by default to indicate that it will redirect to your page after the payment is completed.
});
}The images below show the rendering effect when the SDK redirects the checkout page to the payment method authorization page:

Web
WAP
The image below shows the redirection from the merchant checkout page to the payment method page.

The image below shows the merchant checkout page launches a half-screen pop-up or redirects to the digital wallet app.

2. Handle SDK callback event codes
Below are the event codes returned by
onEventCallback
and handling recommendations:The following sample code shows how to handle the callback function:
// Step 2: Create onEventCallback handler.
function onEventCallback({ code }) {
switch (code) {
case 'SDK_PAYMENT_CANCEL':
console.log(
'The buyer canceled the payment (the buyer exited the payment page without submitting the order). You can re-invoke the SDK using paymentSessionData within its validity period; If it has expired, you need to initiate a new createPaymentSession (EasySafePay) request.'
);
break;
case 'SDK_CALL_URL_SUCCESS':
console.log('Successfully launched the payment method app or redirected to the merchant page.');
break;
case 'SDK_LAUNCH_PAYMENT_APP_ERROR':
console.log('Failed to redirect to the checkout page of the payment method, or failed to redirect to the merchant page. Check whether the paymentRedirectUrl parameter is correctly passed when calling the createPaymentSession (EasySafePay) request. Web/WAP scenarios rarely experience redirection exceptions. However, in the event of any exceptions, it is recommended to verify the redirection link.');
break;
case 'SDK_PAYMENT_SUCCESSFUL':
console.log('The wallet has successfully processed the payment. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result. Suggest redirecting buyers to the payment result page.');
break;
case 'SDK_PAYMENT_FAIL':
console.log('The wallet failed to process the payment. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result. Suggest redirecting buyers to the payment result page.');
break;
default:
console.log(code);
}
};3. Free SDK component resources
Call the
unmount
method to free SDK component resources in the following situations:- When the buyer switches views to exit the checkout page, free the component resources created in the createPaymentSession (EasySafePay) API.
- When the buyer initiates multiple payments, free the component resources created in the previous createPaymentSession (EasySafePay) API.
- After obtaining the final payment result, free the component resources.
The following sample code shows how to free components:
// Free SDK component resources
checkoutApp.unmount();Common questions
Q: Can an
A: No. If you need to initiate a new payment, you need to create a new
AMSEasyPay
instance execute createComponent
multiple times?A: No. If you need to initiate a new payment, you need to create a new
AMSEasyPay
instance.Q: Are SDK calls required for both first and subsequent payments?
A: Yes.
A: Yes.
User experience
This iOS integration guide is designed to help you quickly integrate the digital wallet and online banking payment functions within the app and easily complete the payment interface rendering.




The user experience of each payment method on the iOS side varies; refer to the table below for specific interaction experiences:
Digital wallet
Online banking
Below is the user experience for first and subsequent payments using digital wallets.
First payment
Subsequent payments
Upon the first payment, the buyer can choose to pay immediately or complete the authorization process. After successful authorization, subsequent payments will be processed by the password-free feature.
Pay on the merchant page
Pay on the payment method app


Subsequent payments are processed without requiring a password upon order submission.

Below is the user experience for first and subsequent payments using online banking payment methods.
First payment
Subsequent payments
Upon the first payment, the buyer can choose to pay immediately or complete the authorization process. After successful authorization, subsequent payments will be processed by the password-free feature.

Subsequent payments are processed without requiring a password upon order submission.

Payment flow
First payment
Subsequent payments
The first payment flow chart:

- The buyer enters the checkout page.
- Create a payment session request.
After the buyer selects a payment method and submits the order, you can obtain the payment session by calling the createPaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session and the SDK will automatically collect payment elements, render the payment interface, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. For detailed interaction differences across payment methods, refer to the User experience table. - Obtain the authorization result.
When the authorization is successful, Antom sends you the asynchronous notification through the notifyAuthorization API. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
The subsequent payment flow chart:

- The buyer enters the checkout page.
- Create a payment session request.
After the buyer selects a payment method and submits the order, you can obtain the payment session by calling the createPaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session and the SDK will automatically collect payment elements, render the payment interface, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. For detailed interaction differences across payment methods, refer to the User experience table. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
Integration preparations
Before you start integrating, read the Integration Guide and API Overview 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.
- If you need to conduct joint debugging by connecting the sandbox with the production environment, please contact Antom technical support at least two business days in advance to request configuration. The sandbox environment and production environment require separate configuration.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke the SDK
- Obtain the authorization and payment result
(Optional) Step 1: Preload the SDK Client-side
Preloading the SDK during the checkout page initialization significantly improves the rendering performance with no negative impact. It is recommended to trigger preloading of the SDK when the buyer selects a payment method.
Follow the code example below to perform the preloading:
Preload SDK
[AMSEasyPay.shared preload];Step 2: Create a payment session Server-side
When a buyer selects a payment method provided by Antom, you need to collect essential information including the payment request ID, order amount, payment method, order description, payment redirect page URL, and payment result notification URL.
Call the createPaymentSession (EasySafePay) API to create a payment session and initialize the Antom SDK using the paymentSessionData value returned in the response.
The table below lists the parameter specifications for calling the createPaymentSession (EasySafePay) API during the first and subsequent payments:
Note: For subsequent payments with Express Bank Transfer, simply keep the parameters consistent with the first payment. The buyer can open the Express Bank Transfer webpage and enter the phone number to proceed directly with the payment.
The parameter format for the buyer's payment account for each payment method is as follows:
During the first-time payment, passing the buyer's payment account will auto-fill the buyer's account on the payment page, eliminating manual input. Below is a comparison of the user experience with and without these fields:
With account parameter passed
Without account parameter passed
Login account input is not required.

Manual input of login account is required.

Below are code examples for first and subsequent payments.
First payment
Subsequent payments
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your server side)
// For details, refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
User loginUser = users.get(payment.getUserId());
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType(payment.paymentMethodType).build();
if (loginUser.getPaymentMethodTypeAccessToken().containsKey(payment.getPaymentMethodType())) {
// buyer has authorized
String accessToken = loginUser.getPaymentMethodTypeAccessToken().get(payment.getPaymentMethodType());
paymentMethod.setPaymentMethodId(accessToken);
} else {
// set agreementInfo
// replace with your authState
String authState = UUID.randomUUID().toString();
// The login ID that the buyer used to register in the payment method client. The login ID can be the buyer's email address or phone number.
// Specify this parameter to free buyers from manually entering their login IDs.
String userLoginId = loginUser.getPhoneNumber();
AgreementInfo agreementInfo = AgreementInfo.builder().authState(authState).userLoginId(userLoginId).build();
alipayPaymentSessionRequest.setAgreementInfo(agreementInfo);
// save the paymentMethodType corresponding to the authState
authStatePayment.put(authState, payment);
}
alipayPaymentSessionRequest.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 sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms
");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}The following code shows a sample of the request message:
{
"agreementInfo": {
"authState": "authState001",
"userLoginId": "userLoginId001"
},
"order": {
"buyer": {
"referenceBuyerId": "referenceBuyerId001"
},
"orderAmount": {
"currency": "CNY",
"value": "100"
},
"orderDescription": "orderDescription001",
"referenceOrderId": "referenceOrderId001"
},
"paymentAmount": {
"currency": "CNY",
"value": "100"
},
"paymentMethod": {
"paymentMethodType": "ALIPAY_CN"
},
"paymentNotifyUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/record/notify?env=main_online&paymentMethodType=ALIPAY_CN",
"paymentRedirectUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/result",
"paymentRequestId": "paymentRequestId001",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message:
{
"paymentSessionData": "ZqeGpu7pbMb/I3dNWTTEL3o4w5mXh20j13VnmsE1p3cjK3CVpnMXY7BfQlIvwNqQWtXHEMUo0R5pQwnSyNtxTA==&&SG&&188&&eyJh***",
"paymentSessionExpiryTime": "2024-09-27T15:57:30+08:00",
"paymentSessionId": "ZqeGpu7pbMb/I3dNWTTEL3o4w5mXh20j13VnmsE1p3fI21eGbgq240lFVquZsLrM",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId and authstate value.
public static void createPaymentSession() {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// set amount
// you should convert amount unit(in practice, amount should be calculated on your server side)
Amount amount = Amount.builder().currency("HKD").value("98080").build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
//set settlement currency
SettlementStrategy settlementStrategy = new SettlementStrategy();
settlementStrategy.setSettlementCurrency("USD");
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("ALIPAY_HK")
.paymentMethodId("28288803001319861727421828000Cv96OFlYoi17100****").build();
alipayPaymentSessionRequest.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();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl("http://www.yourRedirectUrl.com");
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}
The following code shows a sample of the request message:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "98080"
},
"orderDescription": "antom api testing order",
"referenceOrderId": "5e445b58-49ad-4552-a36d-d38f311a090d"
},
"paymentAmount": {
"currency": "HKD",
"value": "98080"
},
"paymentMethod": {
"paymentMethodId": "28288803001319861727421828000Cv96OFlYoi17100****",
"paymentMethodType": "ALIPAY_HK"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com",
"paymentRedirectUrl": "http://www.yourRedirectUrl.com",
"paymentRequestId": "5810a84e-3a3e-4e47-bbac-9dfe3f2dd2b3",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message:
{
"paymentSessionData": "paymentSessionData****",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId value.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of a certain payment method, do not use Chinese characters for parameters in the request.
Q: How to set the URL to receive the payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to receive the asynchronous notification about the payment result (notifyPayment), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
Q: What is the difference between paymentAmount and orderAmount?
A: paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
A: paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
Q: What does paymentSessionExpiryTime specifically refer to in payment requests?
A: paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
A: paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
Q: Which parameters should be prioritized in the response message?
A: Pay attention to the following key parameters:
A: Pay attention to the following key parameters:
- result.resultStatus: Indicates the result of the API call.
- paymentSessionData: Encrypted payment session data, which is passed to the frontend for initializing the Antom SDK.
- paymentSessionExpiryTime: Expiration timestamp of the payment session.
Step 3: Invoke the SDK Client-side
After obtaining the paymentSessionData value on the merchant server side, the merchant client can invoke the SDK to redirect the checkout page to the payment method authorization page. When the buyer submits a payment request, the SDK will automatically handle encrypted communication, risk control verification, page redirection, and payment instruction execution, enabling an end-to-end payment authorization process.
1. Instantiate the SDK
- Use AMSEasyPayConfigurationto create the SDK instance. The configuration object includes the following parameters:
- Create an instance of the AMSPaymentProtocol API to process the payment callback result, which includes the following method:
The following sample code shows how to instantiate the SDK:
#import <AMSComponent/AMSComponent-Swift.h>
AMSEasyPayConfiguration *componentConfig = [AMSEasyPayConfiguration new];
// Alipay needs to add fromScheme. Note that this address refers to the corresponding APP startup page after the payment is completed.
componentConfig.fromScheme = @"exampleForScheme";
componentConfig.locale = @"en_US";
// Set the sandbox environment. If you leave it empty, the production environment is used by default.
NSDictionary *options = @{@"sandbox": @"true",
@"notRedirectAfterComplete": @"false"};
componentConfig.options = options;
[[AMSEasyPay shared] initConfiguration:componentConfig];
// Set the callback to monitor payment events on the checkout page.
[AMSEasyPay shared].paymentDelegate = self;
#pragma AMSPaymentProtocol
- (void)onEventCallback:(NSString *)eventCode eventResult:(AMSEventResult *)eventResult
{
NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}
The following image shows the rendering effect of the merchant checkout page invoking a half-screen pop-up or redirecting to the digital wallet app:

- Use the createComponentmethod in the instance object to create a payment component, which includes the following parameter:
The sample code is as follows:
[[AMSEasyPay shared] createComponent:sessionData];2. Handle SDK callback event codes
Below are the event codes returned by
onEventCallback
and handling recommendations:The following sample code shows how to handle the callback function:
-(void)onEventCallback:(NSString *)eventCode eventResult:(AMSEventResult *)eventResult {
if ([[_selectMethod title] isEqualToString:@"ALIPAY_CN"]) {
if ([eventCode isEqualToString:@"SDK_PAYMENT_CANCEL"]) {
NSLog(@"The buyer canceled the payment (the buyer exited the payment page without submitting the order). You can re-invoke the SDK using paymentSessionData within its validity period; If it has expired, you need to initiate a new createPaymentSession (EasySafePay) request.");
} else if ([eventCode isEqualToString:@"SDK_PAYMENT_SUCCESSFUL"]) {
NSLog(@"The Alipay wallet has successfully processed the payment. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
} else if ([eventCode isEqualToString:@"SDK_PAYMENT_FAIL"]) {
NSLog(@"The Alipay wallet failed to process the payment. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
} else if ([eventCode isEqualToString:@"SDK_PAYMENT_PROCESSING"]) {
NSLog(@"The payment status of the Alipay wallet is unknown. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
} else if ([eventCode isEqualToString:@"SDK_PAYMENT_ERROR"]) {
NSLog(@"The payment processing of the Alipay wallet is abnormal. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
} else {
NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}
} else {
// Please note that payment success will not be notified through this callback function, but will instead redirect to the success result page you specified.
if ([eventCode isEqualToString:@"SDK_PAYMENT_CANCEL"]) {
NSLog(@"The buyer canceled the payment (the buyer exited the payment page without submitting the order). You can re-invoke the SDK using paymentSessionData within its validity period; If it has expired, you need to initiate a new createPaymentSession (EasySafePay) request.");
} else if ([eventCode isEqualToString:@"SDK_CALL_URL_SUCCESS"]) {
NSLog(@"Open wallet app or redirect to the merchant page successfully.");
} else if ([eventCode isEqualToString:@"SDK_LAUNCH_PAYMENT_APP_ERROR"]) {
NSLog(@"Open wallet app or redirect to the merchant page failed");
} else if ([eventCode isEqualToString:@"SDK_CREATEPAYMENT_PARAMETER_ERROR"]) {
NSLog(@"The input parameter provided is invalid. Please check the value and try again.");
} else {
NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}
}
}
3. Free SDK component resources
Call the
onDestroy
method to free SDK component resources in the following situations:- When the buyer exits the checkout page, completely free the component resources created in the createPaymentSession (EasySafePay) API.
- When the buyer initiates multiple payments, and the parameters in initConfigurationhave changed, free the component resources created in the previous createPaymentSession (EasySafePay) API.
In the following scenario, you do not need to call
onDestroy
, and the SDK will automatically free partial resources (for iOS SDK AMSComponents 1.33.0 or above).- When the buyer initiates multiple payments, and the parameters in initConfigurationhave not changed. The SDK will automatically free partial resources after the payment is completed to reset to the state beforecreateComponentwas called.
The following sample code shows how to free components:
// Completely free SDK component resources
[[AMSEasyPay shared] onDestroy];Common questions
Q: Is it mandatory to handle SDK callback events?
A: For Alipay, you must process event codes to display payment results, but this payment method is optional. Callback events can also be used for logging.
A: For Alipay, you must process event codes to display payment results, but this payment method is optional. Callback events can also be used for logging.
Q: Can an AMSEasypay instance execute createComponent multiple times?
A: No. You need to create a freshAMSEasypay instance to initiate a new payment.
A: No. You need to create a freshAMSEasypay instance to initiate a new payment.
Q: Are SDK calls required for both first-time and subsequent payments?
A: Yes.
A: Yes.
4. Receive notification from callback function (When integrating Alipay)
When integrating with Alipay, the merchant-client can receive notifications from the callback function. After receiving the callback notification, use the
openURL
method in the AppDelegate file to handle the result returned by Alipay:- Use canProcessOrderWithPaymentResult()to check whether the redirect URL, to redirect from the wallet to the merchant side, is valid.
- Use processOrderWithPaymentResult()to handle the redirection from the wallet to the merchant's side.
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
if ([url.scheme isEqualToString:@"exampleForScheme"]) {
if ([[AMSEasyPay shared] canProcessOrderWithPaymentResult:url]) {
[[AMSEasyPay shared] processOrderWithPaymentResult:url];
}
}
return YES;
}User experience
This Android integration guide is designed to help you quickly integrate the digital wallet and online banking payment functions within the app and easily complete the payment interface rendering.




The user experience of each payment method on the Android side varies; refer to the table below for specific interaction experiences:
Digital wallet
Online banking
Below is the user experience for first and subsequent payments using digital wallets.
First payment
Subsequent payments
Upon the first payment, the buyer can choose to pay immediately or complete the authorization process. After successful authorization, subsequent payments will be processed by the password-free feature.
Pay on the merchant page
Pay on the payment method app


Subsequent payments are processed without requiring a password upon order submission.

Below is the user experience for first and subsequent payments using online banking payment methods.
First payment
Subsequent payments
Upon the first payment, the buyer can choose to pay immediately or complete the authorization process. After successful authorization, subsequent payments will be processed by the password-free feature.

Subsequent payments are processed without requiring a password upon order submission.

Payment flow
First payment
Subsequent payments
The first payment flow chart:

- The buyer enters the checkout page.
- Create a payment session request.
After the buyer selects a payment method and submits the order, you can obtain the payment session by calling the createPaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session and the SDK will automatically collect payment elements, render the payment interface, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. For detailed interaction differences across payment methods, refer to the User experience table. - Obtain the authorization result.
When the authorization is successful, Antom sends you the asynchronous notification through the notifyAuthorization API. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
The subsequent payment flow chart:

- The buyer enters the checkout page.
- Create a payment session request.
After the buyer selects a payment method and submits the order, you can obtain the payment session by calling the createPaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session and the SDK will automatically collect payment elements, render the payment interface, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. For detailed interaction differences across payment methods, refer to the User experience table. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
Integration preparations
Before you start integrating, read the Integration Guide and API Overview 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.
- If you need to conduct joint debugging by connecting the sandbox with the production environment, please contact Antom technical support at least two business days in advance to request configuration. The sandbox environment and production environment require separate configuration.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke the SDK
- Obtain the authorization and payment result
(Optional) Step 1: Preload the SDK Client-side
Preloading the SDK during the checkout page initialization significantly improves the rendering performance with no negative impact. It is recommended to trigger preloading of the SDK when the buyer selects a payment method.
Follow the code example below to perform the preloading:
Preload SDK
AMSEasyPay.preload(getApplicationContext());Step 2: Create a payment session Server-side
When a buyer selects a payment method provided by Antom, you need to collect essential information including the payment request ID, order amount, payment method, order description, payment redirect page URL, and payment result notification URL.
Call the createPaymentSession (EasySafePay) API to create a payment session and initialize the Antom SDK using the paymentSessionData value returned in the response.
The table below lists the parameter specifications for calling the createPaymentSession (EasySafePay) API during the first and subsequent payments:
Note: For subsequent payments with Express Bank Transfer, simply keep the parameters consistent with the first payment. The buyer can open the Express Bank Transfer webpage and enter the phone number to proceed directly with the payment.
The parameter format for the buyer's payment account for each payment method is as follows:
During the first-time payment, passing the buyer's payment account will auto-fill the buyer's account on the payment page, eliminating manual input. Below is a comparison of the user experience with and without these fields:
With account parameter passed
Without account parameter passed
Login account input is not required.

Manual input of login account is required.

Below are code examples for first and subsequent payments.
First payment
Subsequent payments
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
User loginUser = users.get(payment.getUserId());
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType(payment.paymentMethodType).build();
if (loginUser.getPaymentMethodTypeAccessToken().containsKey(payment.getPaymentMethodType())) {
// buyer has authorized
String accessToken = loginUser.getPaymentMethodTypeAccessToken().get(payment.getPaymentMethodType());
paymentMethod.setPaymentMethodId(accessToken);
} else {
// set agreementInfo
// replace with your authState
String authState = UUID.randomUUID().toString();
AgreementInfo agreementInfo = AgreementInfo.builder().authState(authState).build();
alipayPaymentSessionRequest.setAgreementInfo(agreementInfo);
// save the paymentMethodType corresponding to the authState
authStatePayment.put(authState, payment);
// The login ID that the user used to register in the payment method client. The login ID can be the user's email address or phone number.
// Specify this parameter to free users from manually entering their login IDs.
if(StringUtil.isNotBlank(loginUser.getPhoneNumber()){
buyer.setBuyerPhoneNo(loginUser.getPhoneNumber());
}
if(StringUtil.isNotBlank(loginUser.getEmail() && "ALIPAY_HK".equals(payment.getPaymentMethodType())){
buyer.setBuyerPhoneNo(loginUser.getPhoneNumber());
}
}
alipayPaymentSessionRequest.setPaymentMethod(paymentMethod);
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId)
.orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect URL
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}The following code shows a sample of the request message:
{
"agreementInfo": {
"authState": "authState001",
"userLoginId": "userLoginId001"
},
"order": {
"buyer": {
"referenceBuyerId": "referenceBuyerId001"
},
"orderAmount": {
"currency": "CNY",
"value": "100"
},
"orderDescription": "orderDescription001",
"referenceOrderId": "referenceOrderId001"
},
"paymentAmount": {
"currency": "CNY",
"value": "100"
},
"paymentMethod": {
"paymentMethodType": "ALIPAY_CN"
},
"paymentNotifyUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/record/notify?env=main_online&paymentMethodType=ALIPAY_CN",
"paymentRedirectUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/result",
"paymentRequestId": "paymentRequestId001",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message:
{
"paymentSessionData": "ZqeGpu7pbMb/I3dNWTTEL3o4w5mXh20j13VnmsE1p3cjK3CVpnMXY7BfQlIvwNqQWtXHEMUo0R5pQwnSyNtxTA==&&SG&&188&&eyJh***",
"paymentSessionExpiryTime": "2024-09-27T15:57:30+08:00",
"paymentSessionId": "ZqeGpu7pbMb/I3dNWTTEL3o4w5mXh20j13VnmsE1p3fI21eGbgq240lFVquZsLrM",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId and authstate value.
public static void createPaymentSession() {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// set amount
// you should convert amount unit(in practice, amount should be calculated on your server side)
Amount amount = Amount.builder().currency("HKD").value("98080").build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
//set settlement currency
SettlementStrategy settlementStrategy = new SettlementStrategy();
settlementStrategy.setSettlementCurrency("USD");
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("ALIPAY_HK")
.paymentMethodId("28288803001319861727421828000Cv96OFlYoi17100****").build();
alipayPaymentSessionRequest.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();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl("http://www.yourRedirectUrl.com");
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}
The following code shows a sample of the request message:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "98080"
},
"orderDescription": "antom api testing order",
"referenceOrderId": "5e445b58-49ad-4552-a36d-d38f311a090d"
},
"paymentAmount": {
"currency": "HKD",
"value": "98080"
},
"paymentMethod": {
"paymentMethodId": "28288803001319861727421828000Cv96OFlYoi17100****",
"paymentMethodType": "ALIPAY_HK"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com",
"paymentRedirectUrl": "http://www.yourRedirectUrl.com",
"paymentRequestId": "5810a84e-3a3e-4e47-bbac-9dfe3f2dd2b3",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message:
{
"paymentSessionData": "paymentSessionData****",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId value.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of a certain payment method, do not use Chinese characters for parameters in the request.
Q: How to set the URL to receive the payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to receive the asynchronous notification about the payment result (notifyPayment), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
Q: What is the difference between paymentAmount and orderAmount?
A: paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
A: paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
Q: What does paymentSessionExpiryTime specifically refer to in payment requests?
A: paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
A: paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
Q: Which parameters should be prioritized in the response message?
A: Pay attention to the following key parameters:
A: Pay attention to the following key parameters:
- result.resultStatus: Indicates the result of the API call.
- paymentSessionData: Encrypted payment session data, which is passed to the frontend for initializing the Antom SDK.
- paymentSessionExpiryTime: Expiration timestamp of the payment session.
Step 3: Invoke the SDK Client-side
After obtaining the paymentSessionData value on the merchant server side, the merchant client can invoke the SDK to redirect the checkout page to the payment method authorization page. When the buyer submits a payment request, the SDK will automatically handle encrypted communication, risk control verification, page redirection, and payment instruction execution, enabling an end-to-end payment authorization process.
1. Instantiate the SDK
- Use AMSEasyPayConfigurationto create the SDK instance. The configuration object includes the following parameters:
- Create an instance of the setOnCheckoutListener API to handle corresponding events that occur in subsequent processes, which include the following method:
The following sample code shows how to instantiate the SDK:
// Step 1: Create the AMSEasyPayConfiguration type.
AMSEasyPayConfiguration configuration = new AMSEasyPayConfiguration();
configuration.setLocale(new Locale("en", "US"));
// Set the sandbox environment. If you leave it empty, the production environment is used by default.
configuration.setOption("sandbox", "true");
// Set as false by default
configuration.setOption("notRedirectAfterComplete", "false");
// Set the callback to monitor payment events on the checkout page.
configuration.setOnCheckoutListener(new OnCheckoutListener() {
@Override
public void onEventCallback(String eventCode, AMSEventResult eventResult) {
// For eventCode, refer to the respective sample codes or event codes.
Toast.makeText(activity, "eventCode=" + eventCode + " message=" + message, Toast.LENGTH_SHORT).show();
}
});
// Instantiate AMSEasyPay.
AMSEasyPay checkout = new AMSEasyPay.Builder(activity, configuration).build();
The following image shows the rendering effect of the merchant checkout page invoking a half-screen pop-up or redirecting to the digital wallet app:

- Use the createComponentmethod in the instance object to create a payment component, which includes the following parameter:
The sample code is as follows:
checkout.createComponent(activity, sessionData);2. Handle SDK callback event codes
Below are the event codes returned by
onEventCallback
and handling recommendations:Note: In the Android Native environment, Alipay only supports redirecting to the merchant app's launch page, rather than the paymentRedirectUrl specified in the createPaymentSession (EasySafePay) API. The specific redirect page needs to be controlled through the event code.
The following sample code shows how to handle the callback function:
configuration.setOnCheckoutListener(new OnCheckoutListener() {
@Override
public void onEventCallback(String eventCode, AMSEventResult eventResult) {
if (selectPayment != null && selectPayment.getPaymentMethodCode().equals("ALIPAY_CN")) {
switch (eventCode) {
case "SDK_PAYMENT_CANCEL":
AlertUtils.showAlertWithMessage(MainActivity.this, "The buyer canceled the payment (the buyer exited the payment page without submitting the order). You can re-invoke the SDK using paymentSessionData within its validity period; If it has expired, you need to initiate a new createPaymentSession (EasySafePay) request.");
break;
case "SDK_PAYMENT_SUCCESSFUL":
AlertUtils.showAlertWithMessage(MainActivity.this, "The Alipay wallet has successfully processed the payment. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
break;
case "SDK_PAYMENT_FAIL":
AlertUtils.showAlertWithMessage(MainActivity.this, "The Alipay wallet failed to process the payment. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
break;
case "SDK_PAYMENT_PROCESSING":
AlertUtils.showAlertWithMessage(MainActivity.this, "The payment status of the Alipay wallet is unknown. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
break;
case "SDK_PAYMENT_ERROR":
AlertUtils.showAlertWithMessage(MainActivity.this, "The payment processing of the Alipay wallet is abnormal. Please obtain the final payment result from Antom server. You can use the inquiryPayment API or the notifyPayment API to confirm the result.");
break;
default:
AlertUtils.showAlertWithMessage(MainActivity.this, "eventCode=" + eventCode + " message=" + eventResult.getMessage());
break;
}
} else {
// Please note that payment success will not be notified from this callback function, but rather the page will be redirected to the success result page you specified
switch (eventCode) {
case "SDK_PAYMENT_CANCEL":
AlertUtils.showAlertWithMessage(MainActivity.this, "The buyer canceled the payment (the buyer exited the payment page without submitting the order). You can re-invoke the SDK using paymentSessionData within its validity period; If it has expired, you need to initiate a new createPaymentSession (EasySafePay) request.");
break;
case "SDK_CALL_URL_SUCCESS":
AlertUtils.showAlertWithMessage(MainActivity.this, "Open wallet app or redirect to the merchant page successfully.");
break;
case "SDK_LAUNCH_PAYMENT_APP_ERROR":
AlertUtils.showAlertWithMessage(MainActivity.this, "Open wallet app or redirect to the merchant page failed");
break;
case "SDK_CREATEPAYMENT_PARAMETER_ERROR":
AlertUtils.showAlertWithMessage(MainActivity.this, "The input parameter provided is invalid. Please check the value and try again.");
break;
default:
AlertUtils.showAlertWithMessage(MainActivity.this, "eventCode=" + eventCode + " message=" + eventResult.getMessage());
break;
}
}
}
});
3. Free SDK component resources
Call the
onDestroy
method to free SDK component resources in the following situations:- When the buyer exits the checkout page, completely free the component resources created in the createPaymentSession (EasySafePay) API.
- When the buyer initiates multiple payments, and the parameters in AMSEasyPayConfigurationhave changed, free the component resources created in the previous createPaymentSession (EasySafePay) API.
In the following scenario, you do not need to call
onDestroy
, and the SDK will automatically free partial resources (for SDK 1.33.0 or above).- When the buyer initiates multiple payments, and the parameters in AMSEasyPayConfigurationhave not changed. The SDK will automatically free partial resources after the payment is completed to reset to the state beforecreateComponentwas called.
The following sample code shows how to free components:
// Completely free SDK component resources
checkout.onDestroy();Common questions
Q: Is it mandatory to handle SDK callback events?
A: For Alipay, you must process event codes to display payment results, but this payment method is optional. Callback events can also be used for logging.
A: For Alipay, you must process event codes to display payment results, but this payment method is optional. Callback events can also be used for logging.
Q: Can an AMSEasypay instance execute createComponent multiple times?
A: No. You need to create a freshAMSEasypay instance to initiate a new payment.
A: No. You need to create a freshAMSEasypay instance to initiate a new payment.
Q: Are SDK calls required for both first-time and subsequent payments?
A: Yes.
A: Yes.
User experience
The following screenshots show the user experience of wallet and bank transfer respectively:
Digital wallet
Online banking
In the digital wallet payment scenario, the system will guide the buyer to complete the transaction on the merchant's page or within the payment method app after the buyer confirms the payment. The first payment verification and subsequent simplified payment process are illustrated as follows:
First payment
Subsequent payments
The first payment requires security authentication. Once authorized, the buyer will be enabled for password-free payments on subsequent transactions.
Pay on the merchant page
Pay on the payment method app


Subsequent payments are processed without requiring a password upon order submission.

Below is the user experience for first and subsequent payments using online banking payment methods.
First payment
Subsequent payments
For the first payment, the buyer completes the payment authorization process to enable subsequent password-free payments.

Subsequent payments are processed without requiring a password upon order submission.

Payment flow
The following are flow chart for the first payment and subsequent payment:
First payment
Subsequent payments

- The buyer enters the checkout page.
- Preload the Antom SDK when the buyer chooses a payment method.
- Create a payment session request.
After the buyer submits the order, you can obtain the payment session by calling thecreatePaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session on the client side and the SDK will automatically collect payment elements, Display the payment page, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. - Obtain the authorization result.
When the authorization is successful, Antom sends you the asynchronous notification through thenotifyAuthorization API. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.

- The buyer enters the checkout page.
- Preload the Antom SDK when the buyer chooses a payment method.
- Create a payment session request.
After the buyer submits the order, you can obtain the payment session by calling thecreatePaymentSession (EasySafePay) API. - Invoke the client SDK.
Invoke the SDK using a payment session on the client side and the SDK will automatically collect payment elements, Display the payment page, handle page redirections, and guide buyers through payment completion based on the specific payment method's characteristics. - Obtain the payment result.
Obtain the payment result using one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to set the address for receiving asynchronous notifications. When the payment is successful or expires, Antom will use notifyPayment to send asynchronous notifications to you.
- Synchronous inquiry: Call the inquiryPayment API to check the real-time payment status.
Integration preparations
Before you start integrating, read the Integration Guide and API Overview 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.
- If you need to conduct joint debugging by connecting the sandbox with the production environment, please contact Antom technical support at least two business days in advance to request configuration. The sandbox environment and production environment require separate configuration.
Version Requirements
- iOS:
- Install Xcode 12 or later.
- Compatible with iOS 11 or later.
- Android:
- Compatible with Android 4.4 (API level 19) or later.
Note: Flutter and React Native (RN) development frameworks are not currently supported.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke the SDK
- Obtain the authorization and payment result
(Optional) Step 1: Preload the SDK Client-side
Preloading the SDK during the checkout page initialization significantly improves the rendering performance with no negative impact. It is recommended to trigger preloading of the SDK when the buyer selects a payment method.
Follow the code example below to perform the preloading:
AMSEasypay.preload();Step 2: Create a payment session Server-side
Call the createPaymentSession (EasySafePay) API to create a payment session and initialize the Antom SDK using the paymentSessionData value returned in the response.
The table below lists the parameter specifications for calling the createPaymentSession (EasySafePay) API during the first and subsequent payments:
Note: For subsequent payments with Express Bank Transfer, simply keep the parameters consistent with the first payment. The buyer can open the Express Bank Transfer webpage and enter the phone number to proceed directly with the payment.
The parameter format for the buyer's payment account for each payment method is as follows:
Below are code examples for first and subsequent payments.
First payment
Subsequent payments
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit (in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
User loginUser = users.get(payment.getUserId());
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType(payment.paymentMethodType).build();
if(loginUser.getPaymentMethodTypeAccessToken().containsKey(payment.getPaymentMethodType())){
// user has authorized
String accessToken = loginUser.getPaymentMethodTypeAccessToken().get(payment.getPaymentMethodType());
paymentMethod.setPaymentMethodId(accessToken);
}else{
// set agreementInfo
// replace with your authState
String authState = UUID.randomUUID().toString();
// The login ID that the user used to register in the payment method client. The login ID can be the user's email address or phone number.
// Specify this parameter to free users from manually entering their login IDs
String userLoginId = loginUser.getPhoneNumber();
AgreementInfo agreementInfo = AgreementInfo.builder().authState(authState).userLoginId(userLoginId).build();
alipayPaymentSessionRequest.setAgreementInfo(agreementInfo);
// save the paymentMethodType corresponding to the authState
authStatePayment.put(authState, payment);
}
alipayPaymentSessionRequest.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 sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms
");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}The following code shows a sample of the request message:
{
"agreementInfo": {
"authState": "authState001",
"userLoginId": "userLoginId****"
},
"order": {
"buyer": {
"referenceBuyerId": "referenceBuyerId****"
},
"orderAmount": {
"currency": "CNY",
"value": "100"
},
"orderDescription": "orderDescription001",
"referenceOrderId": "referenceOrderId****"
},
"paymentAmount": {
"currency": "CNY",
"value": "100"
},
"paymentMethod": {
"paymentMethodType": "ALIPAY_CN"
},
"paymentNotifyUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/record/notify?env=main_online&paymentMethodType=ALIPAY_CN",
"paymentRedirectUrl": "http://debug1688017773824.test.alipay.net:9090/amsdemo/result",
"paymentRequestId": "paymentRequestId****",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message, including the following key parameters:
- paymentSessionData: Encrypted payment session data. This data is passed to the frontend for invoking the Antom SDK.
- paymentSessionExpiryTime: Expiration time of the payment session.
{
"paymentSessionData": "paymentSessionData****",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId and authstate value.
public static void createPaymentSession() {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.AGREEMENT_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.EASY_PAY);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// set amount
// you should convert amount unit (in practice, amount should be calculated on your server side)
Amount amount = Amount.builder().currency("HKD").value("98080").build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement currency
SettlementStrategy settlementStrategy = new SettlementStrategy();
settlementStrategy.setSettlementCurrency("USD");
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set paymentMethod
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("ALIPAY_HK")
.paymentMethodId("28288803001319861727421828000Cv96OFlYoi17100****").build();
alipayPaymentSessionRequest.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();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl("http://www.yourRedirectUrl.com");
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}The following code shows a sample of the request message:
{
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "98080"
},
"orderDescription": "antom api testing order",
"referenceOrderId": "5e445b58-49ad-4552-a36d-d38f311****"
},
"paymentAmount": {
"currency": "HKD",
"value": "98080"
},
"paymentMethod": {
"paymentMethodId": "28288803001319861727421828000Cv96OFlYoi17100****",
"paymentMethodType": "ALIPAY_HK"
},
"paymentNotifyUrl": "http://www.yourNotifyUrl.com",
"paymentRedirectUrl": "http://www.yourRedirectUrl.com",
"paymentRequestId": "5810a84e-3a3e-4e47-bbac-9dfe3f2d****",
"productCode": "AGREEMENT_PAYMENT",
"productScene": "EASY_PAY",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}The following code shows a sample of the response message, including the following key parameters:
- paymentSessionData: Encrypted payment session data. This data is passed to the frontend for invoking the Antom SDK.
- paymentSessionExpiryTime: Expiration time of the payment session.
{
"paymentSessionData": "paymentSessionData****",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please take the next step according to the value of the result.resultStatus.
Note: If you do not receive a response, it may be due to a network timeout. Please retry the API call with a new paymentRequestId value.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of a certain payment method, do not use Chinese characters for parameters in the request.
Q: How to set the URL to receive the payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (EasySafePay) API to receive the asynchronous notification about the payment result (notifyPayment), or configure the receiving URL in Antom Dashboard. If the URL is specified in both the request and Antom Dashboard, the value specified in the request takes precedence.
Q: What is the difference between paymentAmount and orderAmount?
A:paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
A:paymentAmount refers to the payment amount, while orderAmount refers to the order amount. The actual charged amount is determined by paymentAmount.
Q: What does paymentSessionExpiryTime specifically refer to in payment requests?
A:paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
A:paymentSessionExpiryTime indicates the validity period from successful payment session creation until the buyer submits the payment. After submission, the payment processing timeout is 10 minutes. Therefore, the maximum total duration from session creation to payment completion is 1 hour and 10 minutes.
Step 3: Invoke the SDK Server-side
After obtaining the paymentSessionData value on the merchant server side, the merchant client can invoke the SDK to redirect the checkout page to the payment method authorization page. When the buyer submits a payment request, the SDK will automatically handle encrypted communication, risk control verification, page redirection, and payment instruction execution, enabling an end-to-end payment authorization process.
1. Instantiate the SDK
- Use AMSEasyPayto create the SDK instance. The configuration object includes the following parameters:
The following sample code shows how to instantiate the SDK using npm or CDN:
npm
CDN
import { AMSEasyPay } from '@alipay/ams-checkout' // manage the package
const checkoutApp = new AMSEasyPay({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({code, message})=>{},
});const checkoutApp = new window.AMSEasyPay({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({code, message})=>{},
});- Use createComponentin the instance object to create a payment component. The parameters involved are as follows:
The following sample code shows how to create the component:
async function create(sessionData) {
await checkoutApp.createComponent({
sessionData: sessionData,
isNativeAppWebview: true, // Set as false by default to indicate that the merchant integrates the web SDK via an H5 webpage.
notRedirectAfterComplete: false // Set as false by default to indicate that it will redirect to your page after the payment is completed.
});
}- Listen for event code to handle redirection events.
By monitoring the
SDK_REDIRECT
event code, you can handle the subsequent process. An example code snippet is shown below:import { AMSEasyPay } from '@alipay/ams-checkout' // Package management
const checkoutApp = new AMSEasyPay({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({code, message, result}) => {
switch (code) {
case 'SDK_REDIRECT':
// Handle redirect logic
const redirectUrls = result?.redirectUrls || {};
const jsonString = JSON.stringify(redirectUrls);
// Check if the current environment's espJSBridge is available
if (window.espJSBridge) {
// Call the sdkRedirect method of espJSBridge, passing the redirect information.
// This approach is for reference; merchants can also use their own native communication methods for data transfer.
window.espJSBridge.sdkRedirect(jsonString)
// After data transfer is complete, perform component cleanup
checkoutApp.unmount();
}
break;
default:
console.log(code);
}
},
});- Handle redirection events using a WebView container.
Use a WebView container to manage in-app redirection events. The following are sample codes for iOS and Android respectively:
iOS
Android
// Step 1: Create webview container
let url = "https://www.merchantWeb.com"
let webView = WKWebView()
webView.load(URLRequest(url: url))
webView.configuration.userContentController.addUserScript(
WKUserScript(
source: "window.espJSBridge = { sdkRedirect: function(message) { window.webkit.messageHandlers.espJSBridge.postMessage(message); } }",
injectionTime: .atDocumentStart,
forMainFrameOnly: true
)
)
webView.configuration.userContentController.add(self, name: "espJSBridge")
// Step 2: Handle redirect event
extension DemoViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// Monitor redirect event
if message.name == "espJSBridge",
let bodyString = message.body as? String,
let bodyData = bodyString.data(using: .utf8),
let body = try? JSONSerialization.jsonObject(with: bodyData, options: []) as? [String: Any]
{
let applinkUrl = body["applinkUrl"] as? String
let schemeUrl = body["schemeUrl"] as? String
let normalUrl = body["normalUrl"] as? String
// Redirect to link
// Attempt to redirect to applinkUrl
tryRedirect(url: applinkUrl) { [weak self] success in
// If failed, attempt to redirect to schemeUrl
if !success {
self?.tryRedirect(url: schemeUrl) { [weak self] success in
// If failed, attempt to redirect to normalUrl
if !success {
self?.tryRedirect(url: normalUrl) { _ in }
}
}
}
}
}
}
}
func tryRedirect(url: String?, completion: @escaping (Bool) -> Void) {
guard let url = url, let url = URL(string: url) else {
completion(false)
return
}
UIApplication.shared.open(url) { success in
completion(success)
}
}// Step 1: Create webview container
WebView webView;
webView = findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JSBridgeInterface(this), "espJSBridge");
webView.loadUrl(url);
// Step 2: Handle redirect event
public class JSBridgeInterface {
private Context mContext;
public JSBridgeInterface(Context context) {
mContext = context;
}
// Monitor redirect event
@JavascriptInterface
public void sdkRedirect(String redirectInfo) {
JSONObject jsonObject = JSONObject.parseObject(redirectInfo);
String schemeUrl = jsonObject.getString("schemeUrl");
String applinkUrl = jsonObject.getString("applinkUrl");
String normalUrl = jsonObject.getString("normalUrl");
// Attempt to redirect to schemeUrl
if (openRedirectionUrl(schemeUrl, true)) {
return;
}
// Attempt to redirect to applinkUrl
if (openRedirectionUrl(applinkUrl, false)) {
return;
}
// Attempt to redirect to normalUrl
if (openRedirectionUrl(normalUrl, false)) {
return;
}
showToast(mContext, "Failed to open URL");
}
private boolean openRedirectionUrl(String url, boolean isScheme) {
if (TextUtils.isEmpty(url)) {
return false;
}
try {
Intent intent = isScheme ? Intent.parseUri(url, Intent.URI_INTENT_SCHEME) : new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(mContext, intent, null);
return true;
} catch (Exception exception) {
showToast(mContext, exception.getMessage()); // Display prompt message
return false;
}
}
private void showToast(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
}2. Handle SDK callback event codes
Below are the event codes returned by
onEventCallback
and handling recommendations:The following sample code shows how to handle the callback function:
function onEventCallback({ code, result }) {
switch (code) {
case 'SDK_REDIRECT':
// Handle redirect logic
break;
case 'SDK_PAYMENT_CANCEL':
// Within the validity period, paymentSessionData can be used to reinvoke the SDK
break;
default:
break;
}
}3. Free SDK component resources
Call the
unmount
method to free SDK component resources in the following situations:- When the buyer switches views to exit the checkout page, free the component resources created in the createPaymentSession (EasySafePay) API.
- When the buyer initiates multiple payments, free the component resources created in the previous createPaymentSession (EasySafePay) API.
- After obtaining the final payment result, free the component resources.
The following sample code shows how to free components:
// Free SDK component resources
checkoutApp.unmount();Common questions
Q: Is it mandatory to handle SDK callback events?
A: Perform the following operations based on the value ofisNativeAppWebview:
A: Perform the following operations based on the value ofisNativeAppWebview:
- When isNativeAppWebview is true, you need to handle SDK callback events. They are generally categorized into two types:
- Key callbacks (e.g., payment redirect SDK_REDIRECT): Must be handled, otherwise the payment process will be interrupted.
- Other callbacks: Optional handling. You may use these callback events for logging or tracking purposes.
- When isNativeAppWebviewisfalse, callback handling is optional. You may use the callback events for logging or tracking purposes.
Q: Can an AMSEasyPay instance execute createComponent multiple times?
A: No. If you need to initiate a new payment, you need to create a newAMSEasyPay instance.
A: No. If you need to initiate a new payment, you need to create a newAMSEasyPay instance.
Q: Are SDK calls required for both first and subsequent payments?
A: Yes.
A: Yes.
Step 4: Obtain authorization and payment result Client-side
For the first payment, you can obtain both the authorization and payment results, while for subsequent payments, only the payment result is available. Below are common scenarios:
Obtain the authorization result
Obtain the payment result
Obtain the authorization result
When the authorization is successful during the first payment, Antom sends you the asynchronous notification through the notifyAuthorization API.
- Follow the steps below to set the notification webhook URL:
Log in to Antom Dashboard > Developer > Notification URL. Add the notification URL to alipay.ams.authorizations.notify. Refer to Notification URL for detailed steps.
The following code shows a sample of the asynchronous authorization notification request:
{
"accessToken": "28288803001319861727421828000Cv96OFlYoi17100****",
"accessTokenExpiryTime": 2145916817000,
"authState": "36a38e87-0453-495e-ad17-b46553b918da",
"authorizationNotifyType": "TOKEN_CREATED",
"userLoginId": "852-91****67",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Based on the value of result.resultStatus in the authorization result notification request (only
S
is returned), process as follows:S
: Indicates successful authorization, and the following parameters are returned:The table below shows the token validity period for each payment method:
- The result notification sent by Antom is signed by Antom, it is recommended that you verify the signature to confirm that the notification was sent by Antom. Refer to the following code example to verify the notification:
@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())
&& "TOKEN_CREATED".equals(authNotify.getAuthorizationNotifyType())) {
// save buyer's PaymentMethodType corresponding to accessToken
PaymentVO payment = authStatePayment.get(authNotify.getAuthState());
User user = users.get(payment.getUserId());
user.getPaymentMethodTypeAccessToken().put(payment.getPaymentMethodType(), authNotify.getAccessToken());
return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
}
// other types of notifications
} 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();
}- After receiving the notification, whether the authorization is successful or not, you are not required to sign the response, but each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}Obtain the payment result
After the first or subsequent payment is completed, you can obtain the payment result through one of the following methods:
- Receive the asynchronous notification: Receive the payment result delivered by the Antom server.
- Inquire about the result: Call inquiryPayment API to query payment status.
Receive the asynchronous notification
Inquire about the payment result
- Follow the steps below to set the notification webhook URL:
When the payment reaches a final status of success or failure, Antom sends an asynchronous notification to your configured webhook URL. You can choose one of the following two methods to set up the Webhook URL for receiving notifications:
- Order-level notification configuration: Specify an independent notification URL for each order through the paymentNotifyUrl parameter in the createPaymentSession (EasySafePay) API request.
- Merchant-level notification configuration: Log in to Antom Dashboard > Developer > Notification URL and add a notification URL for the alipay.ams.payments.payNotify API. For specific operations, refer to Notification URL.
Note: If you have configured notification URLs through both methods mentioned above, the API settings will take precedence.
The following code shows a sample of the notification request:
{
"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 table below displays the possible values returned in the resultStatus parameter of the response. Please follow the corresponding instructions for handling:
- The result notification sent by Antom is signed by Antom, it is recommended that you verify the signature to confirm that the notification was sent by Antom. Refer to the following code example to verify the notification:
/**
* 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 buyers 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();
}
}
// other types of notifications
} catch (Exception e) {
// handle error condition
return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
}
return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}- After receiving the notification, you are not required to sign the response, but must reply to every notification request in the following standardized format, regardless of whether the payment was successful or not.
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}Call the inquiryPayment API to initiate a query on the payment result. The payment status can be checked via polling or scheduled tasks after the payment is initiated.
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// replace with your paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}The following code shows a sample of the request message:
{
"paymentRequestId": "bc93d19e-e1f6-4b68-b6b1-3d6ddc2a****"
}The following code shows a sample of the response message:
{
"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"
}
}The table below displays the possible values returned in the paymentStatus parameter of the response. Please follow the corresponding instructions for handling:
Common questions
Q: When is the payment notification sent?
A: It depends on whether the payment is completed: If the payment is successfully completed, Antom usually sends an asynchronous notification within 3 to 5 seconds.
Q: Is there an asynchronous notification sent for authorization failure?
A: No. An asynchronous notification will only be sent if the authorization is successful; there will be no notification returned for authorization failure.
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.
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: Are the authorization notification and payment result notification sent separately, and will the authorization notification always be received before the payment result notification?
A: Due to the uncontrollable nature of network stability, it is possible for the authorization notification to arrive later than the payment result notification.
Q: Is authorization result inquiry supported?
A: Currently, calling an interface to query the authorization result is not supported.
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, but you do not need to countersign the response.
After payments
Revoke authorization
After authorization is completed, the buyer can revoke the authorization from either the merchant side or the payment method side. Once revoked, the original authorization token immediately becomes invalid and cannot be used for payments again. For details, refer to Revoke.
Cancel
You can cancel orders through the cancel API within the time window (by D+1 day 00:15 GMT+8). For details, refer to Cancel.
Refund
Reconciliation
After a transaction is completed, use the provided Antom financial reports to perform reconciliation. For settlement rules and reconciliation operations, refer to Reconciliation.
Best practices
Antom provides you with the following best practice solutions. Refer to Best practices for more details.
- Intelligent risk control service
- Security expansion package
- Order query after redirecting to the merchant result page
- Merchant-initiated transaction cancellation
- Payment failure retry