---
url: >-
https://acquirer-api-docs-v4-en.pingpongx.com/notes/zh/integrate/non-hosted-apm/index.md
description: 说明 Non-hosted 本地支付 API 接入流程,帮助商户在自建收银台中接入电子钱包、网银等本地支付方式。
---
PingPong Non-hosted 本地支付是一款专为跨境交易打造的轻量级、高安全后端解决方案。通过标准化的 API 集成,商户可一站式接入全球丰富的本地支付方式(涵盖电子钱包、网银、银行卡等)。我们致力于为您扫除多通道对接的技术壁垒,在保障交易安全合规的前提下,为全球买家提供极致顺滑的支付体验,助力您的出海业务快速落地与规模化扩张。
## 支付流程
```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',
'noteBkgColor': '#E1F5FE',
'noteTextColor': '#01579B',
'noteBorderColor': '#0288D1',
'loopTextColor': '#0D47A1',
'activationBkgColor': '#B3E5FC',
'activationBorderColor': '#0277BD'
}
}}%%
sequenceDiagram
participant Buyer as 👤 买家
participant Client as 💻 商户前端
participant Server as 🏪 商户服务端
participant PP as 🔄 PingPongCheckout
participant APM as 🧾 本地支付通道
Buyer->>Client: 1. 进入下单页并选择本地支付方式
Client->>Server: 2. 提交订单信息、支付方式、设备信息
Server->>PP: 3. 调用下单并支付
PP-->>Server: 4. 返回 code、bizContent.status、action
Server-->>Client: 5. 返回支付推进参数
Client->>APM: 6. 根据 action 推进支付
Buyer->>APM: 7. 在支付方式页面完成登录、授权或确认付款
APM-->>Client: 8. 按需跳回 payResultUrl
APM-->>PP: 9. 返回支付处理结果
PP-->>Server: 10. 推送支付异步通知
Server-->>PP: 11. 返回 HTTP 2xx 确认接收
Server->>PP: 12. 未收到通知时主动查询交易
Server-->>Client: 13. 返回商户订单状态
```
流程说明:
1. 买家在商户下单页面选择本地支付方式,例如钱包、网银或银行转账。
2. 商户前端将订单信息、支付方式、设备信息提交到商户服务端。
3. 商户服务端调用 [下单并支付](/notes/zh/checkout/api/uniformly/) 创建支付订单。
4. PingPongCheckout 返回同步响应;若交易需要买家继续操作,响应中会包含 `action`。
5. 商户前端根据 `action` 推进买家继续完成支付。本文以下以跳转类本地支付场景说明接入步骤。
6. 买家完成支付后,PingPongCheckout 通过 `notificationUrl` 推送支付结果。
7. 如果商户长时间未收到异步通知,应主动调用 [交易查询](/notes/zh/checkout/api/getOne/) 确认最终状态。
::: warning 注意
买家从本地支付页面跳回 `payResultUrl`,只表示买家回到了商户页面,不代表支付成功。订单落账、发货或发放权益必须以服务端异步通知或交易查询结果为准。
:::
## 接口列表
Non-hosted 本地支付通常涉及以下接口和通知:
| 阶段 | 类型 | 文档 | 是否必接 | 用途 |
|:---|:---|:---|:---:|:---|
| 支付创建 | API | [下单并支付](/notes/zh/checkout/api/uniformly/) | 必接 | 创建本地支付订单并获取支付推进参数 |
| 支付结果 | 通知 | [支付通知](/notes/zh/notify/payment/notify/) | 必接 | 接收最终支付结果并更新商户订单状态 |
| 支付结果 | API | [交易查询](/notes/zh/checkout/api/getOne/) | 推荐 | 在通知延迟、未达或需要补偿确认时主动核验交易状态 |
| 退款 | API | [申请退款](/notes/zh/checkout/api/modifications/refund/) | 按需 | 对成功支付的本地支付交易发起退款 |
| 退款 | 通知 | [退款通知](/notes/zh/notify/refundNotify/) | 推荐 | 接收退款结果并更新退款状态 |
| 退款 | API | [退款查询](/notes/zh/checkout/api/getRefund/) | 推荐 | 在通知延迟、未达或对账时主动确认退款状态 |
## 集成准备
开始开发前,请确认以下信息已经准备完成。
| 准备项 | 说明 |
|:---|:---|
| 账号信息 | 已获取 `clientId`、`accId`,并确认店铺状态可正常交易 |
| 支付方式 | 已开通本次需要接入的本地支付方式,并确认支持的国家、币种、金额范围和退款能力 |
| 签名能力 | 已根据 [签名规约](/notes/zh/onlinePayment/developer/sign/) 完成请求签名,所有请求参数都需要参与签名 |
| 验签能力 | 已能对 PingPongCheckout 返回响应和异步通知中的 `sign` 执行验签 |
| 通知地址 | 已准备公网可访问的 `notificationUrl`,用于接收支付结果异步通知 |
| 结果页地址 | 已准备 `payResultUrl`,用于跳转类支付方式完成后回到商户页面 |
| 订单状态处理 | 已在商户系统内保存 `merchantTransactionId`、`requestId`、`transactionId` 和订单状态,并支持幂等更新 |
::: tip 提示
不同本地支付方式可能要求额外字段,例如 `customer`、`goods`、`billingAddress`、`shippingAddress` 或特定 `device.orderTerminal`。请以目标支付方式页面和 [下单并支付](/notes/zh/checkout/api/uniformly/) 参数表为准。
:::
::: warning 注意
`notificationUrl` 必须是公网可访问的完整地址,不能填写 `localhost`、`127.0.0.1`、内网 IP,也不要在 URL 后携带 query 参数。
:::
## 集成步骤
请按以下步骤完成集成:
1. [步骤 1:展示可用支付方式](#步骤-1-展示可用支付方式)
2. [步骤 2:创建支付订单](#步骤-2-创建支付订单)
3. [步骤 3:根据 action 推进支付](#步骤-3-根据-action-推进支付)
4. [步骤 4:获取最终支付结果](#步骤-4-获取最终支付结果)
### 步骤 1:展示可用支付方式
在买家下单页面展示本次需要集成的支付方式标识和名称,供买家根据自身需求和偏好选择。支付方式列表页面需要由您的前端自行实现。
展示支付方式时,建议至少基于以下条件过滤:
| 条件 | 处理建议 |
|:---|:---|
| 交易国家 | 使用订单国家或买家结账国家匹配 `tradeCountry` |
| 交易币种 | 使用支付方式支持的 `currency`,金额精度参考 [交易币种](/notes/zh/appendix/transactionCurrency/) |
| 支付终端 | 根据 Web、WAP、App 等场景准备 `device.orderTerminal` |
| 支付方式类型 | 将买家选择的支付方式写入 `paymentMethod.type` |
### 步骤 2:创建支付订单
调用 [下单并支付](/notes/zh/checkout/api/uniformly/) 创建支付订单。您需要收集买家的支付方式、订单信息、设备信息、支付金额等,并由商户服务端提交支付请求。
支付请求关键参数:
| 参数 | 必填 | 说明 |
|:---|:---:|:---|
| `captureDelayHours` | M | 本地支付固定使用 `0`,表示立即 capture |
| `amount` | M | 交易金额 |
| `currency` | M | ISO 4217 三位交易币种 |
| `merchantTransactionId` | M | 商户网站订单流水号,订单唯一标识 |
| `requestId` | M | 支付请求流水号,全局唯一 |
| `tradeCountry` | M | 交易国家,使用 ISO 3166-1 alpha-2 国家码 |
| `shopperIP` | M | 买家下单 IP |
| `paymentMethod.type` | M | 买家选择的本地支付方式 |
| `goods` | M | 商品信息,至少包含 `goods[].name`、`goods[].unitPrice`、`goods[].number`、`goods[].imgUrl` |
| `device.orderTerminal` | M | 下单终端。`01` 移动端浏览器(WAP)、`02` PC 端浏览器(WEB)、`04` iOS App、`05` Android App |
| `notificationUrl` | O | 支付结果通知地址,建议传入 |
| `payResultUrl` | C | 跳转类支付完成后的商户结果页地址 |
| `merchantUserId` | M | 商户侧用户唯一 ID |
| `customer.email` | C | 用户邮箱。实物类商户必传;部分支付方式也可能要求传入,请以具体支付方式要求为准 |
| `customer.phone` | C | 用户手机号。部分本地支付方式会要求传入,请以具体支付方式要求为准 |
有关完整参数的更多信息,请参阅 [下单并支付](/notes/zh/checkout/api/uniformly/)。
支付请求示例(仅展示 `bizContent` 内容):
```json
{
"captureDelayHours": 0,
"amount": "1000",
"currency": "THB",
"merchantTransactionId": "ORDER_202606100001",
"requestId": "REQ_202606100001",
"tradeCountry": "TH",
"shopperIP": "203.0.113.10",
"merchantUserId": "USER_12345",
"notificationUrl": "https://www.example.com/checkout/notify",
"payResultUrl": "https://www.example.com/checkout/result",
"paymentMethod": {
"type": "TrueMoney Wallet"
},
"customer": {
"email": "buyer@example.com",
"phone": "66123456789"
},
"goods": [
{
"name": "Digital product",
"description": "Order item",
"sku": "SKU_001",
"imgUrl": "https://www.example.com/product/SKU_001.png",
"unitPrice": "1000",
"number": "1",
"virtualProduct": "Y"
}
],
"device": {
"orderTerminal": "02"
}
}
```
::: tip 提示
为便于阅读,本文示例将 `bizContent` 展开为 JSON 对象。实际请求时,请按照 [下单并支付](/notes/zh/checkout/api/uniformly/) 和 [签名规约](/notes/zh/onlinePayment/developer/sign/) 的要求处理 `bizContent` 和签名。
:::
响应关键字段:
| 参数 | 说明 |
|:---|:---|
| `transactionId` | PingPong 交易流水号 |
| `merchantTransactionId` | 商户网站订单流水号 |
| `requestId` | 支付请求流水号 |
| `status` | 交易状态 |
| `action` | 支付推进参数,买家需要继续操作时返回 |
响应示例(仅展示 `bizContent` 内容):
```json
{
"transactionId": "2026061050010001",
"merchantTransactionId": "ORDER_202606100001",
"requestId": "REQ_202606100001",
"amount": "1000.000000",
"currency": "THB",
"status": "PROCESSING",
"paymentMethod": {
"type": "TrueMoney Wallet"
},
"action": {
"type": "PAYMENT_REDIRECT_URL",
"paymentRedirectUrl": "https://sandbox-acquirer-static.pingpongx.com/payment/apm.html?token=example"
},
"payResultUrl": "https://www.example.com/checkout/result",
"transactionTime": "1781080205000",
"captureDelayHours": 0
}
```
下单响应中的 `status` 可能返回以下值,请根据指引进行处理:
| `status` | 说明 | 处理指引 |
|:---|:---|:---|
| `SUCCESS` | 同步响应已成功 | 商户服务端可以更新订单状态,但仍建议接收异步通知或查询结果做最终一致性校验 |
| `FAILED` | 支付失败 | 提示买家更换支付方式或重新发起支付 |
| `PROCESSING` | 支付处理中 | 若响应包含 `action`,继续执行步骤 3;同时等待异步通知或主动查询 |
### 步骤 3:根据 action 推进支付
当下单响应的 `status` 为 `PROCESSING` 且返回 `action` 时,前端需要根据 `action` 推进支付流程。本文以下以 `action.type=PAYMENT_REDIRECT_URL` 的跳转类支付方式为例说明。
| `action.type` | 关键字段 | 前端处理 |
|:---|:---|:---|
| `PAYMENT_REDIRECT_URL` | `action.paymentRedirectUrl` | 将用户重定向到该地址,让用户在对应支付方式页面完成支付 |
::: warning 支付推进注意事项
- `action.paymentRedirectUrl` 是 PingPongCheckout 返回的完整支付推进链接。商户前端应直接使用服务端返回的原始值,不要自行拼接额外参数,也不要替换域名或路径。
- 建议在顶层页面、系统浏览器或系统级网页容器中打开支付推进链接;如果必须在 `WKWebView` 或 `WebView` 中承载,请提前完成真机验证。
:::
商户服务端拿到 PingPong 返回的支付推进链接后,将该地址传递给前端,由商户前端跳转至支付方式页面。
以下为商户前端加载支付推进链接的示例代码:
::: tabs
@tab Web
```js
function redirectOnWeb(action) {
if (action?.type !== 'PAYMENT_REDIRECT_URL') return;
const paymentWindow = window.open(action.paymentRedirectUrl, '_blank');
if (!paymentWindow) {
window.location.assign(action.paymentRedirectUrl);
}
}
```
@tab WAP
```js
function redirectOnWap(action) {
if (action?.type !== 'PAYMENT_REDIRECT_URL') return;
window.location.href = action.paymentRedirectUrl;
}
```
@tab App (iOS)
```objc
// Objective-C 示例:
NSURL *url = [NSURL URLWithString:paymentRedirectUrl];
if (url) {
[[UIApplication sharedApplication] openURL:url
options:@{}
completionHandler:^(BOOL success) {
if (!success) {
// 引导买家重试或更换支付方式
}
}];
}
// Swift 示例:
guard let url = URL(string: paymentRedirectUrl) else { return }
UIApplication.shared.open(url, options: [:]) { success in
if !success {
// 引导买家重试或更换支付方式
}
}
```
@tab App (Android)
```java
// Java 示例:
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(paymentRedirectUrl));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
// Kotlin 示例:
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(paymentRedirectUrl))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
}
```
:::
### 步骤 4:获取最终支付结果
本地支付的最终结果,建议优先通过服务端异步通知确认。若异步通知延迟、未达、通知处理失败,或商户在买家回跳后需要立即核验结果,可再主动调用交易查询。交易查询的完整集成方案请参考 [支付后 > 查询交易](#查询交易)。
如果通过异步通知获取结果,商户服务端应优先返回 HTTP `2xx` 确认已接收,再根据通知中的 `status` 更新订单状态。
支付通知示例:
```json
{
"accId": "2023042011040310224447",
"clientId": "2023042011040310224",
"code": "000000",
"description": "Transaction succeeded",
"sign": "{{Sign}}",
"signType": "SHA256",
"bizContent": {
"amount": "1000.000000",
"currency": "THB",
"transactionId": "2026061050010001",
"merchantTransactionId": "ORDER_202606100001",
"requestId": "REQ_202606100001",
"notifyType": "RECHARGE",
"paymentMethod": {
"type": "TrueMoney Wallet"
},
"status": "SUCCESS",
"transactionTime": "1781080205000",
"transactionEndingTime": "1781080265000",
"captureDelayHours": 0
}
}
```
通知关键字段:
| 参数 | 说明 | 处理建议 |
|:---|:---|:---|
| `sign` / `signType` | 通知签名和签名类型 | 必须验签,验签通过后再处理业务 |
| `notifyType` | 通知类型,支付通知固定为 `RECHARGE` | 用于区分通知事件类型 |
| `transactionId` | PingPong 交易流水号 | 保存并用于后续查询、对账 |
| `merchantTransactionId` | 商户网站订单流水号 | 用于定位商户订单 |
| `requestId` | 支付请求流水号 | 用于定位本次支付请求 |
| `amount` / `currency` | 交易金额和币种 | 必须与商户订单金额、币种核对 |
| `status` | 支付结果状态 | 按状态更新商户订单 |
通知中的 `status` 建议按以下方式处理:
| `status` | 处理指引 |
|:---|:---|
| `SUCCESS` | 支付成功,可以进行发货、权益发放或订单完成处理 |
| `FAILED` | 支付失败,订单保持未支付或失败状态,可允许买家重新支付 |
| `CANCEL` | 支付取消或风控审核拒绝,订单不可按成功处理 |
| `CLOSED` | 订单已关闭,买家不能继续使用该订单支付 |
收到通知后,您无需对响应内容进行加签处理。但无论订单支付是否成功,均必须严格按照以下固定格式返回响应。
通知响应示例:
```http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 2
OK
```
## 支付后操作
以下内容介绍在支付流程推进后,如何通过服务端主动查询交易状态、处理退款及对账,帮助您实现稳定可靠的支付管理。
### 查询交易
当买家从支付页面跳回商户结果页、异步通知延迟、通知处理失败,或商户需要执行补偿任务时,可以调用 [交易查询](/notes/zh/checkout/api/getOne/) 获取交易最新状态。
交易查询请求示例(仅展示 `bizContent` 内容):
```json
{
"merchantTransactionId": "ORDER_202606100001",
"requestId": "REQ_202606100001"
}
```
交易查询响应示例(仅展示 `bizContent` 内容):
```json
{
"transactionId": "2026061050010001",
"merchantTransactionId": "ORDER_202606100001",
"requestId": "REQ_202606100001",
"amount": "1000.000000",
"currency": "THB",
"status": "SUCCESS",
"paymentMethod": {
"type": "TrueMoney Wallet"
},
"transactionTime": "1781080205000",
"transactionEndingTime": "1781080265000"
}
```
查询响应关键字段:
| 参数 | 处理方式 |
|:---|:---|
| `status` | 商户订单状态应以该字段为准 |
| `transactionId` | 保存为 PingPong 交易流水号,用于后续退款、对账或查询 |
| `amount` / `currency` | 与商户订单金额和币种核对 |
| `transactionEndingTime` | 交易到达终态时间,可用于订单完成时间记录 |
交易查询状态处理建议:
| `status` | 处理指引 |
|:---|:---|
| `SUCCESS` | 支付成功,可以完成订单 |
| `FAILED` | 支付失败,可允许买家重新支付 |
| `PROCESSING` | 支付处理中,继续等待异步通知或稍后查询 |
| `CANCEL` | 支付取消或风控审核拒绝,不可按成功处理 |
| `CLOSED` | 订单已关闭,买家不能继续使用该订单支付 |
### 退款
不同支付方式的退款能力不同,主要包括是否支持退款、退款有效期、是否支持部分退款以及是否支持多次部分退款。请参考 [支付方式](/notes/zh/paymentMethods/overview/) 页面或目标支付方式文档,确认具体退款能力。
支付成功后,如买家申请退款、商户取消已支付订单或需要退回部分或全部款项,您可以调用 [申请退款](/notes/zh/checkout/api/modifications/refund/) 对原交易发起退款。
PingPongCheckout 支持的退款能力如下:
- 支持全额退款,即一次性退回原交易可退金额。
- 支持部分退款,即单次退款金额可小于原交易金额。
- 支持多次部分退款,即同一笔交易可发起多笔退款;累计退款金额需小于等于原交易可退金额。
请参考 [Refund](/notes/zh/integrate/modify/Refund/) 了解退款集成方案。具体发起退款的请求参数、响应字段和处理规则,请参考 [申请退款](/notes/zh/checkout/api/modifications/refund/);若需要确认退款处理结果,请参考 [退款查询](/notes/zh/checkout/api/getRefund/)。
### 对账
如需了解账单生成规则与结算周期,可参考 [结算周期和对账单](/notes/zh/reconciliation/settlementCycle/);如需开通账单下载能力,可参阅 [SFTP服务申请](/notes/zh/reconciliation/transactionStatementDownload/)。