跳转到内容
最后更新于

法币付款 API 支持组织从 Infini USD 余额向第三方银行账户付款 USD。

所有接口使用以下前缀:

/v2/payouts

最小接口集合

方法接口用途
POST/v2/payouts/quotes校验银行资料并获取有时效性的付款报价
POST/v2/payouts创建并立即开始执行法币付款
POST/v2/payouts/status/batch按创建时间区间分页查询付款状态
GET/v2/payouts/{payout_id}查询当前付款状态

第一期不提供收款人资源。银行收款资料随 Quote 一次性提交,并不可变地绑定到 quote_idPOST /v2/payouts 不能替换或修改这份收款资料。

选择需要固定的金额

创建 Quote 时,请选择需要准确固定的是收款金额,还是付款账户的总扣款金额。fee_paid_by 会改变 Infini 对两侧金额的计算方式,并非仅用于展示。第一期支持以下两种方式。

固定收款金额

适用于收款人必须准确收到指定金额的场景,例如支付发票。

{
  "amount": "1000.00",
  "amount_mode": "receive",
  "fee_paid_by": "PAYER"
}

收款人准确收到 1000.00 USDPAYER 表示手续费外扣,付款手续费会额外计入 Infini USD 余额的扣款金额。

  • receiving_amount1000.00
  • sending_amount = receiving_amount + transfer_fee_amount + bank_fee_amount
  • transfer_fee_amount = sending_amount × fee_rate_decimal;Infini 会反算并增加 sending_amount,确保扣除全部手续费后收款金额仍然准确。

例如,服务费率为 0.001、银行费为 50.00 USD 时,计算结果为 sending_amount=1051.05transfer_fee_amount=1.05receiving_amount=1000.00

固定总扣款金额

适用于付款总扣款不能超过固定预算的场景。

{
  "amount": "1000.00",
  "amount_mode": "send",
  "fee_paid_by": "BENEFICIARY"
}

Infini 准确扣除 1000.00 USDBENEFICIARY 表示手续费内扣,付款手续费从该金额中扣除,因此收款人的到账金额会更少。

  • sending_amount1000.00
  • receiving_amount = sending_amount - transfer_fee_amount - bank_fee_amount
  • transfer_fee_amount = sending_amount × fee_rate_decimal

例如,服务费率为 0.001、银行费为 50.00 USD 时,计算结果为 sending_amount=1000.00transfer_fee_amount=1.00receiving_amount=949.00

请仅使用以上字段组合。第一期不支持其他 amount_modefee_paid_by 组合。修改 fee_paid_by 后必须重新请求 Quote;quote_id 会固定 Payout 使用的手续费承担方和计算结果。

查看 Quote 金额

  • sending_amount:Infini USD 余额的实际总扣款金额。
  • receiving_amount:发送到收款银行账户的金额。
  • transfer_fee_amount:Infini 为处理该笔付款收取的服务费,不包含任何银行或通道费。
  • bank_fee_amount:所选银行及付款通道对应的银行手续费,例如 SWIFT、ACH 或 Wire。
  • billing.total_fee:所有手续费项目的合计,完整明细见 billing
  • fee_rate_decimal:Quote 使用的手续费率;rate 是汇率。

对账时,请使用 sending_amount 作为该笔付款的支出金额。

直接执行

API 付款不会进入后台人工审批流。POST /v2/payouts 会执行具有最终效力的付款前校验,并立即开始执行。

银行付款是异步过程。创建成功并返回 status=processing,表示请求已经通过 Infini 校验且付款执行已经开始,不代表收款人的银行账户已经到账。

completed 表示付款已经成功完成。对端银行仍可能拒收并退回一笔已经完成的汇款。原付款继续保持 completed,独立补偿退款通过可选的 return 对象体现。

Quote 与执行前校验

POST /v2/payouts/quotes 会校验收款资料,并执行初步的路由、金额、合规和限额检查。它返回一份包含收款资料、金额、汇率、费用和手续费承担方的有时效快照。一份 Quote:

  • 不会冻结组织余额;
  • 不会批准或创建付款;
  • 过期后不能继续使用;
  • 不保证当前限额、合规状态、余额或服务商可用性保持不变。

POST /v2/payouts 会在创建主付款单、扣减余额并开始银行执行前,重新执行所有关键校验。

幂等

client_reference_id 在商户范围内唯一标识一笔逻辑付款:

  • 使用相同引用和完全相同的业务请求重试时,返回已有资源;
  • 付款幂等重试时,响应中的 is_duplicate=true
  • 使用相同引用提交不同业务数据时,返回 409 idempotency_conflict

quote_id 和其他决定付款内容的字段都会参与幂等一致性比较。

并发提交

同一组织同一时间只允许一笔 POST /v2/payouts 请求进入执行流程。如果已有付款请求正在提交,API 会在消费 Quote、创建付款单和扣减组织余额之前拒绝并发请求:

{
  "code": 108015,
  "message": "Another payout submission is in progress. Please retry shortly.",
  "data": {
    "error": "payout_submission_in_progress",
    "field": null,
    "retryable": true
  }
}

请在短暂的随机退避后重试。同一笔逻辑付款应继续使用原来的 client_reference_id,以保持幂等保护有效。

错误码

应用层错误统一使用以下响应结构:

{
  "code": 108006,
  "message": "Insufficient payout balance",
  "data": {
    "error": "insufficient_balance",
    "field": "amount",
    "retryable": false
  }
}

程序逻辑应依据 codedata.error 处理,不要依赖仅用于排查问题的 message。仅当 data.retryable=true 且对应的临时状态已经恢复时才进行重试。HMAC 请求如果被网关直接拒绝,由于没有进入应用层,响应可能只有 message 字段。

Fiat Payout 专属业务错误码使用预留的 108001-108099 号段。HTTP 状态码与响应体 code 的职责不同:HTTP 状态码表示错误类别,code 表示稳定的业务原因。

HTTPcodedata.error可能接口可重试含义与处理方式
40030013invalid_parameterQuote、Create、Get、List请求字段缺失、格式错误、不支持或彼此不一致。修正 data.field 后重新提交。
401401authentication_failed全部接口HMAC 或应用鉴权失败。检查 API Key、签名、Date、Digest 和参与签名的请求路径。
403403permission_denied全部接口API Key 缺少所需权限、IP 策略拒绝请求,或组织无权访问对应资源。
403108010payout_source_account_not_foundQuote、Create组织没有 USD 付款账户。
404404resource_not_foundCreate、Get当前鉴权组织下不存在该 quote_idpayout_id
409108012idempotency_conflictCreateclient_reference_id 已被不同业务数据使用。不同的逻辑付款必须使用新的引用。
409108013quote_already_usedCreateQuote 已被消费,请重新获取 Quote。
409108014quote_not_activeCreateQuote 已不再处于可用状态,请重新获取 Quote。
409108015payout_submission_in_progressCreate当前组织已有另一笔付款正在提交。短暂随机退避后重试。
409108011payout_source_account_invalidQuote、CreateUSD 付款账户配置不一致,请联系 Infini 支持。
422108001invalid_fee_modeQuoteamount_modefee_paid_by 组合不受支持。
422108002quote_expiredCreateQuote 已过期。请重新获取 Quote,不要继续重试过期的 quote_id
422108003quote_unavailableQuote、CreateQuote 计算或其绑定的收款资料快照暂时不可用,短暂等待后重新获取 Quote。
422108004amount_exceeds_limitQuote金额超过当前支持的付款金额,请降低金额。
422108005amount_too_smallQuotesending_amount 必须大于 100 USD,请提高金额。
422108006insufficient_balanceCreate组织 USD 可用余额不足以支付 sending_amount,入金后再创建付款。
422108007daily_limit_exceededCreate该付款会超过账户共享的每日提现限额,请等待下一个限额周期或降低金额。
503108009payout_service_unavailableCreate付款执行服务或服务商流动性暂时不可用。同一笔逻辑付款稍后重试时继续使用原来的 client_reference_id
500500internal_error全部接口发生未预期的内部错误。可安全重试;如果持续出现,请携带 Request ID 联系 Infini 支持。

银行敏感信息

Quote 请求包含银行账户敏感信息,响应只返回脱敏账号。客户端不得将完整银行账号写入 URL、日志、client_reference_idstatement_reference 或其他自由文本元数据。

状态与对账

付款状态含义
processing已开始执行,等待最终结算
completed银行合作方在当前已知状态下报告付款完成
failed付款在银行成功完成前失败

API 付款不会出现待审批状态。

使用 POST /v2/payouts/status/batch 可以按包含边界的 Unix 秒时间区间对账付款。结果按创建时间倒序排列。接口使用页码分页:page 默认值为 1page_size 默认值为 20,且不能超过 100

银行退汇与退款

如果对端银行随后退回一笔已完成付款,status 继续保持 completedfailure 保持 nullreturn 返回独立退款信息:

{
  "status": "completed",
  "return": {
    "status": "refunded",
    "reason_code": "recipient_bank_rejected",
    "reason": "Beneficiary bank rejected the transfer",
    "returned_amount": "1000.00",
    "refund_amount": "1000.00",
    "retained_fee": "51.00",
    "currency": "USD",
    "returned_at": 1786674271
  }
}
  • returned_amount:银行合作方报告的退回金额。
  • refund_amount:实际退回组织余额的金额。
  • retained_fee:原付款未退还的手续费。
  • returned_at:独立退款入账时间。

未发生银行退汇时,returnnull

查询一笔已知付款时使用 GET /v2/payouts/{payout_id},按时间窗口对账时使用 POST /v2/payouts/status/batch;两者均为对外权威对账接口。