> ## Documentation Index
> Fetch the complete documentation index at: https://docs.velafi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 上线检查清单

> 在将 VelaFi 集成切换到生产环境之前，检查凭证、Webhook、幂等性、错误处理、对账、限额和监控。

在将任何 VelaFi 集成从沙盒环境切换到生产环境之前，请逐项完成本页内容。通用部分适用于所有集成。最后一部分链接到各使用场景页面上的检查清单。

我们看到的大多数生产事故都源于三个缺口：Webhook 端点未按要求的格式确认推送、重试时未使用 `clientId`，以及没有对账任务来发现 Webhook 遗漏的内容。

## 凭证与认证

* 将沙盒环境凭证与生产环境凭证分开管理。沙盒环境密钥由 VelaFi 提供，配合 `https://api-test.velafi.com` 使用。生产环境密钥在 **API Management** 页面创建，配合 `https://api.velafi.com` 使用。两套密钥不可互换。参见[沙盒环境与生产环境密钥](https://docs.velafi.com/cn/api-reference/authentication.md#sandbox-vs-production-keys)。
* 将每台调用 API 的生产服务器的公网 IP 地址添加到密钥的 IP 白名单中（每个密钥最多 5 个地址，不支持 CIDR 网段）。没有白名单的密钥无法获取令牌（`-1023`），来自其他地址的调用会以 `-2015`（令牌请求）或 `-2019`（API 调用）失败。在迁移服务器或更改出口 IP 之前，请先更新白名单。
* 将 API 密钥、API 私钥和令牌保存在您的服务器上。切勿将它们放入浏览器或移动端代码、日志或源代码管理中。
* 缓存令牌，并在其 `expireTime`（Unix 毫秒）之前请求新令牌。如果调用返回 `-1022`，说明令牌已过期或无法识别：请获取新令牌并重新发送该调用。
* 规划密钥轮换：创建新密钥，为其配置 IP 白名单，完成切换，然后删除旧密钥。参见[安全最佳实践](https://docs.velafi.com/cn/api-reference/authentication.md#security-best-practices)。

## Webhook

Webhook 不会在沙盒环境中触发，因此生产环境是您的处理程序首次接收真实推送的地方。请仔细检查。

* **为您使用的每种事件类型注册生产环境 Webhook**：使用生产环境凭证调用[创建 Webhook](https://docs.velafi.com/cn/api-reference/webhooks/create-webhook-endpoints.md)（`POST /v2/webhook`）。每种事件类型（`ORDER_WEBHOOK`、`GLOBAL_PAYMENT_WEBHOOK`、`FUNDING_WEBHOOK`、`ON_RAMP_WITHDRAW_WEBHOOK`、`CRYPTO_WITHDRAW_WEBHOOK`、`STABLE_COIN_PAYMENT_WEBHOOK`）都需要单独注册。在某事件类型没有有效 Webhook 期间发生的事件不会排队保留，因此请在首笔真实交易之前完成注册。
* **保存每个 Webhook 的 `publicKey`**，并在解析或重新序列化 JSON 之前，基于原始请求体字节验证 RSA-SHA256 `signature` 请求头。参见 [Webhook 设置](https://docs.velafi.com/cn/api-reference/webhooks/webhook-setup.md)。
* **对您接受的每次推送，以 HTTP `2xx` 和完全相同的以下 JSON 响应体进行确认。** 如果签名验证失败，请返回 `{"callbackStatus":"FAIL"}`，以便该推送被重试。

```json theme={null}
{"callbackStatus":"SUCCESS"}
```

> [!WARNING]
>
> 任何其他响应都视为推送失败并会触发重试，即使您的系统已处理该事件。以下每一种都属于失败：
>
> * 纯文本 `SUCCESS`、`success` 或 `OK`
> * `{"callbackStatus":"success"}`（该值区分大小写）
> * `{"received":true}`、`{"status":"ok"}` 或任何不包含 `"callbackStatus":"SUCCESS"` 的其他 JSON
> * 空响应体，或在开头的 `{` 之前带有空白字符或字节顺序标记（BOM）的响应体
> * 您自己的错误 JSON，或任何非 `2xx` 状态码
> * 在推送超时前未响应

* **快速响应。** 验证签名、保存事件、返回确认，并异步执行耗时的工作（数据库更新、调用其他系统）。
* **处理重复事件。** 同一事件可能到达不止一次。请基于事件类型、记录 ID（`orderId`、`txId` 或 `withdrawId`）和状态实现幂等处理。
* **不要依赖顺序，也不要指望看到每个状态。** 推送可能乱序到达，当记录已进入后续状态时，中间状态可能被跳过。请将 Webhook 视为一个信号：通过相应的查询端点读取记录的当前状态，并据此采取行动。
* **对 Webhook 遗漏的内容进行对账。** 一次失败的推送总共会尝试 3 次（第二次约在第一次之后 5–10 分钟，第三次约在第二次之后 60–65 分钟）。之后该事件将被丢弃，且 API 没有重新推送的端点。请运行下文所述的对账任务。
* **上线前测试处理程序的响应。** 向您自己的端点发送示例负载，检查原始响应是否恰好为 `{"callbackStatus":"SUCCESS"}` 且状态码为 `2xx`。

## 使用 `clientId` 实现幂等性

在每个创建类调用中传入一个新的唯一 `clientId`，在发送请求前保存它，并在重试该请求时复用相同的值。VelaFi 会拒绝重复使用的 `clientId`，而不是创建第二条记录。重复请求的响应不会返回原记录，因此请自行查询。

| 调用 | `clientId` | 唯一性范围 | 重复使用 `clientId` | 查询方式 |
| - | - | - | - | - |
| `POST /v2/order/fiat_to_crypto`、`POST /v2/order/crypto_to_fiat` | 可选，最多 40 个字符 | 您账户下所有 `fiat_to_crypto` 和 `crypto_to_fiat` 订单 | 以 `-1174` 拒绝 | 使用 `orderType` 和 `clientId` 调用[获取订单](https://docs.velafi.com/cn/api-reference/order/retrieve-a-specific-order.md) |
| `POST /v2/order/fiat_to_fiat` | 可选，最多 40 个字符 | 您账户下所有 `fiat_to_fiat` 订单 | 以 `-1174` 拒绝 | [获取订单列表](https://docs.velafi.com/cn/api-reference/order/retrieve-a-list-of-orders.md)，匹配 `clientId` |
| `POST /v2/merchant/claimfunds`、`POST /v2/merchant/transfer` | 每个请求都传入 | 您账户下所有资金记录 | 以 `-1174` 拒绝 | 使用 `clientId` 调用[获取资金记录](https://docs.velafi.com/cn/api-reference/merchant/retrieve-funding-records.md) |
| `POST /v2/assets/withdraw` | 必填 | 该商户同类提现 | 以 `Duplicate withdrawal request` 拒绝 | 使用 `clientId` 调用[获取加密货币提现记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-withdrawal-history.md) |
| `POST /v2/assets/internalTransfer` | 可选 | 该商户发出的内部划转 | 以 `Duplicate withdrawal request` 拒绝 | 使用 `clientId` 调用[获取加密货币划转记录](https://docs.velafi.com/cn/api-reference/merchant/query-crypto-transfers.md) |

`clientId` 会永久绑定到其记录，包括记录被取消之后。新的操作请使用新的值。

[创建商户](https://docs.velafi.com/cn/api-reference/merchant/create-merchant.md)没有 `clientId`。重试之前，请通过[获取商户列表](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-of-merchants.md)（`status=-1`）按 `email` 查找该商户。

## 错误处理

* 根据 `code` 字段而不是 HTTP 状态码进行分支处理。错误使用 HTTP `400`（`-1001` 为 `500`），并带有负数 `code`（`30012` 除外）。不存在 `401` 或 `429`。参见[错误码](https://docs.velafi.com/cn/docs/error-codes.md)。
* 在创建或变更类调用中，将 `-1001`、`-1006`、`-1007` 和 `30012` 视为**结果未知**。该操作可能已经完成。请通过 `clientId` 查询（见上表），仅在查不到时才使用相同的 `clientId` 重试。如果重试时返回 `-1174`，说明第一次请求已成功。
* 不要匹配 `msg`。它可能包含运行时值和占位符。
* 对于[有速率限制的端点](https://docs.velafi.com/cn/api-reference/overview.md#rate-limits)返回的 `-1006` 以及 `30012`（并发请求过多），请进行退避。
* 对于失败的订单，请从[获取订单](https://docs.velafi.com/cn/api-reference/order/retrieve-a-specific-order.md)中读取 `failCode` 和 `failReason`。`failReason` 可能为空，也可能包含服务商的原始文本，因此请记录日志，并根据订单状态进行处理。

## 对账

Webhook 是通知渠道，而不是您的账本。请运行定时任务，读取 VelaFi 最近几小时或几天的记录，并与您自己的记录进行比对。

| 内容 | 唯一可信来源 |
| - | - |
| 法币余额上的法币充值、出金（`claimfunds`）、入金扣款、退款和商户划转 | [获取资金记录](https://docs.velafi.com/cn/api-reference/merchant/retrieve-funding-records.md)（`GET /v2/merchant/funding/records`），按 `txId` 或 `clientId` 查询 |
| 逐笔法币余额变动，包括手续费和回滚 | [获取法币流水](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-merchant-fiat-flow.md)（`GET /v2/merchant/fiat/flows`） |
| 入金、出金和全球支付订单 | [获取订单](https://docs.velafi.com/cn/api-reference/order/retrieve-a-specific-order.md)和[获取订单列表](https://docs.velafi.com/cn/api-reference/order/retrieve-a-list-of-orders.md) |
| 商户钱包的加密货币提现 | [获取加密货币提现记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-withdrawal-history.md) |
| 加密货币充值 | [获取加密货币充值记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-deposit-history.md) |
| 法币和加密货币余额 | [获取商户账户列表](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-of-merchant-accounts.md)和[获取加密资产余额](https://docs.velafi.com/cn/api-reference/merchant/get-crypto-assets-balance.md) |

* 重新检查您系统中所有处于非最终状态的记录，以免因错过一条 Webhook 而让订单或出金在您这边永远处于待处理状态。
* 对停留在非最终状态时间超过该支付通道预期的记录发出告警。
* 每日对账余额：期初余额加上资金记录应等于期末余额。

## 限额

* 通过[获取商户列表](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-of-merchants.md)检查每个商户的每日和每月限额及使用情况（`dayFiatLimit`、`monthFiatLimit`、`monthCryptoLimit` 以及对应的 `...Used` 字段），并通过[获取商户账户列表](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-of-merchant-accounts.md)检查各渠道限额（`monthBuyLimit`、`monthSellLimit`）。
* 处理限额错误：`-5050` 和 `-5060`（订单低于最低限额或高于最高限额），`-5029`、`-5030` 和 `-5081`（超出每月或每日限额）。
* 如果预期交易量需要，请在上线前申请提升限额。参见[交易限额](https://docs.velafi.com/cn/docs/limits.md)。
* 遵守报价和订单端点的[速率限制](https://docs.velafi.com/cn/api-reference/overview.md#rate-limits)。

## 监控

* 记录每个请求和响应，并附上您的 `clientId` 和 VelaFi 的 ID（`orderId`、`txId`、`withdrawId`），以便追踪任意交易。
* 对令牌失败（`-1022`、`-1023`、`-2015`、`-2019`）发出告警。它们通常意味着令牌已过期、密钥已被禁用或 IP 未加入白名单。
* 当 Webhook 推送停止到达，或您的处理程序返回确认以外的任何内容时，发出告警。
* 对错误率上升、结果未知错误码，以及停留在非最终状态的订单或出金发出告警。
* 监控您用于付款的余额（法币余额用于出金和预先注资订单，加密货币余额用于加密货币兑法币出金订单），以免出金因资金不足而失败。

## 按使用场景

每个使用场景页面末尾都有针对该流程的检查清单。请为您上线的每个流程完成对应的清单：

> [card] [使用虚拟账户收款](https://docs.velafi.com/cn/docs/use-cases/collect-with-virtual-accounts.md#go-live-checklist)
>
> 每个付款人一个虚拟账户、`FUNDING_WEBHOOK` 处理、按 `depositAlias` 匹配充值。

> [card] [从余额出金](https://docs.velafi.com/cn/docs/use-cases/payouts-from-balance.md#go-live-checklist)
>
> 收款人、余额与手续费检查、出金状态跟踪。

> [card] [兑换为稳定币](https://docs.velafi.com/cn/docs/use-cases/convert-to-stablecoins.md#go-live-checklist)
>
> 预先注资或按单付款的入金订单、报价、过期处理。

> [card] [以稳定币注资出金](https://docs.velafi.com/cn/docs/use-cases/payouts-funded-by-stablecoins.md#go-live-checklist)
>
> 出金订单、加密货币余额、出金失败与退款。

> [card] [客户入驻](https://docs.velafi.com/cn/docs/use-cases/onboard-your-customers.md#go-live-checklist)
>
> 商户创建、验证状态、渠道激活。

> [card] [跨境支付](https://docs.velafi.com/cn/docs/guides/global-payments.md)
>
> 使用 `GLOBAL_PAYMENT_WEBHOOK` 的法币兑法币订单。


## Related topics

- [从余额支付本地货币](https://docs.velafi.com/cn/docs/use-cases/payouts-from-balance.md)
- [将您的客户注册为商户](https://docs.velafi.com/cn/docs/use-cases/onboard-your-customers.md)
- [将本地货币兑换为稳定币](https://docs.velafi.com/cn/docs/use-cases/convert-to-stablecoins.md)
- [使用虚拟账户收取本地付款](https://docs.velafi.com/cn/docs/use-cases/collect-with-virtual-accounts.md)
- [以稳定币注资支付本地货币](https://docs.velafi.com/cn/docs/use-cases/payouts-funded-by-stablecoins.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.