---
url: >-
https://acquirer-api-docs-v4-en.pingpongx.com/en/notes/integrate/sdk-v4-2/index.md
description: >-
This solution is specifically designed for merchants who have adopted the
OnePage Checkout model, providing embeddable payment components that
seamlessly integrate into your existing checkout page. Without changing the
original checkout flow, you can quickly access PingPong payment capabilities,
supporting multiple mainstream payment methods covering regions such as Europe
and Singapore.
---
## What is OnePage Checkout?
OnePage Checkout is a modern e-commerce checkout model that consolidates the traditional multi-page checkout process (such as: shopping cart → fill in delivery information → select payment method → confirm order) onto a single page. Users can complete all checkout steps within one page without page jumps, greatly simplifying the shopping process.
::: tip Design philosophy of this solution
This SDK solution is specially designed to adapt to **OnePage Checkout pages**. If your e-commerce website has already adopted the one-page checkout model, this solution can seamlessly embed PingPong payment components into your existing checkout page, displaying alongside modules such as address filling and shipping selection, maintaining user experience consistency without requiring reconstruction of your checkout flow.
:::
### Main Advantages
**Enhanced User Experience**
- Reduces page loading and jumping, improving checkout efficiency
- Users can view and modify order information in real-time
- Clean and intuitive interface, reducing cart abandonment rate
**Improved Conversion Rate**
- Simplified process means fewer operational steps and potential drop-off points
- Shorter and more direct path for users to complete purchases
- Particularly suitable for mobile users with more friendly responsive design
### Core Function Modules
Typical one-page checkout usually includes the following modules:
- **Address Information**: Delivery address filling and selection
- **Shipping Method**: Available shipping options and fees
- **Payment Method**: Various payment options (credit card, PayPal, Alipay, etc.)
- **Order Summary**: Product list, prices, totals, etc.
- **Coupons/Discount Codes**: Input discount information
### Implementation Suggestions
1. **Progressive Design**: Use collapsible design, expand modules as needed
2. **Form Validation**: Real-time validation of user input, reducing errors
3. **Guest Checkout**: Allow users to purchase without registration
4. **Save Information**: Automatically save address and payment information for logged-in users
5. **Security Authentication**: Ensure PCI DSS compliance, display security indicators
### Applicable Scenarios
- Mobile shopping platforms
- E-commerce websites pursuing high conversion rates
- Subscription services
- Digital product sales
## SDK Integration Process
```mermaid
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#E3F2FD',
'primaryTextColor': '#0D47A1',
'primaryBorderColor': '#1976D2',
'lineColor': '#1565C0',
'secondaryColor': '#BBDEFB',
'tertiaryColor': '#90CAF9',
'background': '#F8FBFF',
'mainBkg': '#E3F2FD',
'secondBkg': '#BBDEFB',
'tertiaryBkg': '#90CAF9',
'actorBkg': '#2196F3',
'actorBorder': '#1976D2',
'actorTextColor': '#FFFFFF',
'actorLineColor': '#1565C0',
'signalColor': '#0D47A1',
'signalTextColor': '#0D47A1',
'c0': '#E8F4FD',
'c1': '#D1E7DD',
'c2': '#B3D9FF',
'c3': '#81C784',
'noteBkgColor': '#E1F5FE',
'noteTextColor': '#01579B',
'noteBorderColor': '#0288D1',
'loopTextColor': '#0D47A1',
'activationBkgColor': '#B3E5FC',
'activationBorderColor': '#0277BD'
}
}}%%
sequenceDiagram
participant Merchant as 🏪 Merchant Backend
participant Frontend as 💻 Merchant Frontend
participant SDK as 📦 JS-SDK
participant PP as 🔄 PingPong Server
Note over Merchant, PP: 🚀 SDK Integration and Payment Process
Note over Merchant, Frontend: 📋 Preparation Phase:• Get access credentials• Import SDK script
Merchant->>+PP: 1. Get sdkAccessToken
Note right of PP: Verify merchant identity Generate access credentials
PP-->>-Merchant: 2. Return sdkAccessToken
Merchant->>Frontend: 3. Pass sdkAccessToken to frontend
Frontend->>Frontend: 4. Import JS-SDK script
Note right of Frontend: CDN loading: Sandbox/Production environment
Frontend->>+SDK: 5. Initialize cashier PingPong.Checkout.create()
Note right of SDK: Parameters include:• amount, currency• tradeCountry• sdkAccessToken• paymentMethods
SDK->>SDK: 6. Render cashier interface
SDK-->>-Frontend: 7. Cashier ready
opt 🔄 [Dynamic Update - Optional]
Note over Frontend, SDK: 🔧 Update cashier elements:• Amount changes• Country changes
Frontend->>+SDK: 8. updateCheckoutHook({amount, tradeCountry})
SDK->>SDK: 9. Update cashier display
SDK-->>-Frontend: 10. Update completed
end
Note over Frontend, PP: 💳 Payment process begins
Frontend->>+SDK: 11. User clicks payment button
opt 🔍 [Pre-payment verification - Optional]
SDK->>+Frontend: 12. Trigger beforeCheckoutHook
Note right of Frontend: Business logic:• Inventory check• Event tracking• Order creation
Frontend->>+Merchant: 13. Call merchant API
Merchant-->>-Frontend: 14. Return order token
Frontend-->>-SDK: 15. Return processing result
end
SDK->>+PP: 16. Initiate payment request
Note right of PP: Call order placement API Process payment logic
PP->>PP: 17. Process payment
Note right of PP: • Risk control check• Payment routing• Third-party calls
alt ✅ [Payment Success]
PP-->>SDK: 18. 🎉 Payment successful
SDK-->>-Frontend: 19. Payment completion callback
Note over Frontend: Page redirect or display success message
else ❌ [Payment Failed]
PP-->>SDK: 20. ❌ Payment failed
SDK->>+Frontend: 21. 🚨 Trigger checkoutFailedHook
Note right of Frontend: Custom error handling:• Error alerts• Log recording• Retry logic
Frontend-->>-SDK: 22. Error handling completed
SDK-->>Frontend: 23. Display error message
end
Note over Merchant, PP: 🎯 SDK integration process completed
```
# Integration Process
## 1. Get sdkAccessToken API
The merchant backend system obtains the JS-SDK access credential (token) through the Get sdkAccessToken API, which is used for the frontend JS-SDK initialization call.
## 2. Import Javascript-SDK
Copy the following code to import the PingPongCheckout Javascript-SDK via CDN address
::: code-tabs
@tab 🧪 Sandbox Environment
```html
```
@tab 🇪🇺 FRA Production Environment
```html
```
@tab 🇸🇬 SG Production Environment
```html
```
:::
### 3. Initialize Cashier
Insert the ```pp-checkout``` tag into the ```html``` ```body```
```html:title="components/checkout.html" :line-numbers
```
Call ```PingPong.Checkout.create``` to complete initialization
#### Parameters
::::: field-group
:::: field name="amount" type="String" required
Transaction amount
This transaction is only for cashier display. Subsequent amount changes need to call the `updateCheckoutHook` function to update
::::
:::: field name="currency" type="String" required
Transaction currency
::::
:::: field name="tradeCountry" type="String" required
Used to specify the PingPong cashier country
Subsequent country changes need to call the `updateCheckoutHook` function to update
::::
:::: field name="sdkAccessToken" type="String" required
JS-SDK access credential
::::
:::: field name="originalPay" type="Boolean" optional default="true"
Controls whether to use the default PingPong payment button
If set to `false`, it means not using the built-in payment button. In this case, you need to call the `PingPong.Checkout.pay.run()` method in the custom payment button click event to trigger the payment process.
::::
:::: field name="isChallengeIframe" type="Boolean" optional default="false"
Controls whether to display the 3DS Challenge page in an iframe
When set to `true`, the Challenge flow is rendered in an iframe.
::::
:::: field name="paymentMethods" type="String[]" optional
Specify payment method list, embedded cashier will display according to specified payment methods
The passed payment methods will perform intersection operation with configured payment methods under this `accId`. The display order of payment methods will be arranged according to the order of the passed array.
::::
:::: field name="useTabMode" type="Boolean" optional default="true"
Controls whether to display payment method option box
When set to `false`, if the merchant only has card payment configuration, the option box will not be displayed and the payment form will be directly shown. Suitable for scenarios to simplify user experience.
::::
:::: field name="goods" type="Array" optional
Product list, containing the following sub-fields
::::
:::: field-group goods Sub-fields
::: field name="goods.description" type="String" optional
Product description
:::
::: field name="goods.imgUrl" type="String" optional
Product image URL
:::
::: field name="goods.name" type="String" required
Product name
:::
::: field name="goods.number" type="String" required
Product quantity
:::
::: field name="goods.sku" type="String" optional
Product SKU code
:::
::: field name="goods.unitPrice" type="String" required
Product unit price
:::
::: field name="goods.virtualProduct" type="String" optional default="N"
Whether it's a virtual product
`Y` - Virtual product, `N` - Physical product
:::
::::
:::: field name="bizType" type="String" optional
ApplePay card binding business parameter
Required for ApplePay transactions, fixed value: `CodeGrant`
::::
:::: field name="recurringInfoDTO" type="Object" optional
Configure Recurring payment (required for ApplePay transactions), containing the following sub-fields
::::
:::: field-group recurringInfoDTO Sub-fields
::: field name="recurringInfoDTO.recurringPaymentStartDate" type="Date" optional
First payment date
eg: `"2024-06-01 00:00:00"`
:::
::: field name="recurringInfoDTO.recurringPaymentIntervalUnit" type="String" optional
Type representing calendar units such as year, month, day, hour, etc.
enum: `year` / `month` / `day` / `hour` / `minute`, eg: `"month"`
:::
::: field name="recurringInfoDTO.recurringPaymentIntervalCount" type="String" optional
Number of interval units constituting the total payment interval
eg: `"6"`
:::
::: field name="recurringInfoDTO.recurringPaymentEndDate" type="Date" optional
Last payment date
eg: `"2024-12-01 00:00:00"`
:::
::::
:::::
```js:line-numbers
// Create PingPong Cashier
PingPong.Checkout.create({
amount: '1.08', // Transaction amount
currency: 'USD', // Transaction currency
tradeCountry: 'US', // Transaction country
originalPay: true,
isChallengeIframe: true, // Render the 3DS Challenge page in an iframe
useTabMode: false, // Hide option box when only card payment available
sdkAccessToken, // SDK access token
paymentMethods: ['VISA', 'Klarna'],
goods: [{
description: 'short legs',
imgUrl: 'http://pic.bizhi360.com/bpic/30/5230.jpg',
name: '한국어/English',
number: '1',
sku: '20230524001',
unitPrice: '1',
virtualProduct: 'N'
}],
// ApplePay payment parameters
bizType: 'CodeGrant', // Required for ApplePay transactions
recurringInfoDTO: {
recurringPaymentStartDate: "2024-06-01 00:00:00",
recurringPaymentIntervalUnit: "month",
recurringPaymentIntervalCount: "6",
recurringPaymentEndDate: "2024-12-01 00:00:00"
},
})
```
#### Custom Payment Button (Optional)
```js:line-numbers title="src/config/payment.js"
// Custom payment button configuration
// When originalPay is false in initialization parameters, custom payment button click event is needed
document.querySelector('#pay').onclick = function () {
PingPong.Checkout.pay.run() // Manually trigger payment
}
```
#### Event Listeners (Optional)
SDK supports listening to ready and error events during initialization, facilitating external state management and error handling.
```js:line-numbers title="src/config/payment.js"
// Listen to SDK initialization events
// Listen to initialization success event
document.querySelector('pp-checkout').addEventListener('ready', (e) => {
console.log('SDK initialization successful'); // Initialization success callback
// You can execute post-initialization logic here
});
// Listen to initialization failure event
document.querySelector('pp-checkout').addEventListener('error', (e) => {
console.log('SDK initialization failed', e.detail); // Error information
// You can execute error handling logic here, such as displaying error prompts, retrying, etc.
});
```
**Event Description:**
- `ready`: Triggered when SDK initialization is successful, indicating cashier is ready
- `error`: Triggered when SDK initialization fails, event details contained in `e.detail`
### 4. Modify Amount, Country and Products
Before using global variables, please ensure the Javascript-SDK has loaded completely.
#### updateCheckoutHook (Optional)
```updateCheckoutHook``` is used to update cashier elements.
##### ts types
```ts:line-numbers title="src/types/hooks.ts"
// updateCheckoutHook type definition
PingPong.Checkout.updateCheckoutHook:
({ amount?: string, tradeCountry?: string, goods?: Goods[] }) => void
```
##### Usage Instructions
> ⚠️ **Important**: This method uses a **partial update** mechanism. Only pass in the fields that have changed, no need to pass in other fields.
| Scenario | Parameter | Example Code |
|----------|-----------|--------------|
| Country changes | `tradeCountry` | `PingPong.Checkout.updateCheckoutHook({ tradeCountry: newCountry });` |
| Amount changes | `amount` | `PingPong.Checkout.updateCheckoutHook({ amount: newAmount });` |
| Goods changes | `goods` | `PingPong.Checkout.updateCheckoutHook({ goods: newGoods });` |
##### Correct Examples
```js:line-numbers title="src/config/update.js"
// Scenario 1: User switches country - only pass tradeCountry
const newCountry = 'US';
PingPong.Checkout.updateCheckoutHook({ tradeCountry: newCountry });
// Scenario 2: Amount changes after user applies coupon - only pass amount
const newAmount = '99.99';
PingPong.Checkout.updateCheckoutHook({ amount: newAmount });
// Scenario 3: Product information changes - only pass goods
const newGoods = [{
description: 'updated description',
imgUrl: 'http://pic.bizhi360.com/bpic/30/5230.jpg',
name: 'Updated Product Name',
number: '2',
sku: '20230524001',
unitPrice: '2',
virtualProduct: 'N'
}];
PingPong.Checkout.updateCheckoutHook({ goods: newGoods });
```
##### ❌ Incorrect Examples
> The following approaches are **not recommended** - passing unnecessary fields or null values:
```js:line-numbers title="src/config/update-error.js"
// ❌ Incorrect: No need to pass unchanged fields or null values
PingPong.Checkout.updateCheckoutHook({
amount: newAmount ? newAmount : null,
tradeCountry: newCountry ? newCountry : null,
goods: newGoods ? newGoods : null
});
// ❌ Incorrect: When updating amount only, no need to pass country and goods
PingPong.Checkout.updateCheckoutHook({
amount: '99.99',
tradeCountry: 'US', // Unchanged field, not needed
goods: [] // Unchanged field, not needed
});
```
### 5. Pre-order Verification
#### beforeCheckoutHook (Optional)
type:
```ts:line-numbers title="src/types/hooks.ts"
// beforeCheckoutHook type definition
(() => void) | (() => Promise)
```
`beforeCheckoutHook` is used to set the hook function before initiating payment request.
When you need to execute your own business logic before the user clicks the payment button and initiates the payment request, such as reporting analytics, checking inventory, etc., you can set this hook function.
This function can return a `Promise`, and subsequent payment processes will wait until the Promise status becomes Fulfilled before continuing execution. If you want to interrupt the payment process when the Promise status is Rejected or the asynchronous result doesn't meet your business conditions, you can throw an exception, and the SDK will interrupt the payment process after capturing the exception.
```js:line-numbers title="src/config/payment.js"
PingPong.Checkout.beforeCheckoutHook = () => {
return fetch('/api/requestInventory').then(res => {
const {inventoryQuantity} = res;
if (inventoryQuantity < MIN_QUANTITY) {
throw new Error('Insufficient inventory, transaction needs to be interrupted')
}
}).catch((error) => {
throw new Error('Interface exception, transaction needs to be interrupted')
})
};
```
##### ts types
```ts:line-numbers title="src/types/hooks.ts"
// beforeCheckoutHook return type definition
PingPong.Checkout.beforeCheckoutHook:
(() => string) | (() => Promise)
```
### 6. Place Order
After clicking the payment button, call the Place Order API to complete the payment
### 7. Error Handling
#### checkoutFailedHook (Optional)
type:
```ts:line-numbers title="src/types/hooks.ts"
// checkoutFailedHook type definition
(() => void) | (() => Promise)
```
checkoutFailedHook receives the following parameters:
```ts:line-numbers title="src/types/hooks.ts"
// checkoutFailedHook parameter type definition
(code: string, message: string) => void | Promise;
// code: string - Error code
// message: string - Error message
```
`checkoutFailedHook` is used to customize error logic
When user payment fails, PingPong will default to showing a popup with the failure reason. If you want to customize the popup UI or text, you can set this hook function.
This function can return a Promise. If returning Promise, subsequent processes will wait until the Promise status becomes Fulfilled before continuing execution
```js:line-numbers title="src/config/payment.js"
PingPong.Checkout.checkoutFailedHook = (code: string, message: string) => {
notification.open({
message: 'Error title',
description: `${code}: ${message}`
})
};
```
## Usage Example:
::: code-tree title="PingPong Checkout Integration Example" height="500px"
```html title="examples/onepage/pages/checkout.html"
PingPong Checkout Demo