International Credit Card Payment (Non-hosted)
About 3144 wordsAbout 10 min
2025-03-07
| Pay-in (Immediate Capture) | Authorization (Auth then Capture) | Partial Capture | Refund & Partial Refund | Remember Card | 重新支付 | CardOnFile | Recurring | 首笔0元 Recurring | 3DS |
|---|---|---|---|---|---|---|---|---|---|
International credit card payment (Non-hosted) is designed for merchants with PCI-DSS certification who build and operate their own card payment page. The merchant front end collects cardholder data and integrates the risk control and 3DS components required by Dynamic 3D Secure; the merchant server calls Create Order and Pay to create the payment order, and then decides whether to continue the 3DS challenge according to status and threeDContinue in the synchronous response. The final payment result must be confirmed by the merchant server through Payment Notification or Transaction Query.
Solution Overview
In this model, the shopper always enters card details on the merchant page. If 3DS is required, the merchant front end redirects the shopper to the issuer challenge page according to the synchronous response. This model is better suited to merchants that want a fully customized checkout experience and already have the PCI-DSS compliance and front-end payment capabilities required to operate it.
Prerequisites
- The merchant has PCI qualification and has been verified by PingPongCheckout. (For PCI-DSS, please send email attachments to
acquire-risk@pingpongx.comand CCgig-tech-acq@pingpongx.com) - The merchant has the capability to develop its own credit card checkout page.
- The merchant already has the front-end capability required to integrate the risk control and 3DS components.
Note
With the international credit card payment (Non-hosted) solution, the merchant must store and process cardholder data on its own side, so PCI-DSS certification is mandatory.
Interface List
International credit card payment (Non-hosted) typically involves the following APIs and notifications:
| Phase | Type | Document | Required | Purpose |
|---|---|---|---|---|
| Payment Creation | Guide | Dynamic 3D Secure | Required reading | Integrate the risk control and 3DS components and collect the required parameters for payment |
| API | Create Order and Pay | Required | Submit card data, risk parameters, and order information to create the payment order | |
| Payment Result | Notification | Payment Notification | Required | Receive the final payment result and update the merchant order status |
| API | Transaction Query | Recommended | Actively confirm the transaction result when notifications are delayed, not received, or need verification | |
| Refund | API | Refund Request | As needed | Initiate a refund for a successfully paid international card transaction |
| Notification | Refund Notification | Recommended | Receive the refund result and update the refund status | |
| API | Refund Query | Recommended | Actively confirm the refund status when notifications are delayed, not received, or during reconciliation | |
| Authorization Capture / Void | API | Authorization Capture | Required for manual capture scenarios | Capture a previously authorized transaction |
| API | Authorization Void | Required for manual capture scenarios | Void a previously authorized but not yet captured transaction | |
| Notification | Capture Notification | Recommended for manual capture scenarios | Receive the capture result | |
| Notification | Void Notification | Recommended for manual capture scenarios | Receive the void result |
Interaction Flow
Flow summary:
- The merchant front end collects risk control and 3DS parameters before payment submission.
- The merchant server calls Create Order and Pay to create the international card payment order.
- After PingPongCheckout returns the synchronous response, the merchant front end decides whether to enter the 3DS challenge flow according to
statusandthreeDContinue. - If 3DS is required, the merchant front end should redirect to
threeDUnionParams.threeDRedirectUrl; after the challenge is completed, PingPongCheckout redirects the shopper back topayResultUrl. - The shopper returning to
payResultUrlonly means the front-end flow is finished. It does not mean the transaction succeeded. The final result must be confirmed through Payment Notification or Transaction Query.
Integration Steps
Complete the integration in the following steps:
Step 1: Prepare 3DS and risk parameters, then create the payment
Before calling Create Order and Pay, the merchant front end must integrate SafePayGuardJs and SecureShieldJs and collect the required browserInfo, jsGeneratedData, and other risk-related parameters. The merchant server then calls Create Order and Pay to create the payment order. For component initialization, when to trigger triggerThreeDsInit, and how to obtain the generated parameters, refer to:
Note
If you cannot embed the required JS components into your payment page, first confirm with your business or risk contact whether another 3DS integration approach can be evaluated.
When creating the payment request, pay special attention to the following fields:
| Field | Description |
|---|---|
paymentMethod.type | Card brand or card scheme, such as VISA, MasterCard, JCB, AmericanExpress, Discover, DinersClub, and UnionPay. For supported card brands, see International Cards |
paymentMethod.cardInfo | Cardholder card data, including card number, expiry date, CVV, and cardholder name |
requestId | Payment request ID. It should remain globally unique |
merchantTransactionId | Merchant order ID used to associate the merchant order with the payment transaction |
merchantUserId | Unique merchant-side user identifier used to associate the shopper identity |
goods | Goods information used to enrich transaction context |
browserInfo | Browser information collected by the 3DS component and submitted with the payment request |
jsGeneratedData | Security and risk parameters generated by the risk and 3DS components and submitted with the payment request |
notificationUrl | Asynchronous callback URL for the final payment result |
payResultUrl | URL where the shopper returns after completing the 3DS or payment flow |
device.orderTerminal | Order terminal. 01 WAP, 02 Web, 04 iOS App, 05 Android App |
For full parameter details, see Create Order and Pay.
Payment request example (bizContent only):
{
"captureDelayHours": "0",
"amount": "10",
"currency": "USD",
"requestId": "PMT-E46D6LAAKB1782628205616",
"merchantTransactionId": "PMT-E46D6LAAKB1782628205616",
"payResultUrl": "https://www.example.com/card/pay-result",
"payCancelUrl": "https://www.example.com/card/pay-cancel",
"notificationUrl": "https://www.example.com/card/pay-notify",
"language": "en",
"shopperIP": "222.126.52.23",
"merchantUserId": "888888888",
"threeDSRequestData": {
"executeThreeD": "Y"
},
"customer": {
"email": "buyer@example.com",
"phone": "19999999999"
},
"goods": [
{
"name": "Product name mepsking1",
"description": "sample description",
"unitPrice": "10",
"number": "1",
"virtualProduct": "Y",
"imgUrl": "https://yourOrderSample/001.png"
}
],
"device": {
"orderTerminal": "02"
},
"paymentMethod": {
"type": "scheme",
"cardInfo": {
"number": "4242424242424242",
"holderFirstName": "zhang",
"holderLastName": "san",
"expireMonth": "09",
"expireYear": "2030",
"cvv": "239"
}
},
"browserInfo": {
"acceptHeader": "content-type=application/x-www-form-urlencoded;accept=*/*;cache-control=no-cache;postman-token=cf489264-5378-4d5d-a86c-72c86a408c03;accept-encoding=gzip, deflate;content-length=588;connection=keep-alive;",
"colorDepth": "32",
"jetLag": "480",
"screenHeight": "1980",
"screenWidth": "1080",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
"windowSize": "05"
},
"jsGeneratedData": {
"channel": "CyberSource",
"version": "1.0",
"correlationId": "af43fce6-70a9-4224-8583-bb106a96a12b",
"threeDInitTransId": "0b13e799-b802-4c85-adcc-a8a738ee0381",
"threeDSecureReferenceId": "af43fce6-70a9-4224-8583-bb106a96a12b"
}
}Note
payResultUrl is only the return page after the shopper completes the front-end flow. It does not mean the payment has succeeded. For order finalization, fulfillment, or entitlement delivery, always rely on the server-side result.
After the payment request is submitted, the merchant server first receives a synchronous response.
Synchronous response example (bizContent only):
{
"issuerInfo": {},
"transactionTime": "1782466165000",
"requestId": "PMT-WWK4L1L2Q11782466163266",
"merchantTransactionId": "PMT-WWK4L1L2Q11782466163266",
"currency": "USD",
"exchangedAmount": "10",
"exchangedCurrency": "USD",
"amount": "10",
"authenticationInfo": {
"avsResult": "U",
"cvvResult": "Y",
"threeDSecure": "N"
},
"cardInfo": {
"isoCountryA2": "MY",
"lastFourDigits": "1096",
"cardLevel": "STANDARD",
"paymentBrand": "Mastercard",
"cardType": "CREDIT",
"issuringBank": "PUBLIC BANK BERHAD",
"ipCountry": "CN",
"firstSixDigits": "520000",
"isoCountry": "MALAYSIA"
},
"transactionEndingTime": "1782466167761",
"threeDUnionParams": {
"threeDContinue": "false"
},
"transactionId": "26062600000050931108",
"threeDContinue": "false",
"token": "919110fb49484e1760b3a206d26909bc4c42d09eef818d113e4b20a83cdc11fb",
"paymentMethod": {
"type": "scheme"
},
"captureDelayHours": 0,
"status": "SUCCESS"
}Key response fields:
| Field | Description |
|---|---|
status | Current transaction status, such as SUCCESS, FAILED, or PROCESSING |
threeDContinue | Whether the shopper must continue to the 3DS challenge flow |
threeDUnionParams.threeDRedirectUrl | Redirect URL used by the front end when a 3DS challenge is required |
transactionId | PingPong transaction ID |
requestId | Payment request ID |
The authorization result should be determined based on status: SUCCESS and FAILED indicate final payment results, while PROCESSING indicates that the payment is still being processed.
The table below shows the possible values of status in the synchronous response and the recommended follow-up actions:
status | Meaning | Next action |
|---|---|---|
SUCCESS | The authorization payment succeeds. | No further 3DS redirect is required. Save transactionId, then continue confirming the final payment result through the asynchronous notification or transaction query. |
FAILED | The authorization payment fails. | Ask the shopper to retry or use another card. |
PROCESSING | The transaction is being processed. | If threeDUnionParams.threeDRedirectUrl is returned, the shopper still needs to complete the 3DS challenge and the front end should redirect there when required. If no redirect URL is returned, continue waiting for the asynchronous notification or actively call the transaction query. |
Redirect to the 3DS Authentication Page (Optional)
This is an optional step and is required only when threeDContinue=true in the synchronous response. In that case, the shopper still needs to complete a 3DS challenge, and the synchronous response typically returns threeDUnionParams.threeDRedirectUrl, for example:
{
"issuerInfo": {},
"transactionTime": "1782794168000",
"requestId": "PMT-K9X4L2N7QV1782794167312",
"merchantTransactionId": "PMT-K9X4L2N7QV1782794167312",
"currency": "USD",
"exchangedAmount": "10",
"exchangedCurrency": "USD",
"amount": "10",
"authenticationInfo": {
"avsResult": "Unknown",
"cvvResult": "Y",
"threeDSecure": "Y"
},
"cardInfo": {
"isoCountryA2": "US",
"lastFourDigits": "1096",
"cardLevel": "CLASSIC",
"paymentBrand": "Mastercard",
"cardType": "CREDIT",
"issuringBank": "",
"ipCountry": "CN",
"firstSixDigits": "520000",
"isoCountry": "UNITED STATES"
},
"transactionEndingTime": "1782794170200",
"threeDUnionParams": {
"threeDContinue": "true",
"threeDRedirectUrl": "https://sandbox-acquirer-static.pingpongx.com/payment/3ds-redirect.html?token=example"
},
"transactionId": "26062900000150950001",
"threeDContinue": "true",
"paymentMethod": {
"type": "scheme"
},
"captureDelayHours": 0,
"status": "PROCESSING"
}If the synchronous response indicates that 3DS is required, pass threeDUnionParams.threeDRedirectUrl directly to the front end and redirect the shopper to complete the challenge.
3DS redirect notes
threeDRedirectUrlis the complete redirect URL returned by PingPongCheckout. The merchant front end should use the original value returned by the server directly and treat it as an opaque link. Do not append extra parameters ordecodeand thenencodeit again, otherwise the 3DS page may fail to open correctly.- Do not rely on fixed domains, fixed paths, or static rules to identify the 3DS challenge page. Always use the
threeDRedirectUrlreturned by the server. - Open the 3DS challenge in a top-level page. Do not host the challenge page inside an
iframe, to avoid redirect, input, or return-page issues. - For apps, we recommend using the system browser or a system-level web container first. If you must use
WKWebVieworWebView, complete real-device testing in advance and confirm that redirect, back navigation, keyboard, and page scaling all behave correctly.
function redirectThreeDOnWeb(threeDRedirectUrl) {
if (!threeDRedirectUrl) return;
window.location.assign(threeDRedirectUrl);
}function redirectThreeDOnWap(threeDRedirectUrl) {
if (!threeDRedirectUrl) return;
window.location.href = threeDRedirectUrl;
}We recommend opening the 3DS page in the system browser:
guard let url = URL(string: threeDRedirectUrl) else { return }
UIApplication.shared.open(url, options: [:]) { success in
if !success {
// Ask the shopper to retry or use another card
}
}If you must load the page in WKWebView, use the original URL returned by the server and make sure the URL is encoded only once. For example, if the URL already contains %20, do not encode it again into %2520.
guard let url = URL(string: threeDRedirectUrl) else { return }
let request = URLRequest(url: url)
webView.load(request)We recommend opening the 3DS page in the system browser or Chrome Custom Tabs:
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(threeDRedirectUrl))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
}If you must load the page in WebView, enable at least the following settings. This helps when some issuer 3DS pages render with a desktop-like layout on Android phones:
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(true);
webView.loadUrl(threeDRedirectUrl);Tip
threeDRedirectUrl is a PingPongCheckout intermediate 3DS page. After the shopper opens it, the page continues the redirect to the issuer's 3DS challenge page. When the challenge is completed, PingPongCheckout redirects the shopper back to the payResultUrl configured in the payment request.
Step 2: Get the final payment result
For international card payments, we recommend confirming the final result through server-side asynchronous notification first. Transaction query is better suited to active verification and follow-up checks.
The final result of a card payment should preferably be confirmed through a server-side asynchronous notification. If the asynchronous notification is delayed, not delivered, handled abnormally, or the merchant needs to verify the result immediately after the shopper returns, the merchant can actively call Transaction Query in the After Payment section. For the full transaction query integration approach, see After Payment > Transaction Query.
If you use the asynchronous notification flow, the merchant server should first return HTTP 2xx to acknowledge receipt, and then update the order according to the notification status.
Payment notification example (bizContent only):
{
"exchangedCurrency": "USD",
"amount": "10.000000",
"authenticationInfo": {
"avsResult": "Unknown",
"cvvResult": "Y",
"threeDSecure": "Y"
},
"cardInfo": {
"firstName": "zhang",
"isoCountryA2": "US",
"lastName": "san",
"lastFourDigits": "1096",
"cardLevel": "CLASSIC",
"paymentBrand": "Mastercard",
"cardType": "CREDIT",
"issuringBank": "",
"ipCountry": "CN",
"firstSixDigits": "520000",
"isoCountry": "UNITED STATES"
},
"issuerInfo": {
"issuerResultMsg": "Successful approval/completion",
"issuerResultCode": "00"
},
"threeDSecure": "Y",
"transactionTime": "1782794170000",
"transactionId": "26062900000150950001",
"notifyType": "RECHARGE",
"requestId": "PMT-K9X4L2N7QV1782794167312",
"merchantTransactionId": "PMT-K9X4L2N7QV1782794167312",
"paymentMethod": {
"type": "Mastercard"
},
"currency": "USD",
"exchangedAmount": "10.000000",
"captureDelayHours": 0,
"status": "SUCCESS"
}status in the payment notification indicates the final payment result, so the merchant can update the order based on SUCCESS or FAILED.
Notification response example:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 2
OKAfter Payment
The following sections describe how to actively query transaction status after card payment, and how to continue with Capture, Void, Refund, and Reconciliation.
Transaction Query
When the shopper returns from the payment page to the merchant result page, the asynchronous notification is delayed, not delivered, notification handling fails, or the merchant needs to run a compensation task, you can call Transaction Query to get the latest transaction status.
Transaction query request example (bizContent only):
{
"merchantTransactionId": "PMT-WWK4L1L2Q11782466163266"
}Transaction query response example (bizContent only):
{
"threeDSecure": "",
"resultCode": "000000",
"transactionTime": "1782466164000",
"requestId": "PMT-WWK4L1L2Q11782466163266",
"merchantTransactionId": "PMT-WWK4L1L2Q11782466163266",
"currency": "USD",
"exchangedAmount": "10.000000",
"resultDescription": "Transaction succeeded",
"exchangedCurrency": "USD",
"amount": "10.000000",
"authenticationInfo": {
"avsResult": "U",
"cvvResult": "Y",
"threeDSecure": "N"
},
"cardInfo": {
"isoCountryA2": "MY",
"lastFourDigits": "1096",
"cardLevel": "STANDARD",
"paymentBrand": "Mastercard",
"cardType": "CREDIT",
"issuringBank": "PUBLIC BANK BERHAD",
"ipCountry": "CN",
"firstSixDigits": "520000",
"isoCountry": "MALAYSIA"
},
"transactionEndingTime": "1782466168000",
"transactionId": "26062600000050931108",
"token": "919110fb49484e1760b3a206d26909bc4c42d09eef818d113e4b20a83cdc11fb",
"paymentMethod": {
"type": "scheme"
},
"captureDelayHours": 0,
"status": "SUCCESS"
}The authorization result should be determined based on status: SUCCESS and FAILED indicate final payment results, while PROCESSING indicates that the payment is still being processed.
Capture
If the original transaction uses manual Capture, refer to Capture to complete the later capture step.
Notifications
For the payment result notification integration approach, refer to Step 2: Get the final payment result on this page. If you need Capture, Void, or Refund, the corresponding documents also include how to receive and confirm their result notifications.
Void
If the original transaction has been authorized but not yet captured, refer to Void to stop the later charge.
Refund
Refund capability varies by payment method, including whether refunds are supported, the refund window, whether partial refunds are supported, and whether multiple refunds are supported. Refer to Payment Methods or the target payment method page to confirm the exact refund capability.
After a payment succeeds, if the shopper requests a refund, the merchant cancels a paid order, or part or all of the funds need to be returned, you can call Refund Request for the original transaction.
PingPongCheckout supports the following refund capabilities:
- Full refund
- Partial refund
- Multiple refunds, as long as the cumulative refund amount does not exceed the refundable amount of the original transaction
Refer to Refund for the refund integration solution. For request parameters, response fields, and handling rules, see Refund Request. To confirm the refund result, see Refund Query.
Reconciliation
If you need to understand statement generation rules and settlement cycles, refer to Settlement Cycle and Reconciliation Statement. If you need statement download capability, refer to SFTP Service Application.
