接入引导
你的服务端调用 API 创建收款,kokiwa 在到账后发 Webhook 通知你。资金由链上直接进你的钱包,kokiwa 不经手。
准备工作
以下都在商户后台完成。
- 注册验证邮箱,绑定身份验证器,保存恢复码。
- 创建项目一个项目对应你的一个产品或网站,有自己的收款地址、API key 和 Webhook。
- 设定收款在项目的“收款设置”页选择链、收款方式和代币,并在每条链上用钱包登记一次收款地址。收款地址记录在链上,只有登记它的钱包能修改。登记需要你的钱包付一点 gas,同一个钱包可以登记所有 EVM 链。
- 创建 API keykey 只显示一次,保存在服务端的环境变量里,不要放进前端或 App。
- 设置 Webhook在“回调通知”页填写 https 接收地址,保存签名密钥,再点“发送测试事件”确认能收到。
选择收款方式
| 支付单 | 充值地址 | |
|---|---|---|
| 适合 | 订单:金额固定,一次付清 | 账户充值:金额由用户决定,可以多次 |
| 地址 | 每张单一个,过期作废 | 每个用户一个,永久不变 |
| 用户怎么付 | 打开收银台,用钱包付款;BNB Chain 上也可以转账到专属地址 | 从钱包或交易所转账 |
| 链 | 全部 8 条 | BNB Chain |
| gas | 钱包付款由用户支付;转账的归集由 kokiwa 支付 | 转账由用户支付;归集由 kokiwa 支付 |
两种方式可以同时使用。
支付单
用户下单时创建支付单,把返回的 checkout_url 给用户打开。下面的请求会列出项目所有能收 USDT 的链,用户自己选择。
curl https://api.kokiwa.com/v1/payment_intents \
-H "Authorization: Bearer $KOKIWA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-10086" \
-d '{
"currency": "USDT",
"amount": "25.00",
"customer": "user_42",
"metadata": { "order_id": "10086" },
"success_url": "https://your-shop.com/orders/10086"
}'充值地址
customer 填你系统里的用户 ID。同一个用户重复调用,返回同一个地址。
curl https://api.kokiwa.com/v1/deposit_addresses \
-H "Authorization: Bearer $KOKIWA_KEY" \
-H "Content-Type: application/json" \
-d '{ "customer": "user_42" }'确认入账
付款在链上确认后,kokiwa 发送 Webhook。只凭 Webhook 入账,不要凭用户跳回 success_url。
- 支付单:收到
payment_intent.paid,把订单标记为已付款。 - 充值地址:收到
deposit.confirmed,给data.deposit.customer加余额。
每个事件都要校验签名,并按事件 id 去重,见 Webhook。
金额
所有金额都是代币数量的字符串,例如 "25.00"、"24.9125"。请求、返回和 Webhook 都一样,不需要按链换算精度。金额保留链上的完整精度,所以小数位数不固定。不要用浮点数计算。
退款
资金已经在你的钱包里,kokiwa 没有退款接口,也无法撤回付款。退款时从你的收款地址转给用户。请向用户索取退款地址,不要直接退到 transaction.from:用户从交易所提币时,那是交易所的地址。手续费不退还。
上线前检查
- API key 只存在服务端,不在代码仓库和日志里。
- Webhook 校验了签名,同一事件重复到达不会重复入账。
- 创建支付单时带了
Idempotency-Key,网络重试不会产生两张单。 - 处理了
payment_intent.paid_late:过期后才到账的付款不会被漏掉。 - 主网上已登记收款地址,并换成
sk_live_开头的 key。 - 收款地址的助记词已备份。