Payment Element integration
Antom Payment Element is a payment component integrated via SDK, designed to provide a seamless payment experience and help increase conversion rates. For different client types, Antom offers the following solutions:
- Web/WAP: Web Element for browser and mobile web environments
- App (Android & iOS & Flutter): Mobile Element designed for merchants' native mobile applications
The capabilities supported by Payment Element on each platform are shown in the table below:
Web/WAP
iOS
Android
Flutter
User experience
Web
WAP
The following figures demonstrate the user experience of using Payment Element in different scenarios:
Payment Element-rendered payment method list
Merchant-rendered payment method list
The following figure shows templates with embedded Payment Element-rendered payment method list:

If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Stored card payments
Payment Element displays a QR code for buyers to complete the payment.

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

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

Payment Element handles the stored card payment scenario.

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

If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Payment Element displays a QR code for buyers to complete the payment.

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

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

The following figures demonstrate the user experience of using Payment Element in different scenarios:
Payment Element-rendered payment method list
Merchant-rendered payment method list
The following figure shows templates with embedded Payment Element-rendered payment method list:

If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Stored card payments
Payment Element displays a QR code for buyers to complete the payment.

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

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

Payment Element handles the stored card payment scenario.

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

If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Payment Element displays a QR code for buyers to complete the payment.

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

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

Order lifecycle
Learn about the lifecycle of different payment methods:
APM Payments
Card payments, Apple Pay, Google Pay
For APM payments, such as Alipay and Touch'n Go eWallet, funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can cancel or refund the order within the allowable period.

For card payments, Apple Pay, and Google Pay, the order lifecycle includes the following stages:
- Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can cancel the order during the allowable period from when the order is placed until authorization is completed.
- Capture: You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to Capture. After capture, you can initiate a refund within the allowable period if needed.
- Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to Dispute.

Payment flow
The following flow illustrates how to integrate One-time Payments using Payment Element:
Payment Element-rendered payment method list
Merchant-rendered payment method list


- The buyer lands on the checkout page and submits payment.
- Create a payment session request.
You can obtain the payment session by calling the createPaymentSession (One-time Payments) API. - Invoke Payment Element.
On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the method, or the system will automatically return to your result page. - Confirm the payment result.
Obtain the payment result by using one of the following two methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard 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 payment status.
Note: For card payments, Apple Pay, and Google Pay, an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.
- Initiate capture and obtain the result.
By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the capture (One-time Payments) API. The capture result can be obtained through one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the notifyCapture (One-time Payments) API.
- Synchronous inquiry: Call the inquiryPayment API to check the capture status.
Integration preparations
Before you start integrating, read Integration guide and API overview to understand the integration steps of the server-side API and the precautions for calling the API. Furthermore, ensure the following prerequisites are met:
- Obtained your client ID
- Complete the key configuration
- Complete the configuration of paymentNotifyUrl to receive the asynchronous notification
- Integrate the server-side SDK package, install the server-side library, and initialize a request instance. For more details, refer to Server-side SDKs.
- Integrate the client-side SDK package by following the steps detailed in Integrate the SDK package for Web/WAP, and ensure to use the latest SDK version or no lower than 1.46.0.
Integration steps
Start your integration by taking the following steps:
- Create a payment session
- Invoke Payment Element
- Obtain the payment result
- Capture
Step 1: Create a payment session Server-side
Call the createPaymentSession (One-time Payments) API with order information to create a payment session and obtain the paymentSessionData required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list. Pass the corresponding parameters when calling the createPaymentSession (One-time Payments) API:
Payment Element-rendered payment method list
Merchant-rendered payment method list
When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can specify payment methods to display only the options you need.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.WAP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:
{
"env": {
"terminalType": "WAP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}When rendering the payment method list yourself, you must pass the parameters for specifying payment methods listed in the table below. Note that for certain payment methods (e.g., card payments), you need to embed the payment details component rendered by Payment Element. The optimal timing for calling the createPaymentSession (One-time Payments) API when offering card payment options is as follows:
- If Payment Element needs to collect payment details: Call the createPaymentSession (One-time Payments) API after the buyer selects the payment method, and pass the card payment parameters listed in the table.
- If Payment Element does not need to collect payment details: Call the createPaymentSession (One-time Payments) API after the buyer selects the payment method and submits payment.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.WAP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// replace with your specified payment method
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:
{
"env": {
"terminalType": "WAP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // Specify payment method
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}The following code shows a sample of the response, which contains the following parameters:
- result.resultStatus: The result of the createPaymentSession (One-time Payments) API call.
- paymentSessionData: The payment session data to be returned to the client.
- paymentSessionExpiryTime: The expiration time of the payment session.
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The table below shows the possible values of result.resultStatus in the response. Please handle the result according to the guidance provided:
Note: If no response is received, it may indicate a network timeout. Please use a new paymentRequestId and call the API again. If the issue persists, contact Antom Technical Support.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
Q: How to set the address to receive payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) 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: Does the returned paymentSessionData require processing before passing it to the client?
A: Do not process or modify paymentSessionData in any way, as this may cause the Payment Element invocation to fail.
Step 2: Invoke Payment Element Client-side
Use paymentSessionData to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.
Depending on the rendering method you chose in Step 1 (merchant-rendered or Payment Element-rendered payment method list), the following table compares how to invoke Payment Element in different scenarios:
- After obtaining paymentSessionData from the server, use the class to create a Payment Element instance. The following sample code how to instantiate the SDK using CDN or npm:
CDN
npm
// Get the browser language
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // Replace "-" with "_"
// Create Payment Element instance
const elementPayment = new window.AMSElement({
environment: "sandbox",
locale: "en_US",
sessionData:sessionData
})import { AMSElement, ThemeType, PaymentElementLayout } from '@alipay/ams-checkout' // Package management
// Get the browser language
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // Replace "-" with "_"
// Create Payment Element instance
const elementPayment = new AMSElement({
environment: "sandbox",
locale: "en_US",
sessionData:sessionData
})- Use the method from the instance object to create the payment component, and embed the component into the specified view if needed. Before calling the method, you may add a loading indicator and close it when handling the callback in the .then()method. If the callback result contains error information, determine the specific error type via error?.code, and refer to the callback function event codes for detailed error causes and handling suggestions. If no error information is present, the method rendering was successful.
Note:
- If you need to embed the payment details collection component (see Payment methods requiring embedding for details), it is recommended that the container for the payment element have a minimum width of 375 px and no height restriction, allowing the Payment Element to automatically expand the container height.
- The different configuration of notRedirectAfterComplete in the method handles the redirection of the merchant page differently. For details, refer to Redirect to the merchant page.
- When Payment Element renders the payment method list, the merchantAppointParam.singleOption parameter in the method defaults to skip. When only one payment method is specified, it will skip the payment method list and enter the payment flow directly. If you need to display the payment method list, you can change the value of this parameter tolist.
let loading = false;
// Customize appearance
const appearance = {
theme: "default",
layout: {
type: "Accordion"
},
variables: {},
};
// Set the loading state of the external container before calling mount
loading = true;
// Mount to the document.querySelector("#payment-element") node
elementPayment.mount({
type: 'payment',
appearance: appearance,
notRedirectAfterComplete: false,
merchantAppointParam: {
singleOption: 'skip'
}
},
'#payment-element',
).then(({
error
}) => {
// Manually turn off the loading state of the external container
loading = false;
// Consume the error message and handle exceptions based on error.code
if (error && error?.code) {
// PARAM_INVALID: SDK parameter exception. Please check the integration code
// UI_STATE_ERROR: Abnormal timing for the mount call. Please check the integration code
console.log(error.message);
if (error?.code === 'INITALIZE_API_TIMEOUT') {
// The inquiryPayment API timed out, causing the checkout page to fail to render. Please guide the buyer to retry
} else if (error?.code === 'INITALIZE_WEB_TIMEOUT') {
// Timeout while loading static resources for the checkout page. Please guide the buyer to retry
}...
return;
}
// Mount rendered successfully, no action needed
})- After the buyer clicks your custom payment button, call the method to submit payment.
Before calling the method, you may add a loading indicator and close it when handling the callback in the.then()method. It is recommended to display the loading state after the buyer clicks the payment button to prevent repeated submissions within a short period. After receiving the payment result returned by Payment Element, guide the buyer to either retry the payment or redirect to the payment result page based on the actual outcome.
- If the callback result contains error information, you can simplify integration based on the status value. Refer to the sample code below for specific operations. You may also refer to error?.code for specific exception handling and refer to callback function event codes for detailed error causes and handling suggestions.
- If no error information exists, proceed with subsequent operations based on the status value.
let loading = false;
function checkout() {
loading = true;
// When the buyer clicks the payment button:
elementPayment.submitPayment().then(({ status, userCanceled3D, session, error }) => {
// Manually turn off the loading state of the external container
loading = false;
if (error) { // Handle errors first
const { code, message, traceId, context } = error;
if (userCanceled3D) {
// The buyer manually closed the 3D secure pop-up. Please poll for the result from the server
}
if (status === 'PROCESSING') {
// The status is unknown due to network issues or channel instability. Please poll for the result from the server
} else {
// FAIL
// Form validation failed. Payment Element has already prompted the buyer, so this can be ignored
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// Or customize the experience based on the code
if (code) {
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// SUCCESS. In some scenarios, Payment Element will show a toast notification. Please redirect directly to the result page
} else if (status === 'CANCELLED') {
// The order has been cancelled. This can be ignored if this scenario is not applicable
} else {
// Monitoring can be added here
}
})
}- (Optional) You can call the method and pass the handleActions parameter to control whether Payment Element handles automatic redirects:
let loading = false;
function checkout() {
loading = true;
// When the buyer clicks the payment button:
elementPayment.submitPayment({ handleActions: false }).then(({ status, userCanceled3D, session, error }) => {
// Manually turn off the loading state of the external container
loading = false;
if (error) { // Handle errors first
const { code, message, traceId, context } = error;
if (userCanceled3D) {
// The buyer manually closed the 3D secure pop-up. Please poll for the result from the server
}
if (status === 'PROCESSING') {
// The status is unknown due to network issues or channel instability. Please poll for the result from the server
} else {
// FAIL
// Form validation failed. Payment Element has already prompted the buyer, so this can be ignored
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// Or customize the experience based on the code
if (code) {
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// SUCCESS. In some scenarios, Payment Element will show a toast notification. Please redirect directly to the result page
} else if (status === 'CANCELLED') {
// The order has been cancelled. This can be ignored if this scenario is not applicable
} else {
// Monitoring can be added here
}
if (session && session.nextAction) {
const { normalUrl, appLinkUrl, schemeUrl } = session.nextAction;
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/iphone|ipad|ipod/i.test(userAgent)) {
// iOS browser
if (appLinkUrl) {
window.open(appLinkUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(schemeUrl, '_blank');
return;
}
} else if (/android/i.test(userAgent)) {
// Android browser
if (appLinkUrl) {
window.open(schemeUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(appLinkUrl, '_blank');
return;
}
}
// PC/Web/WAP
window.open(normalUrl, '_blank');
}
})
}- (Optional) You can call the method and pass the shippingInfo parameter to submit shipping address information:
let loading = false;
const shippingInfo = {
shippingAddress: {
region: 'CN',
state: 'SM',
city: 'Shanghai',
address1: '88 Century Avenue',
address2: 'Floor 20, Tower A, Lujiazui',
zipCode: '200120'
},
shippingPhoneNo: '+86 18200000000',
shippingName: {
firstName: 'Cui',
lastName: 'Tom',
middleName: '**',
fullName: 'Tom ** Cui'
}
}
function checkout() {
loading = true;
// When the buyer clicks the payment button:
elementPayment.submitPayment({shippingInfo: shippingInfo, handleActions: true }).then(({ status, userCanceled3D, session, error }) => {
// Manually turn off the loading state of the external container
loading = false;
if (error) { // Handle errors first
const { code, message, traceId, context } = error;
if (userCanceled3D) {
// The buyer manually closed the 3D secure pop-up. Please poll for the result from the server
}
if (status === 'PROCESSING') {
// The status is unknown due to network issues or channel instability. Please poll for the result from the server
} else {
// FAIL
// Form validation failed. Payment Element has already prompted the buyer, so this can be ignored
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// Or customize the experience based on the code
if (code) {
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// SUCCESS. In some scenarios, Payment Element will show a toast notification. Please redirect directly to the result page
} else if (status === 'CANCELLED') {
// The order has been cancelled. This can be ignored if this scenario is not applicable
} else {
// Monitoring can be added here
}
if (session && session.nextAction) {
const { normalUrl, appLinkUrl, schemeUrl } = session.nextAction;
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/iphone|ipad|ipod/i.test(userAgent)) {
// iOS browser
if (appLinkUrl) {
window.open(appLinkUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(schemeUrl, '_blank');
return;
}
} else if (/android/i.test(userAgent)) {
// Android browser
if (appLinkUrl) {
window.open(schemeUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(appLinkUrl, '_blank');
return;
}
}
// PC/Web/WAP
window.open(normalUrl, '_blank');
}
})
}Validate payment elements for the currently selected payment method
The method is used to verify whether the form fields under the currently selected payment method are complete and properly formatted. This method automatically identifies and validates the required parameters based on the selected payment method, eliminating the need for developers to manually maintain the parameter list. Even if is not explicitly called, when executing , the component will automatically display the corresponding error messages if any form issues are detected.
let loading = false;
function checkout() {
loading = true;
// Validate the payment elements for the currently selected payment method
elementPayment.validateFields().then(({isValid}) => {
console.log(isValid);
// Form validation failed
if (!isValid) {
console.log('Form validation failed');
return;
}
});
// After validation passes, you can initiate submitPayment()
elementPayment.submitPayment().then(({ status, userCanceled3D, session, error }) => {
...
})
}Configure CVV verification for stored card payment scenarios
To enhance payment convenience and transaction success rates, the default value of the merchantAppointParam.storedCard.needCVV parameter in the method is
false
, meaning CVV verification is not performed by default in stored card payment scenarios. If your business scenario has special requirements for payment security, you can set this parameter to true
to enable CVV verification.Note: Unless specifically required, it is recommended that you maintain the default value of
false
to avoid requiring buyers to re-enter the CVV code, thereby optimizing the payment experience and improving transaction success rates.The following is a sample code for enabling CVV verification in specified stored card payment scenarios:
// Embed in document.querySelector("#payment-element")
elementPayment.mount({
...
merchantAppointParam: {
storedCard: {
needCVV: false
}
}
},
'#payment-element',
).then(({
error
}) => {
...
})Listen for component events
- event: Triggered when the buyer switches payment methods, the callback function receives a parameter payload, which contains data related to the payment method change.
elementPayment.on('paymentMethodChanged', (({type, name}) => {
console.log(type + name);
}));- event: Triggered when the buyer edits the billing address form data, the callback function receives a parameter payload, which contains the latest billing address form data.
elementPayment.on('billingAddressChanged', (({sameAsShipping, billingAddress}) => {
console.log(sameAsShipping + JSON.stringify(billingAddress));
}));Unmount Payment Element
elementPayment.destroy();Common questions
Q: Can I integrate the Web Element using Webview in PC or mobile applications?
A: Currently not supported.
Step 3: Obtain the payment result Server-side
After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:
- Receive asynchronous notifications from Antom
- Inquire about the payment result
Receive asynchronous notifications
Inquire about the result
1. Configure the webhook URL to receive asynchronous notifications
When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):
- If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through paymentNotifyUrl in the createPaymentSession (One-time Payments) API.
- If all your orders share a unified notification URL, you can set the webhook URL on Antom Dashboard through Developer > Notification URL. For detailed steps, refer to Notification URL.
The following code shows a sample of the asynchronous notification request:
Card payments, Apple Pay, Google Pay
APM payments
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // store cardToken for future card payments
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
2. Verify the asynchronous notification
When you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
You need to verify the signature of the payment notification sent by Antom:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// retrieve the required parameters from http request.
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// retrieve the required parameters from request header.
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// verify the signature of notification
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// deserialize the notification body
// update the order status with notify result
// respond the server that the notification is received
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// handle error condition
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}Common questions
Q: When will the notification be sent?
A: It depends on whether the payment is completed:
- If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
- If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
Q: Will the asynchronous notification be re-sent?
A: Yes, the asynchronous notification will be re-sent automatically within 24 hours for the following cases:
- If you didn't receive the asynchronous notification due to network reasons.
- If you receive an asynchronous notification from Antom, but you did not respond to the notification in the Sample code format.
The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
Q: When responding to an asynchronous notification, do I need to add a digital signature?
A: If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
Q: What key parameters do I need to use in the notification?
A: Please note the following key parameters:
A: Please note the following key parameters:
- result: For APM payments, it represents the final payment result. For Apple Pay, Google Pay, and card payments, it only represents the authorization result, and further capture is required.
- paymentRequestId: The payment request ID used for inquiries, cancellations, and reconciliation.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
- paymentAmount: The payment amount.
You can also inquire about the payment result by calling the inquiryPayment API using paymentRequestId from the payment request, regardless of whether it is an APM payment, card payment, Apple Pay, or Google Pay.
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// replace with your paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}The following sample code shows a request message:
{
"paymentRequestId": "paymentRequestId01"
}The following sample code shows a response message:
APM payments
Card payments, Apple Pay, Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please handle the result based on the value of the paymentStatus parameter in the response. For specific return values, refer to the API documentation.
Common questions
Q: What key parameters should I pay attention to when using the inquiryPayment API to check the payment or authorization status?
A: Please note the following key parameters:
- result: Only indicates the result of the API call. For APM payments, the final payment result should be determined based on paymentStatus (SUCCESS/FAIL/PROCESSING). For card payments, Apple Pay, and Google Pay, paymentStatus only represents the authorization result, and the decision to ship goods should rely on the capture result.
- paymentAmount: Used to verify the payment amount.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
Q: How often should I call the inquiryPayment API?
A: Call the inquiryPayment API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.
Step 4: Capture Server-sideFor card payments/Apple Pay/Google Pay only
Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to Capture.
User experience
The following figures demonstrate the user experience of using Payment Element in different scenarios:
Payment Element-rendered payment method list
Merchant-rendered payment method list
The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Stored card payments
Payment Element displays a QR code for buyers to complete the payment.

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

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

Payment Element handles the stored card payment scenario.

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

If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Payment Element displays a QR code for buyers to complete the payment.

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

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

Order lifecycle
Learn about the lifecycle of different payment methods:
APM Payments
Card payments, Apple Pay, Google Pay
For APM payments, such as Alipay and Touch'n Go eWallet, funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can cancel or refund the order within the allowable period.

For card payments, Apple Pay, and Google Pay, the order lifecycle includes the following stages:
- Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can cancel the order during the allowable period from when the order is placed until authorization is completed.
- Capture: You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to Capture. After capture, you can initiate a refund within the allowable period if needed.
- Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to Dispute.

Payment flow
The following flow illustrates how to integrate One-time Payments using Payment Element:
Payment Element-rendered payment method list
Merchant-rendered payment method list


- The buyer lands on the checkout page and submits payment.
- Create a payment session request.
You can obtain the payment session by calling the createPaymentSession (One-time Payments) API. - Invoke Payment Element.
On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the method, or the system will automatically return to your result page. - Confirm the payment result.
Obtain the payment result by using one of the following two methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard 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 payment status.
Note: For card payments, Apple Pay, and Google Pay, an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.
- Initiate capture and obtain the result.
By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the capture (One-time Payments) API. The capture result can be obtained through one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the notifyCapture (One-time Payments) API.
- Synchronous inquiry: Call the inquiryPayment API to check the capture status.
Integration preparations
Before you start integrating, read Integration guide and API overview to understand the integration steps of the server-side API and the precautions for calling the API. Furthermore, ensure the following prerequisites are met:
- Obtained your client ID
- Complete the key configuration
- Complete the configuration of paymentNotifyUrl to receive the asynchronous notification
- Integrate the server-side SDK package, install the server-side library, and initialize a request instance. For more details, refer to Server-side SDKs.
- Integrate the client-side SDK package by following the steps detailed in Integrate the SDK package for iOS, and ensure to use the latest SDK version or no lower than 1.46.0.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke Payment Element
- Obtain the payment result
- Capture
(Optional) Step 1: Preload the SDK Client-side
Before creating a payment session, it is highly recommended that you call the method to preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment. Follow the code example below to perform the preloading:
[AMSPaymentElement.shared preload];Step 2: Create a payment session Server-side
Call the createPaymentSession (One-time Payments) API with order information to create a payment session and obtain the paymentSessionData required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list.
It is recommended that you create a payment session after the buyer clicks the payment button. Depending on the method you selected for rendering the payment method list at the checkout page, pass the corresponding parameters when calling the createPaymentSession (One-time Payments) API.
Payment Element-rendered payment method list
Merchant-rendered payment method list
When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can specify payment methods to display only the options you need.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order Info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}When rendering the payment method list yourself, you must pass the parameters for specifying payment methods listed in the table below. If Payment Element needs to collect payment details, pass the card payment parameters listed in the table below.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// replace with your specified payment method
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}The following code shows a sample of the response, which contains the following parameters:
- result.resultStatus: The result of the createPaymentSession (One-time Payments) API call.
- paymentSessionData: The payment session data to be returned to the client.
- paymentSessionExpiryTime: The expiration time of the payment session.
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The table below shows the possible values of result.resultStatus in the response. Please handle the result according to the guidance provided:
Note: If no response is received, it may indicate a network timeout. Please use a new paymentRequestId and call the API again. If the issue persists, contact Antom Technical Support.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
Q: How to set the address to receive payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) 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: Does the returned paymentSessionData require processing before passing it to the client?
A: Do not process or modify paymentSessionData in any way, as this may cause the Payment Element invocation to fail.
Step 3: Invoke Payment Element Client-side
Use paymentSessionData to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.
- After obtaining paymentSessionData from the server, use the class to create a Payment Element instance.
- Creating the object and complete the SDK configuration.
- Implement to handle corresponding events in subsequent processes.
The following shows a sample code for creating the Payment Element instance using :
#import <AMSComponent/AMSComponent-Swift.h>
// Create an AMSPaymentElementConfiguration object
AMSPaymentElementConfiguration *componentConfig = [AMSPaymentElementConfiguration new];
componentConfig.locale = @"en_US";
NSString *appearance = @"{\n \"theme\": \"night\",\n \"layout\": {\n \"type\": \"Tabs\"\n },\n \"variables\": {\n \"content-quaternary\": \"#FFFF00\"\n }\n}";
// Set sandbox environment. If left empty, the online production environment will be used by default
NSDictionary *options = @{@"showLoading": @"true",
@"sandbox": @"true",
@"appearance": appearance
};
componentConfig.options = options;
// initConfiguration usage
[[AMSPaymentElement shared] initConfiguration:componentConfig completion:^(AMSStatusResult * _Nonnull result) {
// Handle error events during the initConfiguration phase
if (result.error) {
// Handle failure
if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
NSLog(@"integration code error, please check the integration code");
} else {
NSLog(@"unknown error, please contact support");
}
} else {
// Handle success
}
}];
// Set callback to listen for payment events on the checkout page
[AMSPaymentElement shared].paymentDelegate = self;
// Server calls the Create Payment Session API to obtain paymentSessionData
#pragma AMSPaymentProtocol
// Handle submitPay phase event codes via callback
- (void)onSubmitPayCallback:(AMSStatusResult *)eventResult {
AMSStatusResultType statusType = eventResult.status;
AMSResultError *error = eventResult.error;
switch (statusType) {
case AMSStatusResultTypePROCESSING:
if (error && error.code) {
if ([@"PAYMENT_IN_PROCESS" isEqualToString:error.code]) {
NSLog(@"payment is in processing, please try polling the payment result from the server");
} else if ([@"USER_CANCELED" isEqualToString:error.code]) {
NSLog(@"user cancelled the payment process, please try invoke createComponent again");
} else if ([@"UNKNOWN_EXCEPTION" isEqualToString:error.code]) {
NSLog(@"unknown exception, please contact support");
} else if ([@"PAYMENT_RESULT_TIMEOUT" isEqualToString:error.code]) {
NSLog(@"get payment result timeout, please try polling the payment result from the server");
}
}
break;
case AMSStatusResultTypeCANCELLED:
// fall through
case AMSStatusResultTypeSUCCESS:
NSLog(@"payment cancelled or success, do nothing");
break;
case AMSStatusResultTypeFAIL:
if (error && error.code) {
if ([@"ORDER_IS_CANCELLED" isEqualToString:error.code]) {
NSLog(@"the merchant has proactively canceled the order, please check on your own.");
} else if ([@"ORDER_IS_CLOSED" isEqualToString:error.code]) {
NSLog(@"the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
} else {
NSLog(@"unknown error, please contact support");
}
}
break;
default:
break;
}
}- Use the function from the instance object to invoke Payment Element:
// Callback event code method - createComponent usage
[[AMSPaymentElement shared] createComponent:paymentSessionData completion:^(AMSStatusResult * _Nonnull result) {
if (result.error) {
// Handle failure
if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
NSLog(@"integration code error, please check the integration code");
} else if ([result.error.code isEqualToString:@"PARAM_INVALID"]) {
NSLog(@"session data invalid, please check the session data");
} else if ([result.error.code isEqualToString:@"INITIALIZE_WEB_TIMEOUT"]) {
NSLog(@"web app timeout, please invoke component again");
} else {
NSLog(@"unknown error, please contact support");
}
} else {
// Handle success
}
}];
Unmount Payment Element
// Release SDK component resources
[[AMSPaymentElement shared] onDestroy];Step 4: Obtain the payment result Server-side
After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:
- Receive asynchronous notifications from Antom
- Inquire about the payment result
Receive asynchronous notifications
Inquire about the result
1. Configure the webhook URL to receive asynchronous notifications
When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):
- If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through paymentNotifyUrl in the createPaymentSession (One-time Payments) API.
- If all your orders share a unified notification URL, you can set the webhook URL on Antom Dashboard through Developer > Notification URL. For detailed steps, refer to Notification URL.
The following code shows a sample of the asynchronous notification request:
Card payments, Apple Pay, Google Pay
APM payments
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // store cardToken for future card payments
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
2. Verify the asynchronous notification
When you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
You need to verify the signature of the payment notification sent by Antom:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// retrieve the required parameters from http request.
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// retrieve the required parameters from request header.
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// verify the signature of notification
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// deserialize the notification body
// update the order status with notify result
// respond the server that the notification is received
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// handle error condition
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}Common questions
Q: When will the notification be sent?
A: It depends on whether the payment is completed:
- If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
- If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
Q: Will the asynchronous notification be re-sent?
A: Yes, the asynchronous notification will be re-sent automatically within 24 hours for the following cases:
- If you didn't receive the asynchronous notification due to network reasons.
- If you receive an asynchronous notification from Antom, but you did not respond to the notification in the Sample code format.
The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
Q: When responding to an asynchronous notification, do I need to add a digital signature?
A: If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
Q: What key parameters do I need to use in the notification?
A: Please note the following key parameters:
A: Please note the following key parameters:
- result: For APM payments, it represents the final payment result. For Apple Pay, Google Pay, and card payments, it only represents the authorization result, and further capture is required.
- paymentRequestId: The payment request ID used for inquiries, cancellations, and reconciliation.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
- paymentAmount: The payment amount.
You can also inquire about the payment result by calling the inquiryPayment API using paymentRequestId from the payment request, regardless of whether it is an APM payment, card payment, Apple Pay, or Google Pay.
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// replace with your paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}The following sample code shows a request message:
{
"paymentRequestId": "paymentRequestId01"
}The following sample code shows a response message:
APM payments
Card payments, Apple Pay, Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please handle the result based on the value of the paymentStatus parameter in the response. For specific return values, refer to the API documentation.
Common questions
Q: What key parameters should I pay attention to when using the inquiryPayment API to check the payment or authorization status?
A: Please note the following key parameters:
- result: Only indicates the result of the API call. For APM payments, the final payment result should be determined based on paymentStatus (SUCCESS/FAIL/PROCESSING). For card payments, Apple Pay, and Google Pay, paymentStatus only represents the authorization result, and the decision to ship goods should rely on the capture result.
- paymentAmount: Used to verify the payment amount.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
Q: How often should I call the inquiryPayment API?
A: Call the inquiryPayment API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.
Step 5: Capture Server-sideFor card payments or Apple Pay only
Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to Capture.
User experience
The following figures demonstrate the user experience of using Payment Element in different scenarios:
Payment Element-rendered payment method list
Merchant-rendered payment method list
The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Stored card payments
Payment Element displays a QR code for buyers to complete the payment.

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

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

Payment Element handles the stored card payment scenario.

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

If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Payment Element displays a QR code for buyers to complete the payment.

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

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

Order lifecycle
Learn about the lifecycle of different payment methods:
APM Payments
Card payments, Apple Pay, Google Pay
For APM payments, such as Alipay and Touch'n Go eWallet, funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can cancel or refund the order within the allowable period.

For card payments, Apple Pay, and Google Pay, the order lifecycle includes the following stages:
- Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can cancel the order during the allowable period from when the order is placed until authorization is completed.
- Capture: You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to Capture. After capture, you can initiate a refund within the allowable period if needed.
- Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to Dispute.

Payment flow
The following flow illustrates how to integrate One-time Payments using Payment Element:
Payment Element-rendered payment method list
Merchant-rendered payment method list


- The buyer lands on the checkout page and submits payment.
- Create a payment session request.
You can obtain the payment session by calling the createPaymentSession (One-time Payments) API. - Invoke Payment Element.
On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the method, or the system will automatically return to your result page. - Confirm the payment result.
Obtain the payment result by using one of the following two methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard 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 payment status.
Note: For card payments, Apple Pay, and Google Pay, an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.
- Initiate capture and obtain the result.
By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the capture (One-time Payments) API. The capture result can be obtained through one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the notifyCapture (One-time Payments) API.
- Synchronous inquiry: Call the inquiryPayment API to check the capture status.
Integration preparations
Before you start integrating, read Integration guide and API overview to understand the integration steps of the server-side API and the precautions for calling the API. Furthermore, ensure the following prerequisites are met:
- Obtained your client ID
- Complete the key configuration
- Complete the configuration of paymentNotifyUrl to receive the asynchronous notification
- Integrate the server-side SDK package, install the server-side library, and initialize a request instance. For more details, refer to Server-side SDKs.
- Integrate the client-side SDK package by following the steps detailed in Integrate the SDK package for Android, and ensure to use the latest SDK version or no lower than 1.46.0.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke Payment Element
- Obtain the payment result
- Capture
(Optional) Step 1: Preload the SDK Client-side
Before creating a payment session, it is highly recommended that you call the method to preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment. Follow the code example below to perform the preloading:
AMSPaymentElement.preload(getApplicationContext());Step 2: Create a payment session Server-side
Call the createPaymentSession (One-time Payments) API with order information to create a payment session and obtain the paymentSessionData required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list.
It is recommended that you create a payment session after the buyer clicks the payment button. Depending on the method you selected for rendering the payment method list at the checkout page, pass the corresponding parameters when calling the createPaymentSession (One-time Payments) API.
Payment Element-rendered payment method list
Merchant-rendered payment method list
When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can specify payment methods to display only the options you need.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.ANDROID).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "ANDROID"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}When rendering the payment method list yourself, you must pass the parameters for specifying payment methods listed in the table below. If Payment Element needs to collect payment details, pass the card payment parameters listed in the table below.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.ANDROID).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order Info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// replace with your specified payment method
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "ANDROID"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // Specify payment method
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}The following code shows a sample of the response, which contains the following parameters:
- result.resultStatus: The result of the createPaymentSession (One-time Payments) API call.
- paymentSessionData: The payment session data to be returned to the client.
- paymentSessionExpiryTime: The expiration time of the payment session.
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The table below shows the possible values of result.resultStatus in the response. Please handle the result according to the guidance provided:
Note: If no response is received, it may indicate a network timeout. Please use a new paymentRequestId and call the API again. If the issue persists, contact Antom Technical Support.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
Q: How to set the address to receive payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) 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: Does the returned paymentSessionData require processing before passing it to the client?
A: Do not process or modify paymentSessionData in any way, as this may cause the Payment Element invocation to fail.
Step 3: Invoke Payment Element Client-side
Use paymentSessionData to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.
- After obtaining paymentSessionData from the server, use the class to create SDK instance.
- Creating the object and complete the SDK configuration.
- Implement to handle events in the process of invoking the payment component and launching the payment page.
- Implement to handle events related to the payment initiation process.
AMSPaymentElementConfiguration configuration = new AMSPaymentElementConfiguration();
configuration.setLocale(new Locale("en", "US"));
configuration.setOption("showLoading", "true");
configuration.setOption("sandbox", "true");
configuration.setOption("notRedirectAfterComplete", "false");
String appearance = "{\"theme\":\"night\",\"layout\":{\"type\":\"accordion\"},\"variables\":{\"content-primary\":\"#ff5b4d\"}}";
configuration.setOption("appearance", appearance);
configuration.setOnCreateComponentListener(new OnCreateComponentListener() {
@Override
public void onCreateComponentCallback(AMSStatusResult statusResult) {
if (statusResult.getError() != null) {
switch (statusResult.getError().getCode()) {
case "UI_STATE_ERROR":
System.out.println("integration code error, please check the integration code");
break;
case "PARAM_INVALID":
System.out.println("session data invalid, please check the session data");
break;
case "INITIALIZE_WEB_TIMEOUT":
System.out.println("web app timeout, please invoke component again");
break;
default:
System.out.println("unknown error, please contact support");
break;
}
}
}
});
configuration.setOnSubmitPayListener(new OnSubmitPayListener() {
@Override
public void onSubmitPayCallback(AMSStatusResult statusResult) {
AMSStatus status = statusResult.getStatus();
AMSResultError error = statusResult.getError();
if (status == AMSStatus.PROCESSING) {
if (error != null && error.getCode() != null) {
if ("PAYMENT_IN_PROCESS".equals(error.getCode())) {
System.out.println("payment is in processing, please try polling the payment result from the server");
} else if ("USER_CANCELED".equals(error.getCode())){
System.out.println("user cancelled the payment process, please try invoke createComponent again");
} else if ("UNKNOWN_EXCEPTION".equals(error.getCode())) {
System.out.println("unknown exception, please contact support");
} else if ("PAYMENT_RESULT_TIMEOUT".equals(error.getCode())){
System.out.println("get payment result timeout, please try polling the payment result from the server");
}
}
} else if (status == AMSStatus.CANCELLED || status == AMSStatus.SUCCESS) {
System.out.println("payment cancelled or success, do nothing");
} else if (status == AMSStatus.FAIL) {
if (error != null && error.getCode() != null) {
if ("ORDER_IS_CANCELLED".equals(error.getCode())) {
System.out.println("the merchant has proactively canceled the order, please check on your own.");
} else if ("ORDER_IS_CLOSED".equals(error.getCode()) || "INQUIRY_PAYMENT_SESSION_FAILED".equals(error.getCode())){
System.out.println("the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
} else {
System.out.println("unknown error, please contact support");
}
}
}
}
});
AMSPaymentElement amsPaymentElement = new AMSPaymentElement.Builder(this, (AMSPaymentElementConfiguration) configuration).build();
- Use the function from the instance object to invoke Payment Element:
// paymentSessionData obtained when creating a payment session
String paymentSessionData = "exxxxe";
amsPaymentElement.createComponent(this, paymentSessionData);Unmount Payment Element
// release SDK component resources
amsPaymentElement.onDestroy();Step 4: Obtain the payment result Server-side
After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:
- Receive asynchronous notifications from Antom
- Inquire about the payment result
Receive asynchronous notifications
Inquire about the result
1. Configure the webhook URL to receive asynchronous notifications
When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):
- If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through paymentNotifyUrl in the createPaymentSession (One-time Payments) API.
- If all your orders share a unified notification URL, you can set the webhook URL on Antom Dashboard through Developer > Notification URL. For detailed steps, refer to Notification URL.
The following code shows a sample of the asynchronous notification request:
Card payments, Apple Pay, Google Pay
APM payments
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // store cardToken for future card payments
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
2. Verify the asynchronous notification
When you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
You need to verify the signature of the payment notification sent by Antom:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// retrieve the required parameters from http request.
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// retrieve the required parameters from request header.
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// verify the signature of notification
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// deserialize the notification body
// update the order status with notify result
// respond the server that the notification is received
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// handle error condition
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}Common questions
Q: When will the notification be sent?
A: It depends on whether the payment is completed:
- If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
- If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
Q: Will the asynchronous notification be re-sent?
A: Yes, the asynchronous notification will be re-sent automatically within 24 hours for the following cases:
- If you didn't receive the asynchronous notification due to network reasons.
- If you receive an asynchronous notification from Antom, but you did not respond to the notification in the Sample code format.
The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
Q: When responding to an asynchronous notification, do I need to add a digital signature?
A: If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
Q: What key parameters do I need to use in the notification?
A: Please note the following key parameters:
A: Please note the following key parameters:
- result: For APM payments, it represents the final payment result. For Apple Pay, Google Pay, and card payments, it only represents the authorization result, and further capture is required.
- paymentRequestId: The payment request ID used for inquiries, cancellations, and reconciliation.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
- paymentAmount: The payment amount.
You can also inquire about the payment result by calling the inquiryPayment API using paymentRequestId from the payment request, regardless of whether it is an APM payment, card payment, Apple Pay, or Google Pay.
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// replace with your paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}The following sample code shows a request message:
{
"paymentRequestId": "paymentRequestId01"
}The following sample code shows a response message:
APM payments
Card payments, Apple Pay, Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please handle the result based on the value of the paymentStatus parameter in the response. For specific return values, refer to the API documentation.
Common questions
Q: What key parameters should I pay attention to when using the inquiryPayment API to check the payment or authorization status?
A: Please note the following key parameters:
- result: Only indicates the result of the API call. For APM payments, the final payment result should be determined based on paymentStatus (SUCCESS/FAIL/PROCESSING). For card payments, Apple Pay, and Google Pay, paymentStatus only represents the authorization result, and the decision to ship goods should rely on the capture result.
- paymentAmount: Used to verify the payment amount.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
Q: How often should I call the inquiryPayment API?
A: Call the inquiryPayment API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.
Step 5: Capture Server-sideFor card payments or Google Pay only
Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to Capture.
User experience
The following figures demonstrate the user experience of using Payment Element in different scenarios:
iOS
Android
Payment Element-rendered payment method list
Merchant-rendered payment method list
The following figure shows templates for invoking the Payment Element-rendered payment method list in a pop-up:

If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Stored card payments
Payment Element displays a QR code for buyers to complete the payment.

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

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

Payment Element handles the stored card payment scenario.

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

If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Payment Element displays a QR code for buyers to complete the payment.

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

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

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

If you use the Payment Element-rendered payment method list, all supported payment methods will be displayed on the checkout page by default. The following figures illustrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Stored card payments
Payment Element displays a QR code for buyers to complete the payment.

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

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

Payment Element handles the stored card payment scenario.

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

If you render the payment methods by specifying them yourself, the following figures demonstrate the user experience for different payment methods:
Scan to pay
Redirect to payment page
New card payment
Payment Element displays a QR code for buyers to complete the payment.

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

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

Order lifecycle
Learn about the lifecycle of different payment methods:
APM Payments
Card payments, Apple Pay, Google Pay
For APM payments, such as Alipay and Touch'n Go eWallet, funds are transferred directly to your account once the payment is initiated and completed by the buyer. You can cancel or refund the order within the allowable period.

For card payments, Apple Pay, and Google Pay, the order lifecycle includes the following stages:
- Authorization: After the buyer completes the payment using a card, the funds are temporarily frozen. You can cancel the order during the allowable period from when the order is placed until authorization is completed.
- Capture: You can manually capture the frozen funds to transfer them to your account, or let Antom automatically handle capture for you. For details, refer to Capture. After capture, you can initiate a refund within the allowable period if needed.
- Chargeback: You may submit a chargeback defense based on the specific situation. For more information, refer to Dispute.

Payment flow
The following flow illustrates how to integrate One-time Payments using Payment Element:
Payment Element-rendered payment method list
Merchant-rendered payment method list


- The buyer lands on the checkout page and submits payment.
- Create a payment session request.
You can obtain the payment session by calling the createPaymentSession (One-time Payments) API. - Invoke Payment Element.
On the client side, invoke Payment Element using the payment session. You can choose to use the Payment Element-rendered payment method list, or render the payment methods by specifying them yourself. Payment Element will handle information processing, collect payment details, perform redirects, manage app invocations, display QR codes, and conduct validations based on the features of the selected payment method. After the payment is completed, depending on your configuration and the payment method features, you need to handle redirections based on the result returned by the method, or the system will automatically return to your result page. - Confirm the payment result.
Obtain the payment result by using one of the following two methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard 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 payment status.
Note: For card payments, Apple Pay, and Google Pay, an authorized-capture mode is used. Steps 1 to 4 only complete the authorization stage-where the buyer completes payment using a card and the funds are temporarily frozen. To transfer the funds to your account, you must complete the capture step. A successful capture result should be used as the basis for shipping goods.
- Initiate capture and obtain the result.
By default, Antom automatically handles fund capture on your behalf. You can also manually capture funds by calling the capture (One-time Payments) API. The capture result can be obtained through one of the following methods:
- Asynchronous notification: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) API or configure on Antom Dashboard to set the address for receiving asynchronous notifications. Upon capture completion, Antom will send you asynchronous notifications via the notifyCapture (One-time Payments) API.
- Synchronous inquiry: Call the inquiryPayment API to check the capture status.
Integration preparations
Before you start integrating, read Integration guide and API overview to understand the integration steps of the server-side API and the precautions for calling the API. Furthermore, ensure the following prerequisites are met:
- Obtained your client ID
- Complete the key configuration
- Complete the configuration of paymentNotifyUrl to receive the asynchronous notification
- Integrate the server-side SDK package, install the server-side library, and initialize a request instance. For more details, refer to Server-side SDKs.
- Integrate the client-side SDK package by following the steps detailed in Integrate the SDK package for Flutter.
Integration steps
Start your integration by taking the following steps:
- (Optional) Preload the SDK
- Create a payment session
- Invoke Payment Element
- Obtain the payment result
- Capture
(Optional) Step 1: Preload the SDK Client-side
Before creating a payment session, it is highly recommended that you call the method to preload the SDK to improve the rendering speed of the checkout page, reducing the waiting time for buyers during the payment. Follow the code example below to perform the preloading:
// Preload Payment Element SDK
AMSPaymentElement.preload();Step 2: Create a payment session Server-side
Call the createPaymentSession (One-time Payments) API with order information to create a payment session and obtain the paymentSessionData required to invoke Payment Element. You can choose to either render the payment methods by specifying them yourself or use the Payment Element-rendered payment method list.
It is recommended that you create a payment session after the buyer clicks the payment button. Depending on the method you selected for rendering the payment method list at the checkout page, pass the corresponding parameters when calling the createPaymentSession (One-time Payments) API.
Payment Element-rendered payment method list
Merchant-rendered payment method list
When using the Payment Element-rendered payment method list, you only need to pass the parameters listed in the table below. Payment Element renders all supported payment methods on the checkout page by default, but you can specify payment methods to display only the options you need.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you use Payment Element-rendered payment method list, Payment Element will display all supported payment methods by default. The following code shows a sample of the request message:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}When rendering the payment method list by yourself, you must pass the parameters for specifying payment methods listed in the table below. If Payment Element needs to collect payment details, pass the card payment parameters listed in the table below.
The above parameters are the basic parameters for creating a payment session, for full parameters and additional requirements for certain payment methods refer to createPaymentSession (One-time Payments).
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// replace with your environment info
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// replace with your paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// convert amount unit(in practice, amount should be calculated on your serverside)
// For details, please refer to: <a href="https://docs.antom.com/ac/ref/cc">Usage rules of the Amount object</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// set amount
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// set settlement strategy
// replace with your existing settlement currency
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// set buyer info
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// replace with your orderId
String orderId = UUID.randomUUID().toString();
// set order info
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// replace with your notify url
// or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// replace with your redirect url
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// replace with your specified payment method
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}If you render the payment method list yourself, you must integrate by specifying individual payment methods. The following code shows a sample of the request message:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // The buyer's IP adress
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // Specify payment method
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}The following code shows a sample of the response, which contains the following parameters:
- result.resultStatus: The result of the createPaymentSession (One-time Payments) API call.
- paymentSessionData: The payment session data to be returned to the client.
- paymentSessionExpiryTime: The expiration time of the payment session.
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The table below shows the possible values of result.resultStatus in the response. Please handle the result according to the guidance provided:
Note: If no response is received, it may indicate a network timeout. Please use a new paymentRequestId and call the API again. If the issue persists, contact Antom Technical Support.
Common questions
Q: Can I use Chinese characters in the value of the request parameters?
A: To avoid incompatibility of certain payment methods, do not use Chinese characters for fields in the request.
Q: How to set the address to receive payment notification?
A: Specify paymentNotifyUrl in the createPaymentSession (One-time Payments) 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: Does the returned paymentSessionData require processing before passing it to the client?
A: Do not process or modify paymentSessionData in any way, as this may cause the Payment Element invocation to fail.
Step 3: Invoke Payment Element Client-side
Use paymentSessionData to invoke Payment Element on your client. After the buyer clicks to submit payment, Payment Element will handle the entire flow based on the selected payment method, including displaying QR codes, redirecting to payment pages, performing 3DS authentication, and returning to the merchant’s result page.
- After obtaining paymentSessionData from the server, use the method to create Payment Element instance and initialize.
- Implement the method for initialization, and pass the relevant configuration items in the configurations object:
final element = AMSPaymentElement();
element.init(
{
"locale": "en_US",
"showLoading": "true",
"sandbox": "true",
"notRedirectAfterComplete": "false",
"appearance":
"{"theme":"default","layout":{"type":"accordion"},"variables":{}}",
},
(result) {
if (result.getStatus() == AMSStatus.SUCCESS) {
// Initialization succeeded, continue calling createComponent()
print('Initialization succeeded');
} else {
// Initialization failed, check result.getError()
final error = result.getError();
print('Initialization failed: ${error?.getCode()} - ${error?.getMessage()}');
}
},
);Note: Different configurations of "notRedirectAfterComplete" in the method will affect the merchant page's redirection behavior. For details, please refer to Redirect to the merchant page.
- Implement the callback function in the method to monitor exception events during the payment component initialization process. Please refer to the error code and message in the callback parameters for handling.
- (Optional) Implement the callback function in the method to monitor events during the payment process. Please refer to the error code and message in the callback parameters for handling.
Note: It is strongly recommended that you use the method to monitor payment events in order to enhance user experience.
- Implement the method to create and display the payment component UI, and implement the callback function to monitor exception events during the payment component creation process. Please refer to the error code and message in the callback parameters for handling.
AMSPaymentElement.preload();
// Create AMSPaymentElement instance
AMSPaymentElement amsPaymentElement = AMSPaymentElement();
// Set configuration items, parameter settings can be referenced below
Map<String, dynamic> amsPaymentElementConfiguration = {
"locale": "en_US",
"showLoading": "true",
"sandbox": "true",
"notRedirectAfterComplete": "false",
"appearance":
"{"theme":"default","layout":{"type":"accordion"},"variables":{}}",
};
// Initialize and listen to initialization results
amsPaymentElement?.init(config, (result) {
if (result.getError() != null && result.getError()?.getCode() != null) {
print(
"code: ${result.getError()?.getCode()}, message: ${result.getError()?.getMessage()}",
);
}
});
// Optional, but strongly recommended to set payment status listener, handle according to error codes and messages, for specific handling recommendations please refer to the event code list
amsPaymentElement?.setOnSubmitPayListener((result) {
AMSStatus? status = result.getStatus();
if (status != AMSStatus.SUCCESS) {
AMSResultError? error = result.getError();
String code = error?.getCode() ?? "";
String message = error?.getMessage() ?? "";
print("code: $code, message: $message");
}
});
// paymentSessionData obtained when creating payment session
String paymentSessionData = "exxxxe";
// Use the createComponent() method in the instance object to call Payment Element, and set call result listener, if error code is not empty, refer to the event code list for handling
amsPaymentElement.createComponent(sessionData, (result) {
if (result.getError() != null && result.getError()?.getCode() != null) {
print(
"code: ${result.getError()?.getCode()}, message: ${result.getError()?.getMessage()}",
);
}
});Unmount Payment Element
// release SDK component resources
amsPaymentElement.destroy();Step 4: Obtain the payment result Server-side
After the buyer completes the payment or the payment times out, Antom will send the corresponding payment results to you through server interaction. You can obtain the payment results using one of the following methods:
- Receive asynchronous notifications from Antom
- Inquire about the payment result
Receive asynchronous notifications
Inquire about the result
1. Configure the webhook URL to receive asynchronous notifications
When a payment succeeds or fails, Antom will send an asynchronous notification to the webhook URL you set. You can choose one of the following two methods to configure the webhook URL for receiving notifications (if both are set, the URL specified in the request takes precedence):
- If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through paymentNotifyUrl in the createPaymentSession (One-time Payments) API.
- If all your orders share a unified notification URL, you can set the webhook URL on Antom Dashboard through Developer > Notification URL. For detailed steps, refer to Notification URL.
The following code shows a sample of the asynchronous notification request:
Card payments, Apple Pay, Google Pay
APM payments
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // store cardToken for future card payments
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}The following table shows the possible values of result.resultStatus in the notification request of payment result. Please handle the result according to the guidance provided:
2. Verify the asynchronous notification
When you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
You need to verify the signature of the payment notification sent by Antom:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// retrieve the required parameters from http request.
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// retrieve the required parameters from request header.
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// verify the signature of notification
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// deserialize the notification body
// update the order status with notify result
// respond the server that the notification is received
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// handle error condition
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}Whether the payment is successful or not, each notification request must be responded to in the format specified below. Otherwise, Antom will resend the asynchronous notification.
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}Common questions
Q: When will the notification be sent?
A: It depends on whether the payment is completed:
- If the payment is successfully completed, Antom will send you an asynchronous notification within 3 to 5 seconds. For some payment methods like OTC, the notification might take a bit longer.
- If the payment is not completed, Antom needs to close the order first before sending an asynchronous notification. The time it takes for different payment methods to close the order varies, usually defaulting to 14 minutes.
Q: Will the asynchronous notification be re-sent?
A: Yes, the asynchronous notification will be re-sent automatically within 24 hours for the following cases:
- If you didn't receive the asynchronous notification due to network reasons.
- If you receive an asynchronous notification from Antom, but you did not respond to the notification in the Sample code format.
The notification can be resent up to 8 times or until a correct response is received to terminate delivery. The sending intervals are as follows: 0 minutes, 2 minutes, 10 minutes, 10 minutes, 1 hour, 2 hours, 6 hours, and 15 hours.
Q: When responding to an asynchronous notification, do I need to add a digital signature?
A: If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
Q: What key parameters do I need to use in the notification?
A: Please note the following key parameters:
A: Please note the following key parameters:
- result: For APM payments, it represents the final payment result. For Apple Pay, Google Pay, and card payments, it only represents the authorization result, and further capture is required.
- paymentRequestId: The payment request ID used for inquiries, cancellations, and reconciliation.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
- paymentAmount: The payment amount.
You can also inquire about the payment result by calling the inquiryPayment API using paymentRequestId from the payment request, regardless of whether it is an APM payment, card payment, Apple Pay, or Google Pay.
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// replace with your paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}The following sample code shows a request message:
{
"paymentRequestId": "paymentRequestId01"
}The following sample code shows a response message:
APM payments
Card payments, Apple Pay, Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}Please handle the result based on the value of the paymentStatus parameter in the response. For specific return values, refer to the API documentation.
Common questions
Q: What key parameters should I pay attention to when using the inquiryPayment API to check the payment or authorization status?
A: Please note the following key parameters:
- result: Only indicates the result of the API call. For APM payments, the final payment result should be determined based on paymentStatus (SUCCESS/FAIL/PROCESSING). For card payments, Apple Pay, and Google Pay, paymentStatus only represents the authorization result, and the decision to ship goods should rely on the capture result.
- paymentAmount: Used to verify the payment amount.
- paymentId: The payment order ID generated by Antom, used for refunds and reconciliation.
Q: How often should I call the inquiryPayment API?
A: Call the inquiryPayment API constantly with an interval of 2 seconds until the final payment result is obtained or an asynchronous payment result notification is received.
Step 5: Capture Server-sideFor card payments or Google Pay only
Antom provides both automatic and manual capture methods. You can choose based on your business needs. After initiating capture, you can obtain the result via asynchronous notification or active inquiry. You should decide whether to ship goods based on the capture result. For specific operations, refer to Capture.
After payments
After completing the payment, you can perform the following actions:
Cancellation Server-side
For successful payments, if the buyer requests cancellation or a refund on the same day, you can use Antom’s cancellation capability to cancel the order or release funds. Orders not yet completed can also be cancelled directly. For details, refer to Cancel.
Refund Server-side
Different payment methods have varying refund capabilities. To learn about Antom refund rules and how to initiate a refund for a successful transaction, refer to Refund.
Dispute Server-side
Antom provides dispute resolution services for contested transactions. For more information, refer to Dispute Guidance and Dispute resolution.
Payment method features
This section explains differences in supported features across payment methods.
Default timeout
The default order closing time varies for different payment methods. For specific information, refer to Payment method default timeout.
Note: Since Payment Element orders have a default validity period of 1 hour, the actual timeout period is extended by 1 hour beyond the payment method’s default timeout. For example, if a payment method’s default timeout is 14 minutes, the actual timeout period for a Payment Element order will be 1 hour and 14 minutes.
Integration key points
Refer to Integration key considerations to learn about the integration key points and recommended solutions for different payment methods.
Card payment features
Payment Element supports the following card payment features. Click to get detailed information and usage instructions:
Additional content
Antom also offers the following customization options:
- Appearance customization: Antom provides extensive styling options, including theme, layout, and CSS customization.
- Google Pay: Buyers can pay using credit or debit cards stored in their Google account. With Payment Element, no additional Google Pay SDK integration is needed—it loads Google Pay automatically.
- Apple Pay: Buyers can pay using credit or debit cards stored in their Apple account. With Payment Element, no additional Apple Pay SDK integration is needed—it loads Apple Pay automatically.
Specify a payment method
You can pass the parameters in the createPaymentSession (One-time Payments) API to specify the display of payment methods on Payment Element, the order of the payment method list, and the display of quick payments. This feature offers you the following benefits:
- Filter local payment methods based on your business region.
- Sort your preferred payment methods.
- Display the mainstream quick payments, such as Alipay, Apple Pay and Google Pay.
Payment methods requiring embedding
The following payment methods require you to embed the payment details collection component:
Payment retry mechanism
Antom provides a payment retry mechanism. For payment sessions created via the createPaymentSession (One-time Payments) API, buyers can make multiple payment attempts and freely switch payment methods within the validity period of the payment session, without requiring the merchant server to re-invoke the API. For more information, refer to Payment retry mechanism.