沙盒测试
什么是沙盒?
沙盒是您账户的测试模式 — 不是单独的环境。它使用与生产环境相同的 API、相同的基础 URL 和相同的端点。区别在于您的沙盒账户连接到模拟银行提供商:交易即时处理,不会进行真实资金转账,也不会向 BACEN 发送 PIX。
沙盒和生产是独立的账户,每个账户都有自己的凭证(证书、clientId、clientSecret)。您的证书可以在两个账户之间共享,具体取决于配置 — 请咨询您的客户经理。
您的代码在沙盒和生产之间不需要更改。 当您准备上线时,只需切换到生产账户的凭证即可。无需更改端点,无需更改代码。
沙盒 vs 生产
| 沙盒 | 生产 | |
|---|---|---|
| 基础 URL | 相同 (https://api.avista.global) | 相同 |
| 账户 | 专用沙盒账户 | 专用生产账户 |
| 凭证 | 独立的证书 + clientId/clientSecret | 独立的证书 + clientId/clientSecret |
| 余额 | 模拟(虚拟) | 真实资金 |
| 交易 | 模拟(已持久化 — 可通过 API 查询) | 通过 BACEN 的真实 PIX |
| Webhooks | 模拟(~1秒送达),相同的 payload 结构 | 真实,送达取决于提供商 |
| X-Sandbox-Scenario | 支持(控制 webhook 结果) | 返回 400 Bad Request |
| 文档 | 与生产相同 — 所有 API Reference 页面均适用 | 相同 |
开始使用沙盒
联系您的客户经理或 suporte@avista.global 申请沙盒账户。
您将收到沙盒账户的证书和 OAuth 凭证(clientId + clientSecret)。
通过 POST /api/webhooks 注册您的 webhook URL,以便接收模拟的 webhook 事件。
在控制面板中,前往设置确认您的账户已配置为沙盒模式。
进行身份验证,调用 API,并使用 X-Sandbox-Scenario 请求头模拟不同的结果。
概述
X-Sandbox-Scenario 请求头允许您控制任何交易的 webhook 结果。不使用该请求头时,沙盒始终返回成功 webhook。使用它来测试错误处理、延迟和边缘情况。
不发送 X-Sandbox-Scenario 请求头时,沙盒始终返回成功 webhook。 要测试错误场景(余额不足、无效密钥等),您必须在每个请求中显式发送该请求头。
此功能仅在沙盒环境中有效。在生产环境中,该请求头将被忽略,行为由实际交易结果决定。
工作原理
X-Sandbox-Scenario 不会改变 HTTP 响应 -- API 始终返回 201 Created,状态为 "PENDING"。模拟的场景仅影响发送到您回调 URL 的异步 webhook。
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ 您的应用 │──POST──▶│ Avista API │──────▶ │ Mock 提供商 │
│ │◀──201───│ │ │ │
│ │ │ │ │ 处理请求头中 │
│ │ │ │ │ 指定的场景 │
│ │ │ │ │ │
│ │◀────────│──webhook─────│◀────────│ │
│ │ │ │ │ 约 1 秒后 │
└─────────────┘ └──────────────┘ └─────────────────┘
│ │
│ HTTP 响应:始终 201 │
│ Webhook:成功或错误 │
│ (取决于请求头) │| 请求 | HTTP 响应 | 收到的 Webhook |
|---|---|---|
不含 X-Sandbox-Scenario | 201 PENDING | CONFIRMED(成功) |
含 X-Sandbox-Scenario: success | 201 PENDING | CONFIRMED(成功) |
含 X-Sandbox-Scenario: error:insufficient-funds | 201 PENDING | ERROR 带 errorCode |
含 X-Sandbox-Scenario: delayed:5s | 201 PENDING | CONFIRMED 额外延迟 5 秒后 |
如何使用
在任何 Cash-In、Cash-Out 或退款请求中添加 X-Sandbox-Scenario 请求头:
curl -X POST https://api.avista.global/api/pix/cash-out \
-H "Authorization: Bearer $TOKEN" \
-H "X-Sandbox-Scenario: error:insufficient-funds" \
-H "Content-Type: application/json" \
-d '{
"value": 150.00,
"details": {
"key": "recipient@email.com",
"keyType": "EMAIL",
"name": "Recipient Name",
"document": "39284918812"
},
"externalId": "test-error-001"
}'const response = await axios.post(
'https://api.avista.global/api/pix/cash-out',
{
value: 150.00,
details: {
key: 'recipient@email.com',
keyType: 'EMAIL',
name: 'Recipient Name',
document: '39284918812',
},
externalId: 'test-error-001',
},
{
headers: {
Authorization: `Bearer ${token}`,
'X-Sandbox-Scenario': 'error:insufficient-funds',
},
}
);response = requests.post(
"https://api.avista.global/api/pix/cash-out",
json={
"value": 150.00,
"details": {
"key": "recipient@email.com",
"keyType": "EMAIL",
"name": "Recipient Name",
"document": "39284918812",
},
"externalId": "test-error-001",
},
headers={
"Authorization": f"Bearer {token}",
"X-Sandbox-Scenario": "error:insufficient-funds",
},
)可用场景
错误场景
模拟不同类型的 webhook 失败:
| 请求头值 | 描述 | Webhook 状态 |
|---|---|---|
error:insufficient-funds | 账户余额不足 | ERROR |
error:invalid-pix-key | PIX 密钥在 DICT 中不存在 | ERROR |
error:document-mismatch | 证件号与密钥持有人不匹配 | ERROR |
error:account-blocked | 目标账户被冻结或已关闭 | ERROR |
error:duplicate-id | 重复的提交 ID | ERROR |
成功场景
| 请求头值 | 描述 | Webhook 状态 |
|---|---|---|
success | 强制成功(默认行为) | CONFIRMED |
| (不传请求头) | 默认沙盒行为 | CONFIRMED |
延迟场景
模拟慢处理以测试超时和重试:
| 请求头值 | 描述 | Webhook 状态 |
|---|---|---|
delayed:5s | 额外延迟 5 秒后成功 | CONFIRMED |
delayed:30s | 额外延迟 30 秒后成功 | CONFIRMED |
delayed:60s | 额外延迟 60 秒后成功 | CONFIRMED |
最大允许延迟为 120 秒。超过此值将自动截断。
收到的 Webhook 示例
成功 Webhook(默认)
{
"event": "CashOut",
"status": "CONFIRMED",
"transactionType": "PIX",
"movementType": "DEBIT",
"transactionId": "12345",
"externalId": "test-success-001",
"endToEndId": "E17745159XI4QA0EGFU",
"feeAmount": 0.50,
"originalAmount": 150.00,
"finalAmount": 150.50,
"processingDate": "2026-03-26T10:00:00.000Z",
"errorCode": null,
"errorMessage": null,
"counterpart": {
"name": "Recipient Name",
"document": "*.284.918-**",
"bank": {}
},
"metadata": {}
}错误 Webhook (error:insufficient-funds)
{
"event": "CashOut",
"status": "ERROR",
"transactionType": "PIX",
"movementType": "DEBIT",
"transactionId": "12345",
"externalId": "test-error-001",
"endToEndId": null,
"feeAmount": 0.50,
"originalAmount": 150.00,
"finalAmount": 150.50,
"processingDate": "2026-03-26T10:00:00.000Z",
"errorCode": "INSUFFICIENT_FUNDS",
"errorMessage": "Conta sem saldo",
"counterpart": {
"name": null,
"document": null,
"bank": {}
},
"metadata": {}
}当状态为 ERROR 时,endToEndId 字段为 null(因为 PIX 从未被中央银行确认),errorCode 和 errorMessage 字段描述失败原因。
兼容端点
X-Sandbox-Scenario 请求头适用于所有交易端点:
| 端点 | 方法 | 描述 |
|---|---|---|
/api/pix/cash-in | POST | 生成 PIX 收款(二维码) |
/api/pix/cash-out | POST | 按密钥发送 PIX 付款 |
/api/pix/cash-out/qrcode | POST | 按二维码发送 PIX 付款 |
/api/pix/refund-in | POST | 退款请求 |
MED 场景
MED(特殊退款机制)模块无法直接通过 X-Sandbox-Scenario 进行测试。MED 依赖于与 BACEN 以及已配置的 PIX 提供方(Woovi、Hyperwallet 等)的集成,因此无法由沙盒的 mock 提供方模拟。
要验证您对 MED webhook(MedCreated、MedAccepted、MedRejected)的集成,请使用以下方法:
使用 POST /api/webhooks/{id}/resend 将账户中已存在的 MED webhook 重新发送到已配置的 URL。这对于在变更后在本地调试处理器非常有用。
使用 GET /api/med 列出与账户关联的 MED,按状态筛选,并与本地交易进行对账。
如果您需要端到端模拟 MED 流程(开启、分析、批准/拒绝),请联系 suporte@avista.global 申请预生产环境的访问权限。
MED webhook 使用与其他事件相同的认证方式(Basic Auth)和重试机制。完整 payload 已记录在 MedCreated、MedAccepted 和 MedRejected 中。
行为
API 正常处理请求并返回 201 Created,状态为 PENDING。
请求头不会改变即时响应 -- 仅影响后续的 webhook。
约 1 秒后(或更长时间,如果使用 delayed:),webhook 会发送到配置的 URL,包含模拟的场景。
您的系统收到 webhook,状态对应场景(CONFIRMED 或 ERROR),应相应处理。
重要: X-Sandbox-Scenario 请求头仅控制 webhook。端点的 HTTP 响应始终返回成功(201 Created),状态为 "PENDING",无论选择哪个场景。最终结果(成功或错误)通过 webhook 送达。
限制
X-Sandbox-Scenario 请求头仅适用于配置为沙盒模式的账户。如果您的账户配置了生产提供商并发送此请求头,API 将返回错误:
{
"statusCode": 400,
"message": "X-Sandbox-Scenario header is only supported in sandbox mode. This account is not configured with a sandbox provider."
}使用此功能前,请确保您的账户处于沙盒模式。如果收到此错误,请联系 suporte@avista.global 验证您的账户配置。
最佳实践
测试所有场景
在上线生产前,实现对每种 webhook 状态(CONFIRMED、PENDING、ERROR)的处理。
验证错误字段
当 status 为 ERROR 时,使用 errorCode 和 errorMessage 确定适当的操作(重试、通知用户等)。
测试延迟
使用 delayed: 场景验证您的系统能正确处理延迟到达的 webhooks。
幂等性
使用 transactionId 作为幂等键。在交付失败的情况下,相同的 webhook 可能会被重新发送。