Safira Paydocs
集成指南

沙盒测试

概述

沙盒环境允许您模拟不同的 webhook 场景,而不影响真实交易。在任何请求中使用 X-Sandbox-Scenario 请求头来控制收到的 webhook 结果。

此功能仅在沙盒环境中有效。在生产环境中,该请求头将被忽略,行为由实际交易结果决定。

如何使用

在任何 Cash-In、Cash-Out 或退款请求中添加 X-Sandbox-Scenario 请求头:

curl -X POST https://api.safirapay.com/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.safirapay.com/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.safirapay.com/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-keyPIX 密钥在 DICT 中不存在ERROR
error:document-mismatch证件号与密钥持有人不匹配ERROR
error:account-blocked目标账户被冻结或已关闭ERROR
error:duplicate-id重复的提交 IDERROR

成功场景

请求头值描述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 从未被中央银行确认),errorCodeerrorMessage 字段描述失败原因。

兼容端点

X-Sandbox-Scenario 请求头适用于所有交易端点:

端点方法描述
/api/pix/cash-inPOST生成 PIX 收款(二维码)
/api/pix/cash-outPOST按密钥发送 PIX 付款
/api/pix/cash-out/qrcodePOST按二维码发送 PIX 付款
/api/pix/refund-inPOST退款请求

行为

API 正常处理请求并返回 201 Created,状态为 PENDING。 请求头不会改变即时响应 -- 仅影响后续的 webhook。

约 1 秒后(或更长时间,如果使用 delayed:),webhook 会发送到配置的 URL,包含模拟的场景。

您的系统收到 webhook,状态对应场景(CONFIRMEDERROR),应相应处理。

重要: 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@safirapay.com 验证您的账户配置。

最佳实践

测试所有场景

在上线生产前,实现对每种 webhook 状态(CONFIRMEDPENDINGERROR)的处理。

验证错误字段

statusERROR 时,使用 errorCodeerrorMessage 确定适当的操作(重试、通知用户等)。

测试延迟

使用 delayed: 场景验证您的系统能正确处理延迟到达的 webhooks。

幂等性

使用 transactionId 作为幂等键。在交付失败的情况下,相同的 webhook 可能会被重新发送。

本页目录