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

Billing Information

Shipping Information

``` ```css title="examples/onepage/assets/css/checkout.css" /** * PingPong Checkout Style File * Responsible for all style definitions of the checkout page */ /* ========== Variable Definitions ========== */ :root { --primary-color: #007bff; --primary-hover: #0056b3; --success-color: #28a745; --error-color: #dc3545; --warning-color: #ffc107; --border-color: #e1e5e9; --background-light: #f8f9fa; --text-primary: #333; --text-secondary: #666; --shadow-sm: 0 2px 4px rgba(0,0,0,0.1); --shadow-md: 0 2px 8px rgba(0,0,0,0.1); --shadow-lg: 0 4px 12px rgba(0,123,255,0.3); --border-radius: 8px; --border-radius-sm: 4px; --border-radius-lg: 12px; --transition: all 0.3s ease; } /* ========== Basic Style Reset ========== */ * { box-sizing: border-box; } body { margin: 0; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; background-color: var(--background-light); color: var(--text-primary); line-height: 1.6; } /* ========== Main Container ========== */ .checkout-container { max-width: 800px; margin: 0 auto; padding: 24px; background: white; border-radius: var(--border-radius); box-shadow: var(--shadow-md); } /* ========== Checkout Section ========== */ .checkout-section { margin-bottom: 32px; } .billing-form, .shipping-form { margin-bottom: 24px; } .billing-form h3, .shipping-form h3 { margin: 0 0 16px 0; color: var(--text-primary); font-size: 18px; font-weight: 600; } /* ========== Form Components ========== */ .form-group { margin-bottom: 16px; } .form-group label { display: block; margin-bottom: 6px; font-weight: 600; color: var(--text-primary); font-size: 14px; } .form-group input, .form-group select { width: 100%; max-width: 320px; padding: 10px 12px; border: 1px solid var(--border-color); border-radius: var(--border-radius-sm); font-size: 14px; transition: border-color 0.2s ease, box-shadow 0.2s ease; background: white; } .form-group input:focus, .form-group select:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(0,123,255,0.1); } .form-group input::placeholder { color: #999; } /* ========== PingPong Cashier ========== */ .pingpong-checkout { margin: 24px 0; padding: 20px; background: white; border: 1px solid var(--border-color); border-radius: var(--border-radius); box-shadow: var(--shadow-sm); } /* ========== Payment Section ========== */ .payment-section { text-align: center; padding: 24px; background: linear-gradient(135deg, #f8f9ff 0%, #ffffff 100%); border-radius: var(--border-radius); border: 1px solid var(--border-color); } /* ========== Coupon Section ========== */ .coupon-section { margin-bottom: 20px; } .coupon-section label { display: block; margin-bottom: 8px; font-weight: 600; color: var(--text-primary); font-size: 14px; } .coupon-section input { width: 100%; max-width: 280px; padding: 12px 16px; border: 2px solid var(--border-color); border-radius: var(--border-radius); font-size: 14px; transition: var(--transition); background: white; } .coupon-section input:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(0,123,255,0.1); } /* ========== Payment Button ========== */ .pay-button { background: linear-gradient(135deg, var(--primary-color) 0%, #0056b3 100%); color: white; border: none; padding: 16px 48px; border-radius: var(--border-radius); cursor: pointer; font-size: 16px; font-weight: 700; transition: var(--transition); min-width: 200px; position: relative; overflow: hidden; text-transform: uppercase; letter-spacing: 0.5px; } .pay-button:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); background: linear-gradient(135deg, #0056b3 0%, var(--primary-hover) 100%); } .pay-button:active { transform: translateY(0); box-shadow: var(--shadow-md); } .pay-button:disabled { background: #6c757d; cursor: not-allowed; transform: none; box-shadow: none; opacity: 0.7; } .pay-button.loading { color: transparent; pointer-events: none; } .pay-button.loading::after { content: ''; position: absolute; width: 20px; height: 20px; top: 50%; left: 50%; margin-left: -10px; margin-top: -10px; border: 2px solid white; border-radius: 50%; border-top-color: transparent; animation: spin 1s ease-in-out infinite; } /* ========== Message Prompts ========== */ .message { padding: 12px 16px; border-radius: var(--border-radius-sm); margin: 16px 0; font-size: 14px; font-weight: 500; border-left: 4px solid; } .message.error { background: #f8d7da; border-left-color: var(--error-color); color: #721c24; } .message.success { background: #d4edda; border-left-color: var(--success-color); color: #155724; } .message.warning { background: #fff3cd; border-left-color: var(--warning-color); color: #856404; } .message.info { background: #d1ecf1; border-left-color: var(--primary-color); color: #0c5460; } /* ========== Loading State ========== */ .loading-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.8); display: flex; align-items: center; justify-content: center; z-index: 9999; } .loading-overlay .spinner { width: 40px; height: 40px; border: 4px solid var(--border-color); border-top-color: var(--primary-color); border-radius: 50%; animation: spin 1s linear infinite; } /* ========== Animation Definitions ========== */ @keyframes spin { to { transform: rotate(360deg); } } @keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } } /* ========== Responsive Design ========== */ @media (max-width: 768px) { body { padding: 10px; } .checkout-container { padding: 16px; border-radius: var(--border-radius-sm); } .form-group input, .form-group select { max-width: 100%; } .coupon-section input { max-width: 100%; } .pay-button { width: 100%; min-width: unset; padding: 14px 24px; } .pingpong-checkout { padding: 16px; } } @media (max-width: 480px) { .checkout-container { padding: 12px; } .payment-section { padding: 20px 16px; } } /* ========== Print Styles ========== */ @media print { .pay-button, .loading-overlay { display: none !important; } .checkout-container { box-shadow: none; border: 1px solid #ddd; } } /* ========== Accessibility Enhancement ========== */ @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } /* High contrast mode support */ @media (prefers-contrast: high) { :root { --border-color: #000; --text-primary: #000; --background-light: #fff; } } /* ========== Utility Classes ========== */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; } .text-center { text-align: center !important; } .text-left { text-align: left !important; } .text-right { text-align: right !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 8px !important; } .mb-2 { margin-bottom: 16px !important; } .mb-3 { margin-bottom: 24px !important; } .mb-4 { margin-bottom: 32px !important; } ``` ```javascript title="examples/onepage/js/config/app-config.js" /** * Application Configuration File * Contains all application-level configuration constants */ /** * PingPong SDK Configuration */ export const PINGPONG_CONFIG = { // SDK basic configuration amount: '1.08', currency: 'USD', tradeCountry: 'US', originalPay: false, isChallengeIframe: false, useTabMode: true, sdkAccessToken: 'your-sdk-access-token-here', paymentMethods: ['VISA', 'MasterCard', '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 configuration (optional) applePay: { bizType: 'CodeGrant', recurringInfoDTO: { recurringPaymentStartDate: '', recurringPaymentIntervalUnit: 'month', recurringPaymentIntervalCount: '', recurringPaymentEndDate: '' } } }; /** * API Endpoint Configuration */ export const API_ENDPOINTS = { // PingPong API getAccessToken: '/api/auth/sdk-token', createOrder: '/api/orders/create', validateInventory: '/api/inventory/validate', // Business API validateCoupon: '/api/coupons/validate', logError: '/api/logs/error', // Payment related paymentStatus: '/api/payments/status', refundPayment: '/api/payments/refund' }; /** * Country Currency Mapping Configuration */ export const COUNTRY_CURRENCY_MAP = { 'US': 'USD', 'GB': 'GBP', 'DE': 'EUR', 'FR': 'EUR', 'IT': 'EUR', 'ES': 'EUR', 'CA': 'CAD', 'AU': 'AUD', 'JP': 'JPY', 'CN': 'CNY' }; /** * Error Code Mapping Configuration */ export const ERROR_MESSAGES = { 'PAYMENT_DECLINED': 'Payment declined, please check card information or try another payment method', 'INSUFFICIENT_FUNDS': 'Insufficient funds, please use another payment method', 'INVALID_CARD': 'Invalid card information, please check and retry', 'CARD_EXPIRED': 'Card expired, please use another card', 'NETWORK_ERROR': 'Network connection abnormal, please check network and retry', 'TIMEOUT': 'Payment timeout, please retry', 'FRAUD_DETECTED': 'Security verification failed, please contact customer service', 'CURRENCY_NOT_SUPPORTED': 'Currency not supported, please choose another currency', 'AMOUNT_INVALID': 'Invalid payment amount', 'AMOUNT_TOO_LOW': 'Payment amount too low', 'AMOUNT_TOO_HIGH': 'Payment amount too high', 'MERCHANT_ERROR': 'Merchant system error, please contact customer service', 'SDK_TOKEN_EXPIRED': 'Access credential expired, please refresh page and retry', 'SDK_TOKEN_INVALID': 'Access credential invalid, please contact customer service' }; /** * Application Constants Configuration */ export const APP_CONSTANTS = { // Debounce delay time (milliseconds) DEBOUNCE_DELAY: { AMOUNT_INPUT: 500, COUNTRY_CHANGE: 0, COUPON_INPUT: 1000 }, // Validation rules VALIDATION: { MIN_AMOUNT: 0.01, MAX_AMOUNT: 999999.99, COUPON_LENGTH_MIN: 3, COUPON_LENGTH_MAX: 50 }, // Timeout configuration (milliseconds) TIMEOUTS: { PAYMENT: 300000, // 5 minutes API_CALL: 30000, // 30