commet

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Commet Integration

Commet 集成

Commet is an all-in-one billing and payments platform. Merchant of Record handling taxes, compliance, refunds, and payouts. Integrate with a few lines of code.
Commet是一站式计费与支付平台,作为记录商户承担税务、合规、退款和打款相关责任,仅需几行代码即可完成集成。

Packages

工具包

PackagePurposeInstall
@commet/node
Core SDK - customers, subscriptions, usage, seats, features, portal, webhooks
npm i @commet/node
@commet/next
Next.js helpers - webhook handler, customer portal, pricing markdown
npm i @commet/next
@commet/ai-sdk
Vercel AI SDK middleware - automatic AI token usage billing
npm i @commet/ai-sdk
@commet/better-auth
Better Auth plugin - auto customer sync, auth-scoped billing
npm i @commet/better-auth
@commet/cli
CLI - login, link, pull types, scaffold projects from templates
npm i -g @commet/cli
包名用途安装命令
@commet/node
核心SDK - 客户管理、订阅、用量统计、席位、功能、门户、webhook
npm i @commet/node
@commet/next
Next.js 助手工具 - webhook处理器、客户门户、定价页markdown
npm i @commet/next
@commet/ai-sdk
Vercel AI SDK中间件 - 自动实现AI Token用量计费
npm i @commet/ai-sdk
@commet/better-auth
Better Auth 插件 - 自动客户同步、权限域内计费
npm i @commet/better-auth
@commet/cli
CLI工具 - 登录、关联项目、拉取类型定义、基于模板生成项目脚手架
npm i -g @commet/cli

Quick Start

快速开始

typescript
import { Commet } from "@commet/node";

const commet = new Commet({
  apiKey: process.env.COMMET_API_KEY!, // ck_xxx format
  environment: "production", // "sandbox" | "production"
});
Sandbox:
https://sandbox.commet.co
. Production:
https://commet.co
.
typescript
import { Commet } from "@commet/node";

const commet = new Commet({
  apiKey: process.env.COMMET_API_KEY!, // 格式为ck_xxx
  environment: "production", // 可选值 "sandbox" | "production"
});
沙箱环境地址:
https://sandbox.commet.co
,生产环境地址:
https://commet.co

Integration Workflow

集成工作流

  1. Setup:
    commet login
    ->
    commet link
    ->
    commet pull
    (generates
    .commet/types.d.ts
    for autocomplete)
  2. Create customer: On user signup, create Commet customer with
    externalId
    = your user ID
  3. Create subscription: Call
    subscriptions.create()
    -> redirect to
    checkoutUrl
  4. Check state: Query
    subscriptions.get()
    to check subscription status (preferred over webhooks)
  5. Track usage:
    usage.track()
    for metered features,
    seats.add/remove/set()
    for seats
  6. Feature gating:
    features.check()
    ,
    features.canUse()
    ,
    features.get()
  7. Customer portal:
    portal.getUrl()
    -> redirect for self-service billing management
  1. 初始化配置:执行
    commet login
    ->
    commet link
    ->
    commet pull
    (生成
    .commet/types.d.ts
    文件以支持代码自动补全)
  2. 创建客户:用户注册时,创建Commet客户,将
    externalId
    设置为你自有体系的用户ID
  3. 创建订阅:调用
    subscriptions.create()
    -> 重定向到
    checkoutUrl
  4. 状态查询:调用
    subscriptions.get()
    查询订阅状态(优先级高于webhook)
  5. 用量追踪:计量类功能调用
    usage.track()
    ,席位管理调用
    seats.add/remove/set()
  6. 功能准入控制:调用
    features.check()
    features.canUse()
    features.get()
  7. 客户门户:调用
    portal.getUrl()
    -> 重定向到自助计费管理页面

SDK Reference

SDK参考

See references/sdk.md for the complete API surface of
@commet/node
.
查看references/sdk.md获取
@commet/node
完整的API说明。

Next.js Integration

Next.js 集成

See references/nextjs.md for
@commet/next
webhook handlers, customer portal routes, and pricing markdown.
查看references/nextjs.md获取
@commet/next
的webhook处理器、客户门户路由、定价页markdown相关说明。

AI SDK Integration

AI SDK 集成

See references/ai-sdk.md for
@commet/ai-sdk
middleware that auto-tracks AI token usage for billing.
查看references/ai-sdk.md获取
@commet/ai-sdk
中间件的使用说明,该中间件可自动追踪AI Token用量用于计费。

Better Auth Integration

Better Auth 集成

See references/better-auth.md for the
@commet/better-auth
plugin that auto-syncs customers and provides auth-scoped billing endpoints.
查看references/better-auth.md获取
@commet/better-auth
插件的使用说明,该插件可自动同步客户数据并提供权限域内的计费接口。

Billing Concepts

计费概念

See references/billing-concepts.md for plan structure, feature types, consumption models, and charging behavior.
查看references/billing-concepts.md了解套餐结构、功能类型、消费模式和扣费逻辑。

Key Patterns

核心开发模式

Query-first, webhooks optional

优先查询接口,webhook可选

Always query subscription/feature state directly with the SDK instead of relying on webhooks to sync state. The recommended pattern is to call
subscriptions.get()
,
features.check()
, or
features.list()
when you need to know a customer's status. Webhooks are useful for background tasks (sending emails, provisioning resources) but should never be the source of truth for access control.
typescript
// Recommended: query state directly
const { data: sub } = await commet.subscriptions.get("user_123");
if (sub?.status === "active") { /* grant access */ }

// Recommended: feature gating
const { data } = await commet.features.check({ code: "advanced_analytics", externalId: "user_123" });
if (!data?.allowed) { /* show upgrade prompt */ }
始终通过SDK直接查询订阅/功能状态,不要依赖webhook同步状态。推荐的模式是当你需要获取客户状态时,调用
subscriptions.get()
features.check()
features.list()
。webhook适用于后台任务(发送邮件、资源开通),但绝不能作为权限控制的唯一数据来源。
typescript
// 推荐用法:直接查询状态
const { data: sub } = await commet.subscriptions.get("user_123");
if (sub?.status === "active") { /* 授予访问权限 */ }

// 推荐用法:功能准入控制
const { data } = await commet.features.check({ code: "advanced_analytics", externalId: "user_123" });
if (!data?.allowed) { /* 展示升级提示 */ }

Customer identification

客户标识

Always use
externalId
(your user/org ID) to identify customers. The SDK accepts either
customerId
(Commet's
cus_xxx
) or
externalId
- prefer
externalId
to avoid storing Commet IDs.
始终使用
externalId
(你的自有用户/组织ID)来识别客户。SDK同时支持
customerId
(Commet生成的
cus_xxx
格式ID)和
externalId
,优先使用
externalId
可以避免额外存储Commet的ID。

Customer-scoped context

客户维度上下文

typescript
const customer = commet.customer("user_123");
await customer.usage.track("api_calls", 1);
await customer.features.canUse("team_members");
await customer.seats.add("editor");
await customer.subscription.get();
await customer.portal.getUrl();
typescript
const customer = commet.customer("user_123");
await customer.usage.track("api_calls", 1);
await customer.features.canUse("team_members");
await customer.seats.add("editor");
await customer.subscription.get();
await customer.portal.getUrl();

Idempotency

幂等性

All POST requests auto-generate idempotency keys. For critical operations, pass explicit keys:
typescript
await commet.usage.track({
  externalId: "user_123",
  feature: "api_calls",
  idempotencyKey: `req_${requestId}`,
});
所有POST请求会自动生成幂等键。对于核心业务操作,建议显式传入幂等键:
typescript
await commet.usage.track({
  externalId: "user_123",
  feature: "api_calls",
  idempotencyKey: `req_${requestId}`,
});

Error handling

错误处理

typescript
import { CommetAPIError, CommetValidationError } from "@commet/node";

try {
  await commet.subscriptions.create({ ... });
} catch (error) {
  if (error instanceof CommetValidationError) {
    console.log(error.validationErrors); // { field: ["message"] }
  }
  if (error instanceof CommetAPIError) {
    console.log(error.statusCode, error.code);
  }
}
typescript
import { CommetAPIError, CommetValidationError } from "@commet/node";

try {
  await commet.subscriptions.create({ ... });
} catch (error) {
  if (error instanceof CommetValidationError) {
    console.log(error.validationErrors); // 格式为 { field: ["message"] }
  }
  if (error instanceof CommetAPIError) {
    console.log(error.statusCode, error.code);
  }
}

Environment variables

环境变量

env
COMMET_API_KEY=ck_xxx           # API key from dashboard
COMMET_ENVIRONMENT=sandbox      # sandbox | production
COMMET_WEBHOOK_SECRET=whsec_xxx # Optional - webhook secret for signature verification
env
COMMET_API_KEY=ck_xxx           # 后台获取的API密钥
COMMET_ENVIRONMENT=sandbox      # 环境类型 sandbox | production
COMMET_WEBHOOK_SECRET=whsec_xxx # 可选,用于签名验证的webhook密钥