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

# Off-Ramp 实现

> 将加密货币转换为法币

## 概览

Off-ramp 将加密货币（USDC, USDT）转换为法币（COP, MXN, USD）。用户发送加密货币，并在银行账户中接收本地货币。

## 完整的 Off-Ramp 流程

<Steps>
  <Step title="创建用户和银行账户">
    设置用户资料和目标银行账户
  </Step>

  <Step title="获取报价">
    请求加密货币→法币转换的报价
  </Step>

  <Step title="创建 Ramp">
    使用报价 ID 执行 ramp
  </Step>

  <Step title="用户发送加密货币">
    用户将 USDC/USDT 转账到提供的地址
  </Step>

  <Step title="转换">
    KillB 将加密货币转换为法币
  </Step>

  <Step title="法币交付">
    本地货币发送到用户的银行
  </Step>
</Steps>

## 实现示例

```javascript theme={null}
const executeOffRamp = async (userId, bankAccountId, amount) => {
  try {
    // 1. 获取报价
    const quote = await fetch('/api/v2/quotations', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        fromCurrency: 'USDC',
        toCurrency: 'COP',
        amount: amount,
        amountIsToCurrency: false,
        cashInMethod: 'POLYGON',
        cashOutMethod: 'PSE'
      })
    }).then(r => r.json());
    
    console.log(`您将收到: ${quote.toAmount} COP`);
    
    // 2. 创建 ramp
    const ramp = await fetch('/api/v2/ramps', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        quotationId: quote.id,
        userId: userId,
        accountId: bankAccountId,
        externalId: `offramp-${Date.now()}`
      })
    }).then(r => r.json());
    
    // 3. 向用户显示存款地址
    const depositAddress = ramp.paymentInfo[0].address;
    const depositNetwork = ramp.paymentInfo[0].network;
    
    return {
      rampId: ramp.id,
      depositAddress: depositAddress,
      depositNetwork: depositNetwork,
      amountToSend: quote.fromAmount,
      willReceive: quote.toAmount
    };
    
  } catch (error) {
    console.error('Off-ramp 失败:', error);
    throw error;
  }
};
```

## 加密货币存款说明

创建 ramp 后，向用户显示发送加密货币的位置：

```javascript theme={null}
const showDepositInstructions = (ramp) => {
  const paymentInfo = ramp.paymentInfo[0];
  
  return (
    <div>
      <h3>发送 {ramp.fromAmount} {ramp.fromCurrency}</h3>
      <p><strong>网络:</strong> {paymentInfo.network}</p>
      <p><strong>地址:</strong> {paymentInfo.address}</p>
      <QRCode value={paymentInfo.address} />
      
      <button onClick={() => copyToClipboard(paymentInfo.address)}>
        复制地址
      </button>
      
      <p>发送后，您的 {ramp.toCurrency} 将在 1-3 小时内存入您的银行。</p>
    </div>
  );
};
```

## 银行账户设置

创建用于接收法币的银行账户：

<Tabs>
  <Tab title="哥伦比亚（PSE）">
    ```json theme={null}
    {
      "type": "PSE",
      "userId": "user-id",
      "data": {
        "firstName": "Juan",
        "lastName": "García",
        "accountNumber": "1234567890",
        "bankCode": "0001",
        "type": "savings",
        "countryCode": "CO",
        // ... 其他必需字段
      }
    }
    ```
  </Tab>

  <Tab title="墨西哥（SPEI）">
    ```json theme={null}
    {
      "type": "SPEI",
      "userId": "user-id",
      "data": {
        "firstName": "María",
        "lastName": "López",
        "clabe": "012345678901234567",
        "clabeType": "CLABE",
        "countryCode": "MX",
        // ... 其他必需字段
      }
    }
    ```
  </Tab>
</Tabs>

## 监控存款

等待用户的加密货币存款：

```javascript theme={null}
const waitForCryptoDeposit = async (rampId) => {
  return new Promise((resolve, reject) => {
    const interval = setInterval(async () => {
      const ramp = await getRamp(rampId);
      
      if (ramp.status === 'CASH_IN_COMPLETED') {
        console.log('加密货币已收到！正在转换...');
        clearInterval(interval);
      }
      
      if (ramp.status === 'COMPLETED') {
        console.log('法币已交付到银行！');
        clearInterval(interval);
        resolve(ramp);
      }
      
      if (['FAILED', 'CANCELED'].includes(ramp.status)) {
        clearInterval(interval);
        reject(new Error(`Ramp ${ramp.status}`));
      }
    }, 15000); // 每 15 秒检查一次
  });
};
```

## 退款说明

在出现问题时提供备用地址：

```json theme={null}
{
  "quotationId": "quote-id",
  "userId": "user-id",
  "accountId": "bank-id",
  "refundInstructions": {
    "network": "POLYGON",
    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "asset": "USDC"
  }
}
```

<Info>
  如果 off-ramp 失败，加密货币将退还到此地址。
</Info>

## 下一步

<CardGroup cols={2}>
  <Card title="On-Ramp 指南" icon="arrow-up" href="/zh/guides/ramps/on-ramp">
    实现法币到加密货币的转换
  </Card>

  <Card title="状态跟踪" icon="chart-line" href="/zh/guides/ramps/ramp-status">
    监控 ramp 进度
  </Card>
</CardGroup>
