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

# 将本地货币兑换为稳定币

> 通过 fiat_to_crypto 订单用本地货币购买 USDT 或 USDC，由您的待处理资金 (Pending Fund) 余额支付或由付款人逐单付款，并将加密货币交付到您的钱包或外部地址。

本指南介绍如何通过 `fiat_to_crypto` 订单将本地货币（例如 MXN、ARS、COP 或 BRL）兑换为稳定币。您可以选择每笔订单的付款方式：使用商户待处理资金 (Pending Fund) 余额中已持有的法币支付，或由付款人针对该笔订单发起银行转账支付。订单完成后，加密货币会入账到商户的 VelaFi 钱包。之后您可以继续持有、提现，或让其自动发送到外部地址。

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

## 选择注资模式

| | 预先注资（推荐） | 按单付款 |
| - | - | - |
| 订单如何付款 | 从商户该币种的待处理资金余额中支付 | 付款人向订单返回的付款信息发起银行转账 |
| `paymentId` | `70`（VelaFi Pending Fund） | 币种账户的渠道，例如 `105`（SPEI, Finco Pay） |
| 余额检查 | 创建时检查：如果余额不足以覆盖订单，请求将被拒绝 | 创建时不检查 |
| 典型结果 | 创建后几秒内完成 | 付款到账后完成。如果在付款时限内未收到付款，订单将被取消 |
| 您需要处理的事项 | 保持余额充足 | 展示付款指引、付款人延迟、过期订单 |

> [!TIP]
>
> 如果您的业务能够持有本地货币余额，请使用预先注资模式。订单在创建的同时即完成付款，因此不会因未付款而过期，而且您在确定交易前就能知道资金是否到位。按单付款依赖于付款人在时限结束前汇出准确金额，许多按单付款订单最终因未付款而过期。

## 工作原理

```mermaid theme={null}
flowchart TD
    A[可选：获取带 quoteId 的报价] --> B{注资模式}
    B -->|预先注资| C["POST /v2/order/fiat_to_crypto<br/>paymentId 70"]
    C --> D[订单由待处理资金余额支付]
    B -->|按单付款| E["POST /v2/order/fiat_to_crypto<br/>渠道 paymentId"]
    E --> F[向付款人展示 paymentInfo]
    F --> G{是否在时限内付款？}
    G -->|是| D2[充值入账并匹配到订单]
    G -->|否| X["订单已取消：orderStatus 70"]
    D --> H["订单已完成：orderStatus 60<br/>加密货币进入商户钱包"]
    D2 --> H
    H --> I{交付加密货币}
    I -->|持有| J[保留在商户钱包中]
    I -->|自动提现| K[发送到订单地址<br/>ON_RAMP_WITHDRAW_WEBHOOK]
    I -->|手动提现| L["POST /v2/assets/withdraw<br/>CRYPTO_WITHDRAW_WEBHOOK"]
```

## 开始之前

* **API 访问权限。** 一个 API 密钥、已加入白名单的服务器 IP，以及用于 `X-BH-TOKEN` 请求头的业务令牌。参见[认证](https://docs.velafi.com/cn/api-reference/authentication.md)。
* **一个已验证的商户。** 订单的 `merchantId` 必须是您账户下已通过验证的商户。参见[商户](https://docs.velafi.com/cn/docs/merchants.md)。
* **一个已激活的币种账户。** 商户需要拥有该法币的已激活账户。参见[激活商户账户](https://docs.velafi.com/cn/docs/guides/activating-merchant-account.md)。
* **已注册 Webhook。** 注册 `ORDER_WEBHOOK`；如果预先注资，还需注册 `FUNDING_WEBHOOK`；如果需要提现，还需注册 `CRYPTO_WITHDRAW_WEBHOOK`。参见 [Webhook](https://docs.velafi.com/cn/docs/guides/webhooks.md)。您的端点必须返回 HTTP `2xx` 和响应体 `{"callbackStatus":"SUCCESS"}`，否则推送视为失败。参见[推送与重试](https://docs.velafi.com/cn/api-reference/webhooks/webhook-setup.md#delivery-and-retries)。

## 构建流程

**1. 仅限预先注资：为待处理资金余额注资**

通过[获取待入账资金账户](https://docs.velafi.com/cn/api-reference/merchant/get-pending-fund-account.md)（`GET /v2/merchant/addfunds`）获取商户币种账户的充值信息，并将法币汇至该账户。每笔入账的充值都会触发一条 `type` 为 `DEPOSIT`、`status` 为 `2` 的 `FUNDING_WEBHOOK` 事件。

在创建大额订单前，请通过[获取商户账户列表](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-of-merchant-accounts.md)（`balance`）检查当前余额。

如果您已经将付款收取到商户的币种账户，这些充值就构成了该余额。参见[使用虚拟账户收取本地付款](https://docs.velafi.com/cn/docs/use-cases/collect-with-virtual-accounts.md)。

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

调用[获取加密货币/法币报价](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=MXN&to=USDT&createQuoteId=true" \
  -H "X-BH-TOKEN: YOUR_TOKEN"
```

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

**3. 创建订单**

调用 `POST /v2/order/fiat_to_crypto`。务必传入唯一的 `clientId`（最多 40 个字符），以便安全重试并在之后查找订单。

> [tab] 预先注资
>
> 将 `paymentId` 设为 `70`（VelaFi Pending Fund）。
>
> ```bash theme={null}
> curl -X POST https://api.velafi.com/v2/order/fiat_to_crypto \
>   -H "X-BH-TOKEN: YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "merchantId": 100001,
>     "clientId": "onramp-0001",
>     "country": "Mexico",
>     "fiat": "MXN",
>     "crypto": "USDT",
>     "fiatAmount": 1000,
>     "paymentId": 70,
>     "quoteId": "YOUR_QUOTE_ID"
>   }'
> ```
>
> VelaFi 在创建订单时会检查商户该币种的余额。如果余额不足以覆盖订单金额，请求将因余额不足错误被拒绝，且不会创建订单。如果余额足够，订单创建后会立即从余额中支付并进入 `60`（已完成），除非它需要先经过审核或提交材料（`10`、`11` 或 `31`）。该笔扣款会以 `BUY_CRYPTO` 记录的形式出现在[资金记录](https://docs.velafi.com/cn/api-reference/merchant/retrieve-funding-records.md)中。

> [tab] 按单付款
>
> 将 `paymentId` 设为商户币种账户的渠道，例如 SPEI (Finco Pay) 为 `105`。参见[支付方式](https://docs.velafi.com/cn/docs/payment-methods.md)。如果您为每个付款人分配了专属虚拟账户，还需传入该账户的 `depositAlias`。
>
> ```bash theme={null}
> curl -X POST https://api.velafi.com/v2/order/fiat_to_crypto \
>   -H "X-BH-TOKEN: YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "merchantId": 100001,
>     "clientId": "onramp-0002",
>     "country": "Mexico",
>     "fiat": "MXN",
>     "crypto": "USDT",
>     "fiatAmount": 1000,
>     "paymentId": 105,
>     "depositAlias": "PAYER0001"
>   }'
> ```
>
> 订单从 `40`（待付款）开始；如果需要审核或材料，则从 `10`、`11` 或 `31` 开始。

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

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

**4. 仅限按单付款：展示付款指引**

使用 `orderType=fiat_to_crypto` 调用[获取订单](https://docs.velafi.com/cn/api-reference/order/retrieve-a-specific-order.md)，向付款人展示 `paymentInfo` 的内容（例如 SPEI 的 CLABE）以及准确的 `fiatAmount`。

付款人的转账入账后，VelaFi 会将其用于同一币种账户上的未完成订单。金额与某笔订单金额完全相等的充值会优先用于该订单。否则，充值会用于最早的未完成订单。带有 `depositAlias` 的订单只能由该虚拟账户收到的充值支付。没有 `depositAlias` 的订单可以由该币种账户上的任何充值支付，包括已在待处理资金余额中的法币。

> [!WARNING]
>
> 只有在全额可用时订单才会被支付。付款不足不会使订单完成。请要求付款人汇出准确金额，并为每个付款人分配一个虚拟账户（`depositAlias`），以免一个付款人的转账被用于支付另一个付款人的订单。

**5. 跟踪订单直至完成**

等待 `ORDER_WEBHOOK` 事件，或轮询 `GET /v2/order/detail?orderType=fiat_to_crypto&clientId={clientId}`。`orderStatus` 为 `60` 时订单完成，为 `70`、`80` 或 `81` 时订单失败。轮询时，审核中被拒绝的订单显示为 `80`，风控审核中被拒绝的订单显示为 `81`；Webhook 则将两者都以 `70` 发送。参见[订单状态](https://docs.velafi.com/cn/docs/order-statuses.md)。此时加密货币（`cryptoAmount`）已在商户钱包中。可通过[获取加密资产余额](https://docs.velafi.com/cn/api-reference/merchant/get-crypto-assets-balance.md)查询。

**6. 可选：将加密货币从钱包转出**

您有两种方式：

* **按订单自动提现。** 如果 VelaFi 已为您的账户开通入金自动提现，请在创建请求中添加 `network` 和 `address`。订单完成后，VelaFi 会将 `cryptoAmount` 提现到该地址，并在提现成功时发送 `ON_RAMP_WITHDRAW_WEBHOOK`。在生产环境中，`network` 必须为 `POL` 或 `SPL20`。这两个字段需同时传入或同时省略。未开通该功能的账户会被拒绝，并返回 "You are currently not a user of the onRamp automatic withdrawal service."。参见[入金提现事件](https://docs.velafi.com/cn/api-reference/webhooks/on-ramp-withdraw-message-push.md)。
* **自行提现。** 将目标地址添加到您的[提现白名单](https://docs.velafi.com/cn/api-reference/crypto-wallet/add-whitelist-address.md)，然后使用您自己的唯一 `clientId` 调用[创建加密货币提现](https://docs.velafi.com/cn/api-reference/crypto-wallet/create-crypto-withdrawal.md)（`POST /v2/assets/withdraw`）。通过[获取提现额度](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-withdrawal-quota.md)查询有效的 `chainType` 值和最低金额。

两种提现在达到最终状态时都会触发 `CRYPTO_WITHDRAW_WEBHOOK`。对于自动提现，其 `clientId` 为入金订单的 `orderId`。

## 需要处理的 Webhook

| 事件 | 触发时机 | 去重键 | 处理方式 |
| - | - | - | - |
| `ORDER_WEBHOOK`（仅限通过 API 创建的订单） | 订单进入 `10`、`11`、`12`、`31`、`40`、`50`、`60`、`70` 或 `72` | `orderId` + `orderStatus`（`orderType` 为 `BUY`） | 收到 `60` 时将订单标记为完成，收到 `70` 时标记为失败。审核中被拒绝的订单以 `70` 发送。 |
| `FUNDING_WEBHOOK` | 待处理资金记录完成：`DEPOSIT`（充值或付款人转账）、`BUY_CRYPTO`（法币用于支付订单） | `txId` + `status` | 跟踪法币余额。 |
| `ON_RAMP_WITHDRAW_WEBHOOK` | 自动提现成功 | `orderId` | 记录 `txHash`。提现失败时不会发送此事件。 |
| `CRYPTO_WITHDRAW_WEBHOOK` | 提现达到 `SUCCESS`、`FAILED` 或 `CANCELLED` | `withdrawId` + `status` | 将提现标记为最终状态。 |

事件可能重复到达、乱序到达，且中间状态可能被跳过。请进行去重，并在事件与您持有的状态不符时通过 `GET /v2/order/detail` 读取订单。参见[推送与重试](https://docs.velafi.com/cn/api-reference/webhooks/webhook-setup.md#delivery-and-retries)。

## 处理失败

| 您看到的情况 | 可能原因 | 处理方式 |
| - | - | - |
| 创建请求因余额不足错误被拒绝（预先注资） | 待处理资金余额不足以覆盖订单 | 为余额充值或降低金额，然后使用新的 `clientId` 和新的报价重新创建订单。 |
| 创建请求因重复提交被拒绝 | 该 `clientId` 已被使用，可能是被您自己之前超时的请求使用 | 通过 `clientId` 查询订单。不要再次创建。 |
| 传入 `quoteId` 后创建请求被拒绝 | 报价已过期、已被使用，或签发给了其他货币对 | 请求新的报价。被拒绝的创建请求仍可能消耗 `quoteId`。 |
| 按单付款订单的 `orderStatus` 为 `70` | 在付款时限内未收到全额付款，或订单已被取消 | 使用新的 `clientId` 创建新订单，并向付款人展示新的付款指引。 |
| 轮询时 `orderStatus` 为 `80` 或 `81`（Webhook 中为 `70`） | 在审核或风控审核中被拒绝 | 不要原样重新提交。如需了解原因，请联系 VelaFi。 |
| 订单一直停留在 `10`、`11` 或 `31` | 需要审核、风控审核或证明材料 | 在被要求时通过[上传订单文件](https://docs.velafi.com/cn/api-reference/order/upload-invoice-documents-for-a-specific-order.md)上传材料。参见[订单状态](https://docs.velafi.com/cn/docs/order-statuses.md)。 |
| 始终未收到 `ON_RAMP_WITHDRAW_WEBHOOK` | 自动提现失败或未执行 | 检查加密资产余额，并以入金 `orderId` 作为 `clientId` 查询[获取加密货币提现记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-withdrawal-history.md)。如果加密货币仍在钱包中，请自行提现。 |

### 付款时限

按单付款订单只会在 `40` 状态等待有限的时间。VelaFi 为您的账户设定该时限。订单详情中不会返回该时限，因此请向您的 VelaFi 联系人询问具体数值，并根据 `createTime` 向付款人展示截止时间。时限结束仍未收到全额付款时，订单将被取消，并在订单详情和 `ORDER_WEBHOOK` 中报告为 `orderStatus` `70`。已取消的订单无法重新打开。

如果付款人在订单取消后付款，该转账仍会入账到商户的待处理资金余额（您会收到一条 `FUNDING_WEBHOOK` `DEPOSIT`），但不会用于已取消的订单。您可以为该金额创建新订单（随后由余额支付），或通过[提取待处理资金](https://docs.velafi.com/cn/api-reference/merchant/claim-pending-fund.md)将资金支付出去。

## 对账

* **订单：** 通过 `orderId` 或 `clientId` 调用[获取订单](https://docs.velafi.com/cn/api-reference/order/retrieve-a-specific-order.md)，是每笔订单的唯一可信来源：`orderStatus`、`fiatAmount`、`fiatFee`、`cryptoAmount`、`orderPrice`、`failCode` 和 `failReason`。使用带时间范围的[获取订单列表](https://docs.velafi.com/cn/api-reference/order/retrieve-a-list-of-orders.md)统计每日总额。该接口也会列出非通过 API 创建的订单。
* **法币余额：** [获取资金记录](https://docs.velafi.com/cn/api-reference/merchant/retrieve-funding-records.md)显示每笔 `DEPOSIT` 和 `BUY_CRYPTO`，两种注资模式均适用。[获取法币流水](https://docs.velafi.com/cn/api-reference/merchant/get-a-list-merchant-fiat-flow.md)提供带变动后余额的逐笔账目。
* **加密货币转出：** 通过 `clientId` 查询[获取加密货币提现记录](https://docs.velafi.com/cn/api-reference/crypto-wallet/get-crypto-withdrawal-history.md)，直到 `status` 为 `6`（成功）、`7`（失败）或 `9`（已取消）。

请运行定时任务，重新读取您这边所有仍未完成的订单。连续三次推送失败后，Webhook 可能会丢失。

## 在沙盒环境中测试

* 使用 `https://api-test.velafi.com`。沙盒环境中**不会**发送 Webhook，因此请轮询 `GET /v2/order/detail`。
* 使用法币充值模拟器为测试商户的余额注资，或支付按单付款订单（`depositAlias` 可指定虚拟账户）。参见[沙盒环境测试工具](https://docs.velafi.com/cn/docs/sandbox.md#sandbox-testing-tools)。
* 在沙盒环境中，`quoteId` 的有效期为 300 秒，自动提现的 `network` 可接受 `POL` 或 `TSPL20`。
* 模拟器只能生成成功的充值，无法模拟被退回的付款。如需测试过期路径，请创建一笔按单付款订单且不付款。

## 上线检查清单

* [ ] 每个创建请求都传入唯一的 `clientId`，超时时先通过 `clientId` 查询再决定是否重试。
* [ ] 预先注资流程会检查余额，并在遇到余额不足拒绝时不会循环重试同一请求。
* [ ] 按单付款流程会展示 `paymentInfo`、准确金额和截止时间，并在 `70` 后创建新订单。
* [ ] 如果您在同一币种账户上为多个付款人运行按单付款，每个付款人都有一个虚拟账户（`depositAlias`）。
* [ ] `ORDER_WEBHOOK` 端点会验证签名，返回 HTTP `2xx` 和 `{"callbackStatus":"SUCCESS"}`，并基于 `orderId` + `orderStatus` 去重。
* [ ] 有定时任务根据 API 对未完成订单、资金记录和提现进行对账。
* [ ] 提现目标地址已加入白名单，或已开通自动提现并使用 `network` 和 `address` 完成测试。

请参阅完整的[上线检查清单](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/guides/global-payments.md)
- [以稳定币注资支付本地货币](https://docs.velafi.com/cn/docs/use-cases/payouts-funded-by-stablecoins.md)
- [VelaFi API 文档](https://docs.velafi.com/cn/index.md)


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