托管收银台模式是 Infini 最推荐的接入方式。商户只需创建订单、跳转 checkout_url 并处理 Webhook,即可完成支付集成。本章节仅包含托管收银台模式的 API 文档与对应字段说明。
所有接口前缀:
/v1/acquiring
POST /v1/acquiring/order
用于创建订单,并返回托管收银台的访问 URL (checkout_url)。
Content-Type: application/json
Date: {GMT Time}
Authorization: Signature ...| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| amount | string/number | 是 | 订单法币金额(最多 6 位小数) |
| currency | string | 是 | 法币,如 "USD" |
| request_id | string | 是 | 商户自定义生成的幂等key, UUID "a759b99a-9d22-433d-bced-ab1d2e1bea1d" |
| client_reference | string | 否 | 商户自定义订单号,建议保持唯一 |
| description | string | 否 | 订单描述 |
| expires_in | number | 否 | 订单过期相对时间(Unix 秒);不传则使用后台默认值 |
| merchant_alias | string | 否 | 收银台账单名称(覆盖后台配置) |
| success_url | string | 否 | 订单支付成功跳转回商户地址 |
| failure_url | string | 否 | 订单支付失败跳转回商户地址 |
{
"order_id": "10290d05-xxxx",
"amount": "100",
"currency": "USD",
"checkout_url": "https://checkout.infini.money/pay/xxxx",
"expires_in": 3600
}GET /v1/acquiring/order?order_id ={order_id}
返回订单的实时状态信息。
实时计算字段,反映订单当前的支付进度(基于 amount_confirmed vs order_amount)。
| 值 | 说明 |
|---|---|
pending | 待支付,未收到任何资金 |
partial_paid | 部分支付,收到部分资金但不足 |
paid | 已支付,收到足够资金 |
overpaid | 超额支付,收到的资金超过订单金额 |
expired | 已过期 |
closed | 已过期且仅收到部分资金 |
数据库存储字段,记录订单的处理状态。
| 值 | 说明 |
|---|---|
pending | 待支付 |
processing | 处理中(已收到部分资金) |
paid | 已支付 |
partial_paid | 部分支付已过期 |
expired | 已过期未支付 |
Webhook 事件 Webhook 中的 status 字段和查询接口中的 pay_status 一致。
{
"order_id": "ord-123",
"status": "processing",
"pay_status": "processing",
"amount": "100",
"currency": "USD",
"amount_confirming": "0",
"amount_confirmed": "0.5",
"expires_at": 1763512195,
"created_at": 1763512000,
"exception_tags": ["wrong_currency"],
"client_reference": "ORDER-001"
}POST /v1/acquiring/token/reissue
用于重新生成托管收银台 URL,适用于支付页面关闭、Token 过期等场景。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| order_id | string | 是 | 订单唯一 ID |
{
"order_id": "ord-123",
"checkout_url": "https://checkout.infini.money/pay/xxxx"
}商户可在后台配置 Webhook 接收地址。订单状态变化时,Infini 会主动推送以下事件:
- order.created
- order.processing
- order.completed
- order.expired
- order.late_payment
| Header | 说明 |
|---|---|
| X-Webhook-Timestamp | Unix 时间戳 |
| X-Webhook-Event-Id | 事件唯一 ID |
| X-Webhook-Signature | Webhook HMAC 签名 |
{
"event": "order.completed",
"order_id": "ord-123",
"client_reference": "ORDER-001",
"amount": "100",
"currency": "USD",
"status": "paid",
"amount_confirmed": "100",
"amount_confirming": "0",
"created_at": 1763512195,
"updated_at": 1763512573,
"exception_tags": []
}Webhook 验签方法请参考 章节 4:授权与安全机制。
所有错误返回格式:
{
"code": 40001,
"message": "Invalid request",
"detail": "expires_at must be greater than current timestamp"
}| HTTP | Code | 描述 |
|---|---|---|
| 400 | 40003 | amount 必须为正数 |
| 400 | 40006 | amount 必须大于 0.01 |
| 401 | 401 | HMAC 签名无效 |
| 404 | 40401 | 订单不存在 |
| 409 | 40902 | client_reference 重复 |
| 409 | 40906 | 订单已过期 |
以下示例展示完整流程:创建订单 → 跳转收银台 → Webhook → 重新签发 Token。
import hmac, hashlib, base64, time
from datetime import datetime, timezone
import requests
key_id = "merchant-001-prod"
secret_key = b"your-secret-key"
def create_order(amount):
method = "POST"
path = "/v1/acquiring/order"
gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
signing_string = f"{key_id}\n{method} {path}\ndate: {gmt_time}\n"
signature = base64.b64encode(
hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest()
).decode()
response = requests.post(
f"https://openapi.infini.money{path}",
json ={
"amount": amount,
"currency": "USD",
"client_reference": "ORDER-2024-001",
"description": "Product purchase",
"expires_at": int(time.time()) + 3600
},
headers ={
"Date": gmt_time,
"Authorization": f'Signature keyId="{key_id}",algorithm="hmac-sha256",headers="@request-target date",signature="{signature}"',
"Content-Type": "application/json"
}
)
response.raise_for_status()
return response.json()@app.route('/create-payment', methods =['POST'])
def create_payment():
order = create_order(amount = request.json['amount'])
return {"checkout_url": order["checkout_url"]}@app.route('/webhook', methods = ['POST'])
def handle_webhook():
event = request.json
if event['event'] == 'order.completed':
process_fulfillment(event['order_id'], event['amount_confirmed'])
elif event['event'] == 'order.processing':
update_order_progress(event['order_id'], event['status'])
elif event['event'] == 'order.expired':
mark_order_expired(event['order_id'])
return {"status": "ok"}def reissue_checkout_token(order_id):
method = "POST"
path = "/v1/acquiring/token/reissue"
gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
signing_string = f"{key_id}\n{method} {path}\ndate: {gmt_time}\n"
signature = base64.b64encode(
hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest()
).decode()
response = requests.post(
f"https://api.infini.money{path}",
json ={"order_id": order_id},
headers ={
"Date": gmt_time,
"Authorization": f'Signature keyId="{key_id}",algorithm="hmac-sha256",headers="@request-target date",signature="{signature}"',
"Content-Type": "application/json"
}
)
response.raise_for_status()
return response.json()