商户沙盒联调说明

更新时间:2026-03-10

商户沙盒联调说明

💡 X2pay沙盒用于指导商户接入 ,完成签名、下单和订单查询联调。沙盒只模拟商户对接侧的 HTTP 行为,不代表真实资金流 更新时间:2026-03-10

1. 沙盒范围

当前沙盒支持以下接口:

  • POST /api/v1/payin:创建收款订单
  • POST /api/v1/payout:创建付款订单
  • GET /api/v1/payments:查询订单列表
  • GET /api/v1/payments/{payment_id}:查询订单详情
  • GET /health:健康检查

如果创建订单时传入了 notify_url,沙盒还会模拟发送异步回调。

2. 地址与测试凭证

默认地址:

https://sandbox.x2pay.eu.org

测试凭证由对接方提供:

  • ApiKey
  • ApiSecret
  • AppId

请求中的 app_id 必须等于分配的 AppId

3. 请求头与签名

必填请求头

  • X-API-Key
  • X-Signature
  • X-Timestamp(Unix 秒或毫秒时间戳)
  • X-Nonce(长度建议不少于 16,且不可重复)

可选请求头

  • X-Request-ID

签名算法

1. 收集参与签名的参数
2. 按参数名升序排序
3. 拼接为 key1=value1&key2=value2...
4. signature = hex(hmac_sha256(ApiSecret, canonical_string))

参与签名的字段

  • 所有 URL Query 参数
  • 固定字段:
    • api_key:请求头 X-API-Key
    • timestamp:请求头 X-Timestamp
    • nonce:请求头 X-Nonce
    • method:大写 HTTP 方法,如 POSTGET
    • path:请求路径,如 /api/v1/payin
  • 当请求方法为 POSTPUT 时,额外加入:
    • content_type:请求的媒体类型,例如 application/json
  • 当请求体非空时,额外加入:
    • body_sha256:原始请求体的 SHA256 小写十六进制

说明:

  • 所有参与字段按参数名升序排序
  • 空值字段不参与拼接
  • 使用 key=value 形式拼接,并以 & 连接
  • 如果 Content-Type 请求头带参数,例如 application/json; charset=utf-8,签名时使用 application/json
  • 时间偏差允许 ±5 分钟

4. 沙盒场景控制

可通过请求头 X-Sandbox-Scenario 指定沙盒场景:

  • PENDING
  • PROCESSING
  • SUCCESS
  • FAILED

未传时默认使用 PENDING

场景行为说明:

  • PENDING:创建后保持 PENDING,不自动流转,不主动回调
  • PROCESSING:创建后保持 PROCESSING,不自动流转,不主动回调
  • SUCCESS:创建后先进入中间态,3 秒后自动流转为成功并发送成功回调
  • FAILED:创建后先进入中间态,3 秒后自动流转为失败并发送失败回调

中间态规则:

  • PAY_INSUCCESS / FAILED 场景下,创建接口先返回 PENDING
  • PAY_OUTSUCCESS / FAILED 场景下,创建接口先返回 PROCESSING

同一 app_id + merchant_tx_id 的幂等规则与正式接口一致:

  • 金额相同:返回首次创建结果
  • 金额不同:返回错误码 2002

5.1 沙盒异步回调

当创建订单成功、请求体包含 notify_url,且场景最终会流转到终态(SUCCESSFAILED)时,沙盒会在约 3 秒后向该地址发送一条模拟通知。

回调请求头

  • Content-Type: application/json
  • X-Signature
  • X-Event-Type
  • X-Notification-ID
  • X-Timestamp(Unix 秒级时间戳)

回调验签

沙盒使用当前测试凭证中的 ApiSecret 作为回调签名密钥:

signature = hex(hmac_sha256(ApiSecret, raw_body))

事件类型映射

  • SUCCESS -> PAYMENT_SUCCESS
  • FAILED -> PAYMENT_FAILED
  • 其他状态 -> PAYMENT_PENDING

回调 payload 对齐说明

  • 会按正式通知字段返回 end_to_endqrCodeerrorCode
  • 创建订单时传入了 extra,回调中会原样透传;若是 JSON 字符串,会按 JSON 结构返回
  • PAY_IN 订单在 PENDINGPROCESSINGSUCCESS 场景下会生成模拟 qrCode
  • FAILED 场景会返回模拟 errorCode

6. 创建订单示例

收款:

curl -X POST "http://sandbox.x2pay.eu.org/api/v1/payin" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {ApiKey}" \
  -H "X-Signature: {Signature}" \
  -H "X-Timestamp: {Timestamp}" \
  -H "X-Nonce: {Nonce}" \
  -H "X-Sandbox-Scenario: SUCCESS" \
  -d '{
    "app_id": "{AppId}",
    "merchant_tx_id": "order_10001",
    "amount": 10000,
    "currency": "BRL",
    "subject": "Sandbox Test"
  }'

付款:

curl -X POST "http://sandbox.x2pay.eu.org/api/v1/payout" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {ApiKey}" \
  -H "X-Signature: {Signature}" \
  -H "X-Timestamp: {Timestamp}" \
  -H "X-Nonce: {Nonce}" \
  -H "X-Sandbox-Scenario: PROCESSING" \
  -d '{
    "app_id": "{AppId}",
    "merchant_tx_id": "order_10002",
    "amount": 20000,
    "currency": "BRL",
    "account_name": "Maria Silva",
    "account_number": "pix-key-001"
  }'

7. 查询订单示例

先按列表查找:

curl -X GET "http://sandbox.x2pay.eu.org/api/v1/payments?merchant_tx_id=order_10001" \
  -H "X-API-Key: {ApiKey}" \
  -H "X-Signature: {Signature}" \
  -H "X-Timestamp: {Timestamp}" \
  -H "X-Nonce: {Nonce}"

再按 payment_id 查详情:

curl -X GET "http://sandbox.x2pay.eu.org/api/v1/payments/pay_abcd1234" \
  -H "X-API-Key: {ApiKey}" \
  -H "X-Signature: {Signature}" \
  -H "X-Timestamp: {Timestamp}" \
  -H "X-Nonce: {Nonce}"

查询详情验签时,path 必须使用完整动态路径,例如:

/api/v1/payments/pay_abcd1234

如果查询请求带 Query 参数,这些 Query 参数也必须一并加入签名后再排序拼接。

8. 返回规则

成功时:

  • 返回 HTTP 200
  • 响应体 code = "0"

失败时:

  • 返回与正式接口一致的 HTTP 错误状态(如 400401404
  • 响应体中仍会携带业务错误码

创建/查询成功示例:

{
  "code": "0",
  "message": "success",
  "request_id": "req_xxx",
  "data": {
    "payment_id": "pay_xxx",
    "app_id": "app_xxx",
  "merchant_tx_id": "order_10001",
  "transaction_type": "PAY_IN",
  "amount": 10000,
  "currency": "BRL",
  "end_to_end": "e2e_xxx",
  "qrCode": "000201010212...",
  "errorCode": "",
    "status": "PENDING",
    "created_at": "2026-03-03T12:00:00Z",
    "updated_at": "2026-03-03T12:00:00Z",
    "expired_at": "2026-03-03T12:30:00Z"
  }
}

上例表示:当使用 X-Sandbox-Scenario: SUCCESS 创建一笔 PAY_IN 订单时,创建接口会先返回 PENDING,约 3 秒后再流转为 SUCCESS 并触发回调。

失败示例:

{
  "code": "1006",
  "message": "invalid signature",
  "request_id": "req_xxx"
}

9. 常见问题

  • invalid api keyX-API-Key 不正确或已禁用
  • invalid app_id:请求体 app_id 与分配值不一致
  • invalid signature:签名字段、排序顺序、路径、content_type、Query 参数或 body_sha256 与实际请求不一致
  • timestamp expired:本机时间与沙盒时间偏差过大
  • nonce already usedX-Nonce 重复
  • duplicate merchant_tx_id with different amount:同一订单号重复提交但金额变更
  • payment not foundpayment_id 不存在,或不属于当前 AppId

········································································

| accountType | pix类型 | 是 | string | 是 | EMAIL/PHONE/CPF/CNPJ/EVP |

说明:CPF:11位数字; PHONE:11位数字(加前缀’+55’); EMAIL:邮箱格式; CNPJ:14位数;EVP: uuid格式