--- url: >- https://acquirer-api-docs-v4-en.pingpongx.com/notes/zh/integrate/sdk-elements/index.md description: 说明 PingPong Element SDK 的组件化接入方式,覆盖支付元素创建、事件监听、下单支付和钱包绑定场景。 --- # PingPong Element SDK 集成指南 ## SDK集成流程 ```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 User as 👤 用户 participant Browser as 🌐 浏览器 participant Frontend as 💻 商户前端 participant Backend as 🏪 商户后端 participant SDK as 📦 Element SDK participant PP as 🔄 PingPong服务端 Note over User, PP: 🚀 Element SDK 完整集成流程 User->>Browser: 1. 选择商品 Browser->>Frontend: 2. 打开支付页面 Note over Frontend, Backend: 📋 初始化阶段 Frontend->>+Backend: 3. 请求初始化 sdkAccessToken Backend->>+PP: 4. 请求初始化 sdkAccessToken PP-->>-Backend: 5. 返回初始化 sdkAccessToken Backend-->>-Frontend: 6. 返回初始化 sdkAccessToken Frontend->>+SDK: 7. 使用 sdkAccessToken 初始化 SDK Note right of SDK: PingPongSDK.init() SDK->>+PP: 8. 查询店铺配置 PP-->>-SDK: 9. 返回店铺配置 SDK-->>-Frontend: 10. SDK 初始化完成 SDK->>Frontend: 11. 触发 ready 事件 Frontend->>SDK: 12. 创建支付元素 Note right of SDK: createElement() SDK-->>Frontend: 13. 支付元素已就绪 Frontend->>Browser: 14. 在支付页面中渲染支付按钮 Note over User, PP: 💳 支付流程开始 Frontend->>User: 15. 显示支付按钮 User->>Frontend: 16. 点击支付按钮 Frontend->>+SDK: 17. 触发支付流程 SDK->>+Frontend: 18. 调用 createOrder() activate Frontend Note over Frontend: 校验 billing、shipping、优惠券 Frontend->>+Backend: 19. 发送订单详情 Backend->>+PP: 20. 下单(原V4下单接口) PP-->>-Backend: 21. 返回交易 token Backend-->>-Frontend: 22. 返回交易 token Frontend-->>-SDK: 23. 从 createOrder 返回 token deactivate Frontend SDK->>+PP: 24. 请求支付(支付信息 + token) PP->>PP: 25. 处理支付 Note right of PP: • 风控检查
• 支付路由
• 第三方调用 PP-->>-SDK: 26. 支付响应 alt ❌ 支付失败 SDK->>Frontend: 27. 调用 error(code, msg) activate Frontend Note over Frontend: 处理支付失败逻辑 deactivate Frontend else ✅ 支付成功或处理中 SDK->>Browser: 28. 跳转到支付结果页面 Note right of Browser: merchantResultUrl else 🔒 需要 3DS 验证 SDK->>Browser: 29. 跳转到 3DS 验证页面 end Note over User, PP: 🎯 支付流程结束 ``` ## 架构设计 ### 核心模块 | 模块 | 职责 | | --- | --- | | **PingPongSDK** | SDK 唯一入口,暴露 init / createElement 方法 | | **PingPongElement** | 所有支付按钮的基类,提供 .on() / .off() 事件机制 | ### 支付模式 SDK 支持两种主要模式: - **Payment**: 下单并支付模式,适用于标准支付流程 - **Vault**: PayPal 独立签约模式,用于绑定钱包 ## 接入流程 ### 1. 获取 sdkAccessToken 商户后端系统通过调用获取 sdkAccessToken 接口得到访问凭证。 **支付场景:** - 调用 `/v4/session/init` 接口获取 sdkAccessToken **签约场景:** - POST 调用已有签约接口获取 sdkAccessToken 和 JS URL ### 2. 引入 Element SDK 根据您的业务环境,选择相应的 SDK 版本进行引入: :::: code-tabs @tab 🧪 沙箱环境 ```html ``` @tab 🇪🇺 FRA 生产环境 ```html ``` @tab 🇸🇬 SG 生产环境 ```html ``` :::: ### 3. 初始化 SDK #### 入参说明 ::::: field-group :::: field name="mode" type="string" required 业务模式 `Payment`(支付) 或 `Vault`(PayPal 独立签约) :::: :::: field name="env" type="string" required 运行环境 `sandbox`(沙箱) 或 `production`(生产) :::: :::: field name="amount" type="string" required 交易金额 用于收银台展示 :::: :::: field name="currency" type="string" required 交易币种 :::: :::: field name="country" type="string" required 国家/地区代码 如 `US`、`CN`、`UK` 等 :::: :::: field name="accId" type="string" required 商户账户 ID :::: :::: field name="locale" type="string" required 界面语言 `en`、`zh-CN` 等 :::: :::: field name="region" type="string" optional default="fra" 地区 `sg` 或 `fra` :::: :::: field name="sdkAccessToken" type="string" required SDK 访问凭证 :::: :::: field name="merchantResultUrl" type="string" required 支付完成后的跳转地址 :::: :::: field name="createOrder" type="Function" optional 下单函数 mode 为 `Payment` 时必传。该函数接收一个包含 `payMethod` 的对象参数,表示用户选择的支付方式 :::: :::: field name="goods" type="Array" required 商品信息数组 详见下方 [goods 数组结构](#goods-数组结构) :::: :::: field name="biztype" type="string" optional 业务类型 可选值: `CodeGrant` :::: :::: field name="recurringInfoDTO" type="Object" optional Recurring 配置,ApplePay 签约必传 :::: ::::: #### 初始化示例 ```javascript:line-numbers title="src/sdk-init.js" await PingPongSDK.init({ mode: 'Payment', // 业务模式: Payment 或 Vault env: 'sandbox', // 运行环境 amount: '19.99', // 交易金额 currency: 'USD', // 交易币种 country: 'US', // 国家/地区代码 accId: 'ACC_123', // 商户账户ID locale: 'en', // 语言设置 region: 'fra', // 地区: sg 或 fra sdkAccessToken: 'your_sdk_token', // SDK访问令牌 merchantResultUrl: 'https://merchant-result.com', // 支付完成跳转地址 // mode 为 Payment 时必传 createOrder: async ({payMethod}) => { console.log('用户选择的支付方式:', payMethod); // 调用商户后端下单接口 const response = await fetch('/xx/xx', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payMethod, // 传递支付方式到后端 xx: 'xx' }) }); const result = await response.json(); return result.token; // 返回订单 token }, // 商品信息数组(必填) goods: [ { name: '商品名称', description: '商品描述', imgUrl: 'https://example.com/product.jpg', sku: 'SKU123', unitPrice: '19.99', number: '2', virtualProduct: 'N' } ], // ApplePay 签约时必传 recurringInfoDTO: { recurringPaymentStartDate: '2024-06-01 00:00:00', recurringPaymentIntervalUnit: 'month', recurringPaymentIntervalCount: '6', recurringPaymentEndDate: '2024-12-01 00:00:00' } }); ``` ### goods 数组结构 商品信息数组包含每个商品的详细信息。 ::::: field-group :::: field name="name" type="string" required 商品名称 :::: :::: field name="description" type="string" optional 商品描述 :::: :::: field name="imgUrl" type="string" optional 商品图片 URL :::: :::: field name="sku" type="string" optional 商品 SKU :::: :::: field name="unitPrice" type="string" required 商品单价 :::: :::: field name="number" type="string" required 商品数量 :::: :::: field name="virtualProduct" type="string" optional 是否为虚拟产品 `Y` 或 `N` :::: ::::: **示例:** ```javascript:line-numbers title="src/goods-example.js" goods: [ { name: '无线蓝牙耳机', description: '高品质音质,30小时续航', imgUrl: 'https://cdn.example.com/product1.jpg', sku: 'HEADPHONE-BT-001', unitPrice: '99.99', number: '1', virtualProduct: 'N' }, { name: '音乐会员月卡', description: '畅听千万首正版音乐', imgUrl: 'https://cdn.example.com/product2.jpg', sku: 'VIP-MUSIC-1M', unitPrice: '15.00', number: '1', virtualProduct: 'Y' } ] ``` ### 4. 创建支付元素 #### 4.1 Apple Pay 按钮 ```javascript:line-numbers title="src/apple-pay.js" const applePay = await PingPongSDK.createElement('applePayButton', { buttonType: 'buy', // 按钮类型: buy | plain buttonColor: 'black', // 按钮颜色: black | white | white-outline style: { width: '100%', height: '40px', borderRadius: '4px' }, payDiscount: { // 营销活动配置(可选) activityNo: 'EEE', costAmount: '19.99', // 原始金额 discountAmount: '2.00' // 折扣金额 } }); ``` #### 4.2 Google Pay 按钮 ```javascript:line-numbers title="src/google-pay.js" const googlePay = await PingPongSDK.createElement('googlePayButton', { buttonType: 'buy', // 按钮类型: buy | subscribe buttonColor: 'black', // 按钮颜色: black | white isChallengeIframe: true, // 使用 iframe 展示 3DS Challenge 页面 style: { width: '100%', height: '40px', borderRadius: '4px' }, payDiscount: { activityNo: 'EEE', costAmount: '19.99', discountAmount: '2.00' } }); ``` **Google Pay options 参数:** ::::: field-group :::: field name="buttonType" type="string" optional 按钮类型,可选值:`buy`、`subscribe` :::: :::: field name="buttonColor" type="string" optional 按钮颜色,可选值:`black`、`white` :::: :::: field name="isChallengeIframe" type="boolean" optional 是否使用 iframe 展示 3DS Challenge 页面。当设置为 `true` 时,将通过 iframe 承载 Challenge 流程。 :::: :::: field name="style" type="object" optional 按钮样式配置 :::: :::: field name="payDiscount" type="object" optional 营销活动配置 :::: ::::: #### 4.3 PayPal 按钮 ```javascript:line-numbers title="src/paypal.js" const paypal = await PingPongSDK.createElement('paypalButton', { buttonType: 'buttons', // buttons | marks | card-fields | funding-eligibility style: { borderRadius: 4, color: 'gold', // gold | blue | silver | white | black height: 40, label: 'paypal', // paypal | checkout | buynow | pay | installment | subscribe | donate layout: 'vertical', // vertical | horizontal shape: 'rect' // rect | pill | sharp } }); // PayPal 不需要监听 completed 事件 // 当支付完成时,SDK 会发起重定向到 merchantResultUrl ``` ### 5. 事件监听 所有支付元素都支持统一的事件模型: ```javascript:line-numbers title="src/event-listeners.js" // 监听 ready 事件 applePay.on('ready', () => { console.log('Apple Pay 已渲染'); }); // 监听 success 事件 applePay.on('success', (event) => { console.log('Apple Pay 支付完成', event.detail); // event.detail 包含 transactionId 等信息 }); // 监听 error 事件 applePay.on('error', (event) => { console.error('Apple Pay 错误', event.detail); // event.detail 包含 code 和 message }); // 监听 cancel 事件 applePay.on('cancel', () => { console.log('Apple Pay 用户取消'); }); ``` ### 6. 挂载与卸载 ```javascript:line-numbers title="src/lifecycle.js" // 挂载到指定容器 applePay.mount('#apple-pay-container'); // 卸载元素 applePay.unmount(); ``` ## API 参考 ### PingPongSDK.init() 初始化 SDK 配置。 **参数:** ::::: field-group :::: field name="mode" type="string" required `Payment` 或 `Vault` :::: :::: field name="env" type="string" required `sandbox` 或 `production` :::: :::: field name="amount" type="string" required 交易金额 :::: :::: field name="currency" type="string" required 交易币种 :::: :::: field name="country" type="string" required 国家/地区代码 如 `US`、`CN`、`UK` 等 :::: :::: field name="accId" type="string" required 商户账户 ID :::: :::: field name="locale" type="string" required 界面语言 :::: :::: field name="region" type="string" optional default="fra" `sg` 或 `fra` :::: :::: field name="sdkAccessToken" type="string" required SDK 访问凭证 :::: :::: field name="merchantResultUrl" type="string" required 支付完成跳转地址 :::: :::: field name="createOrder" type="Function" optional mode 为 `Payment` 时必传。该函数接收一个包含 `payMethod` 的对象参数,表示用户选择的支付方式 :::: :::: field name="goods" type="Array" required 商品信息数组 :::: :::: field name="biztype" type="string" optional 业务类型 可选值: `CodeGrant` :::: :::: field name="recurringInfoDTO" type="Object" optional ApplePay 签约必传 :::: ::::: ### PingPongSDK.createElement() 创建支付元素实例。 **参数:** ::::: field-group :::: field name="type" type="string" required `applePayButton`、`googlePayButton`、`paypalButton` :::: :::: field name="options" type="object" required 元素配置参数 :::: ::::: **返回:** Promise\ ### element.on() 注册事件监听器。 **支持的事件:** ::::: field-group :::: field name="ready" type="Event" 元素初始化完成 :::: :::: field name="success" type="Event" 支付成功 :::: :::: field name="error" type="Event" 支付失败 :::: :::: field name="cancel" type="Event" 用户取消 :::: ::::: ### element.off() 移除事件监听器。 ### element.mount() 将支付元素挂载到 DOM。 **参数:** ::::: field-group :::: field name="selector" type="string" required CSS 选择器 :::: ::::: ### element.unmount() 从 DOM 中卸载元素,释放资源。