跳转到主要内容

什么是 Ramp?

Ramp 是在法币和加密货币之间转换的交易。KillB 支持** on-ramps**(法币 → 加密货币)和** off-ramps**(加密货币 → 法币)。
将 ramps 视为传统银行和加密货币之间的桥梁。它们处理从报价到结算的整个转换过程。

Ramp 类型

法币 → 加密货币将本地货币(COP、MXN、USD)转换为稳定币(USDC、USDT)。流程:
  1. 用户获取报价(例如,100,000 COP → 23.8 USDC)
  2. 用户使用钱包地址创建 ramp
  3. 用户通过 PSE/SPEI/ACH 支付
  4. KillB 处理转换
  5. USDC/USDT 发送到用户钱包
常见用例:
  • 使用本地货币购买加密货币
  • 为 DeFi 头寸提供资金
  • 跨境汇款
  • 加密货币投资

Ramp 生命周期

Ramp 在处理过程中经历多个状态阶段:

Ramp 状态

处理状态

CREATED
  • Ramp 已初始化,等待支付
  • 已向用户提供支付说明
CASH_IN_REQUEST / CASH_IN_REQUESTED
  • 支付请求已发送给提供商
  • 等待用户支付
CASH_IN_PROCESSING
  • 已收到支付,正在验证
  • 确认进行中
CASH_IN_COMPLETED
  • 支付已确认
  • 准备转换
CONVERSION_PROCESSING
  • 正在转换法币 ↔ 加密货币
  • 执行交易
CONVERSION_COMPLETED
  • 转换完成
  • 准备支付
CASH_OUT_PROCESSING
  • 正在向目的地发送资金
  • 交易进行中
CASH_OUT_COMPLETED
  • 资金已发送到目的地
  • 等待最终确认
COMPLETED
  • 交易完全完成
  • 资金已交付给用户
  • 收据可用
FAILED
  • 交易在某个阶段失败
  • 检查 details 字段了解原因
  • 可能有资格重试
CANCELED 🚫
  • 由用户或系统取消
  • 未转移资金
  • 如果适用,已启动退款
REJECTED
  • 被合规或提供商拒绝
  • 检查 note 了解详情
  • 可能需要额外验证
ERROR ⚠️
  • 发生系统错误
  • 使用 ramp ID 联系支持
  • 将进行调查和解决

创建 Ramp

先决条件

在创建 ramp 之前,您需要:
1

用户

具有适当 KYC 级别的已验证用户
2

账户

作为目的地的活动账户(银行或钱包)
3

报价

有效、未过期的报价

基本 Ramp 创建

POST /api/v2/ramps
请求:
{
  "quotationId": "quot-9f8e7d6c-5b4a-3c2d-1e0f",
  "userId": "4d23aa52-1b40-4584-a8ea-58aba6099c5c",
  "accountId": "7c8b9a3d-2f1e-4b5c-9d8e-1a2b3c4d5e6f"
}
响应:
{
  "id": "ramp-1a2b3c4d-5e6f-7g8h-9i0j",
  "status": "CREATED",
  "type": "ON",
  "fromCurrency": "COP",
  "toCurrency": "USDC",
  "fromAmount": 100000,
  "toAmount": 23.81,
  "cashInMethod": "PSE",
  "cashOutMethod": "POLYGON",
  "paymentInfo": [{
    "url": "https://checkout.pse.com.co/payment/123456"
  }],
  "isPreFunded": false,
  "externalId": null,
  "createdAt": "2024-01-15T10:30:00.000Z"
}

多个目的地账户

您可以将 ramp 拆分到多个目的地账户:
{
  "quotationId": "quot-id",
  "userId": "user-id",
  "accounts": [
    {
      "id": "account-1",
      "amount": 50
    },
    {
      "id": "account-2",
      "amount": 50
    }
  ]
}
对于拆分支付、跨钱包多样化或管理多个受益人很有用。

支付信息

根据支付方式,返回不同的支付信息:
{
  "paymentInfo": [{
    "url": "https://checkout.pse.com.co/payment/abc123"
  }]
}
  • 将用户重定向到 url
  • 用户通过 PSE 完成支付
  • Webhook 通知支付完成

退款说明

对于 on-ramps,在失败情况下提供退款说明:
{
  "quotationId": "quot-id",
  "userId": "user-id",
  "accountId": "account-id",
  "refundInstructions": {
    "clabe": "012345678901234567",
    "beneficiary": "Juan García"
  }
}
退款说明必须与现金入账方法匹配(SPEI 需要 CLABE,加密货币需要钱包地址)。

外部 ID

使用 externalId 防止重复 ramps 并跟踪交易:
{
  "quotationId": "quot-id",
  "userId": "user-id",
  "accountId": "account-id",
  "externalId": "order-12345-from-my-system"
}
优势:
  • 防止重复提交
  • 在您的系统中跟踪 ramps
  • 重试的幂等性
  • 更容易对账

监控 Ramps

按 ID 获取 Ramp

GET /api/v2/ramps/{rampId}

查询 Ramps

GET /api/v2/ramps?userId=user-id&status=PROCESSING
过滤选项:
  • id - 特定 ramp ID
  • externalId - 您的系统 ID
  • status - 按状态过滤
  • limitpage - 分页

状态历史

跟踪所有状态更改:
GET /api/v2/ramps/{rampId}/status-history
返回所有状态转换的时间顺序列表。

Ramp 收据

以多种格式获取交易收据:
GET /api/v2/ramps/{rampId}/receipt
返回适合在浏览器或电子邮件中显示的 HTML 收据。

预充值 Ramps

预充值 ramps 即时执行:
{
  "quotationId": "quot-id",
  "userId": "user-id",
  "accountId": "account-id"
}
当报价使用 PRE_FUNDPRE_FUND_* 方法时:
  • 不需要支付确认
  • 即时执行
  • 立即状态进展
  • 更快的完成(分钟而不是小时)
状态流程: CREATEDCONVERSION_PROCESSINGCASH_OUT_PROCESSINGCOMPLETED

处理失败

常见失败原因

原因描述解决方案
INSUFFICIENT_FUNDS来源余额不足用户需要为账户充值
INVALID_ACCOUNT目的地账户无效验证账户详情
COMPLIANCE_HOLD需要合规审查等待人工审查
PROVIDER_ERROR外部提供商问题重试或联系支持
EXPIRED_QUOTE报价已过期创建新报价

检查失败详情

{
  "id": "ramp-id",
  "status": "FAILED",
  "details": "INSUFFICIENT_FUNDS: Not enough balance in pre-fund account",
  "transferProof": null
}

错误处理指南

了解处理 ramp 失败的最佳实践

Ramps 的 Webhooks

订阅 ramp 事件以获取实时更新: 事件类型: RAMP 操作:
  • CREATE - Ramp 已初始化
  • UPDATE - Ramp 状态已更改(包括所有状态转换)
  • DELETE - Ramp 已取消(罕见)
常见状态更新:
  • 已收到支付(CASH_IN_COMPLETED
  • 转换完成(CONVERSION_COMPLETED
  • Ramp 完全完成(COMPLETED
  • Ramp 失败(FAILED
  • Ramp 已取消(CANCELED
Webhook Payload Example
{
  "id": "evt_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "event": "RAMP",
  "action": "UPDATE",
  "data": {
    "id": "be4d353b-00a2-4309-9ef1-594f37dfb1fd",
    "userId": "2bc703f2-1c54-4cbb-a144-993e1d957688",
    "accountId": "f7df00af-5d12-4b33-b5ab-e2b32290ebad",
    "quotationId": "a656a475-0d53-479e-8f30-91582ecf450b",
    "type": "ON",
    "status": "COMPLETED",
    "cashInMethod": "PSE",
    "cashOutMethod": "POLYGON",
    "fromCurrency": "COP",
    "toCurrency": "USDC",
    "fromAmount": 100000,
    "toAmount": 23.81,
    "transferProof": "0x8e2b1f4645ebc8b6f658c860980567a63d283a42735be7401a7950306a2539b0",
    "isPreFunded": false,
    "active": true,
    "accounts": [
      {
        "id": "f7df00af-5d12-4b33-b5ab-e2b32290ebad",
        "amount": 23.81
      }
    ],
    "createdAt": "2025-01-15T23:46:10.226Z",
    "updatedAt": "2025-01-16T00:29:06.813Z"
  },
  "createdAt": "2025-01-16T00:29:06.813Z",
  "updatedAt": "2025-01-16T00:29:06.813Z",
  "attempts": 0
}
您将收到每个状态更改的 webhook 事件。按 data.status 过滤以处理特定转换,如 COMPLETEDFAILED

Ramp 更新

更新 ramp 信息(有限场景):
PATCH /api/v2/ramps/{rampId}
可更新:
  • 目的地账户(支付前)
  • 账户金额分配
收到支付后无法修改 ramps。

性能考虑

交易时间

方法典型时间网络依赖
PSE5-30 分钟✅ 是
SPEI10-60 分钟✅ 是
ACH1-3 个工作日✅ 是
Wire1 个工作日✅ 是
Crypto (Polygon)2-5 分钟⛓️ 区块链
Crypto (Solana)1-2 分钟⛓️ 区块链
Pre-Funded< 5 分钟❌ 否
为了获得最佳用户体验,对加密货币交易使用 Polygon,对即时执行使用预充值账户

最佳实践

  • 永远不要硬编码汇率
  • 为每个 ramp 创建新报价
  • 遵守报价过期时间(30 秒)
  • 向用户显示确切金额
  • 每 10-30 秒轮询一次 ramp 状态
  • 使用 webhooks 作为主要通知
  • 轮询作为备用机制
  • 向用户显示当前状态
  • 支付时间比预期长
  • 用户在支付期间关闭浏览器
  • 网络连接问题
  • 报价在创建前过期
  • 余额不足场景
  • 为每个 ramp 提供唯一的 externalId
  • 防止重复交易
  • 实现幂等重试
  • 简化对账
  • 立即保存 ramp ID
  • 存储所有响应数据
  • 记录状态转换
  • 保留支付证明
  • 归档已完成的 ramps

测试 Ramps

沙盒测试

在沙盒中,使用 faker 端点:
// Create ramp
const ramp = await createRamp(quoteId, userId, accountId);

// Simulate payment (sandbox only)
await fetch('/api/v2/faker/cash-in', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${token}` },
  body: JSON.stringify({ rampId: ramp.id })
});

// Poll for completion
const completed = await waitForStatus(ramp.id, 'COMPLETED');

生产测试

从小额开始:
  1. 使用最小值测试1010-50 等值)
  2. 验证完整流程端到端
  3. 检查 webhook 交付
  4. 确认收据生成
  5. 验证会计
  6. 扩展到更大金额

常见问题

只有在尚未收到支付的情况下。一旦现金入账完成,ramp 将处理到完成。
如果未支付,ramps 在 24 小时后过期并移动到 EXPIRED 状态。您无需采取任何操作。
  • Polygon: 2-5 分钟(128 个区块确认)
  • Solana: 1-2 分钟
  • Ethereum: 10-15 分钟
  • Tron: 1-3 分钟
不可以。每个 ramp 需要自己的报价。报价是单次使用的,并在 30 秒后过期。
当您使用报价创建 ramp 时,汇率被锁定。用户收到确切的报价金额。

高级功能

拆分支付

将资金发送到多个账户:
{
  "quotationId": "quot-id",
  "userId": "user-id",
  "accounts": [
    { "id": "wallet-1", "amount": 60 },
    { "id": "wallet-2", "amount": 40 }
  ]
}

交易元数据

在您的 ramp 中存储自定义数据:
{
  "quotationId": "quot-id",
  "userId": "user-id",
  "accountId": "account-id",
  "externalId": "order-123",
  "details": {
    "cashIn": {
      "transfiyaAccount": "3001234567"
    }
  }
}

下一步