Hosted mode
This article describes how to integrate card payment methods through the hosted mode. The hosted mode protects you from PCI-DSS restrictions because sensitive data is not passed through your servers and there is no requirement for you to be PCI-qualified. In this mode, Antom provides a payment information collection page that captures payment information and stores it as a card token (cardToken) for use in subsequent processes.
User experience
The following figures show the user experience in the first-time and saved card payments.
First-time payment
Saved card payment
Payment flow
For each payment method, the payment flow composed of the following steps:
For card payments with the hosted mode, the payment flow is composed of the following steps:
- The buyer enters the checkout page.
- The merchant server initiates a payment request with the payment method, amount, currency, and other information.
- The merchant client redirects to the URL returned by the payment request.
- The merchant server receives payment result notification.
- The merchant server receives capture result notification.
Quick start
Most card payments follow the general payment flow and integration process provided by Antom. Start your integration by taking the following steps.
Note: For Korean cards, issuer-authentication and non-authentication payment types exist. Non-authentication payments of Korean cards follow the general card payment process. However, issuer-authentication payments of Korean cards involve additional actions to take.
Step 1: (Optional) Display payment methods
Add the logo and name of the payment methods to be integrated to the payment method list on the payment page for buyers to select. You can obtain the logo and name in one of the following two ways:
- Contact Antom Technical Support to obtain.
- Call the consult API to obtain the payment methods and logo URL supported by the current transactions based on the currency, transaction initiation terminal type, user region, and contracted payment methods.
The following figure shows the page effect after adding a payment method:
Note: For Korean cards with issuer authentication required, you need to display card brands for the buyer to select.
Step 2: Authorize a payment
When the user selects a payment method provided by Antom, the card information collection page is displayed for the user. During this process, you need to collect the user's card, environment, and order information. Call the pay API, and submit an authorization request for payment.
Initiate a payment request
Antom provides server-side API libraries for multiple languages. The following code uses Java as an example. You need to install Java 6 or higher.
Install an API library
You can find the latest version on GitHub.
<dependency>
<groupId>com.alipay.global.sdk</groupId>
<artifactId>global-open-sdk-java</artifactId>
<version>2.0.21</version>
</dependency>
Initialize the request instance
String merchantPrivateKey = "YOUR PRIVATE KEY";
String alipayPublicKey = "ALIPAY PUBLIC KEY"
AlipayClient defaultAlipayClient = new DefaultAlipayClient(EndPointConstants.SG,
merchantPrivateKey, alipayPublicKey);
Create a payment request
When sending a request for the pay API, you can also choose the following features according to your business needs:
- Enable 3D authentication: Specify the value of is3DSAuthentication in the pay API to set whether the transaction is authenticated by using 3D Secure.
- Salvage transaction intelligently: Automatically initiate a 3D Secure authentication for a non-3D Secure transaction if required by the card issuer to salvage a failed transaction.
- Value-added risk control services: Antom provides upgraded risk control services at a transaction level, and intelligently decides risk control strategies based on the risk level of a transaction.
- Address Verification System (AVS) service: This service verifies whether the provided billing address matches the cardholder's address on record at the issuing bank. AVS helps to prevent fraudulent transactions.
- Store card info: Obtain the buyer's agreement to store card information at the first payment, so that the card information does not need to be entered again for the next payment.
- Merchant-initiated transactions (MIT): Initiate scheduled or unscheduled transactions without user involvement.
- Specify card brand: When the buyer chooses co-badged card payment, you can specify the card brand or the region where the card is authorized for payment.
- MPI capability: The merchant prioritizes the third-party verification before the transaction is initiated, passes in the verification result information in the payment request, and specifies non-3D verification, which is not available if the merchant does not capture the card information.
- Installment payments: When making a payment, buyers can choose the installment payment method and make regular payments for each installment period. After the buyer completes the payment for the initial installment period, Antom settles the full order amount based on the settlement period specified in the contract.
The following parameters are included in the payment request.
Parameter name | Is required? | Description |
productCode | Yes | Represents the payment product that is being used, which is stipulated in the contract. For Cashier Payment, the value is fixed as |
paymentRequestId | Yes | The unique ID assigned by a merchant to identify a payment request. |
paymentAmount | Yes | The payment amount that the merchant requests to receive in the order currency. |
paymentMethod | Yes | The payment method that is used to collect the payment by the merchant or acquirer. |
paymentRedirectUrl | Yes | The merchant page URL that the user is redirected to after the payment is completed. |
settlementStrategy | No | The settlement strategy for the payment request. |
order | Yes | The order information, such as buyer, merchant, goods, amount, shipping information, and purchase environment. |
paymentExpiryTime | No | The specific date and time after which the payment session will expire. |
env | Yes | Environmental information: used to improve payment success rate. |
selectedCardBrand | No | For issuer-authentication of Korean cards scenarios, you need to specify the selectedCardBrand parameter as the specific card brand, see Card brands for a list of card brands. |
requireIssuerAuthentication | No | For issuer-authentication of Korean cards scenarios, you need to specify the requireIssuerAuthentication parameter as |
For more information about all parameters, refer to pay API.
The following sample code is used for initiating a payment:
AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
alipayPayRequest.setClientId(CLIENT_ID);
alipayPayRequest.setPath("/ams/sandbox/api/v1/payments/pay");
alipayPayRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
// replace to your paymentRequestId
alipayPayRequest.setPaymentRequestId("paymentRequestId01");
// set amount
Amount amount = new Amount();
amount.setCurrency("SGD");
amount.setValue("4200");
alipayPayRequest.setPaymentAmount(amount);
// set paymentMethod
PaymentMethod paymentMethod = new PaymentMethod();
paymentMethod.setPaymentMethodType("CARD");
alipayPayRequest.setPaymentMethod(paymentMethod);
//set paymentFactor
PaymentFactor paymentFactor = new PaymentFactor();
paymentFactor.setAuthorization(true);
alipayPayRequest.setPaymentFactor(paymentFactor);
// set order Info
Order order = new Order();
order.setReferenceOrderId("referenceOrderId01");
order.setOrderDescription("antom test order");
Buyer buyer = new Buyer();
buyer.setReferenceBuyerId("yourBuyerId");
order.setBuyer(buyer);
order.setOrderAmount(amount);
alipayPayRequest.setOrder(order);
//set env Info
Env env = new Env();
env.setTerminalType(TerminalType.WEB);
env.setClientIp("114.121.121.01");
alipayPayRequest.setEnv(env);
// replace to your notify url
alipayPayRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com");
// replace to your redirect url
alipayPayRequest.setPaymentRedirectUrl("http://www.yourRedirectUrl.com");
//do the Payment
AlipayPayResponse alipayPayResponse = null;
try {
alipayPayResponse = defaultAlipayClient.execute(alipayPayRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
The following code shows a sample of the request message:
{
"paymentNotifyUrl": "http://www.yourNotifyUrl.com",
"paymentRequestId": "paymentRequestId011",
"env": {
"terminalType": "WEB",
"clientIp": "114.121.121.01"
},
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"productCode": "CASHIER_PAYMENT",
"paymentRedirectUrl": "http://www.yourRedirectUrl.com",
"paymentFactor": {
"isAuthorization": true
},
"paymentMethod": {
"paymentMethodType": "CARD"
},
"order": {
"orderAmount": {
"currency": "SGD",
"value": "4200"
},
"referenceOrderId": "referenceOrderId01",
"orderDescription": "antom test order",
"buyer": {
"referenceBuyerId": "yourBuyerId"
}
}
}
FAQs:
If the user initiates a transaction from PC, the terminalType needs to be specified as
Do not use Chinese characters in the request field to avoid incompatible payment methods, such as QRIS and Mastercard.
Antom will send the payment result through the notifyPayment, which you can specify in the pay API via the paymentNotifyUrl parameter. If the address of each payment is the same, you can also configure it in the Antom Dashboard. If you have configured the address and set the parameter in the API, Antom will use the address set in the API. |
Receive a payment response
The returned parameters contain the following content:
- normalUrl: The payment continuation URL, used for redirection.
- paymentId: Order ID.
The following code is the sample response:
{
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentCreateTime": "2021-11-12T01:27:50-08:00",
"paymentId": "20211112194010800100188570271832381",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cvvResultRaw": "Y",
"networkTransactionId": "sampleNetworkTransactionId123456"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}
FAQs
For web transactions, Antom returns normalUrl, which the merchant server needs to pass to the merchant client for redirection. When you initiate payment for the same order again, you need to obtain a new normalUrl for redirection.
If you store the corresponding order number for subsequent refunds and reconciliations, you can specify the paymentId. |
Redirect to the payment continuation URL
The merchant server passes the normalUrl to the client, and the client page handles the redirection process to normalUrl.
Step 3: Obtain the payment result
When the buyer completes the payment or the payment times out, you can get the corresponding payment result from the Antom asynchronous notification or by inquiring the payment result actively.
The response obtained from asynchronous notifications and inquiryPayment contains the authorization payment result as well as other key information such as:
API | Authorization result | AVS info | CVV info | 3DS authentication info |
notifyPayment | resultStatus | avsResultRaw | cvvResultRaw | threeDSResult (only available for the 3DS authentication authorization) |
inquiryPayment | paymentStatus | avsResultRaw | cvvResultRaw | threeDSResult (only available for the 3DS authentication authorization) |
Asynchronous notifications
When a payment is completed or fails, Antom sends an asynchronous notification (notifyPayment) to the address that you specified in the pay API via the paymentNotifyUrl parameter. If the address of each payment is the same, you can also configure the address in Antom Dashboard.
The following sample code shows a notification for a 3D payment:
{
"notifyType": "PAYMENT_RESULT",
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
},
"paymentRequestId": "paymentRequestId01",
"paymentId": "2020010123456789XXXX",
"paymentAmount": {
"value": "4200",
"currency": "SGD"
},
"paymentCreateTime": "2020-01-01T12:01:00+08:30",
"paymentTime": "2020-01-01T12:01:01+08:30",
"paymentResultInfo": {
"avsResultRaw": "A",
"cvvResultRaw": "Y",
"networkTransactionId": "sampleNetworkTransactionId123456",
"threeDSResult": {
"eci": "02",
"threeDSVersion": "2.2.0",
"caav": "cavvSample",
"dsTransactionId": "sample_dsTranasctionId"
}
}
}
The following sample code shows a notification for a non-3D payment:
{
"notifyType": "PAYMENT_RESULT",
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
},
"paymentRequestId": "paymentRequestId01",
"paymentId": "2020010123456789XXXX",
"paymentAmount": {
"value": "4200",
"currency": "SGD"
},
"paymentCreateTime": "2020-01-01T12:01:00+08:30",
"paymentTime": "2020-01-01T12:01:01+08:30",
"paymentResultInfo": {
"avsResultRaw": "A",
"cvvResultRaw": "Y",
"networkTransactionId": "sampleNetworkTransactionId123456"
}
}
The following sample code shows the process of verifying the signature and responding to the notification:
@RequestMapping(path = "/payResult", method = RequestMethod.POST)
public ResponseEntity<AlipayResponse> paymentNotifyProcessor(HttpServletRequest request,
@RequestBody String body) {
// retrieve the required parameters from the request header.
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String rawSignature = request.getHeader("signature");
String signature = "";
// get valid part from raw signature
if(rawSignature==null||rawSignature.isEmpty()){
throw new RuntimeException("empty notify signature");
}else {
String[] parts = rawSignature.split("signature=");
if (parts.length > 1) {
signature = parts[1];
}
}
// verify payment result notify's signature
boolean verifyResult = SignatureTool.verify(request.getMethod(), request.getRequestURI(),
clientId, requestTime, body, signature,
ALIPAY_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// update the record status with notify result
// respond the server that we accept the notify
Result result = new Result("SUCCESS", "success", ResultStatusType.S);
AlipayResponse response = new AlipayResponse();
response.setResult(result);
return ResponseEntity.ok().body(response);
}
FAQs
After the payment is completed, Antom will send the asynchronous notification to you in 3~5s. If the payment is not completed, you need to wait for Antom to close the order before sending the asynchronous notification. The time to close the order is different for different payment methods, generally the default is 14 minutes.
If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format. If you do not respond to the asynchronous notification as required, or the asynchronous notification is not delivered due to network reasons, the notification will be automatically resent within 24 hours. 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.
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 add a digital signature to your response.
|
Inquire about the payment result
Call the inquiryPayment API to inquire about the payment result by specifying the following parameters:
Parameter name | is required? | Description |
paymentRequestId | No | The payment request number generated by the merchant |
The following sample code shows how to call the inquiryPayment API:
AlipayClient defaultAlipayClient = new DefaultAlipayClient(EndPointConstants.SG,
merchantPrivateKey, alipayPublicKey);
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
alipayPayQueryRequest.setClientId(CLIENT_ID);
alipayPayQueryRequest.setPath("/ams/sandbox/api/v1/payments/inquiryPayment");
alipayPayQueryRequest.setPaymentRequstId("paymentRequestId01");
AlipayPayQueryResponse alipayPayQueryResponse;
try {
alipayPayQueryResponse = defaultAlipayClient.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
The following code shows a sample of the request message:
{
"paymentRequestId": "paymentRequestId01"
}
The following code shows a sample of the response message for a 3D payment:
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "Success"
},
"paymentStatus": "SUCCESS",
"paymentRequestId": "paymentRequestId01",
"paymentId": "2019060811401080010018882020035XXXX",
"paymentAmount": {
"value": "4200",
"currency": "SGD"
},
"paymentCreateTime": "2019-06-01T12:01:01+08:30",
"paymentTime": "2019-06-01T12:01:01+08:30",
"paymentResultInfo": {
"avsResultRaw": "A",
"cvvResultRaw": "Y",
"networkTransactionId": "sampleNetworkTransactionId123456",
"threeDSResult": {
"eci": "02",
"threeDSVersion": "2.2.0",
"caav": "cavvSample",
"dsTransactionId": "sample_dsTranasctionId"
}
}
}
The following code shows a sample of the response message for a non-3D payment:
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "Success"
},
"paymentStatus": "SUCCESS",
"paymentRequestId": "paymentRequestId01",
"paymentId": "2019060811401080010018882020035XXXX",
"paymentAmount": {
"value": "4200",
"currency": "SGD"
},
"paymentCreateTime": "2019-06-01T12:01:01+08:30",
"paymentTime": "2019-06-01T12:01:01+08:30",
"paymentResultInfo": {
"avsResultRaw": "A",
"cvvResultRaw": "Y",
"networkTransactionId": "sampleNetworkTransactionId123456"
}
}
FAQs
It is recommended to initiate a round-robin query at an interval of 2 seconds, and you can initiate a round poll after initiating the pay API until the final payment result is queried or an asynchronous payment result notification is received. |
Step 4: Capture
By default, Antom automatically handles funds capture for you. If you specify the value of paymentFactor.captureMode to MANUAL
when calling the pay API, you must capture the funds of the payment by calling the capture API.
- Automatic capture: Antom automatically captures funds immediately after the user authorizes the payment. The capture result is then communicated to you via an asynchronous notification. Automatic capture is activated when one of the following conditions is met:
- You set the value of paymentFactor.captureMode in the pay API to
AUTOMATIC
. - You leave the value of paymentFactor.captureMode in the pay API empty or you do not pass in this parameter.
- Manual capture: You must initiate fund capture by calling the capture API within seven days after successful authorization, otherwise Antom automatically unfreezes the authorized funds of the payment. The total capture amount must be equal to the total authorized amount.
Note: For card payments, it is recommended to confirm the successful capture result before shipping.
The key request parameters in the capture API are shown in the following table:
Parameter | Description |
captureRequestId | A unique identifier that you assign to a capture request. |
paymentId | A unique identifier that Antom assigns to an order. |
captureAmount | The capture amount, which must be equal to the total authorized amount. |
The following sample code is used for initiating a capture.
AlipayCaptureRequest alipayCaptureRequest = new AlipayCaptureRequest();
alipayCaptureRequest.setPath("/ams/sandbox/api/v1/payments/capture");
alipayCaptureRequest.setClientId(CLIENT_ID);
Amount amount = new Amount();
amount.setCurrency("SGD");
amount.setValue("4200");
alipayCaptureRequest.setCaptureAmount(amount);
alipayCaptureRequest.setCaptureRequestId("captureRequestId01");
alipayCaptureRequest.setPaymentId("2019060811401080010018882020035XXXX");
AlipayCaptureResponse alipayCaptureResponse= null;
try{
alipayCaptureResponse = defaultAlipayClient.execute(alipayCaptureRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
}
The following code shows a sample of the response message:
{
"paymentId": "2019060811401080010018882020035XXXX",
"captureRequestId": "captureRequestId01",
"captureAmount": {
"currency": "SGD",
"value": "4200"
}
}
Step 5: Obtain the capture results
When the buyer completes the capture or the capture times out, you can get the corresponding payment result from the Antom asynchronous notification or by inquiring the payment result actively.
Asynchronous notifications
When the capture is completed or fails, Antom sends an asynchronous notification (notifyCapture) to the address that you specified in the pay API via the paymentNotifyUrl parameter. If the address of receiving each capture notification is the same, you can also configure the address in Antom Dashboard.
The following code is a notification sample of a successful payment:
"captureAmount": {
"currency": "SGD",
"value": "4200"
},
"notifyType": "CAPTURE_RESULT",
"captureId": "2022XXXXXXX",
"captureRequestId": "captureRequestId01",
"captureTime": "2022-11-10T00:34:52-08:00",
"paymentId": "2022XXXXXXX",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}
The following code is a notification sample of a failed payment:
"captureAmount": {
"currency": "SGD",
"value": "4200"
},
"notifyType": "CAPTURE_RESULT",
"captureId": "2022XXXXXXX",
"captureRequestId": "captureRequestId01",
"captureTime": "2022-11-10T00:34:52-08:00",
"paymentId": "2022XXXXXXX",
"result": {
"resultCode": "PROCESS_FAIL",
"resultMessage": "fail.",
"resultStatus": "F"
}
}
The following sample code shows the process of verifying the signature and responding to the notification:
@RequestMapping(path = "/captureResult", method = RequestMethod.POST)
public ResponseEntity<AlipayResponse> captureNotifyProcessor(HttpServletRequest request,
@RequestBody String body) {
// retrieve the required parameters from the request header.
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String rawSignature = request.getHeader("signature");
String signature = "";
// get valid part from raw signature
if(rawSignature==null||rawSignature.isEmpty()){
throw new RuntimeException("empty notify signature");
}else {
String[] parts = rawSignature.split("signature=");
if (parts.length > 1) {
signature = parts[1];
}
}
// verify payment result notify's signature
boolean verifyResult = SignatureTool.verify(request.getMethod(), request.getRequestURI(),
clientId, requestTime, body, signature,
ALIPAY_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// update the record status with notify result
// respond the server that we accept the notify
Result result = new Result("SUCCESS", "success", ResultStatusType.S);
AlipayResponse response = new AlipayResponse();
response.setResult(result);
return ResponseEntity.ok().body(response);
}
FAQs
After the payment is completed, Antom will send the asynchronous notification to you in 3~5s. If the payment is not completed, you need to wait for Antom to close the order before sending the asynchronous notification. The time to close the order is different for different payment methods, generally the default is 14 minutes.
If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format. If you do not respond to the asynchronous notification as required, or the asynchronous notification is not delivered due to network reasons, the notification will be automatically resent within 24 hours. 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.
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.
|
Inquire about the payment result
Call the inquiryPayment API to inquire about the capture result by specifying the following parameters:
Parameter name | is required? | Description |
paymentRequestId | No | The payment request number generated by the merchant |
The following sample code shows how to call the inquiryPayment API:
AlipayClient defaultAlipayClient = new DefaultAlipayClient(EndPointConstants.SG,
merchantPrivateKey, alipayPublicKey);
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
alipayPayQueryRequest.setClientId(CLIENT_ID);
alipayPayQueryRequest.setPath("/ams/sandbox/api/v1/payments/inquiryPayment");
alipayPayQueryRequest.setPaymentRequestId("paymentRequestId01");
AlipayPayQueryResponse alipayPayQueryResponse;
try {
alipayPayQueryResponse = defaultAlipayClient.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
The following is the request message:
{
"paymentRequestId":"paymentRequestId01"
}
The value of the transactions field in the API response is the capture status:
Parameter | Description |
transactions.transationType | The value is |
transactions.transactionResult | The capture result. |
The value of transactions indicates the capture status. See the following code samples for a successful capture:
{
"transactions": [
{
"transactionType": "CAPTURE",
"transactionStatus": "SUCCESS",
"transactionRequestId": "test_test_test_XXXX",
"transactionAmount": {
"currency": "SGD",
"value": "4200"
},
"transactionId": "2022XXXXXXXX",
"transactionResult": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "success"
}
}
]
}
The value of transactions indicates the capture status. See the following code samples for a failed capture:
{
"transactions": [
{
"transactionType": "CAPTURE",
"transactionStatus": "FAIL",
"transactionRequestId": "test_test_test_XXXX",
"transactionAmount": {
"currency": "SGD",
"value": "4200"
},
"transactionTime": "2022-09-29T07:13:50-07:00",
"transactionId": "2022XXXXXXXX",
"transactionResult": {
"resultStatus": "F",
"resultCode": "PROCESS_FAIL",
"resultMessage": "General business failure. No retry."
}
}
]
}
The value of transactions indicates the capture status. See the following code samples for a capture that is in processing:
{
"transactions": [
{
"transactionType": "CAPTURE",
"transactionStatus": "PROCESSING",
"transactionRequestId": "test_test_test_XXXX",
"transactionAmount": {
"currency": "SGD",
"value": "4200"
},
"transactionId": "2022XXXXXXXX",
"transactionResult": {
"resultStatus": "U",
"resultCode": "PAYMENT_IN_PROCESS",
"resultMessage": "payment in process"
}
}
]
}
FAQs
It is recommended to initiate a round-robin query at an interval of 2 seconds, and you can initiate a round poll after initiating the order consult API until the final capture result is queried or an asynchronous capture result notification is received. |
Best practice
Follow these best practices to improve integration efficiency.
Customize the payment timeout
In the checkout payment scenario, the default timeout on the Antom side is 14 mins, and after the payment timeout, the buyer can't continue to pay. To define the timeout time, you can specify through the paymentExpireTime parameter of the pay API. After exceeding the specified time, the buyer can not scan the code or log in to the checkout page.
The following sample code shows how to specify the paymentExpireTime parameter in the pay API:
{
"env": {
"osType": "ANDROID",
"terminalType": "APP"
},
"order": {
"orderAmount": {
"currency": "CNY",
"value": "1314"
},
"orderDescription": "Cappuccino #grande (Mika's coffee shop)",
"referenceOrderId": "ORDER_0517884936248XXXX"
},
"paymentAmount": {
"currency": "CNY",
"value": "1314"
},
"paymentMethod": {
"paymentMethodType": "ALIPAY_CN"
},
"paymentExpiryTime":"2024-01-20T08:51:06+08:00",
"paymentNotifyUrl": "https://www.gaga.com/notify",
"paymentRedirectUrl": "imeituan://",
"paymentRequestId": "iJ9lsVgTx8pX7qJpvW6rfqEE2Kdv9M3lgL8e1999ydfz52uMSqwvT3qXYw8IFBYt",
"productCode": "CASHIER_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "USD"
}
}
It is recommended to set the API timeout to 10s to ensure the success rate of getting a response.
Suggestions on processing logic for merchant results pages
- Front-end redirection abnormality
If the buyer pays successfully, the buyer may not be able to redirect to the paymentRedirectUrl that you specified due to network reasons or the limitations of the payment method itself, and the following two points should be noted in this case:
- You cannot use the front-end bounce as the basis for determining the success of the payment.
- If the paymentRedirectUrl of the payment method page fails to redirect to the merchant page, the buyer may manually click the original merchant page. Therefore, in order to avoid the original merchant page manually cutting back to the payment page, leading the buyer to initiate payment of the order again, it is recommended to add a pop-up window for querying the transaction results after redirecting on the original merchant's order page, when the buyer clicks on the pop-up window to display the result of the order, avoiding the payment of the order again.
- Trigger order result query after redirection
If the merchant side is pulled up after triggering a call to the inquiryPayment API, then the following different results are suggested:
- Successful payment: the page will display the content related to the shipment after successful payment;
- Payment Failure: the page displays the payment failure, and it is recommended to guide the re-payment;
- Payment processing: the page displays the landing effect, waits for 3-5s, and at the same time, queries the server-side payment results, if it still does not return successful or failed final results, it is recommended to display the "order processing" or "order management portal to view the final results"; it is not recommended to display the "network processing". If there is still no result, we suggest displaying "order processing" or going to "order management portal for final result".
Payment failed retry
For the same order on the merchant side, if the first payment is not completed and the buyer is supported to initiate the payment again, then it is recommended that you follow the integration steps below:
- In the payment request, set the referenceOrderId to the order ID and the paymentRequestId to the payment order ID.
- When the same order initiates payment again, the order status will be prioritized, and if the payment is successful, the buyer will be shown the "completed payment", and if the payment is not successful, the pay API will be called again to get a new normalUrl to redirect. Note that since it is the same order, the referenceOrderId can be kept unchanged, while the corresponding new payment order needs to update the paymentRequestId.
- The merchant side needs to check that there is only one successful payment order for a merchant order, if there is more than one successful payment order, then it needs to call the cancel API to refund the buyer.
- For payment methods that do not support refunds, it is recommended to cancel the first payment order before initiating a new payment.
Timing of obtaining and checking payment results
In order to guarantee the stable acquisition of payment results and avoid the situation where the buyer's payment is completed but you do not get the payment result. It is recommended that you check the payment results at the following stages:
- When the merchant payment result page is displayed
- Before shipping to the buyer
- When you receive the Antom reconciliation file