commet
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCommet 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
工具包
| Package | Purpose | Install |
|---|---|---|
| Core SDK - customers, subscriptions, usage, seats, features, portal, webhooks | |
| Next.js helpers - webhook handler, customer portal, pricing markdown | |
| Vercel AI SDK middleware - automatic AI token usage billing | |
| Better Auth plugin - auto customer sync, auth-scoped billing | |
| CLI - login, link, pull types, scaffold projects from templates | |
| 包名 | 用途 | 安装命令 |
|---|---|---|
| 核心SDK - 客户管理、订阅、用量统计、席位、功能、门户、webhook | |
| Next.js 助手工具 - webhook处理器、客户门户、定价页markdown | |
| Vercel AI SDK中间件 - 自动实现AI Token用量计费 | |
| Better Auth 插件 - 自动客户同步、权限域内计费 | |
| 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: . Production: .
https://sandbox.commet.cohttps://commet.cotypescript
import { Commet } from "@commet/node";
const commet = new Commet({
apiKey: process.env.COMMET_API_KEY!, // 格式为ck_xxx
environment: "production", // 可选值 "sandbox" | "production"
});沙箱环境地址:,生产环境地址:。
https://sandbox.commet.cohttps://commet.coIntegration Workflow
集成工作流
- Setup: ->
commet login->commet link(generatescommet pullfor autocomplete).commet/types.d.ts - Create customer: On user signup, create Commet customer with = your user ID
externalId - Create subscription: Call -> redirect to
subscriptions.create()checkoutUrl - Check state: Query to check subscription status (preferred over webhooks)
subscriptions.get() - Track usage: for metered features,
usage.track()for seatsseats.add/remove/set() - Feature gating: ,
features.check(),features.canUse()features.get() - Customer portal: -> redirect for self-service billing management
portal.getUrl()
- 初始化配置:执行->
commet login->commet link(生成commet pull文件以支持代码自动补全).commet/types.d.ts - 创建客户:用户注册时,创建Commet客户,将设置为你自有体系的用户ID
externalId - 创建订阅:调用-> 重定向到
subscriptions.create()checkoutUrl - 状态查询:调用查询订阅状态(优先级高于webhook)
subscriptions.get() - 用量追踪:计量类功能调用,席位管理调用
usage.track()seats.add/remove/set() - 功能准入控制:调用、
features.check()、features.canUse()features.get() - 客户门户:调用-> 重定向到自助计费管理页面
portal.getUrl()
SDK Reference
SDK参考
See references/sdk.md for the complete API surface of .
@commet/node查看references/sdk.md获取完整的API说明。
@commet/nodeNext.js Integration
Next.js 集成
See references/nextjs.md for webhook handlers, customer portal routes, and pricing markdown.
@commet/next查看references/nextjs.md获取的webhook处理器、客户门户路由、定价页markdown相关说明。
@commet/nextAI SDK Integration
AI SDK 集成
See references/ai-sdk.md for middleware that auto-tracks AI token usage for billing.
@commet/ai-sdk查看references/ai-sdk.md获取中间件的使用说明,该中间件可自动追踪AI Token用量用于计费。
@commet/ai-sdkBetter Auth Integration
Better Auth 集成
See references/better-auth.md for the plugin that auto-syncs customers and provides auth-scoped billing endpoints.
@commet/better-auth查看references/better-auth.md获取插件的使用说明,该插件可自动同步客户数据并提供权限域内的计费接口。
@commet/better-authBilling 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 , , or 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.
subscriptions.get()features.check()features.list()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同步状态。推荐的模式是当你需要获取客户状态时,调用、或。webhook适用于后台任务(发送邮件、资源开通),但绝不能作为权限控制的唯一数据来源。
subscriptions.get()features.check()features.list()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 (your user/org ID) to identify customers. The SDK accepts either (Commet's ) or - prefer to avoid storing Commet IDs.
externalIdcustomerIdcus_xxxexternalIdexternalId始终使用(你的自有用户/组织ID)来识别客户。SDK同时支持(Commet生成的格式ID)和,优先使用可以避免额外存储Commet的ID。
externalIdcustomerIdcus_xxxexternalIdexternalIdCustomer-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 verificationenv
COMMET_API_KEY=ck_xxx # 后台获取的API密钥
COMMET_ENVIRONMENT=sandbox # 环境类型 sandbox | production
COMMET_WEBHOOK_SECRET=whsec_xxx # 可选,用于签名验证的webhook密钥