Payment 产品指南
余额查询、转账、交易查询、SWIFT 报文、法币账户和入账通知。接口细节见 API 参考。
概述
Stabo Payment OpenAPI 面向企业客户。通过本 API,可以实现以下功能:
- 账户管理:实时查询账户余额和状态
- 资金转账:支持行内转账、MEPS+ 本地转账、SWIFT 跨境汇款
- 交易查询:查询历史交易记录和转账状态
- 法币账户:开立法币收款账户,查询开户进度和收款信息
- 报文获取:获取 MT/MX SWIFT 报文原文
- 实时通知:通过 Webhook 接收入账等事件通知
版本:v1.7
接入准备、环境信息和鉴权见快速开始与鉴权。协议、统一响应格式见通用约定。
API 一览
| 模块 | 接口 | 说明 |
|---|---|---|
| 账户 | GET /openapi/v1/payments/balance | 余额查询 |
| 转账 | POST /openapi/v1/payments/transfer/intra-bank | 行内转账 |
| 转账 | GET /openapi/v1/payments/transfer/intra-bank/{referenceNo} | 行内转账结果查询 |
| 转账 | POST /openapi/v1/payments/transfer/meps | MEPS+ 转账 |
| 转账 | GET /openapi/v1/payments/transfer/meps/{referenceNo} | MEPS+ 转账结果查询 |
| 转账 | POST /openapi/v1/payments/transfer/swift | 跨境汇款 |
| 转账 | GET /openapi/v1/payments/transfer/swift/{referenceNo} | 跨境汇款结果查询 |
| 交易 | GET /openapi/v1/payments/transaction/history | 交易历史查询 |
| 交易 | GET /openapi/v1/payments/message/mtmx | MT/MX 报文查询 |
| 费用 | POST /openapi/v1/payments/fees/estimate | 查询转账预估手续费 |
| 渠道 KYC | GET /openapi/v1/customers/provider-kyc/requirements | 查询 KYC 提交要求 |
| 渠道 KYC | POST /openapi/v1/customers/provider-kyc | 提交 KYB |
| 渠道 KYC | GET /openapi/v1/customers/provider-kyc | 查询 KYC 状态 |
| 渠道 KYC | GET /openapi/v1/customers/provider-kyc/rfis | 查询 RFI 列表 |
| 渠道 KYC | GET /openapi/v1/customers/provider-kyc/rfis/{rfiId} | 查询 RFI 详情 |
| 渠道 KYC | POST /openapi/v1/customers/provider-kyc/rfis/{rfiId}/questions/{questionId}/idv-session | 创建 IDV 会话 |
| 渠道 KYC | POST /openapi/v1/customers/provider-kyc/rfis/{rfiId}/answers | 提交 RFI 答案 |
| 法币账户 | GET /openapi/v1/fiat-accounts/opening-options | 查询开户选项 |
| 法币账户 | POST /openapi/v1/fiat-accounts | 创建法币账户 |
| 法币账户 | GET /openapi/v1/fiat-accounts/{accountId} | 查询账户详情 |
| 数币钱包 | GET /openapi/v1/digital-wallets/assets | 查询支持的资产与网络 |
| 数币钱包 | POST /openapi/v1/digital-wallets | 创建数币钱包 |
| 数币钱包 | GET /openapi/v1/digital-wallets/{walletId} | 查询钱包详情 |
| 数币钱包 | POST /openapi/v1/digital-wallets/{walletId}/addresses | 生成充值地址 |
| 数币钱包 | GET /openapi/v1/digital-wallets/{walletId}/addresses | 查询充值地址列表 |
| Webhook | 商户配置的 HTTPS URL | 接收入账通知 va.credit.create |
| Webhook | 商户配置的 HTTPS URL | LEGEND 法币账户终态 fiat.account.activated、fiat.account.failed、fiat.account.closed。载荷只带少量字段,收款信息调用查询账户详情获取 |
| Webhook | 你配置的 HTTPS URL | 渠道侧 KYC 状态 provider.kyc.submitted、provider.kyc.approved、provider.kyc.rejected、provider.kyc.action_required。见渠道 KYC 与开户 |
每个接口的参数、响应和在线调试见 API 参考。
请求头
Payment 接口在通用约定的请求头之外,还需要 X-Channel-Provider。
| Header | 说明 | 是否必需 |
|---|---|---|
Authorization | Bearer {accessToken} | 是 |
Content-Type | application/json。GLDB 创建法币账户、提交 KYB、提交 RFI 答案用 multipart/form-data | 是,POST 请求必填 |
Idempotency-Key | 唯一请求标识,用于防止重复操作(建议使用 UUID)。规则见幂等性 | 是。三个转账 POST、LEGEND 创建法币账户、创建数币钱包、生成充值地址、提交 KYB、提交 RFI 答案必填。GLDB 创建法币账户不得传 |
X-Channel-Provider | 渠道提供商标识,如 GLDB | 是 |
业务数据基类字段
所有业务响应的 data 对象中都包含以下通用字段:
| 字段 | 说明 | 类型 | 示例 |
|---|---|---|---|
providerStatusCode | 渠道响应码 | String | 000000 |
providerMessage | 渠道响应消息 | String | ok |
providerRequestSerialNo | 渠道请求流水号 | String | 795883203712778240 |
providerResponseSerialNo | 渠道响应流水号 | String | 785957885476737024 |
providerTimestamp | 渠道请求时间戳 | String | 2023-05-17 21:03:48 |
错误响应
请以 HTTP 状态码判断请求是否成功,规则见错误码。渠道返回错误时,HTTP 状态码为 400,响应体中的 code 为 500,data 中带渠道返回的 provider* 字段:
{
"code": 500,
"message": "Operation failed",
"traceId": "trace-uuid-string",
"data": {
"providerStatusCode": "100019",
"providerMessage": "Version number is empty",
"providerRequestSerialNo": "795883203712778240",
"providerResponseSerialNo": "785957885476737024",
"providerTimestamp": "2023-05-17 21:03:48"
}
}渠道响应码
providerStatusCode 的取值由渠道决定。
GLDB 渠道响应码
| 响应码 | 说明 |
|---|---|
000000 | 成功 |
100019 | 版本号为空 |
100020 | 渠道序列号为空 |
100021 | 时间戳为空 |
101119 | 时间戳不匹配(超过 2 分钟) |
100111 | 字段长度超限 |
100017 | 接口不存在或状态异常 |
100004 | 签名验证失败 |
100067 | Payload 解密失败 |
100098 | 开发者应用状态异常 |
100060 | 开发者证书未找到 |
100099 | 发送下游系统异常 |
999999 | 未知异常 |
199999 | 下游系统返回错误 |
交易状态
| 状态 | 说明 |
|---|---|
SUCCESS | 成功 |
PROCESSING | 处理中 |
SENT_TO_BANK | 已发送至银行 |
FAILED | 失败 |
幂等性 (Idempotency)
Stabo API 支持幂等性,避免因网络中断等原因导致的操作重复(如重复扣款)。
机制说明:
- 三个转账
POST、LEGEND 创建法币账户、创建数币钱包和生成充值地址,必须在请求头中提供Idempotency-Key - GLDB 创建法币账户不支持
Idempotency-Key,传了会被拒绝。见法币账户 - 提交 KYB 和提交 RFI 答案也必填
Idempotency-Key,但重复提交不拒绝:渠道已受理时返回当前状态。见渠道 KYC 与开户 - 使用相同的
Idempotency-Key发送请求时,Stabo 只会处理一次 Idempotency-Key由客户端生成(建议使用 UUID),有效期为 24 小时GET请求天然幂等,不需要此 Header
上述每个请求必须使用唯一的 Idempotency-Key。切勿为不同操作复用同一个 Key。
在有效期内再次使用同一个 Idempotency-Key,请求会被拒绝(HTTP 400,message 为 Duplicate request detected),不会返回首次处理的结果。第一次请求仍在处理时,重复请求同样被拒绝。Key 在请求被受理时即被占用,首次请求失败也不会释放。超时或没收到响应时不要重新提交。转账用 referenceNo 查结果。创建账户或钱包用返回的 ID 查询。生成地址用地址列表查询。
余额查询
查询账户可用余额。accountNumber 和 currency 必填。
curl -G "https://api.test.stabofx.com/openapi/v1/payments/balance" \
-H "Authorization: Bearer {accessToken}" \
-H "X-Channel-Provider: GLDB" \
--data-urlencode "accountNumber=10000000001" \
--data-urlencode "currency=USD"响应示例:
{
"code": 200,
"message": "OK",
"traceId": "a1b2c3d4-e5f6-7890",
"data": {
"providerStatusCode": "000000",
"providerMessage": "ok",
"providerRequestSerialNo": "795883203712778240",
"providerResponseSerialNo": "785957885476737024",
"providerTimestamp": "2023-05-17 21:03:48",
"balance": "1000000.00",
"currency": "USD",
"status": "ACTIVE"
}
}status 取值:ACTIVE / CLOSED / INACTIVE / DORMANT。
行内转账
账户之间的行内转账,支持所有币种。适用于同一银行内不同账户间的资金调拨。
curl -X POST "https://api.test.stabofx.com/openapi/v1/payments/transfer/intra-bank" \
-H "Authorization: Bearer {accessToken}" \
-H "Content-Type: application/json" \
-H "X-Channel-Provider: GLDB" \
-H "Idempotency-Key: STABO20231121001" \
-d '{
"referenceNo": "STABO20231121001",
"fromAccount": "10000000001",
"beneficiaryAccount": "10000000002",
"currency": "SGD",
"amount": "200.00",
"remarks": "Payment for services"
}'响应示例:
{
"code": 200,
"message": "OK",
"traceId": "a1b2c3d4-e5f6-7890",
"data": {
"providerStatusCode": "000000",
"providerMessage": "ok",
"providerRequestSerialNo": "795883203712778240",
"providerResponseSerialNo": "785957885476737024",
"providerTimestamp": "2023-05-17 21:03:48",
"channelSerialNo": "742465990302056448",
"status": "SUCCESS",
"coreSerialNo": "FT23131QQQ2P",
"poboAccountNo": "10000000003",
"poboAccountName": "EXAMPLE PTE. LTD."
}
}注意事项
remarks仅支持字母数字、空格及特殊字符/ - ? : ( ) . , ' +- 当返回
PROCESSING状态时,请在 5 分钟后调用结果查询接口确认最终状态 - 走 POBO 出账的订单,响应会返回
poboAccountNo/poboAccountName;调用结果查询接口时建议传入accountNumber=poboAccountNo,以明确指定 POBO 出账账号。未传accountNumber时,系统将根据referenceNo自动匹配对应的 POBO 出账账号。
转账结果查询
三种转账都有对应的结果查询接口,参数和响应相同。转账返回 PROCESSING 时,调用结果查询接口获取最终结果。
# 普通订单 / POBO 出账订单
GET /openapi/v1/payments/transfer/intra-bank/STABO20231121001
# POBO 出账订单也可显式指定出账账号
GET /openapi/v1/payments/transfer/intra-bank/STABO20231121001?accountNumber=10000000003MEPS+ 转账
通过 MEPS+(MAS Electronic Payment System)进行新加坡本地实时转账。
特点:
- 仅支持 SGD 币种
- 实时到账
- 适用于大额本地转账
请求示例:
{
"referenceNo": "STABO20231121002",
"fromAccount": "10000000001",
"beneficiaryAccount": "10000000004",
"beneficiaryName": "Example Company",
"beneficiaryAddress": "1 Example Road, Singapore 000000",
"beneficiaryCountryCode": "SG",
"currency": "SGD",
"amount": "100.00",
"beneficiaryBankCode": "EXMPSGS0XXX",
"beneficiaryBankName": "EXAMPLE BANK LTD",
"purposeCode": "BEXP",
"chargeBearer": "SHA"
}purposeCode 和 chargeBearer 的取值见附录。
注意事项
beneficiaryName、beneficiaryAddress、remarks仅支持字母数字、空格及特殊字符/ - ? : ( ) . , ' +- 如收款银行非 MEPS+ 参与行,需提供中间行信息
- 走 POBO 出账的订单,响应会返回
poboAccountNo/poboAccountName;调用结果查询接口时建议传入accountNumber=poboAccountNo,以明确指定 POBO 出账账号。未传accountNumber时,系统将根据referenceNo自动匹配对应的 POBO 出账账号。
跨境汇款
通过 SWIFT 网络进行跨境汇款。注意:GLDB 渠道不支持 SGD 币种的跨境汇款。
请求示例:
{
"referenceNo": "STABO20231121003",
"fromAccount": "10000000001",
"beneficiaryAccount": "10000000005",
"beneficiaryName": "Example Company",
"beneficiaryAddress": "1 Example Road",
"beneficiaryCountryCode": "SG",
"beneficiaryCountryName": "Singapore",
"currency": "USD",
"amount": "1001.64",
"beneficiaryBankCode": "EXMPSGS0XXX",
"beneficiaryBankName": "EXAMPLE BANK LTD",
"chargeBearer": "SHA",
"purposeCode": "BEXP",
"remarks": "open transfer test"
}注意事项(GLDB 渠道)
- 不支持 SGD 币种
- BIC 代码不足 11 位需补充
X beneficiaryName、beneficiaryAddress、remarks仅支持字母数字、空格及特殊字符/ - ? : ( ) . , ' +- 走 POBO 出账的订单,响应会返回
poboAccountNo/poboAccountName;调用结果查询接口时建议传入accountNumber=poboAccountNo,以明确指定 POBO 出账账号。未传accountNumber时,系统将根据referenceNo自动匹配对应的 POBO 出账账号。
交易历史查询
查询账户的交易历史记录,支持分页查询。适用于对账和财务报表生成。
GET /openapi/v1/payments/transaction/history?accountNumber=10000000001¤cy=SGD&startDate=20240213&endDate=20240426¤tPage=1&pageSize=20amount 为正数表示收入,负数表示支出。pageSize 最大 100。transactionType 的取值见交易类型代码。
查询转账预估手续费
根据转账类型和金额,计算产生的预估手续费。请求体为 JSON。
请求示例:
{
"transferType": "SWIFT",
"amount": "100.00",
"currency": "USD",
"usdEquivalentAmount": "100.00",
"chargeOption": "SHA"
}fee 保留两位小数,向上进位。例如 1.221 会被算成 1.23。INTRA_BANK、MEPS、SWIFT SGD 的手续费币种为 SGD,非 SGD 的 SWIFT 为 USD。当前费用预估逻辑不依赖 chargeOption。
MT/MX 报文查询
查询转账交易关联的 MT/MX SWIFT 报文原文。适用于合规审计和问题排查。paymentReference 来自转账结果查询接口。
GET /openapi/v1/payments/message/mtmx?paymentReference=SGL24241GG0LJHCB&direction=OUTGOINGSWIFT 报文示例
以下是不同场景下返回的 messageContent 字段内容示例。示例中的机构、账号和参考号均为占位值。
入账通知 (va.credit.create)
账户收到入账资金时,Stabo 通过 Webhook 推送 va.credit.create 事件。
通知机制、重试策略、请求头、事件对象结构和签名验证与其他产品相同,见 Webhook。这里只说明本事件的载荷。Webhook-Event-Type 为 va.credit.create。
最佳实践:收到 Webhook 通知后,建议先返回 2xx 响应,再异步处理业务逻辑,避免处理超时导致重复推送。
data.object 字段说明
| 字段名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
transactionReference | String | Y | 交易参考号 |
tradeDate | String | Y | 交易日期,银行原始格式 yyyyMMdd,例如 20260528 |
tradeTime | String | Y | 交易时间,银行原始格式 HHmmssSSS,例如 101135517 表示 10:11:35.517 |
valueDate | String | Y | 起息日,银行原始格式 yyyyMMdd,例如 20260528 |
currency | String | Y | 币种 |
amount | String | Y | 金额 |
senderAccount | String | Y | 付款方账号 |
senderName | String | Y | 付款方名称 |
senderBankCode | String | N | 付款方银行代码 |
receiverAccount | String | Y | 收款方账号 |
receiverName | String | Y | 收款方名称 |
receiverBankCode | String | N | 收款方银行代码 |
remarks | String | N | 备注 |
direction | String | Y | 方向(INCOMING/OUTGOING) |
paymentReference | String | N | 支付参考号 |
source | String | Y | 来源(SWIFT/SWIFTMX/FAST/MEPS/INTERNAL) |
eventReference | String | Y | 事件参考号 |
accountNumber | String | Y | 账号 |
senderBankName | String | N | 付款方银行名称 |
masterAccountNo | String | N | 主账户号,仅多币种账户适用;单币种报文不携带该字段 |
示例 Payload
{
"id": "evt_1234567890",
"object": "event",
"type": "va.credit.create",
"created": 1712345678,
"data": {
"object": {
"transactionReference": "TXN0000000001",
"tradeDate": "20260528",
"tradeTime": "101135517",
"valueDate": "20260528",
"currency": "USD",
"amount": "20600.00",
"senderAccount": "123456789",
"senderName": "EXAMPLE SENDER PTE LTD",
"senderBankCode": "EXMPHKHHXXX",
"receiverAccount": "10000000001",
"receiverName": "EXAMPLE RECEIVER PTE LTD",
"receiverBankCode": "EXMBSGSGXXX",
"remarks": "INVOICE-0001",
"direction": "INCOMING",
"paymentReference": "SGL0000000000000",
"source": "SWIFTMX",
"eventReference": "00000000-0000-4000-8000-000000000001",
"accountNumber": "10000000001",
"senderBankName": "EXAMPLE BANK LIMITED",
"masterAccountNo": "10000000000"
}
}
}法币账户
法币账户通过请求头 X-Channel-Provider 指定渠道。当前支持 LEGEND 和 GLDB。
LEGEND 开户前,客户须在渠道完成 KYC 并取得 providerCustomerId。从 KYB 到开户的完整流程和示例见渠道 KYC 与开户。
两个渠道的请求格式和开户流程不同:
| 项目 | LEGEND | GLDB |
|---|---|---|
| 创建请求格式 | application/json | multipart/form-data,同时上传开户资料 |
Idempotency-Key | 必填 | 不得传。传了返回 fiat.account.idempotency_key.unsupported |
| 渠道专属字段 | providerCustomerId(必填)、bankCountry、alias、openingOptionId | accountName、contactName、contactEmail、contactPhone、companyRegistrationDoc(均必填),accountOpeningProof、otherDocuments(可选) |
| 开户流程 | 同步或异步,由渠道决定 | 人工审核。创建返回 PENDING,审核通过后为 ACTIVE |
| 查询开户选项 | 支持 | 不支持,返回 openapi.channel.unsupported |
| 查询账户详情 | providerCustomerId 必填 | 不得传 providerCustomerId。accountId 是申请单号 |
| 状态通知 | 终态推送 Webhook | 不推送 Webhook。轮询查询账户详情 |
currency两个渠道都必填,只能填一个币种。- 传了另一渠道专属的字段,返回
fiat.account.field.unsupported。 - 缺少本渠道必填字段,返回
fiat.account.field.required。
有的渠道同步开户,创建响应就是账户详情。有的渠道异步开户,创建只返回 PENDING。账户要到 ACTIVE 才能收款。
查询开户选项(可选,仅 LEGEND) → 创建法币账户(必要) → 查询账户详情(条件必要)| 步骤 | 接口 | 是否必要 | 说明 |
|---|---|---|---|
| 1 | 查询开户选项 | 可选,仅 LEGEND | 需要指定开户路由或提前确认费用时调用。不调用则由渠道自行选择路由。 |
| 2 | 创建法币账户 | 必要 | LEGEND 提交 JSON。若第 1 步选定了路由,把返回的 openingOptionId 传回。同步成功时,响应已是标准账户。GLDB 提交 multipart/form-data 并上传开户资料,响应为 PENDING。 |
| 3 | 查询账户详情 | 条件必要 | 创建返回 PENDING 时轮询到终态。GLDB 必须轮询。创建返回 fiat.account.channel.detail_unavailable 时,用消息里的账户 ID 查询,不要再次开户。创建已返回 ACTIVE 时不必再查。 |
PENDING 表示已受理但还不能收款。ACTIVE 至少带账号或 IBAN 其中一项。
接入时序示例
后续渠道的示例加在本节。
数币钱包
数币钱包通过请求头 X-Channel-Provider 指定渠道。
数币钱包是多资产容器,创建时不指定币种和网络。地址按资产逐个生成,钱包必须为 ACTIVE 才能生成地址。
查询资产(必要) → 创建钱包(必要) → 查询钱包(条件必要) → 生成充值地址(必要,按资产) → 查询地址列表(可选)| 步骤 | 接口 | 是否必要 | 说明 |
|---|---|---|---|
| 1 | 查询支持的资产与网络 | 必要 | 拿到可用的 assetCode。生成地址时要原样传回。 |
| 2 | 创建数币钱包 | 必要 | 创建多资产钱包。成功返回 ACTIVE,渠道仍在创建时返回 PENDING。 |
| 3 | 查询钱包详情 | 条件必要 | 仅当创建返回 PENDING 时轮询到 ACTIVE。创建已返回 ACTIVE 时不必再查。 |
| 4 | 生成充值地址 | 必要 | 钱包为 ACTIVE 后,按每个 assetCode 生成地址。渠道已有该资产地址时返回同一个 addressId。 |
| 5 | 查询充值地址列表 | 可选 | 查看已生成的地址与余额。钱包详情接口也会返回 addresses。 |
接入时序示例
后续渠道的示例加在本节。当前示例为 Legend。Legend 不提供钱包关闭回调,钱包状态以查询结果为准。
附录
费用承担方式、汇款目的代码、交易类型代码和国家代码见 Payment 附录。
常见问题与支持
Q: 如何确保转账不会重复执行?
A: 每次转账请求使用唯一的 Idempotency-Key。同一个 Key 只会被处理一次,有效期内再次提交会被拒绝。网络超时或没收到响应时,不要重新提交,用 referenceNo 调用结果查询接口确认状态,见幂等性。