> ## 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.

# 以稳定币注资支付本地货币

> 使用 USDT 或 USDC 为商户钱包注资，并通过 crypto_to_fiat 订单向已登记的收款人支付本地货币、USD 或 EUR，包括失败处理和对账。

本指南介绍如何向第三方（例如供应商、卖家或您的某位用户）支付法币，并以稳定币为该笔出金注资。您将 USDT 或 USDC 充值到商户的 VelaFi 钱包，将收款人的银行账户登记为收款人，并为每笔出金创建一个 `crypto_to_fiat` 订单。VelaFi 按报价汇率兑换加密货币，并通过本地支付通道（例如 SPEI、Pix、CVU、Bre-B）发送法币；USD 和 EUR 则通过 Circle Payment Network (CPN) 发送。

完整的字段说明请参阅[出金指南](https://docs.velafi.com/cn/docs/guides/off-ramp.md)和[创建出金订单](https://docs.velafi.com/cn/api-reference/order/create-a-crypto-to-fiat-order.md)。

## 工作原理

```mermaid theme={null}
sequenceDiagram
    participant You as 您的系统
    participant V as VelaFi API
    participant Bank as 出金通道
    You->>V: GET /v2/assets/depositAddress
    You->>V: 将 USDT/USDC 链上发送到该地址
    You->>V: POST /v2/payments (登记收款人)
    V-->>You: userPaymentId, status 1
    You->>V: GET /v2/user/crypto-quote (createQuoteId=true)
    You->>V: POST /v2/order/crypto_to_fiat
    V-->>You: orderId
    Note over V: 从钱包扣除加密货币 (status 40)
    V->>Bank: 向收款人支付法币
    Bank-->>V: 出金结果
    V-->>You: ORDER_WEBHOOK 50, 然后 60 (或 70 / 72)
```

## 开始之前

* **API 访问权限。** 一个 API 密钥、已加入白名单的服务器 IP，以及用于 `X-BH-TOKEN` 请求头的业务令牌。参见[认证](https://docs.velafi.com/cn/api-reference/authentication.md)。
* **一个已验证的商户**，拥有出金币种和渠道的已激活账户。收款人必须使用该账户的支付方式（`paymentId`）。参见[激活商户账户](https://docs.velafi.com/cn/docs/guides/activating-merchant-account.md)。
* **已注册 `ORDER_WEBHOOK`。** 您的端点必须返回 HTTP `2xx` 和响应体 `{"callbackStatus":"SUCCESS"}`，否则推送视为失败。参见 [Webhook](https://docs.velafi.com/cn/docs/guides/webhooks.md) 和[推送与重试](https://docs.velafi.com/cn/api-reference/webhooks/webhook-setup.md#delivery-and-retries)。

## 构建流程

**1. 为商户的加密货币钱包注资**

获取商户在您要发送的代币和网络上的充值地址：

```bash theme={null}
curl -G https://api.velafi.com/v2/assets/depositAddress \
  -H "X-BH-TOKEN: YOUR_TOKEN" \
  --data-urlencode "tokenId=USDT" \
  --data-urlencode "chainType=TRC20" \
  --data-urlencode "merchantId=100001"
```

将加密货币发送到 `address`（如果 `needAddressTag` 为 `true`，还需附上 `addressExt`），金额至少为 `minQuantity`。支持的代币和网络组合参见[获取加密货币充值地址](https://docs.velafi.com/cn/api-reference/merchant/get-crypto-deposit-address.md)。

加密货币充值到账没有 Webhook。请通过[获取加密货币充值记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-deposit-history.md)确认入账（`status` `2` 表示成功），并通过[获取加密资产余额](https://docs.velafi.com/cn/api-reference/merchant/get-crypto-assets-balance.md)中的 `free` 查看可用金额。

**2. 登记收款人**

通过 `GET /v2/payments/templates?paymentId={paymentId}` 获取出金方式的字段模板，然后通过 `POST /v2/payments` 提交填写好的字段。请使用与订单相同的 `merchantId`。

```json Response theme={null}
{ "code": 200, "msg": "SUCCESS", "data": { "id": 456, "status": 1, "failReason": "", "sameAccountNumberId": 456 } }
```

保存 `data.id`，它就是订单所用的 `userPaymentId`。只有 `status` 为 `1`（有效）的收款人才能接收出金。`2` 表示仍在验证中。`3` 表示验证失败：请读取 `failReason`；如果该账户已存在，请使用 `sameAccountNumberId`，而不要新建记录。收款人只需登记一次即可重复使用。参见[管理收款人](https://docs.velafi.com/cn/docs/guides/managing-beneficiaries.md)。

**3. 可选：通过报价锁定汇率**

调用[获取加密货币/法币报价](https://docs.velafi.com/cn/api-reference/quote/get-user-quote-for-crypto-fiat.md)，将 `from` 设为加密货币、`to` 设为法币，并设置 `createQuoteId=true`。`price` 表示每 1 单位加密货币对应的法币数量。

```bash theme={null}
curl "https://api.velafi.com/v2/user/crypto-quote?country=Mexico&from=USDT&to=MXN&createQuoteId=true" \
  -H "X-BH-TOKEN: YOUR_TOKEN"
```

`quoteId` 在生产环境中的有效期为 10 秒（沙盒环境中为 300 秒），只能使用一次，并且与签发时的 `country`、加密货币和法币绑定。如果不传 `quoteId`，订单将按创建时的价格定价。

**4. 创建出金订单**

使用收款人的 `userPaymentId` 调用 `POST /v2/order/crypto_to_fiat`。请使用收款人的 `country` 和 `fiat`。传入 `fiatAmount` 可固定收款人收到的金额，传入 `cryptoAmount` 可固定您支出的金额。如果同时传入两者，以 `fiatAmount` 为准。务必传入唯一的 `clientId`。

```bash theme={null}
curl -X POST https://api.velafi.com/v2/order/crypto_to_fiat \
  -H "X-BH-TOKEN: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantId": 100001,
    "clientId": "payout-0001",
    "country": "Mexico",
    "fiat": "MXN",
    "crypto": "USDT",
    "fiatAmount": 1000,
    "userPaymentId": 456,
    "quoteId": "YOUR_QUOTE_ID"
  }'
```

```json Response theme={null}
{ "code": 200, "msg": "SUCCESS", "data": { "orderId": 1123123123 } }
```

**订单如何注资。** 加密货币来自商户钱包中该 `crypto` 的余额。VelaFi 在创建订单时扣除该金额，订单进入 `40`（如需审核或材料，则先进入 `10`、`11` 或 `31`）。如果余额不足，请求将因余额不足错误被拒绝，且不会创建订单。

**后付款模式。** 如果 VelaFi 已为您的账户开通后付款出金（可能因法币币种而异），资金不足的订单也会被接受，并在 `32`（等待加密货币充值）状态等待。此时订单详情会返回 `orderExpireTimestamp`，即以 Unix 秒表示的截止时间。请在截止时间前向钱包充值足够的加密货币。VelaFi 每分钟检查一次余额，按从旧到新的顺序将余额用于等待中的订单，并将已覆盖的订单移至 `40`。如果先到达截止时间，订单将被取消（`70`）。参见[为订单注资](https://docs.velafi.com/cn/api-reference/order/create-a-crypto-to-fiat-order.md#funding-the-order)。

如果请求超时，请在重试前先通过 `clientId` 查询订单。参见[幂等性与重试](https://docs.velafi.com/cn/api-reference/order/create-a-fiat-to-crypto-order.md#idempotency-and-retries)。

**5. 跟踪出金直至完成**

等待 `ORDER_WEBHOOK` 事件（`orderType` 为 `SELL`），或轮询 `GET /v2/order/detail?orderType=crypto_to_fiat&clientId={clientId}`。

| `orderStatus` | 对出金的含义 |
| - | - |
| `32` | 仅限后付款模式：等待您的加密货币充值 |
| `40` | 加密货币已扣除，法币出金处理中 |
| `50` | 付款步骤已完成，订单尚未完成。在自动渠道上，订单会自行完成。您也可以通过[确认订单](https://docs.velafi.com/cn/api-reference/order/confirm-a-specific-order.md)完成订单 |
| `60` | 已完成。收款人已收到付款 |
| `70` | 已取消。Webhook 也会将审核拒绝和风控审核拒绝以 `70` 发送 |
| `80` | 审核中被拒绝（轮询时） |
| `81` | 风控审核中被拒绝（轮询时） |
| `72` | 已退款：加密货币已退回钱包 |

当支付通道返回中央银行参考号时，`traceNumber` 会包含该笔出金的参考号。如果收款人要求提供付款凭证，可将其提供给收款人。

## 通过 Circle Payment Network 进行 USD 和 EUR 出金

CPN 承载 USD 和 EUR 出金。它仅支持出金：您无法在 CPN 上收款或创建 `fiat_to_crypto` 订单。

1. 为商户和币种激活 CPN 账户，并将 `trench` 设为 `Circle Payment Network`。参见[激活企业商户账户](https://docs.velafi.com/cn/api-reference/merchant/activate-merchant-account-for-business.md)。
2. 在 CPN 支付方式上登记收款人，例如 USD 使用 `120` Wire (CPN) 或 `127` FEDWIRE (CPN)，EUR 使用 `124` SEPA (CPN)。CPN 模板要求提供收款人地址、`useCase` 和 `reasonForPayment` 代码。参见[获取支付方式模板](https://docs.velafi.com/cn/api-reference/beneficiary/get-payment-templates.md)中的 CPN 模板。
3. 将 `fiat` 设为 `USD` 或 `EUR`，并使用 CPN 收款人的 `userPaymentId` 创建 `crypto_to_fiat` 订单，方法与上文完全相同。

与任何出金一样，CPN 订单也可能进入风控审核（`11`）。此时请通过[上传订单文件](https://docs.velafi.com/cn/api-reference/order/upload-invoice-documents-for-a-specific-order.md)上传所要求的材料。订单随后进入 `12` 并等待决定。

## 需要处理的 Webhook

| 事件 | 触发时机 | 去重键 | 处理方式 |
| - | - | - | - |
| `ORDER_WEBHOOK` | 订单进入 `10`、`11`、`12`、`31`、`32`、`40`、`50`、`60`、`70` 或 `72` | `orderId` + `orderStatus` | 收到 `60` 时标记为已支付。收到 `70` 或 `72` 时，在您这边释放该笔出金，并读取 `failCode` / `failReason` |

`ORDER_WEBHOOK` 仅针对通过 API 创建的订单发送。它不会发送 `71`（取消中）或 `73`（退款中），审核或风控审核中被拒绝的订单以 `70` 发送。事件可能重复到达、乱序到达，且中间状态可能被跳过。请基于 `orderId` + `orderStatus` 去重，并在事件与您持有的状态不符时通过 `GET /v2/order/detail` 读取订单。

## 处理失败

| 您看到的情况 | 可能原因 | 处理方式 |
| - | - | - |
| 创建请求因余额不足错误被拒绝 | 钱包的 `free` 余额不足以覆盖订单 | 充值更多加密货币，然后使用新的 `clientId` 和新的报价重新创建订单。 |
| 创建请求因收款人问题被拒绝 | `userPaymentId` 的 `status` 不为 `1`、属于其他商户，或其币种或渠道与订单不匹配 | 通过[获取收款人列表](https://docs.velafi.com/cn/api-reference/beneficiary/get-beneficiary.md)检查收款人，并检查商户已激活的账户。 |
| 创建请求因重复提交被拒绝 | 该 `clientId` 已被使用 | 通过 `clientId` 查询订单。不要再次创建。 |
| `32` 之后变为 `70` | 在钱包覆盖订单金额之前，后付款截止时间已过 | 先为钱包注资，再创建新订单。 |
| 轮询时为 `80` 或 `81`（Webhook 中为 `70`） | 在审核或风控审核中被拒绝 | 不要原样重新提交。如需了解原因，请联系 VelaFi。 |
| 订单一直停留在 `40` | 出金通道拒绝了该笔出金或尚未确认。被拒绝的出金不会自行使订单进入最终状态；VelaFi 运营团队会重试或取消订单 | 如果订单停留在 `40` 的时间超过该通道的正常时长，请携带 `orderId` 联系 VelaFi 支持团队。在第一笔订单未结束时，不要为同一笔出金创建第二笔订单。 |
| `60` 之后变为 `72` | 出金在完成后被退回，例如收款人的银行退回了该笔款项 | 加密货币已退回商户钱包。更正收款人信息，并使用新的 `clientId` 创建新订单。 |

`failReason` 经常为空，因为许多支付通道不返回原因。请将空的 `failReason` 视为“未知”，而不是成功。为避免重复付款，只有在原订单达到最终状态（`70` 或 `72`）后才创建替代出金。

## 对账

* **每笔出金：** 通过 `orderId` 或 `clientId` 调用[获取订单](https://docs.velafi.com/cn/api-reference/order/retrieve-a-specific-order.md)是唯一可信来源：`orderStatus`、`cryptoAmount`（从钱包扣除）、`fiatAmount`（支付给收款人）、`fiatFee`、`orderPrice`、`orderFeeDetail`、`traceNumber`、`failCode` 和 `failReason`。
* **每日总额：** 使用 `orderType=crypto_to_fiat` 和时间范围调用[获取订单列表](https://docs.velafi.com/cn/api-reference/order/retrieve-a-list-of-orders.md)。该接口也会列出非通过 API 创建的订单。
* **钱包：** 通过[获取加密货币充值记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-deposit-history.md)查看充值，通过[获取加密资产余额](https://docs.velafi.com/cn/api-reference/merchant/get-crypto-assets-balance.md)查看 `free` 和 `locked`。

请运行定时任务，重新读取您这边所有仍未完成的出金，并标记停留在 `40` 或 `50` 超过您正常出金时长的订单。连续三次推送失败后，Webhook 可能会丢失。

## 在沙盒环境中测试

* 使用 `https://api-test.velafi.com`。沙盒环境中**不会**发送 Webhook，因此请轮询 `GET /v2/order/detail`。
* 使用加密货币充值模拟器向商户钱包添加测试 USDT 或 USDC。参见[沙盒环境测试工具](https://docs.velafi.com/cn/docs/sandbox.md#sandbox-testing-tools)。
* 部分支付方式 ID 在沙盒环境中有所不同，例如 CBU/CVU (Momentum) 为 `18` 而不是 `63`。参见[支付方式](https://docs.velafi.com/cn/docs/payment-methods.md#sandbox-vs-production-ids)。
* 模拟器只能生成成功的充值。您无法模拟被退回的出金，因此请使用录制的负载测试 `70` 和 `72` 的处理逻辑。

## 上线检查清单

* [ ] 在创建订单前已为钱包注资，或已开通后付款出金，且您的系统会在 `orderExpireTimestamp` 之前为处于 `32` 的订单注资。
* [ ] 收款人只登记一次，按 `userPaymentId` 保存，且仅在 `status` 为 `1` 时使用。
* [ ] 每个创建请求都传入唯一的 `clientId`，超时时先通过 `clientId` 查询再决定是否重试。
* [ ] `ORDER_WEBHOOK` 端点会验证签名，返回 HTTP `2xx` 和 `{"callbackStatus":"SUCCESS"}`，并基于 `orderId` + `orderStatus` 去重。
* [ ] `70` 和 `72`（包括 `60` 之后的 `72`）会在您这边释放或冲正该笔出金，且只有在原订单达到最终状态后才创建替代出金。
* [ ] 停留在 `40` 或 `50` 的订单会被标记，并携带 `orderId` 升级处理。
* [ ] 对于 USD 和 EUR，CPN 账户已激活，且 CPN 收款人包含所需的合规字段。

请参阅完整的[上线检查清单](https://docs.velafi.com/cn/docs/use-cases/go-live-checklist.md)。


## Related topics

- [核心使用场景](https://docs.velafi.com/cn/docs/use-cases/overview.md)
- [Agent Skills](https://docs.velafi.com/cn/docs/developer-tools/agent-skills.md)
- [将本地货币兑换为稳定币](https://docs.velafi.com/cn/docs/use-cases/convert-to-stablecoins.md)
- [从余额支付本地货币](https://docs.velafi.com/cn/docs/use-cases/payouts-from-balance.md)
- [简介](https://docs.velafi.com/cn/docs/introduction.md)


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