订阅接入(API)
订阅 API 用于把你自己系统里的循环收费,接到 Taria Pay 的稳定币收款上。你的服务端创建套餐、为你自己的客户开订阅,然后通过 webhook 把订阅状态同步回你的系统。
适合谁
适合已经有自己产品、定价和客户系统的商户(SaaS、会员系统、B2B 服务)。你在自己系统里管理用户和权益,Taria Pay 负责按账期收款并回传状态。
如果你没有自己的系统,只想要一个可以分享的订阅页,请用商家后台的订阅套餐(no-code),不需要写代码。
重要边界
当前是客户主动续费流程,Taria Pay 不会自动从客户钱包扣款。订阅 API 给你的是:
- 为某个客户开订阅,并拿到一个付款链接交给他付当期;
- 通过 webhook 同步订阅状态,用来在你自己系统里开通或撤销权益。
它不是自动代扣的 recurring billing。真正的自动扣款需要额外的授权模型,目前尚未提供。
请求由谁发起
必须由你的服务端发起,API key 只能保存在服务端。
两步接入
1. 创建套餐(价格对象)
套餐是可复用的价格定义(金额 + 币种 + 账期),一次创建即可给多个客户开订阅。
const plan = await tariapay.subscriptionPlans.create({
name: "Pro",
amount: "10",
currency: "USDC",
interval: "monthly", // weekly | monthly | quarterly | yearly
});2. 为你的客户开订阅
传入 planId 和你自己系统里的客户标识(merchantCustomerId,可选附带 customerEmail)。返回订阅、首个账期 invoice,以及一个带 checkoutUrl 的付款订单——把 checkoutUrl 交给客户付当期。
const { subscription, invoice, paymentIntent } = await tariapay.subscriptions.create({
planId: plan.id,
merchantCustomerId: "user_42", // 你系统里的用户 ID,会在 webhook 中原样回传
customerEmail: "buyer@example.com", // 可选:用于续费提醒邮件
});
return { checkoutUrl: paymentIntent.checkoutUrl };同一个 (套餐, 客户) 再次调用会复用同一个订阅,不会重复创建;当期 invoice 未付时也会复用同一个付款订单,不会重复开账。
在你的页面里嵌入订阅入口(浏览器 SDK)
第 2 步拿到的 paymentIntent.checkoutUrl 是托管结账页。你可以直接跳转,也可以用 @tariapay/sdk/browser 在你自己的页面里弹出它——买家不离开你的网站,连钱包、签名、付款都由托管页负责(你不用碰钱包逻辑)。
弹窗方式(推荐)
import { subscribe } from "@tariapay/sdk/browser";
button.addEventListener("click", async () => {
// 调你自己的服务端开订阅,拿回 checkoutUrl(见上面第 2 步)
const { checkoutUrl } = await fetch("/api/subscribe", { method: "POST" }).then((r) =>
r.json(),
);
await subscribe({
checkoutUrl,
mode: "popup", // 默认弹窗;整页跳转用 "redirect"
onComplete: () => showActivatedUI(), // 仅即时 UI,别据此开通权益
onClose: () => {}, // 买家关闭弹窗、未完成
});
});mode: "popup"(默认)弹出托管结账页,买家停留在你的页面;mode: "redirect"整页跳转。- 弹窗被浏览器拦截会抛
TariaPayEmbedError(code: "popup_blocked")——务必从点击事件里调用,并准备好降级到mode: "redirect"。 onComplete只用于即时刷新界面,不要据此开通权益。订阅是否真正激活以subscription.*webhook 为准(见下文)。SDK 只接受来自结账页源、且来自它打开的那个窗口的完成消息,其他页面伪造不了。
声明式按钮(无服务端)
如果你用的是后台创建的套餐(有 slug),可以用 mountSubscribeButtons() 给页面上的按钮自动挂上点击处理,无需自己写开订阅的服务端逻辑:
import { mountSubscribeButtons } from "@tariapay/sdk/browser";
mountSubscribeButtons({ checkoutBaseUrl: "https://checkout.tariapay.com" });<button
data-tariapay-plan="pro-monthly"
data-tariapay-mode="popup"
data-tariapay-customer-id="user_42"
data-tariapay-email="buyer@example.com"
>
用稳定币订阅
</button>每个按钮可用 data-tariapay-base、data-tariapay-mode、data-tariapay-customer-id、data-tariapay-email 覆盖;data-tariapay-customer-id 会作为 merchantCustomerId 回传 webhook,data-tariapay-email 预填买家邮箱。
REST 示例
# 创建套餐
curl -X POST "https://api.tariapay.com/v1/subscription-plans" \
-H "Authorization: Bearer tpk_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Pro", "amount": "10", "currency": "USDC", "interval": "monthly" }'
# 为客户开订阅
curl -X POST "https://api.tariapay.com/v1/subscriptions" \
-H "Authorization: Bearer tpk_..." \
-H "Content-Type: application/json" \
-d '{ "planId": "plan_...", "merchantCustomerId": "user_42" }'续费
账期到期不会自动扣款。续费有两种方式,可同时使用:
- 监听订阅 webhook,在你自己系统里到期前提醒客户回来付款;
- 如果客户留了邮箱,Taria Pay 会在账期结束前发送一封一键续费邮件。
客户再次付款会作为续费 invoice 记到同一个订阅下,并把订阅周期延长。
用 webhook 同步状态
业务落账以 webhook 为准,不要只依赖客户是否跳回成功页。订阅相关事件:
| 事件 | 含义 |
|---|---|
subscription.created | 首笔付款确认,订阅激活 |
subscription.renewed | 后续账期续费确认 |
subscription.past_due | 账期到期未续费,或已确认付款发生链上 reorg |
subscription.canceled | 订阅被取消(立即取消,或到期取消在周期末生效) |
subscription.expired | 过宽限期仍未续费,订阅自动失效 |
payload 的 data 包含 subscription、invoice 和 paymentIntent(生命周期类事件 subscription.canceled / past_due / expired 时 invoice 和 paymentIntent 可能为 null)。subscription.merchantCustomerId 会原样回传你的客户 ID。
const event = tariapay.webhooks.constructEvent(
rawBody,
req.headers,
process.env.TARIAPAY_WEBHOOK_SECRET!,
);
switch (event.type) {
case "subscription.created":
case "subscription.renewed":
// event.data.subscription.merchantCustomerId:开通/延长权益
break;
case "subscription.past_due":
// 暂停权益或提醒客户重新付款
break;
case "subscription.canceled":
case "subscription.expired":
// 撤销权益
break;
default:
break;
}查询与取消
| 方法 | 路径 | 作用 |
|---|---|---|
GET | /subscriptions?customerId=user_42 | 按你自己的客户 ID 查订阅 |
GET | /subscriptions/:id | 获取单个订阅 |
GET | /subscriptions/:id/invoices | 列出订阅的账期 invoice |
POST | /subscriptions/:id/cancel | 取消订阅(默认立即;传 { "atPeriodEnd": true } 在周期末取消) |
默认立即取消并撤销权益。若想让客户用到当前已付周期结束再失效,传 atPeriodEnd: true——订阅保持 active 并打上 cancelAtPeriodEnd 标记,到期后由系统在周期末改为 canceled:
await tariapay.subscriptions.cancel("sub_...", { atPeriodEnd: true });订阅状态
incomplete:已创建订阅,首笔付款尚未确认。active:最近账期付款已确认,当前周期有效。past_due:账期到期未续费(或确认付款发生 reorg),需要重新收款,仍在宽限期内可恢复。canceled:已取消(立即取消,或到期取消在周期末生效)。expired:过宽限期仍未续费,已自动失效。