快速开始
十分钟跑通第一笔稳定币支付并验证 Webhook。
1. 安装 SDK
pnpm add @stableops/api-sdk @stableops/wallet-sdkAPI SDK 纯 TypeScript 实现,运行时只依赖 Node crypto。
钱包 SDK 用于浏览器端调用用户的钱包发起链上转账。
2. 配置服务端客户端
import { StableOps } from '@stableops/api-sdk'
const client = new StableOps({
apiKey: process.env.STABLEOPS_API_KEY!,
environment: 'sandbox', // 默认 sandbox。测试后再切到 "live"。
})不要把 STABLEOPS_API_KEY 暴露给浏览器。创建支付单、查询订单等商户 API
调用应放在你的服务端完成。
3. 在 Dashboard 完成准备
创建第一笔订单前,先在 Dashboard 里完成两件事:
- 导入收款地址:导入你接受的链上收款地址。StableOps 会从地址池分配一个地址给支付单。
- 注册 Webhook 端点:填写你的回调 URL,例如
https://your-app.example.com/hooks/stableops。
Webhook secret 只会在创建或轮换时展示,请保存到服务端环境变量,例如
STABLEOPS_WEBHOOK_SECRET。需要自动化时,也可以使用
收款地址 API 与
Webhook 端点 API。
4. 创建支付单
const order = await client.paymentOrders.create(
{
merchantOrderId: 'sub_89231_2026_06',
amount: '49.00',
settlementAsset: 'USDC',
acceptedAssets: [
{ chain: 'base-sepolia', asset: 'USDC' },
{ chain: 'ethereum-sepolia', asset: 'USDC' },
],
// 30 分钟后未支付自动过期,订单状态推进到 expired 并释放收款地址。
expiresAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(),
metadata: { customerId: 'cus_9821', plan: 'pro_monthly' },
},
{ idempotencyKey: crypto.randomUUID() },
)
console.log(order.paymentInstructions)
// [
// { chain: 'base-sepolia', asset: 'USDC', address: '0x...' },
// { chain: 'ethereum-sepolia', asset: 'USDC', address: '0x...' },
// ]把订单 id、金额和 paymentInstructions 返回给你的前端即可;不要把 API key
一起下发。
5. 调用钱包 SDK 支付
前端拿到服务端创建的订单后,用钱包 SDK 调用浏览器钱包发起链上转账:
import {
getInjectedWalletProviders,
selectWalletPaymentInstruction,
sendWalletPayment,
} from '@stableops/wallet-sdk'
const { instruction, provider } = selectWalletPaymentInstruction(
order.paymentInstructions,
getInjectedWalletProviders(),
)
const sent = await sendWalletPayment({
provider,
amount: order.amount,
instruction,
})
console.log(sent.txHash)上面的例子会按当前浏览器已有的钱包,从候选链中选出一条可支付指令。TRON、Solana 或自定义多链选择器可以参考 钱包 SDK。转账上链后,StableOps 的 scanner 会按 订单收款地址匹配入金,并在状态变化时投递 Webhook。
钱包 SDK 只是为了方便——并非必须。付款方可以用任意方式完成这笔转账:手动从 MetaMask / Phantom / TronLink 等钱包发送、从交易所提币、或用其他后端脚本,只要把 订单金额(
order.amount)转到对应链的paymentInstructions[].address即可。scanner 一律按(链, 收款地址)匹配入金,与资金来源无关。
6. 验证签名
每一次投递都带 X-Product-Signature: t=…,v1=…。在解析 body 之前调用 SDK 的
常量时间验签助手:
import { verifySignature } from '@stableops/api-sdk/webhooks'
export async function POST(req: Request) {
const rawBody = await req.text()
const result = verifySignature({
secrets: [process.env.STABLEOPS_WEBHOOK_SECRET!],
header: req.headers.get('x-product-signature') ?? undefined,
rawBody,
})
if (!result.ok) {
return new Response(`invalid: ${result.reason}`, { status: 400 })
}
const event = JSON.parse(rawBody)
// 用 event.data.payment_order_id 与自家账本对账即可。
return new Response('ok')
}你刚刚完成
- 在 Dashboard 导入了收款地址并注册了 Webhook 端点。
- 创建了一笔带具体收款地址的订单。
- 通过钱包 SDK 发起了一笔链上支付。
- 端到端验证了一次签名的 Webhook 投递。