收银台
了解如何使用 StableOps 托管收银台创建一次性结账会话和可重复使用的付款链接,配置商户名称、图标、主题色与联系商户信息,查看支付转化漏斗,并通过经过验签的 Webhook 在链上最终确定后安全履约。
收银台适合想降低前端集成成本的场景:支付页由 StableOps 托管,负责展示链、资产、精确金额、收款地址和订单状态。商户可以从后端为每个业务订单创建一次性收银台会话,也可以在控制台创建一个可重复分享的付款链接;两种入口最终都会为每次付款生成独立支付订单,并通过同一套 Webhook 生命周期通知商户系统。
选择收款入口
| 入口 | 适用场景 | 公开地址 | 每次付款发生什么 |
|---|---|---|---|
| 一次性收银台会话 | 电商订单、发票、已经有内部订单号的业务 | /c/{sessionId}?client_secret=... | 商户后端先创建支付订单与会话,再把专属地址交给付款人 |
| 可重复使用的付款链接 | 固定金额商品、活动报名、打赏与线下二维码 | /p/{slug},不包含 API 密钥或 clientSecret | 付款人打开链接后,系统创建新的收银台会话与独立支付订单 |
一次性会话可以把 merchantOrderId 和 metadata 直接绑定到现有业务对象,适合需要精确追踪某一订单的场景。付款链接保存的是一份可重复使用的收款配置,不是一个可以反复支付的订单;如果每位付款人需要不同金额、客户信息或内部订单号,应继续使用一次性会话。
一次性收银台会话
- 后端创建收银台会话:在你的服务端用 API 密钥调用
stableops.checkoutSessions.create,传入商户订单号、金额、可接受资产、展示标题、成功返回地址、取消返回地址,以及可选的 WalletConnect 项目 ID。 - 把用户跳转到收银台:创建成功后使用响应里的
checkout.url做 303 跳转,或把 URL 返回给前端再window.location.assign(checkout.url)。 - 用户在收银台付款:托管页面展示链、资产、精确金额和收款地址,并实时跟踪状态。用户可以通过浏览器钱包、手机钱包或手动转账支付。无论采用哪种方式,链上扫描器都使用相同规则匹配转账。
- 用 Webhook 完成业务动作:你的后端接收并验签
payment.confirmed/payment.finalized等 Webhook 事件,再开通服务、入账或更新订单状态。不要只依赖用户跳回successUrl,它只是前端体验,不是最终支付凭证。
你可以通过在收银台 URL 上添加 lang 参数控制页面语言,例如 ?client_secret=...&lang=es。支持的值包括 en、zh、zh-Hant、es、pt-BR、vi、id、ja。如果不传 lang,收银台会尽量匹配用户的浏览器语言,并兜底为英文。
可重复使用的付款链接
在控制台展开“收银台”菜单并打开“付款链接”页面,点击“新建付款链接”后会打开创建对话框。无需编写代码,只需填写:
- 名称,以及可选的付款说明;
- 固定基础金额;
auto或exact金额分配方式;- 一组允许付款的链与资产,控制台会按当前沙盒或生产环境过滤可选项。
创建后,控制台会生成形如 https://pay.stableops.dev/p/{slug} 的稳定地址。你可以复制链接、在新窗口打开,或者把它编码成线下二维码。付款链接默认启用,也可以随时停用和重新启用。
每次打开链接都会创建独立订单
付款人打开 /p/{slug} 时,公开页面会根据付款链接保存的配置创建一个新的收银台会话和支付订单,然后跳转到该会话的 /c/{sessionId} 页面。每次付款都有自己的:
- 支付订单号、收银台会话号与
clientSecret; - 精确应付金额、候选链与收款地址;
- 订单有效期、确认进度和最终状态。
同一浏览器标签页在当前会话有效期内刷新时,会复用该次创建请求,避免因为刷新重复占用地址。会话过期后再次打开链接,才会开始新的付款尝试。
停用付款链接只会阻止它继续创建新会话,不会取消已经生成的支付订单或收银台会话。若链接被公开传播、活动已经结束或出现异常流量,应及时停用,并检查每条链的收款地址池是否仍有足够容量。
amountMode: 'auto' 适合共享地址:只有基础金额在所有候选共享地址上都发生冲突时,系统才会按代币最小单位微调应付金额。exact 则始终使用固定金额;付款人仍必须支付页面返回的 order.amount,不能少付、多付或拆成多笔。
配置收银台
在控制台展开“收银台”菜单并打开“品牌配置”页面,可以配置以下品牌内容,并在保存前查看右侧的基础收银台预览:
| 设置 | 在收银台中的用途 |
|---|---|
| 商户名称 | 替换页首默认品牌名称 |
| 图标地址 | 展示商户图标;地址必须能被付款人的浏览器公开访问 |
| 主色 | 用于主要按钮、进度和重点交互 |
| 强调色 | 用于悬停态及辅助品牌元素 |
| 联系商户 | 网页地址会在新页面打开;多语言文案会按收银台当前语言通过对话框展示 |
多语言联系文案目前支持简体中文、繁体中文、英语、西班牙语、葡萄牙语、越南语、印度尼西亚语和日语。未填写付款人当前使用的语言时,收银台使用英文文案兜底;英文也未填写时不显示“联系商户”入口。
品牌设置按组织和环境隔离,沙盒与生产环境需要分别维护。无论会话来自后端 API 还是付款链接,创建时都会保存一份当时的品牌快照;以后修改品牌只影响新建会话,不会改变已经打开或仍在处理中的会话。将某一字段清空并保存,可以恢复该字段的默认显示。
查看收银台转化漏斗
“付款链接”页面顶部展示当前组织和环境最近 30 天的收银台漏斗。统计按浏览器会话去重,依次包括:
- 打开页面:付款人打开收银台页面;
- 载入会话:页面成功读取收银台会话;
- 开始付款:付款人开始使用浏览器钱包、WalletConnect 或手动转账;
- 已提交交易:钱包已经提交链上交易;
- 完成付款:支付订单到达
finalized; - 付款转化率:完成付款的浏览器会话数除以打开页面的浏览器会话数。
付款链接列表中的“生成会话”是该链接累计创建的会话数量,“转化率”则使用最近 30 天的页面打开与完成数据。漏斗用于发现页面载入、钱包连接或付款提交环节的流失,不是财务账本,也不能代替 Webhook、支付订单列表与每日对账。
支持的钱包方式
收银台支付页支持以下三种支付方式,用户可根据场景自由选择。
浏览器钱包(桌面)
页面自动检测已注入的钱包提供者并连接,用户确认交易后发送。
- EVM 链:支持 MetaMask、Rabby 等通过
window.ethereum注入的钱包,共 12 条链。 - Solana:支持 Phantom 等通过
window.phantom.solana注入的钱包,主网 + devnet。 - TRON:支持 TronLink 等通过
window.tronLink.tronWeb注入的钱包,主网 + Nile。
手机钱包(WalletConnect)
需要创建会话时传入 walletConnectProjectId。收银台展示手机钱包列表,用户选择后通过 WalletConnect 二维码或深链连接并签名。支持 EVM、Solana 和 TRON 链——TRON 通过 WalletConnect 请求钱包对转账交易签名,收银台再广播上链。
当前控制台创建的付款链接不提供 WalletConnect 项目 ID 输入项,因此这类链接默认只展示浏览器注入钱包与手动转账。如果需要手机钱包入口,请由后端创建一次性收银台会话并传入 walletConnectProjectId。
兼容的钱包:MetaMask、Trust Wallet、Coinbase Wallet、OKX、Binance Wallet、TokenPocket、TronLink、Rainbow、Zerion、Ledger Live,以及任意 WalletConnect 兼容钱包。收银台会按订单的链族过滤钱包;TRON 订单展示支持 TRON 的钱包:Trust Wallet、TokenPocket、TronLink。
Solana 和 TRON 的钱包支付需要 RPC 节点来构造并广播转账交易,收银台已自动处理:主网订单经 StableOps 后端 RPC 代理转发,但测试网订单(Solana Devnet、TRON Nile)直连公共 RPC 节点,免费但偶尔可能限流,如果测试网支付构造失败,稍候重试即可。
手动转账
任何场景都可用。用户从页面上复制收款地址,在自己选择的任意钱包或交易所发送,链上扫描器按收款地址匹配入金。
后端创建会话
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' }],
expiresAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(),
title: 'StableOps Starter Plan',
successUrl: `https://stableops.dev?result=success&orderId=${merchantOrderId}`,
cancelUrl: `https://stableops.dev?result=canceled&orderId=${merchantOrderId}`,
walletConnectProjectId: process.env.WALLETCONNECT_PROJECT_ID,
},
{ idempotencyKey: 'order_123' },
)
return Response.redirect(checkout.url!, 303)参数建议
merchantOrderId:使用你系统里的订单号,并同时作为幂等键,避免重复创建。amountMode: 'auto':让 StableOps 自动微调金额,降低共享收款地址下的撞单概率。acceptedAssets:先从测试网资产开始;生产环境再切到你实际支持的主网资产。successUrl/cancelUrl:只用于用户体验。最终业务状态以 Webhook 为准。walletConnectProjectId:可选,可在 Reown Cloud 免费注册获取。传入后,收银台展示手机钱包入口,EVM、Solana 和 TRON 链均通过 WalletConnect 二维码或深链连接手机钱包签名:- EVM 和 Solana 链:MetaMask、Trust Wallet、Coinbase、OKX、Binance Wallet、Rainbow、Zerion、Ledger Live 及通用 WalletConnect。
- TRON 链:Trust Wallet、TokenPocket、TronLink。钱包通过 WalletConnect 对转账交易签名,收银台再广播上链。
- 不传时不展示手机钱包入口(EVM / Solana / TRON 均不展示);用户仍可用浏览器注入钱包或手动转账支付。
metadata:可以放套餐、用户 ID、内部订单标签等,但公开收银台不会展示订单元数据。
在线测试
下面的测试面板会直接在浏览器里使用你的沙盒 API 密钥创建收银台会话,并跳转到公开收银台页面。你可以自定义商户订单号、金额、标题、描述、返回地址和订单元数据,方便验证商户侧参数会如何进入支付页。
请使用 sandbox key;它只保存在你的浏览器并直接发送给 API。生产环境请在服务端调用 API,不要在浏览器中调用。
开启时会在创建会话前为本订单导入一个确定性 burner 地址,适合 org 还没有任何收款地址的场景。若只想使用自己管理的地址,请关闭。
安全注意
- 这个面板只用于沙盒测试。生产环境请在你的后端创建收银台会话,不要在浏览器暴露生产 API 密钥。
clientSecret是打开公开支付页的凭证,只应该发送给本次付款用户。- 收银台页面只读取公开会话,不需要 Clerk 登录,也不会暴露订单元数据。
- 付款链接本身不包含 API 密钥或
clientSecret,但它是公开且可重复使用的入口;任何拿到地址的人都可以发起新的付款尝试。只在预期渠道分享,并监控地址池容量与转化漏斗。 - 停用付款链接不能撤销已经生成的支付订单。需要停止一笔现有订单时,应按支付订单自身的状态和取消规则处理。
处理 Webhook
收银台与 SDK 流程走的是同一套支付订单,支付状态始终通过 Webhook 到达——不要只信任 successUrl 跳转。
- Webhooks —— 事件类型、负载结构、投递/重试行为。
- 验证 Webhook 签名 —— 在解析 body 前校验
X-Product-Signature。 - Webhook 排障 —— 排查漏投/失败的投递。
这篇文档怎么样?
最后更新