泰国支付 API(Thailand Payment API)
本文档描述 SoPay 在泰国的 商户对接 API:代收(Payin)、代付(Payout)、商户钱包与异步回调。
商户只需要对接 SoPay 平台 API,无需直接对接底层支付通道。泰国商户的国家与币种由商户号绑定,固定为 TH / THB,创建订单时无需传 countryCode、currency。
环境与地址
| 环境 | API Base(示例,以运维下发为准) |
|---|---|
| 生产 | https://api.soranopro.com |
| 沙盒 | https://sandbox-api.soranopro.com |
完整路径示例:POST {API_BASE}/api/v1/merchant/payin/create
详见 环境说明。
商户身份与密钥
| 项目 | 说明 |
|---|---|
商户号 merchantNo | 开户后分配,放在 Header X-Merchant-No |
| 商户 RSA 密钥对 | 商户私钥签名请求;公钥提交给平台 |
| 平台 RSA 公钥 | 用于验证平台异步回调签名 |
| 国家/币种 | 商户号绑定,泰国为 TH / THB |
鉴权与签名详见 签名与商户 API 规范。
请求头(商户 API)
| Header | 必填 | 说明 |
|---|---|---|
Content-Type | POST 必填 | application/json |
X-Merchant-No | 是 | 商户号 |
X-Timestamp | 是 | Unix 秒级时间戳 |
X-Nonce | 是 | 唯一随机串 |
X-Sign | 是 | RSA2 Base64 签名 |
API 一览
| 能力 | Method | Path |
|---|---|---|
| 创建代收 | POST | /api/v1/merchant/payin/create |
| 查询代收 | GET | /api/v1/merchant/payin/query |
| 创建代付 | POST | /api/v1/merchant/payout/create |
| 查询代付 | GET | /api/v1/merchant/payout/query |
| 商户钱包 | GET | /api/v1/merchant/wallet |
| 钱包流水 | GET | /api/v1/merchant/wallet/transactions |
泰国业务要点
| 项 | 说明 |
|---|---|
| 币种 | THB,金额最多 2 位小数 |
代收 bankCode | 当前仅支持 QR |
| 代收扩展字段 | extJson.accountNo 用于传递代收账户号 |
代付 bankCode | 必须填写本文档 代付 bankCode 枚举 中的编码 |
| 代付出款方式 | 响应 payoutMethod=BANK_TRANSFER |
| 扩展字段 | 使用 extJson(对象),不要使用 metadata |
历史字段 bankName | 兼容接收但不会参与路由、费率匹配或上游请求;新接入无需传递 |
| 回调地址 | 创建订单传 notifyUrl;为空时使用商户后台默认回调地址 |
bankCode 枚举
bankCode 是创建代收/代付订单时传给平台的 JSON 字段名。商户请求中只需要传 bankCode 的值,不需要传 BankId、银行名称 或 bankName。
| 订单类型 | 请求字段 | 可传值 | 说明 |
|---|---|---|---|
| 代收 Payin | bankCode | QR | 当前泰国代收只支持 QR |
| 代付 Payout | bankCode | 下方代付枚举表的 bankCode 列 | 例如政府储蓄银行传 GSB |
注意
bankCode 大小写敏感,请按文档枚举原样传递。BankId 和 银行名称 仅用于识别银行,不是商户请求字段。
代收 bankCode 枚举
| bankCode | 说明 |
|---|---|
QR | 泰国 QR 代收 |
代付 bankCode 枚举
| BankId | bankCode | 银行名称 |
|---|---|---|
1001 | BAAC | BANK FOR AGRICULTURE AND AGRICULTURAL COOPERATIVES |
1002 | BAY | BANK OF AYUDHYA PUBLIC COMPANY LIMITED |
1003 | BBL | BANGKOK BANK PUBLIC COMPANY LTD. |
1004 | CITI | CITIBANK, N.A. |
1005 | GHB | THE GOVERNMENT HOUSING BANK |
1006 | GSB | THE GOVERNMENT SAVINGS BANK |
1007 | KBANK | KASIKORNBANK PUBLIC COMPANY LTD. |
1008 | KTB | KRUNG THAI BANK PUBLIC COMPANY LTD. |
1009 | LHBANK | LAND AND HOUSES BANK PUBLIC COMPANY LIMITED |
1010 | SCB | SIAM COMMERCIAL BANK PUBLIC COMPANY LTD |
1012 | TISCO | TISCO BANK PUBLIC COMPANY LIMITED |
1014 | TTB | TMBTHANACHART BANK PUBLIC COMPANY LIMITED |
1015 | CIMB | CIMB THAI BANK PUBLIC COMPANY LTD. |
1023 | UOBT | UNITED OVERSEAS BANK (THAI) PUBLIC COMPANY LIMITED |
1018 | KKP | KIATNAKIN BANK PUBLIC COMPANY LIMITED |
创建代收订单
| 项目 | 值 |
|---|---|
| Method | POST |
| Path | /api/v1/merchant/payin/create |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
merchantOrderNo | string | 是 | 商户订单号,商户内唯一 |
amount | string/number | 是 | THB 金额,最多 2 位小数 |
bankCode | string | 是 | 固定传 QR |
notifyUrl | string | 否 | 为空则使用商户默认回调地址 |
remark | string | 否 | 订单备注 |
payer_mobile | string | 否 | 付款人手机号 |
payer_realname | string | 否 | 付款人姓名 |
payer_email | string | 否 | 付款人邮箱 |
payer_id_no | string | 否 | 付款人证件号 |
extJson.accountNo | string | 是 | QR 代收账户号 |
请求示例
{
"merchantOrderNo": "PAYIN-20260719-115013-002",
"amount": "1000",
"bankCode": "QR",
"notifyUrl": "https://merchant.example.com/callback/payin",
"remark": "",
"payer_mobile": "",
"payer_realname": "",
"payer_email": "",
"payer_id_no": "",
"extJson": {
"accountNo": "5555"
}
}响应示例
{
"code": 0,
"msg": "ok",
"data": {
"orderNo": "PI20260719035111d3d4b5",
"merchantOrderNo": "PAYIN-20260719-115013-002",
"amount": "1000",
"feeAmount": "50",
"netAmount": "950",
"status": "processing",
"payUrl": "https://card-h5-test.forapayhub.com/#/CEndRepayment?orderNo=PAYIN2078689080662335488",
"payQr": "https://card-h5-test.forapayhub.com/#/CEndRepayment?orderNo=PAYIN2078689080662335488",
"createdAt": 1784433071
}
}代收成功后,商户钱包增加 netAmount = amount - feeAmount。订单终态会通过 notifyUrl 推送回调。
创建代付订单
| 项目 | 值 |
|---|---|
| Method | POST |
| Path | /api/v1/merchant/payout/create |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
merchantOrderNo | string | 是 | 商户订单号,商户内唯一 |
amount | string/number | 是 | THB 金额,最多 2 位小数 |
bankCode | string | 是 | 代付银行编码,见 代付 bankCode 枚举 |
payee_realname | string | 是 | 收款人姓名 |
payee_account | string | 是 | 收款银行账号 |
payee_mobile | string | 建议 | 收款人手机号 |
payee_email | string | 建议 | 收款人邮箱 |
payee_id_no | string | 否 | 收款人证件号,可传空字符串 |
notifyUrl | string | 否 | 为空则使用商户默认回调地址 |
remark | string | 否 | 订单备注 |
extJson | object | 否 | 扩展信息;无扩展时传 {} |
历史字段
bankName可继续传入,平台会兼容接收但不会参与路由、费率匹配或上游请求;新接入请只传bankCode。
请求示例
{
"merchantOrderNo": "PAYOUT-20260719-115249-005",
"amount": "500",
"bankCode": "GSB",
"payee_realname": "NGUYEN VAN A",
"payee_account": "0123456789",
"payee_mobile": "84901234567",
"payee_email": "pay@example.com",
"payee_id_no": "",
"notifyUrl": "https://merchant.example.com/callback/payout",
"remark": "",
"extJson": {}
}响应示例
{
"code": 0,
"msg": "ok",
"data": {
"orderNo": "PO2026071904004225dc5a",
"merchantOrderNo": "PAYOUT-20260719-115249-005",
"amount": "500",
"feeAmount": "25",
"netAmount": "525",
"status": "processing",
"payoutMethod": "BANK_TRANSFER",
"createdAt": 1784433642
}
}代付创建成功后,平台冻结商户钱包 netAmount = amount + feeAmount。代付完成、失败或超时时会通过 notifyUrl 推送回调。
查询订单
查询代收
GET /api/v1/merchant/payin/query?orderNo={平台订单号}
或:
GET /api/v1/merchant/payin/query?merchantOrderNo={商户订单号}
查询代付
GET /api/v1/merchant/payout/query?orderNo={平台订单号}
或:
GET /api/v1/merchant/payout/query?merchantOrderNo={商户订单号}
回调通知
终态 completed / failed / timeout 时,平台会向订单 notifyUrl 或商户默认 callbackUrl 发起 POST JSON 回调。商户验签成功并处理完成后,请返回 HTTP 200,响应 body 为:
OK回调签名与字段说明见 异步回调指南。
手续费说明
| 类型 | 计费 | 商户侧金额 |
|---|---|---|
| 代收 Payin | feeAmount = amount × rate + fixed | 入账 netAmount = amount - feeAmount |
| 代付 Payout | feeAmount = amount × rate + fixed | 冻结/扣减 netAmount = amount + feeAmount |
具体费率由运营在后台为商户配置。
常见错误
| code | msg | 说明 |
|---|---|---|
40020 | invalid params | 请求参数错误或签名参数缺失 |
40304 | merchant order no already exists | 商户订单号重复 |
40306 | merchant balance insufficient | 商户可用余额不足,无法创建代付 |
40410 | unsupported bankCode | bankCode 不在当前商户支持列表中 |
50210 | payin failed / payout failed 或具体失败原因 | 创建订单失败 |
50213 | channel is under maintenance | 渠道维护中 |
完整错误码见 附录 · 错误码。
