On-Ramp

墨西哥 MXN 购买 USDT。收款账号开通与查询、报价、下单、查单、订单状态和 Webhook 事件。接口细节见 API 参考。

概述

On-Ramp 接口让商户代付款人用墨西哥比索(MXN)购买 USDT。付款人通过 SPEI 转账付款。订单完成后,USDT 记入商户在 Stabo 的钱包余额。

本期能力:

  • 收款账号:为付款人开通专属 CLABE,并查询开通状态
  • 报价:按 MXN 金额查询参考价
  • 下单:按 MXN 或 USDT 金额下单,返回付款人专属 CLABE 和付款指引
  • 查单:查询订单状态
  • 订单通知:订单完成或失败时,通过 Webhook 推送订单

本期范围:

项目取值
国家MX
法币MXN
付款方式SPEI
稳定币USDT
付款人类型个人

接口字段可能调整,调整时更新变更记录。

版本:v0.1

接入准备

  • 创建 API 密钥:在控制台「集成 → 密钥管理」新增密钥,获取 client_id、client_secret 和 tenant_id。详见快速开始
  • 开通功能:联系 Stabo 客户经理确认 On-Ramp 已开通。未开通时接口返回 On-ramp is not enabled
  • 配置 IP 白名单:在密钥的「修改 IP 白名单」中填写服务器出口 IP
  • 配置 Webhook(建议):在控制台「集成 → Webhooks」添加 HTTPS Endpoint,并订阅 onramp.order.completed、onramp.order.failed

鉴权方式、请求头和通用数据格式见快速开始、鉴权和通用约定。On-Ramp 接口不需要 X-Channel-Provider。商户身份从 Token 解析,请求体不接受商户或租户字段。

环境信息

环境Base URL说明
测试环境https://api.test.stabofx.com用于开发和测试
生产环境https://api.stabo.io正式生产环境

接入流程

开通收款账号

付款人注册或绑定时,调用开通收款账号接口。用查询收款账号接口确认状态为 ACTIVE。

查询报价

调用报价接口,展示参考价给付款人。报价不锁价,最终价格以下单响应为准。

创建订单

调用下单接口,拿到 paymentInfo.clabe 和应付金额 fiatAmount。

付款人转账

付款人在 expiresAt 之前,向 clabe 转账 fiatAmount MXN。

接收结果

接收 Webhook 通知,或轮询查单接口。状态变为 COMPLETED 时,cryptoAmount USDT 已记入商户钱包。

API 一览

模块接口说明
Receive AccountPOST /openapi/v1/collections/on-ramp/receive-accounts开通收款账号
Receive AccountGET /openapi/v1/collections/on-ramp/receive-accounts/{payerId}查询收款账号
QuoteGET /openapi/v1/collections/on-ramp/quote查询报价
OrderPOST /openapi/v1/collections/on-ramp/orders创建订单
OrderGET /openapi/v1/collections/on-ramp/orders/{orderId}查询订单
Webhook商户配置的 HTTPS URL接收订单完成、失败事件

每个接口的参数、响应和在线调试见 API 参考。

接口说明

开通收款账号

为付款人开通专属收款 CLABE。开通需要几分钟。请在付款人注册或绑定时调用,不要等到付款时再开户。

curl -X POST "https://api.test.stabofx.com/openapi/v1/collections/on-ramp/receive-accounts" \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -d '{
    "payerId": "payer-0001",
    "fiatCurrency": "MXN"
  }'

响应示例:

{
  "code": 200,
  "message": "OK",
  "traceId": "trace-uuid-string",
  "data": {
    "payerId": "payer-0001",
    "fiatCurrency": "MXN",
    "paymentMethod": "SPEI",
    "status": "PENDING",
    "clabe": null
  }
}

开通状态:

状态说明处理方式
PENDING开通中用查询收款账号接口查询,直到状态变为 ACTIVE 或 FAILED
ACTIVE已开通可以下单
FAILED开通失败提供 payerId 和 traceId 联系 Stabo

注意事项:

  • 本接口幂等。同一 payerId 重复调用,返回同一个收款账号的当前状态,不会重复开户。不需要 Idempotency-Key。
  • 开户不需要付款人 KYC。KYC 在下单时提交。
  • 本期不推送开户结果通知。请用查询收款账号接口查询,建议间隔 1 分钟以上。
  • 收款账号长期有效。同一付款人以后的订单都使用这个 CLABE。

查询收款账号

查询付款人收款账号的开通状态和 CLABE。payerId 为路径参数,fiatCurrency 为查询参数,固定 MXN。

curl -X GET "https://api.test.stabofx.com/openapi/v1/collections/on-ramp/receive-accounts/payer-0001?fiatCurrency=MXN" \
  -H "Authorization: Bearer {accessToken}"

响应结构与开通收款账号的响应相同。已开通时的响应示例:

{
  "code": 200,
  "message": "OK",
  "traceId": "trace-uuid-string",
  "data": {
    "payerId": "payer-0001",
    "fiatCurrency": "MXN",
    "paymentMethod": "SPEI",
    "status": "ACTIVE",
    "clabe": "706180000000000001"
  }
}

注意事项:

  • 只能查询本商户的付款人。没有开过户的 payerId 返回「收款账号不存在」。

查询报价

报价只支持按 MXN 金额查询。下单可以按 MXN(fiatAmount)或 USDT(cryptoAmount)金额。

curl -X GET "https://api.test.stabofx.com/openapi/v1/collections/on-ramp/quote?country=MX&fiatCurrency=MXN&cryptoCurrency=USDT&fiatAmount=954.77" \
  -H "Authorization: Bearer {accessToken}"

报价不生成报价 ID。下单时不需要传报价信息。

创建订单

Idempotency-Key 必填,最长 128 字符,建议用 UUID。fiatAmount 和 cryptoAmount 必须传且只传一个。示例中的付款人信息均为虚构数据。

curl -X POST "https://api.test.stabofx.com/openapi/v1/collections/on-ramp/orders" \
  -H "Authorization: Bearer {accessToken}" \
  -H "Idempotency-Key: 7f9c2a1e-0b6d-4c2f-9d7e-1a2b3c4d5e6f" \
  -H "Content-Type: application/json" \
  -d '{
    "referenceNo": "merchant-order-0001",
    "country": "MX",
    "fiatCurrency": "MXN",
    "cryptoCurrency": "USDT",
    "cryptoAmount": "50.000000",
    "payerId": "payer-0001",
    "payer": {
      "name": "Juan Perez Lopez",
      "email": "juan@example.com",
      "phone": "+5215512345678",
      "country": "MX",
      "address": "Av. Reforma 1, Ciudad de Mexico",
      "dateOfBirth": "1990-01-31",
      "idType": "NATIONAL_ID",
      "idNumber": "XEXX010101HNEXXXA4"
    },
    "payerAccount": {
      "accountType": "BANK",
      "accountNumber": "012180001234567891",
      "accountName": "Juan Perez Lopez"
    },
    "remark": "optional"
  }'

响应示例:

{
  "code": 200,
  "message": "OK",
  "traceId": "trace-uuid-string",
  "data": {
    "orderId": "bco_8f3k2m9q1x7z4t6w",
    "referenceNo": "merchant-order-0001",
    "status": "AWAITING_PAYMENT",
    "country": "MX",
    "fiatCurrency": "MXN",
    "fiatAmount": "954.77",
    "fiatFee": "13.50",
    "cryptoCurrency": "USDT",
    "cryptoAmount": "50.000000",
    "price": "18.8253",
    "paymentInfo": {
      "method": "SPEI",
      "clabe": "706180000000000001",
      "reference": "REF123456"
    },
    "payer": {
      "name": "Juan Perez Lopez"
    },
    "expiresAt": "2026-11-01T06:15:00Z",
    "createdAt": "2026-11-01T10:15:00+08:00",
    "completedAt": null,
    "failureReason": null
  }
}

注意事项:

  • 付款人必须在 expiresAt 之前,向 paymentInfo.clabe 转账 fiatAmount MXN。
  • 下单价格由渠道实时确定,可能与报价不同。以下单响应为准。
  • fiatAmount 和 cryptoAmount 必须传且只传一个。
  • 按 fiatAmount 下单时,到账 USDT 由渠道确认,记账金额以响应中的 cryptoAmount 为准。渠道确认前,cryptoAmount 可能为空。
  • paymentInfo 为空时,表示渠道收款还没确认。用同一 Idempotency-Key 重试下单,或稍后查单。
  • 渠道拒绝时,订单置为 FAILED。用同一 Idempotency-Key 重放会返回该 FAILED 订单。
  • 付款人 KYC 只用于转发给渠道。Stabo 不保存,也不在响应中返回证件号和联系方式。
  • 付款人的收款账号必须已开通,见开通收款账号。未开通时,下单返回「收款账号开通中」,不建单。

查询订单

curl -X GET "https://api.test.stabofx.com/openapi/v1/collections/on-ramp/orders/bco_8f3k2m9q1x7z4t6w" \
  -H "Authorization: Bearer {accessToken}"

响应结构与创建订单的响应相同。

注意事项:

  • 只能查询本商户的 On-Ramp 订单。其他订单返回「订单不存在」。
  • 建议以 Webhook 为主、查单为辅。轮询时建议间隔 30 秒以上,到达终态后停止。
  • Webhook 与查单结果不一致时,以查单结果为准。

订单状态

状态说明终态
AWAITING_PAYMENT等待付款人付款,或已付款等待记账否
COMPLETED已完成。USDT 已记入商户钱包是
FAILED失败、取消或超时是

付款人与收款账号

  • 每个付款人有一个专属收款 CLABE。商户用 payerId 标识付款人。
  • 同一商户的同一 payerId,总是对应同一个 CLABE。
  • payerId 由商户生成,1~64 位,只允许字母、数字、_、-。
  • payerId 不得使用邮箱、手机号、证件号等个人信息。
  • 请在付款人注册或绑定时,调用开通收款账号接口提前开户。开通需要几分钟,状态变为 ACTIVE 后才能下单。
  • 下单时收款账号还没开通,Stabo 会自动发起开户,下单返回「收款账号开通中」,不建单。这只是兜底,不要依赖它,否则付款人要在付款时等待开通。

幂等性

下单接口必须带 Idempotency-Key,最长 128 字符,建议用 UUID。

  • 同一商户内,Idempotency-Key 已存在时,返回原订单,不新建订单。
  • 重放时以首次请求的订单为准,不使用新请求体。
  • Idempotency-Key 永久有效,不会过期后重新可用。
  • 每笔新订单使用新的 Idempotency-Key。
  • 以下情况,用同一 Idempotency-Key 重试:请求超时、网络中断、返回「收款账号开通中」。
  • 以下情况,用新的 Idempotency-Key 重新下单:订单 FAILED。

通用规则见通用约定。

数据格式差异

On-Ramp 的金额精度与其他产品不同。

类型格式示例
金额十进制字符串。MXN 保留 2 位(四舍五入)。USDT 保留 6 位(向下截断)"954.77"、"50.000000"
汇率十进制字符串,表示 1 USDT 对应的 MXN"18.8253"
时间ISO 8601,带时区偏移。不同字段的偏移可能不同(如 Z 或 +08:00),请按偏移解析2026-11-01T10:15:00+08:00
国家ISO 3166-1 alpha-2MX

请求中的金额字段可以传数字或字符串。建议传字符串,避免浮点精度问题。

业务错误说明

错误响应格式见错误码。请以 HTTP 状态码判断成功与否,body 中的 code 不一定与 HTTP 状态码相同。

业务错误返回 HTTP 400,响应体 code 为 500。响应示例:

{
  "code": 500,
  "message": "The payer receive account is being opened. Please retry later with the same Idempotency-Key",
  "traceId": "trace-uuid-string",
  "data": {
    "errorCode": "onramp.receive_account.pending"
  }
}
HTTP 状态场景
200成功
400请求失败,包括参数校验失败和业务错误。响应体 code 为 500。参数校验失败:message 列出不合法的字段,例如 cryptoAmount must be greater than 0,data 为空。业务错误:data.errorCode 为错误码,见下表
401Token 无效或过期
403无权访问
500系统异常。保留 traceId 联系 Stabo。下单接口可用同一 Idempotency-Key 重试

联系 Stabo 排查问题时,请提供 traceId。

请按 data.errorCode 区分业务错误。message 只用于展示和排查,内容可能调整,不要用于程序判断。

错误errorCodemessage(英文)处理方式
功能未开通onramp.disabledOn-ramp is not enabled联系 Stabo 开通
参数不合法onramp.request.invalidThe on-ramp request is missing required fields or has an invalid format检查请求参数,见下方说明
缺少幂等键error.idempotent.key.missingIdempotency-Key header [Idempotency-Key] is required下单请求加上 Idempotency-Key 请求头
收款账号开通中onramp.receive_account.pendingThe payer receive account is being opened. Please retry later with the same Idempotency-Key收款账号还没开通。用查询收款账号接口查询,状态变为 ACTIVE 后,用同一 Idempotency-Key 重试下单
收款账号不存在onramp.receive_account.not_foundThe payer receive account does not exist先调用开通收款账号接口开户
收款账号开通失败onramp.receive_account.failedThe payer receive account could not be opened. Please contact operations联系 Stabo
渠道拒绝onramp.provider.rejectedThe provider rejected the request: {原因}订单已置为 FAILED。检查付款人信息后,用新的 Idempotency-Key 重新下单
订单不存在onramp.order.not_foundOn-ramp order not found检查 orderId
其他错误其他值—保留 traceId 联系 Stabo。下单接口可用同一 Idempotency-Key 重试

返回「参数不合法」的常见原因:

  • country、fiatCurrency、cryptoCurrency 不是 MX、MXN、USDT。
  • 报价请求没有 fiatAmount,或同时传了 cryptoAmount。
  • 下单请求同时传了 fiatAmount 和 cryptoAmount,或两个都没传。
  • 下单的 Idempotency-Key 已被该商户的其他收款业务使用。

Webhook 事件

订单进入终态时,Stabo 向商户配置的 Webhook 地址推送事件。

事件类型

事件类型触发时机
onramp.order.completed订单完成,USDT 已记入商户钱包。订单状态为 COMPLETED
onramp.order.failed订单失败、取消或付款超时。订单状态为 FAILED

通知机制

通知机制、请求头和签名验证与其他产品的 Webhook 相同,见 Webhook。

  • 请求方式:HTTPS POST,application/json。
  • 请求头:Webhook-Event-Id(事件唯一 ID)、Webhook-Event-Type(事件类型)、Webhook-Signature(签名,格式 t=timestamp,v1=signature)。
  • 签名:HMAC-SHA256,待签名字符串为 {Webhook-Event-Id}.{t}.{原始请求体}。商户必须验签。
  • 重试:响应不是 2xx 时,按 1 分钟、5 分钟、30 分钟、2 小时、6 小时重试。
  • 超时:30 秒。建议先返回 2xx,再异步处理。

事件对象结构

data.object 为订单对象,字段与创建订单的响应 data 相同。

{
  "id": "evt_1234567890",
  "object": "event",
  "type": "onramp.order.completed",
  "created": 1762151528,
  "data": {
    "object": {
      "orderId": "bco_8f3k2m9q1x7z4t6w",
      "referenceNo": "merchant-order-0001",
      "status": "COMPLETED",
      "country": "MX",
      "fiatCurrency": "MXN",
      "fiatAmount": "954.77",
      "fiatFee": "13.50",
      "cryptoCurrency": "USDT",
      "cryptoAmount": "50.000000",
      "price": "18.8253",
      "paymentInfo": {
        "method": "SPEI",
        "clabe": "706180000000000001",
        "reference": "REF123456"
      },
      "payer": {
        "name": "Juan Perez Lopez"
      },
      "expiresAt": "2026-11-01T06:15:00Z",
      "createdAt": "2026-11-01T10:15:00+08:00",
      "completedAt": "2026-11-01T10:32:08+08:00",
      "failureReason": null
    }
  }
}

注意事项

  • 用 Webhook-Event-Id 去重。同一事件可能因重试而重复送达。
  • onramp.order.failed 中,failureReason 为失败原因,completedAt 为空。
  • 订单在渠道确认前就失败时,fiatAmount、cryptoAmount、price、paymentInfo 可能为空。
  • 订单取消或超时后,付款人仍完成付款时,订单会变为 COMPLETED。商户会先后收到 onramp.order.failed 和 onramp.order.completed。请以最新事件和查单结果为准。

常见问题

错误与支持

通用错误口径见错误码。其他问题见常见问题。如需帮助,可通过 Stabo 客户经理或技术支持渠道联系,并提供 traceId。

本页目录