Embedded mode

APO Checkout Page (CKP) is a user-friendly, low-code payment solution that simplifies global transactions. Supporting a wide range of payment methods, CKP meets the needs of different markets and business scenarios. With minimal setup, you can quickly create a professional, feature-rich checkout page that offers buyers a smooth and convenient payment experience while significantly improving payment integration efficiency and driving business growth.

This guide shows you how to integrate CKP through an SDK, where the APO Checkout Page is embedded into your product purchase page for buyers to make payment.

User experience

The image shows the user experience where the APO Checkout Page is embedded into the merchant page: 

Pc.png

The image shows the user experience for scenarios where certain payment methods redirect to the corresponding payment page within the embedded Checkout Page:

Pc-1.png

Note:

  • Currently, APO embedded CKP is only supported on PC and mobile (H5), but not supported on mobile apps.
  • APO embedded CKP is not supported on Apple Pay, integrate APO hosted CKP instead.

Payment flow

The following process shows how to integrate the embedded CKP:

嵌入式时序图英文.png

  1. The buyer places an order in the merchant side.
  2. Create a payment session request.

When a buyer places an order on the merchant side, you need to call the createPaymentSession API to obtain the paymentSessionData that calls the SDK.

  1. Invoke the client SDK.

The merchant server uses the paymentSessionData to call the SDK embedded Checkout Page component in the merchant web page, and then the buyer submits the payment in the Checkout Page component, and the SDK will process the payment process.

  1. Get the payment result.

You can retrieve payment results through asynchronous notifications. Configure the paymentNotifyUrl parameter in the createPaymentSession API to specify the URL to receive asynchronous notifications. APO sends an asynchronous notification through the notifyPayment API when a payment request succeeds or expires.

Notes:
  • For transactions paid with cards, Google Pay, or PayPal, APO will send capture results to you via the notifyCapture API. It is recommended to confirm the successful capture result before shipping.
  • If the payment method is linked to multiple acquirers, you can configure routing rules on APO Dashboard. Otherwise, APO will use random routing rules.

Integration preparations

  • Integrate the APO server-side SDK package, install the server-side library and initialize a request instance. For more details, refer to Server-side SDKs.
  • Refer to Integrate the SDK Package for Web/WAP to complete integration preparations, and ensure to use SDK 1.41.0 or above.

Integration steps

Follow these steps to start the integration:

  1. Create a payment session
  2. Embed the APO Checkout Page
  3. Process asynchronous notifications

Step 1: Create a payment session Server-side

You can specify the desired payment methods when you activate APO services. For payment method configurations, see Specify a payment method. When the buyer makes a payment, you need to collect key information, such as the payment request ID, order details, payment redirect URL, and payment notification URL. Call the createPaymentSession API to create a payment session and redirect to the APO Checkout Page.

1. Call the createPaymentSession API

The following sample code shows how to call the createPaymentSession API:

copy
public static void createPaymentSession() {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.CHECKOUT_PAYMENT);

    // set amount
    Amount amount = Amount.builder().currency("SGD").value("6000").build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

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

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();

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

    // set goods info
    Goods goods = Goods.builder().goodsBrand("Antom Brand").goodsCategory("outdoor goods/bag").goodsName("Classic Woman Bag").goodsQuantity("1")
    .goodsSkuName("Black").goodsImageUrl("https://mdn.alipayobjects.com/portal_pdqp4x/afts/file/A*H8M9RrxlArAAAAAAAAAAAAAAAQAAAQ")
    .goodsUnitAmount(amount).goodsUrl("https://yourGoodsUrl").referenceGoodsId("yourGoodsId").build();

    // set order info
    Order order = Order.builder().referenceOrderId(orderId)
    .orderDescription("antom ckp testing order").orderAmount(amount).buyer(buyer).goods(Stream.of(goods).collect(Collectors.toList())).build();
    alipayPaymentSessionRequest.setOrder(order);

    // replace with your notify url
    // or configure your notify url here: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receiveNotify");
    // replace with your redirect url
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

    AlipayPaymentSessionResponse alipayPaymentSessionResponse;
    try {
        System.out.println("paymentSession request: " + JSON.toJSONString(alipayPaymentSessionRequest));
        alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
        System.out.println("paymentSession response: " + JSON.toJSONString(alipayPaymentSessionResponse));
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

2. Create a payment session 

If your payment methods include card payments, buyer information from the merchant side must be provided in the payment session parameters. For details, please refer to Card payments

Creating a payment session includes the following parameters:

Field Type

Field Name

Whether required

Description

Base fields

productCode

Yes

The value of this field in this scenario is fixed as CASHIER_PAYMENT.

productScene

Yes

The value of this field in this scenario is fixed as CHECKOUT_PAYMENT.

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. The amount to charge is a positive integer in the smallest currency unit, e.g., CNY in fen and KRW in won.

paymentRedirectUrl

Yes

The merchant page URL that the buyer is redirected to after the payment is completed. The display bases on server-side results, not fixes as a result page. It must be an HTTPS URL.

paymentNotifyUrl

No

The URL that is used to receive the payment result notification. You can set the URL to receive the notification via API or on APO Dashboard. If the notification URL is set on APO Dashboard, you do not need to pass this parameter through the API. The URL must be in HTTPS.

settlementStrategy

No

This field is only applicable when the acquirer is Antom. The settlement strategy for the payment request. Specify the settlementCurrency  parameter in the API if you signed up for multiple settlement currencies.

locale

No

Language tag specified for the Checkout Page. If the provided language is not supported, the default language setting of the browser will be used, which is usually English.

Order fields

order.orderAmount

Yes

Order amount.

order.referenceOrderId

Yes

Order ID.

order.orderDescription

Yes

Order description.

The above parameters are the basic parameters for creating a payment session. For complete and additional requirements for specific payment methods, please refer to createPaymentSession.

The following shows the sample code of a request: 

copy
{
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "goods": [
      {
        "goodsBrand": "Antom Brand",
        "goodsCategory": "outdoor goods/bag",
        "goodsImageUrl": "https://mdn.alipayobjects.com/portal_pdqp4x/afts/file/A*H8M9RrxlArAAAAAAAAAAAAAAAQAAAQ",
        "goodsName": "Classic Woman Bag",
        "goodsQuantity": "1",
        "goodsSkuName": "Black",
        "goodsUnitAmount": {
          "currency": "SGD",
          "value": "6000"
        },
        "goodsUrl": "https://yourGoodsUrl",
        "referenceGoodsId": "yourGoodsId"
      }
    ],
    "orderAmount": {
      "currency": "SGD",
      "value": "6000"
    },
    "orderDescription": "antom ckp testing order",
    "referenceOrderId": "c3df9b82-ff67-424b-880b-06c3615****"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "6000"
  },
  "paymentFactor":{
    "isAuthorization":true
  },
  "paymentNotifyUrl": "http://www.yourNotifyUrl.com/payment/receiveNotify",
  "paymentRedirectUrl": "http://localhost:8080/index.html?paymentRequestId=597795b7-c812-4132-bd7d-c55914ee****",
  "paymentRequestId": "597795b7-c812-4132-bd7d-c55914ee****",
  "productCode": "CASHIER_PAYMENT",
  "productScene": "CHECKOUT_PAYMENT"
}

The following shows the sample code of a response, which contains the following parameters:

  • paymentSessionData: The encrypted payment session data. Pass the data to your front end.
  • paymentSessionExpiryTime: The specific date and time after which the payment session will expire.
  • normalUrl: The URL used to redirect to the Checkout Page (In APO embedded CKP scenario, this field can be ignored.).
copy
{
    "normalUrl": "https://checkout.antom.com/checkout-page/pages/payment/index.html?sessionData=1iwX2rH5kXnUGT5372d0kHD7PwcgPmRSMgAsvKs8hqRkqobbtWbep59PU2eO5w72h%2B%2XXXX",
    "paymentSessionData": "1iwX2rH5kXnUGT5372d0kHD7PwcgPmRSMgAsvKs8hqRkqobbtWbep59PU2eO5w72h+/c278B+P+nDVNzrQySQQ==&&SG&&188&&eyJleHRlbmRJbmZvIjoie1wiT1BFTl9NVUxUSXXXX",
    "paymentSessionExpiryTime": "2025-03-19T16:21:06+08:00",
    "paymentSessionId": "1iwX2rH5kXnUGT5372d0kHD7PwcgPmRSMgAsvKs8hqSln4WiVZXXXX",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}

The table shows the possible values that the result.resultStatus field in the request message may return. Please handle the result according to the guidances: 

result.resultStatus

Message

Further actions

S

Indicates that payment session creation succeeded.

The merchant server can use paymentSessionData to call the SDK.
UIndicates that payment session creation failed for unknown reasons.

Change the paymentRequestId and call the API again to resolve the issue. Please contact APO technical support if the problem persists.

FIndicates that the payment session creation failed.

Check and verify whether the current API required request fields (including header fields and body fields) are correctly passed and valid.

NoteIf you did not receive a response message, it might be due to a network timeout. Change the paymentRequestId and call the API again to resolve the issue.

Step 2: Embed APO Checkout Page Client-side

The SDK is a component used to handle the payment process. To collect information and switch between applications based on the payment method specified in the createPaymentSession API, you need to use the paymentSessionDataobtained from the creation of the payment session to initialize the SDK, seamlessly embedding the APO Checkout Page into the web payment interface. Once the buyer submits a payment request on this page, the SDK will automatically perform encrypted communication, risk verification, and payment instruction processing, achieving end-to-end payment closed-loop management.

1. Instantiate the SDK

Use AMSCheckoutPage to create an SDK instance. The configuration object includes the following parameters: 

Parameter Name

Required

Description

environment

Yes

It is used to pass in environmental information. Valid values are:

  • sandbox: Sandbox environment
  • prod: Production environment

onEventCallback

Optional

A callback function returns a specific event code when a payment event happens during SDK runtime, like payment result or a form submission error. For further information, refer to SDK References.

The following sample code shows how to instantiate the SDK:

copy
npm:
import { AMSCheckoutPage } from '@alipay/ams-checkout' // Package manager
const checkoutApp = new AMSCheckoutPage({
  environment: "sandbox",
  onEventCallback: ({code, message}) => {},
});
cdn:
// Under CDN method: Use window.AMSCheckoutPage to instantiate 
const checkoutApp = new AMSCheckoutPage({
  environment: "sandbox",
  onEventCallback: ({code, message}) => {},
});

2. Invoke the SDK

When the buyer places an order and redirects to the APO Checkout Page, you need to create the SDK and instantiate it with a payment session.

Create a DOM node

On your checkout page, create a DOM node to embed the APO Checkout Page component. 

copy
<div class="content">
  <div class="checkout-container" id="ckp-embed-wrapper"></div>
</div>
Create the component

Use the mountComponent function in the instance object to create the APO Checkout Page component:

Parameter Name

Required

Description

sessionData

Yes

Create a configuration object using the sessionData parameter. Pass the complete paymentSessionData parameter obtained in the createPaymentSession API response to the sessionData parameter. 

copy
async function create(sessionData) {
  await checkoutApp.mountComponent({ 
    sessionData: sessionData, 
  },'#ckp-embed-wrapper');
}
Destroy the component

Call the unmount method to free SDK component resources in the following situations:

  • When the buyer switches views away from the checkout page, free the component resources created in createPaymentSession.
  • When the buyer initiates multiple payments, free the previously created component resources in createPaymentSession.
  • Free the component resources after obtaining the final payment result codes.
copy
// Free SDK component resources
checkoutApp.unmount();

3. Process payment results

The payment result will be returned by the onEventCallback function. You need to customize the processing flow you want for each payment result through the data in the result of onEventCallback. The payment result here is only for front-end display, and the final order status is subject to the server side.

The following are the possible event codes of the payment result returned by onEventCallback:

Event Code

Message

Further actions

SDK_PAYMENT_SUCCESSFUL

Payment is successful.

It is recommended to redirect the buyer to the payment result page. 

SDK_PAYMENT_FAIL

Payment failed.

It is recommended that you check the value of paymentResultCode in the onEventCallback result data for details. Guide buyers to retry the payment based on the provided information.

SDK_PAYMENT_CLICK_BACK_TO_MERCHANT

Event that is triggered when the buyer clicks the Back to merchant control on the results page.

It is recommended to redirect the buyer to the payment result page.

SDK_PAYMENT_CANCEL

The buyer exits the payment page without submitting the order.

The SDK can be reinvoked with paymentSessionData within the validity period; if it has expired, paymentSessionData needs to be requested again.

The following sample code shows how to process onEventCallback:

copy
function onEventCallback({ code, result }) {
  switch (code) {
    case 'SDK_PAYMENT_SUCCESSFUL':
      // Payment was successful. Redirect buyers to the payment result page.
      break;
    case 'SDK_PAYMENT_FAIL':
      console.log('Check the payment result data', result);
      // Payment failed. Guide buyers to retry the payment based on the provided information.
      break;
    case 'SDK_PAYMENT_CANCEL':
      // Guide buyers to retry the payment.
      break;
    case 'SDK_PAYMENT_CLICK_BACK_TO_MERCHANT':
      // User click the Back to merchant button. Redirect buyers to the payment result page.
      break;
    default:
      break;
  }
}

The image shows the rendered merchant page embedded with the APO Checkout Page:

Group 2117129530.png

Step 3: Process asynchronous notifications Server-side

1. Set the webhook URL to receive notifications

You can choose one of following two methods to set the webhook URL to receive notifications:

  • If each of your order has a unique notification URL, we recommend to set the webhook URL in each individual request. You can pass the asynchronous notification receiving URL for the specific order through the paymentNotifyUrl field in the createPaymentSession API.
  • If all your orders share a unified notification URL, you can set the webhook URL on APO Dashboard through Developer > Notification Address.

APM payment

When a payment succeeds or fails, APO sends an asynchronous notification (notifyPayment) to the address that you specified in the createPaymentSession API via the paymentNotifyUrl parameter. After receiving the notifications from APO, you need to return response according to Return a receipt acknowledgement messageIt is recommended to save the information on acquirers (acquirerInfo), refer to Order number management for specific reasons.

APO allows you to specify the URL in the createPaymentSession API via the paymentNotifyUrl parameter. If the address of each payment is the same, you can also configure the address on APO Dashboard.

The following is the notification request sample code:

copy
{
    "acquirerInfo": {
        "acquirerMerchantId": "21********99147",
        "acquirerName": "ALIPAY",
        "acquirerResultCode": "SUCCESS",
        "acquirerResultMessage": "success",
        "acquirerTransactionId": "2025061819********0188540299977984",
        "referenceRequestId": "PAYMENT_20250618100222331_****"
    },
    "customsDeclarationAmount": {
        "currency": "CNY",
        "value": "10"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "CNY",
        "value": "10"
    },
    "paymentCreateTime": "2025-06-17T19:02:31-07:00",
    "paymentId": "2025061819********0188540299977984",
    "paymentMethodType": "ALIPAY_CN",
    "paymentRequestId": "PAYMENT_20250618100222331_****",
    "paymentResultInfo": {

    },
    "paymentTime": "2025-06-17T19:02:50-07:00",
    "pspCustomerInfo": {
        "pspCustomerId": "20*******9879519",
        "pspName": "ALIPAY_CN"
    },
    "pspPaymentId": "2025061*********11432765638",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}

The table shows the possible values that the result.resultStatus field in the request message may return. Please handle the result according to the guidances:

result.resultStatus

Message

Further actions

S

Indicates that the payment is successful.

You can advance the order status, and use the information in the following fields for after-payment processes: 

  • paymentRequestId: the payment request ID used for consult, cancellation, and reconciliation.
  • paymentId: the payment ID generated by APO, used for refunds and  reconciliation.
  • paymentAmount: indicates the payment amount.
  • paymentMethodType: indicates the payment method used by the buyer.

F

Indicates that the payment failed.

Please guide the buyer to place a new order.

Common Questions

Q: When will the notification be sent?

A: The sending time of asynchronous notifications varies in different scenarios.

  • If the payment is successfully completed, APO will usually 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 buyer does not submit a payment, when the payment session times out, APO does not send an asynchronous notification.

Note: The default payment session expiry time is 1 hour. The time it takes to close an order varies for different payment methods, Antom' default payment session expiry time is 14 minutes while PayEasy and Konbini are 7 days.

Q: When will the buyer receive the timeout notification after submiting a payment?

A: If the buyer selects a payment method within the payment session expiry time, the maximum delay is the payment method timeout plus the payment session expiry time. For example, if the payment session expiry time is 1 hour and the buyer selects bank transfer at the 59 minute but does not complete the payment, the timeout notification will be sent to you after 59 minutes + 48 hours. (depending on the specific payment methods).

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 APO, but you didn't make a response 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: What are the key parameters in the notification that I need to use?

A: Pay attention to the following key parameters:

  • result: indicates the payment result of the order.
  • paymentRequestId: indicates the payment request number you generated for consult, cancel, and reconciliation.
  • paymentId: indicates the payment order number generated by APO, used for refund and reconciliation.
  • paymentAmount: indicates the payment amount.
  • paymentMethodTpye: indicates the payment method type that is included in payment method options. 
  • acquirerInfo: indicates the information about the acquirers.

Q: There are two types of asynchronous notifications. Which one should be used as the basis for shipment?

A: When you receive a notification where the value of notifyType is PAYMENT_RESULT, you should first check whether the value of paymentMethodType is CARD/GOOGLEPAY/PAYPAL. If it is not CARD/GOOGLEPAY/PAYPAL, you can decide whether to proceed with shipment based on the result of this notification. If the value of paymentMethodType is CARD/GOOGLEPAY/PAYPAL, you need to wait for a notification where the value of notifyType is CAPTURE_RESULT before making the decision to ship.

2. Verify asynchronous notifications

If you receive an asynchronous notification from APO, 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 APO.

copy
/**
 * receive notify
 *
 * @param request    request
 * @param notifyBody notify body
 * @return Result
 */
@PostMapping("/receiveNotify")
@ResponseBody
public Result receiveNotify(HttpServletRequest request, @RequestBody String notifyBody) {
    // retrieve the required parameters from http request
    String requestUri = request.getRequestURI();
    String requestMethod = request.getMethod();
    // retrieve the required parameters from request header
    String requestTime = request.getHeader("request-time");
    String clientId = request.getHeader("client-id");
    String signature = request.getHeader("signature");
    try {
        // verify the signature of notification
        boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId,
                                                          requestTime, signature, notifyBody, ANTOM_PUBLIC_KEY);
        if (!verifyResult) {
            throw new RuntimeException("Invalid notify signature");
        }
        // deserialize the notification body
        JSONObject jsonObject = JSON.parseObject(notifyBody);
        String notifyType = (String)jsonObject.get("notifyType");
        if("PAYMENT_RESULT".equals(notifyType)){
            AlipayPayResultNotify paymentNotify = jsonObject.toJavaObject(AlipayPayResultNotify.class);
            if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
                // handle your own business logic.
                // e.g. The relationship between payment information and users is kept in the database.
                System.out.println("receive payment notify: " + JSON.toJSONString(paymentNotify));
                return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
            }
        }else if("CAPTURE_RESULT".equals(notifyType)){
            AlipayCaptureResultNotify captureNotify = jsonObject.toJavaObject(AlipayCaptureResultNotify.class);
            if (captureNotify != null && "SUCCESS".equals(captureNotify.getResult().getResultCode())) {
                // handle your own business logic.
                System.out.println("receive capture notify: " + JSON.toJSONString(captureNotify));
                return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
            }
        }
    } catch (Exception e) {
        // handle error condition
        return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
    }
    return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}

You do not need to countersign the response of the result notification. However, you must respond to each notification request in the following fixed format, regardless of whether the payment is successful or not.

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

After payments

Inquire payments

In addition to obtaining the buyer's payment result through the asynchronous notification, you can retrieve the corresponding payment result through the inquiry payments service. You can call the inquiryPayment API and use the paymentRequestId from the payment session to check the payment status.

The following code shows how to call the inquiryPayment API:

copy
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
    }
}

It is recommended to save the information on acquirers (acquirerInfo), refer to Order number management for specific reasons. The following code shows an example of a response:

copy
{
    "acquirerInfo": {
        "acquirerMerchantId": "76476400001****",
        "acquirerName": "2C2P",
        "acquirerTransactionId": "823c1fe4-1168-4abc-9687-c42f3269****",
        "referenceRequestId": "202504301903130001032028917****"
    },
    "acquirerReferenceNo": "202504301903130001032028917****",
    "paymentAmount": {
        "currency": "USD",
        "value": "110"
    },
    "paymentCreateTime": "2025-04-30T00:16:12-07:00",
    "paymentId": "2025043019401089010011132026330****",
    "paymentMethodType": "MIXEDCARD",
    "paymentRequestId": "PAYMENT_20250430151543077_****",
    "paymentResultCode": "SUCCESS",
    "paymentResultInfo": {
        "avsResultRaw": "",
        "cardBin": "53**32",
        "cardBrand": "MASTERCARD",
        "cardNo": "************1310",
        "cardholderName": "*******",
        "cvvResultRaw": "",
        "expiryMonth": "**",
        "expiryYear": "**",
        "fingerprint": "2684e4fa13af655191************0aff65851486d4f575183f46",
        "funding": "CREDIT",
        "issuerName": "CHINA MERCHANTS BANK",
        "issuingCountry": "CN",
        "lastFour": "1310",
        "threeDSResult": {
            "cavv": "",
            "eci": "00",
            "threeDSType": "INTERNAL",
            "xid": ""
        }
    },
    "paymentResultMessage": "success.",
    "paymentStatus": "SUCCESS",
    "paymentTime": "2025-04-30T00:16:14-07:00",
    "transactions": [
        {
            "acquirerInfo": {
                "acquirerMerchantId": "76476400001****",
                "acquirerName": "2C2P",
                "referenceRequestId": "202504301903130101032028917****"
            },
            "transactionAmount": {
                "currency": "USD",
                "value": "110"
            },
            "transactionId": "2025043019401089010011132026318****",
            "transactionRequestId": "PAYMENT_20250430151543077_****",
            "transactionResult": {
                "resultCode": "SUCCESS",
                "resultMessage": "success",
                "resultStatus": "S"
            },
            "transactionStatus": "SUCCESS",
            "transactionTime": "2025-04-30T00:16:15-07:00",
            "transactionType": "CAPTURE"
        }
    ],
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}

The values of the paymentMethodType and transactions.transactionType fields in the response represent different status. The following outlines the returned values in respective scenarios:

If the value of paymentMethodType is not CARDAPPLEPAY, or GOOGLEPAY, you need to handle the transaction based on the value of paymentStatus. The returned values include: 

  • SUCCESS: indicated that the payment is successful.
  • FAIL: indicated that the payment failed.

Note: When inquiring about the transaction, if the buyer does not submit the order, the ORDER_NOT_EXIST error code will be returned. This error is not returned if the order is submitted. 

Refund

To learn about APO refund rules and how to initiate a refund for a successful transaction, see Refund for more information.

Dispute

When a buyer chooses to pay with a card, a dispute may occur. To learn more, see Dispute.

Reconciliation

After the transaction is completed, use the financial reports provided by APO for reconciliation. For more information on how to reconcile and the settlement rules of APO, please refer to Reconciliation.

Payment method features

Card payments

If your payment method includes card payments, the buyer's information from the merchant side must be passed in the payment session parameters. In the order.buyer field, at least one of the following parameters must be provided: referenceBuyerId, buyerPhoneNo, or buyerEmail. If the buyer's information is not provided, when the buyer selects the card payment method and submits the payment, an error will occur on the page, resulting in the inability to complete the payment process.

copy
{
    "order": {
        ...
        "buyer": {
            "referenceBuyerId": "88888888",
            "buyerEmail": "gaga@test.com",
            "buyerPhoneNo": "18888888888"
        }
    },
...
}

Activate 3D Secure 2

To learn more about 3D Secure 2, see 3D Secure 2 authentication.

  • You can conduct your risk assessment, and specify the value of availablePaymentMethod.paymentMethodMetaData.is3DSAuthentication as TRUE through the createPaymentSession API. In this case, APO designates the payment as 3D-authenticated and passes it to the corresponding acquirer.
  • If you do not specify the availablePaymentMethod.paymentMethodMetaData.is3DSAuthentication parameter or specify the value as FALSEAPO designates the payment as non-3D-authenticated and passes it to the corresponding acquirer. However, the final decision will be based on the acquirer's processing.
copy
{
  ...
    "availablePaymentMethod": {
        "paymentMethodMetaData": {
            "is3DSAuthentication": true
        }
    },  
  ...
}

When a transaction passes 3DS authentication, the corresponding 3DS information will be included in the asynchronous notification. You can check the information in the paymentResultInfo.threeDSResult field.

copy
{
    "acquirerInfo": {
        "acquirerMerchantId": "219117000551****",
        "acquirerName": "ALIPAY",
        "acquirerResultCode": "SUCCESS",
        "acquirerResultMessage": "success",
        "acquirerTransactionId": "2025043019401080010019178029053****",
        "referenceRequestId": "PAYMENT_20250430155835598_****"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "GBP",
        "value": "100"
    },
    "paymentCreateTime": "2025-04-30T00:59:08-07:00",
    "paymentId": "2025043019401080010019178029053****",
    "paymentMethodType": "CARD",
    "paymentRequestId": "PAYMENT_20250430155835598_****",
    "paymentResultInfo": {
        "avsResultRaw": "U",
        "cardBin": "53**32",
        "cardBrand": "MASTERCARD",
        "cardCategory": "CONSUMER",
        "cardNo": "************1310",
        "cardholderName": "*******",
        "cvvResultRaw": "U",
        "expiryMonth": "**",
        "expiryYear": "**",
        "funding": "CREDIT",
        "issuingCountry": "CN",
        "lastFour": "1310",
        "paymentMethodRegion": "GLOBAL",
        "threeDSResult": {
            "cavv": "kAPDv**********+btfgoJhBG+N",
            "eci": "02",
            "threeDSOffered": true,
            "threeDSVersion": "2.2.0"
        }
    },
    "paymentTime": "2025-04-30T00:59:28-07:00",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}

APM payments

Przelewy24

When the buyer selects Przelewy24 as the payment method, you can optimize the email input experience:

Pass the availablePaymentMethod.paymentMethodMetaData.payerEmail field in the createPaymentSession API. The APO Checkout Page will automatically pre-fill the email address in the payment options, eliminating the need for manual input by the buyer.

The sample code: 

copy
{
  ...
    "availablePaymentMethod": {
        "paymentMethodMetaData": {
            "payerEmail": "123221321@test.com",
        }
    },  
  ...
}

When the buyer selects Przelewy24 to pay, APO Chechout page will pre-fill the email address:

przelewy 1.png

Mercado Pago

When the buyer selects to pay with Mercado Pago, the following parameters may be involved: 

Acquirer

Payment method

Payment elements

Payment element parameter name

Best practice

Antom

Mercado Pago (Brazil)

The CPF number

paymentMethodMetaData.cpf

Guide the buyer to enter the CPF number on the merchant page and manually open the Mercado Pago app to complete the payment.

Antom

Mercado Pago (Brazil, Mexico, Chile, and Peru)

The buyer's email address.

paymentMethodMetaData.payerEmail 

Guide the buyer to enter the email address on the merchant page and manually open the Mercado Pago app to complete the payment.

Use the following methods to optimize the input experience:

  • Pass the availablePaymentMethod.paymentMethodMetaData.payerEmail field in the createPaymentSession API. The APO Checkout Page will automatically pre-fill the email address in the payment options, eliminating the need for manual input by the buyer.
  • Pass the availablePaymentMethod.paymentMethodMetaData.cpf field in the createPaymentSession API. The APO Checkout Page will automatically pre-fill the CPF number, eliminating the need for manual input by the buyer.

The sample code:

copy
{
  ...
    "availablePaymentMethod": {
        "paymentMethodMetaData": {
            "payerEmail": "123221321@test.com",
        }
    },  
  ...
}

When the buyer selects Mercado Pago to pay, APO Chechout page will pre-fill the email address:

mercado 1.png

Additional content

Specify a payment method

You can modify the parameters in the createPaymentSession API to specify the display of payment methods on Checkout Page, the order of the payment method list, and the display of quick payments.

Note: If you need to enable the payment method, please contact APO Technical Support.

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.

How to enable

You can pass payment methods through API parameters or configure them on APO Dashboard through Checkout page > Payment method. If you pass parameters through the API, the API values take priority.

Pass through API parameters

Specify and filter the display of payment methods

copy
{ ...
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN",
        "expressCheckout": true,
        "paymentMethodOrder": "0"
      },
      {
        "paymentMethodType": "TNG",
        "expressCheckout": false,
        "paymentMethodOrder": "1"
      }
    ]
  }
}
Sort the payment methods
copy
{ ...
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN",
        "expressCheckout": true,
        "paymentMethodOrder": "0"
      },
      {
        "paymentMethodType": "TNG",
        "expressCheckout": false,
        "paymentMethodOrder": "1"
      }
    ]
  }
}

Display quick payments

copy
{ ...
  "availablePaymentMethod": {
    "paymentMethodTypeList": [
      {
        "paymentMethodType": "ALIPAY_CN",
        "expressCheckout": true,
        "paymentMethodOrder": "0"
      },
      {
        "paymentMethodType": "TRUEMONEY",
        "expressCheckout": false,
        "paymentMethodOrder": "1"
      }
    ]
  }
}

APO tokenization

If the buyer pays with a card, the Checkout Page can allow the buyer to save their card information during the first payment using APO Tokenization. For subsequent payments, the buyer will not need to re-enter the card details, and the Checkout Page will display the buyer's tokenized masked card number for payment.

You can help the buyer complete tokenized payments by saving and passing the buyer's card token information, the user experience is as follows:

image

Benefits

  • Allow buyers to store their payment method information for a faster checkout experience in future transactions.
  • Storing payment method information allows the display of detailed payment method information, which helps boost buyers' trust during payment.
  • Data shows that using cardToken during payment helps achieve a higher payment success rate. 
  • The usage of cardToken has no restrictions on any acquirers and can be used with any acquirers that you have activated.

How to enable

You can use the following steps to complete tokenized payments:

  1. To display the card-vaulting button, specify the value of the availablePaymentMethod.paymentMethodMetaData.tokenizeMode field as ASKFORCONSENT through the createPaymentSession API, the card-vaulting button can be displayed in the card payment option on the APO Checkout Page.
copy
{
...
    "availablePaymentMethod": {
        "paymentMethodMetaData": {
            "tokenizeMode": "ASKFORCONSENT"
        }
    }
}
  1. To vault the card after the first payment, when the buyer saves their bank card information on your page, make sure to associate it with the buyer information and save the corresponding card information on your server. (Retrieve the value of cardToken from the paymentResultInfo field in the notifyPayment API.)
copy
{
    "acquirerInfo": {
        "acquirerMerchantId": "219117000551****",
        "acquirerName": "ALIPAY",
        "acquirerResultCode": "SUCCESS",
        "acquirerResultMessage": "success",
        "acquirerTransactionId": "2025043019401080010019178029053****",
        "referenceRequestId": "PAYMENT_20250430155835598_****"
    },
    "notifyType": "PAYMENT_RESULT",
    "paymentAmount": {
        "currency": "GBP",
        "value": "100"
    },
    "paymentCreateTime": "2025-04-30T00:59:08-07:00",
    "paymentId": "2025043019401080010019178029053****",
    "paymentMethodType": "CARD",
    "paymentRequestId": "PAYMENT_20250430155835598_****",
    "paymentResultInfo": {
        "avsResultRaw": "U",
        "cardBin": "53**32",
        "cardBrand": "MASTERCARD",
        "cardCategory": "CONSUMER",
        "cardNo": "************1310",
        "cardToken": "ALIPAY5ITT+wDZhYuE1f********************vJ5BksK4yWCloE4MwfmN48sP1+rSPQ==",
        "cardholderName": "*******",
        "cvvResultRaw": "U",
        "expiryMonth": "**",
        "expiryYear": "**",
        "funding": "CREDIT",
        "issuingCountry": "CN",
        "lastFour": "1310",
        "networkTransactionId": "MCGQ120DH****",
        "paymentMethodRegion": "GLOBAL",
        "threeDSResult": {
            "cavv": "kAPDv**********+btfgoJhBG+N",
            "eci": "02",
            "threeDSOffered": true,
            "threeDSVersion": "2.2.0"
        }
    },
    "paymentTime": "2025-04-30T00:59:28-07:00",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}
  1. To use the card token in subsequent payments, when the buyer has a saved bank card, you need to pass the card token information through the createPaymentSession API. This is to display the buyer's saved card information on the APO Checkout Page, allowing the buyer to use it to complete payments. 

The sample code below shows the createPaymentSession API initiates a request using the card token when the buyer uses a saved bank card to make payment.

copy
{
  ...
    "savedPaymentMethods": [
        {
            "paymentMethodType": "CARD",
            "paymentMethodId": "ALIPAYEfG2DFbGx2Eh739qU+VMnCPEe7MfRKfMfC5k7k/IFASWpAh/vCxHV3dPYpbkGz1iyWCloE4MwfmN48sP8+rS****"
        }
    ]
}