商户沙盒联调说明
更新时间: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
测试凭证由对接方提供:
ApiKeyApiSecretAppId
请求中的 app_id 必须等于分配的 AppId。
3. 请求头与签名
必填请求头
X-API-KeyX-SignatureX-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-Keytimestamp:请求头X-Timestampnonce:请求头X-Noncemethod:大写 HTTP 方法,如POST、GETpath:请求路径,如/api/v1/payin
- 当请求方法为
POST或PUT时,额外加入:content_type:请求的媒体类型,例如application/json
- 当请求体非空时,额外加入:
body_sha256:原始请求体的SHA256小写十六进制
说明:
- 所有参与字段按参数名升序排序
- 空值字段不参与拼接
- 使用
key=value形式拼接,并以&连接 - 如果
Content-Type请求头带参数,例如application/json; charset=utf-8,签名时使用application/json - 时间偏差允许 ±5 分钟
4. 沙盒场景控制
可通过请求头 X-Sandbox-Scenario 指定沙盒场景:
PENDINGPROCESSINGSUCCESSFAILED
未传时默认使用 PENDING。
场景行为说明:
PENDING:创建后保持PENDING,不自动流转,不主动回调PROCESSING:创建后保持PROCESSING,不自动流转,不主动回调SUCCESS:创建后先进入中间态,3 秒后自动流转为成功并发送成功回调FAILED:创建后先进入中间态,3 秒后自动流转为失败并发送失败回调
中间态规则:
PAY_IN在SUCCESS/FAILED场景下,创建接口先返回PENDINGPAY_OUT在SUCCESS/FAILED场景下,创建接口先返回PROCESSING
同一 app_id + merchant_tx_id 的幂等规则与正式接口一致:
- 金额相同:返回首次创建结果
- 金额不同:返回错误码
2002
5.1 沙盒异步回调
当创建订单成功、请求体包含 notify_url,且场景最终会流转到终态(SUCCESS 或 FAILED)时,沙盒会在约 3 秒后向该地址发送一条模拟通知。
回调请求头
Content-Type: application/jsonX-SignatureX-Event-TypeX-Notification-IDX-Timestamp(Unix 秒级时间戳)
回调验签
沙盒使用当前测试凭证中的 ApiSecret 作为回调签名密钥:
signature = hex(hmac_sha256(ApiSecret, raw_body))
事件类型映射
SUCCESS->PAYMENT_SUCCESSFAILED->PAYMENT_FAILED- 其他状态 ->
PAYMENT_PENDING
回调 payload 对齐说明
- 会按正式通知字段返回
end_to_end、qrCode、errorCode - 创建订单时传入了
extra,回调中会原样透传;若是 JSON 字符串,会按 JSON 结构返回 PAY_IN订单在PENDING、PROCESSING、SUCCESS场景下会生成模拟qrCodeFAILED场景会返回模拟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 错误状态(如
400、401、404) - 响应体中仍会携带业务错误码
创建/查询成功示例:
{
"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 key:X-API-Key不正确或已禁用invalid app_id:请求体app_id与分配值不一致invalid signature:签名字段、排序顺序、路径、content_type、Query 参数或body_sha256与实际请求不一致timestamp expired:本机时间与沙盒时间偏差过大nonce already used:X-Nonce重复duplicate merchant_tx_id with different amount:同一订单号重复提交但金额变更payment not found:payment_id不存在,或不属于当前AppId
········································································
| accountType | pix类型 | 是 | string | 是 | EMAIL/PHONE/CPF/CNPJ/EVP |
说明:CPF:11位数字; PHONE:11位数字(加前缀’+55’); EMAIL:邮箱格式; CNPJ:14位数;EVP: uuid格式