收银台
用托管收银台承接稳定币支付,商户后端创建会话后将用户跳转到支付页。
收银台适合想降低前端集成成本的场景:你的后端创建收银台会话,然后把用户跳转到 StableOps 托管支付页;支付页展示链、资产、收款地址和订单状态。这样商户侧只需要处理 创建会话 和 接收 webhook,不用自己拼支付 UI。
使用方式
- 后端创建收银台会话:在你的服务端用 API key 调用
stableops.checkoutSessions.create,传入商户订单号、金额、可接受资产、展示标题、成功返回地址和取消返回地址。 - 把用户跳转到收银台:创建成功后使用响应里的
checkout.url做 303 跳转,或把 URL 返回给前端再window.location.assign(checkout.url)。 - 用户在收银台付款:托管页面展示链、资产、准确金额和收款地址,并实时跟踪状态。用户可以用浏览器钱包支付——页面连接已注入的钱包,支持自动或手动选择网络——也可以用手动转账复制地址,从任意钱包或交易所发送。两种方式 scanner 都按收款地址匹配入金。
- 用 Webhook 完成业务动作:你的后端接收并验签
payment.confirmed/payment.finalized等 Webhook 事件,再开通服务、入账或更新订单状态。不要只依赖用户跳回successUrl,它只是前端体验,不是最终支付凭证。
后端创建会话
import { StableOps } from '@stableops/api-sdk'
const stableops = new StableOps({
apiKey: process.env.STABLEOPS_API_KEY!,
})
const merchantOrderId = 'order_123'
const checkout = await stableops.checkoutSessions.create(
{
merchantOrderId,
amount: '49.00',
amountMode: 'auto',
acceptedAssets: [{ chain: 'base-sepolia', asset: 'USDC' }],
title: 'Acme Pro',
successUrl: `https://app.example.com/success?orderId=${merchantOrderId}`,
cancelUrl: `https://app.example.com/billing?orderId=${merchantOrderId}`,
},
{ idempotencyKey: 'order_123' },
)
return Response.redirect(checkout.url!, 303)参数建议
merchantOrderId:使用你系统里的订单号,并同时作为幂等键,避免重复创建。amountMode: 'auto':让 StableOps 自动微调金额,降低共享收款地址下的撞单概率。acceptedAssets:先从测试网资产开始;生产环境再切到你实际支持的主网资产。successUrl/cancelUrl:只用于用户体验。最终业务状态以 webhook 为准。metadata:可以放套餐、用户 ID、内部订单标签等,但公开收银台不会展示订单元数据。
在线测试
下面的测试面板会直接在浏览器里使用你的 sandbox API key 创建收银台会话,并跳转到公开收银台页面。你可以自定义商户订单号、金额、标题、描述、返回地址和订单元数据,方便验证商户侧参数会如何进入支付页。
仅用于文档测试,密钥只保存在当前浏览器。生产环境请在后端创建收银台会话。
安全注意
- 这个面板只用于 sandbox 测试。生产环境请在你的后端创建收银台会话,不要在浏览器暴露 live API key。
clientSecret是打开公开支付页的凭证,只应该发送给本次付款用户。- 收银台页面只读取公开会话,不需要 Clerk 登录,也不会暴露订单元数据。
处理 Webhook
收银台与 SDK 流程走的是同一套支付订单,支付状态始终通过 Webhook 到达——不要只信任 successUrl 跳转。
- Webhooks —— 事件类型、负载结构、投递/重试行为。
- 验证 Webhook 签名 —— 在解析 body 前校验
X-Product-Signature。 - Webhook 排障 —— 排查漏投/失败的投递。
这篇文档怎么样?
最后更新