kemBusiness
平台产品运作方式薪酬发放开发者常见问题
登录立即开始↗

开发者文档

使用 Kem Business API 收取 USDT 付款所需的一切:身份认证、支付端点,以及驱动订单状态的签名 Webhooks。

身份认证付款错误与限制Webhooks测试

身份认证

在仪表盘的「API 密钥」中创建密钥,并在每个请求中以 Bearer token 发送。测试密钥(sk_test_…)创建测试付款;正式密钥(sk_live_…)会转移真实资金。

Authorization: Bearer sk_live_...   # or sk_test_...
Base URL: https://api-business.kemapp.io

付款

创建付款并将客户引导至托管的 checkout_url——钱包、网络与确认全部由 Kem 处理。可通过查询付款跟踪状态,更推荐使用 Webhooks。

POST/v1/payments
curl -X POST https://api-business.kemapp.io/v1/payments \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042" \
  -d '{
    "amount": "25.000000",
    "currency": "USDT",
    "merchant_reference": "order-1042",
    "customer_email": "[email protected]",
    "description": "Pro plan",
    "return_url": "https://yourshop.example/thanks",
    "metadata": {"order_id": "1042"}
  }'
{
  "id": "pay_01J...",
  "status": "pending",
  "mode": "test",
  "amount": "25.000000",
  "amount_minor": 25000000,
  "currency": "USDT",
  "merchant_reference": "order-1042",
  "checkout_url": "https://pay.kemapp.io/pay_01J...",
  "checkout_expires_at": "2026-07-13T13:30:00+00:00",
  "created_at": "2026-07-13T13:00:00+00:00"
}

Idempotency-Key — 可选但推荐——使用相同 key 重试会返回原付款,而不是创建重复项。

GET/v1/payments— query: status, limit (1–100, default 20), cursor · returns has_more, next_cursor
GET/v1/payments/{id}

amount — decimal string with 6 places ("25.000000"); amount_minor — the same value as an integer in micro-USDT.

付款生命周期

pending → detected → succeeded · failed · expired

pending——等待转账 · detected——链上已发现,确认中 · succeeded——资金已确认入账(在此事件发货)· failed / expired——终态。退款变更以 Webhook 事件送达。

checkout window: 30 minutes, then → expired

错误与限制

所有错误使用同一信封。code 是稳定的——请依据 error.code 分支,而不是文案。

HTTP 4xx/5xx
{
  "error": {
    "code": "idempotency_conflict",
    "message": "Idempotency-Key reused with a different request"
  }
}
401 unauthorizedmissing or invalid API key
404 not_foundunknown payment id (or a live id with a test key)
409 idempotency_conflictIdempotency-Key reused with a different body — identical retries replay the original response
422 (validation)malformed body — bad amount, unsupported currency
429 rate_limitedover the per-key budget: 100 writes/min, 1000 reads/min

产品、支付链接、Webhook 端点与退款均在仪表盘中管理——暂无公开 REST 端点。

Webhooks

在仪表盘「Webhooks」中添加端点并选择关注的事件。每个端点都有自己的 whsec_… 签名密钥,仅在创建时显示一次。

payment.createdA payment intent was created (API or checkout link).
payment.detectedThe transfer was seen on-chain / in the KEM ledger; confirming.
payment.succeededFunds are confirmed in your business wallet. Fulfill on this event.
payment.failedThe payment failed.
payment.expiredThe checkout window closed without payment.
payment.refund.createdA refund was initiated from the dashboard.
payment.refund.succeededThe refund settled back to the customer.

事件负载

{
  "id": "payment_event_01J...",
  "type": "payment.succeeded",
  "created": "2026-07-13T13:04:12+00:00",
  "data": {
    "payment": {
      "id": "pay_01J...",
      "status": "succeeded",
      "amount_minor": 25000000,
      "currency": "USDT",
      "merchant_reference": "order-1042",
      "network": "TRON",
      "product_id": null,
      "payment_link_id": null
    }
  }
}

验证签名

每次推送都带有 Kem-Signature 请求头。用端点密钥对「<t>.」加原始请求体重新计算 HMAC,并做恒定时间比较。不匹配的一律拒绝。

Kem-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>

signed_input = "<t>." + raw_request_body
v1 = HMAC_SHA256(endpoint_secret, signed_input)   # secret: whsec_...

# reject replays: drop the delivery when |now - t| > 300s
import crypto from "node:crypto";

export function verifyKemSignature(rawBody, header, secret) {
  // header: "t=1720000000,v1=hex"
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", secret)               // secret: whsec_...
    .update(`${parts.t}.`)
    .update(rawBody)                            // the RAW request bytes
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
import hashlib, hmac

def verify_kem_signature(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=") for p in header.split(","))
    expected = hmac.new(
        secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

投递与重试

请尽快返回 2xx。失败的投递会按退避策略重试,最终进入死信:

1m · 5m · 30m · 2h · 12h · 24h

测试

使用测试密钥可以在不转移资金的情况下走完付款全流程——模拟状态变更并观察你的 Webhooks 触发:

curl -X POST https://api-business.kemapp.io/v1/payments/{id}/_simulate/succeeded \
  -H "Authorization: Bearer sk_test_..."
BUILT IN THE GULF · SETTLED IN USDT ·
kemBusiness

收款,
就用稳定币。

打开后台,今天就收下你的第一笔 USDT 付款 — 或与我们在 20 分钟通话中一起走一遍流程。

打开后台↗预约通话↗

已是 kem 用户? 登录

产品

  • 登录
  • 创建账户
  • 预约演示

Kem 服务大众

  • 消费者 App
  • iOS — App Store
  • Android — Google Play

公司

  • Tether 投资
  • 隐私政策
  • 条款与条件

© 2026 Kem · Kem 通过 KEM BAHRAIN W.L.L(商业登记号 1-195589)运营,是一家在巴林注册的持牌加密资产服务提供商(CASP)。 [email protected]

立足海湾。