Skip to content

订阅接入(API)

订阅 API 用于把你自己系统里的循环收费,接到 Taria Pay 的稳定币收款上。你的服务端创建套餐、为你自己的客户开订阅,然后通过 webhook 把订阅状态同步回你的系统。

适合谁

适合已经有自己产品、定价和客户系统的商户(SaaS、会员系统、B2B 服务)。你在自己系统里管理用户和权益,Taria Pay 负责按账期收款并回传状态。

如果你没有自己的系统,只想要一个可以分享的订阅页,请用商家后台的订阅套餐(no-code),不需要写代码。

重要边界

当前是客户主动续费流程,Taria Pay 不会自动从客户钱包扣款。订阅 API 给你的是:

  • 为某个客户开订阅,并拿到一个付款链接交给他付当期;
  • 通过 webhook 同步订阅状态,用来在你自己系统里开通或撤销权益。

它不是自动代扣的 recurring billing。真正的自动扣款需要额外的授权模型,目前尚未提供。

请求由谁发起

必须由你的服务端发起,API key 只能保存在服务端。

两步接入

1. 创建套餐(价格对象)

套餐是可复用的价格定义(金额 + 币种 + 账期),一次创建即可给多个客户开订阅。

ts
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 交给客户付当期。

ts
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 在你自己的页面里弹出它——买家不离开你的网站,连钱包、签名、付款都由托管页负责(你不用碰钱包逻辑)。

弹窗方式(推荐)

ts
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" 整页跳转。
  • 弹窗被浏览器拦截会抛 TariaPayEmbedErrorcode: "popup_blocked")——务必从点击事件里调用,并准备好降级到 mode: "redirect"
  • onComplete 只用于即时刷新界面,不要据此开通权益。订阅是否真正激活以 subscription.* webhook 为准(见下文)。SDK 只接受来自结账页源、且来自它打开的那个窗口的完成消息,其他页面伪造不了。

声明式按钮(无服务端)

如果你用的是后台创建的套餐(有 slug),可以用 mountSubscribeButtons() 给页面上的按钮自动挂上点击处理,无需自己写开订阅的服务端逻辑:

ts
import { mountSubscribeButtons } from "@tariapay/sdk/browser";

mountSubscribeButtons({ checkoutBaseUrl: "https://checkout.tariapay.com" });
html
<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-basedata-tariapay-modedata-tariapay-customer-iddata-tariapay-email 覆盖;data-tariapay-customer-id 会作为 merchantCustomerId 回传 webhook,data-tariapay-email 预填买家邮箱。

REST 示例

bash
# 创建套餐
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 包含 subscriptioninvoicepaymentIntent(生命周期类事件 subscription.canceled / past_due / expiredinvoicepaymentIntent 可能为 null)。subscription.merchantCustomerId 会原样回传你的客户 ID。

ts
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

ts
await tariapay.subscriptions.cancel("sub_...", { atPeriodEnd: true });

订阅状态

  • incomplete:已创建订阅,首笔付款尚未确认。
  • active:最近账期付款已确认,当前周期有效。
  • past_due:账期到期未续费(或确认付款发生 reorg),需要重新收款,仍在宽限期内可恢复。
  • canceled:已取消(立即取消,或到期取消在周期末生效)。
  • expired:过宽限期仍未续费,已自动失效。

下一步