polar-better-auth
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePolar + Better Auth Integration
Polar + Better Auth 集成
A Better Auth plugin for integrating Polar payments and subscriptions into your authentication flow.
Note: Fetch complete documentation index at:https://polar.sh/docs/llms.txt
一款Better Auth插件,用于将Polar支付和订阅功能集成到你的认证流程中。
注意: 完整文档索引可通过以下地址获取:https://polar.sh/docs/llms.txt
Features
功能特性
- Automatic Customer Creation: Syncs signup users to Polar customers.
- Sync Deletion: Deletes Polar customer when user is deleted.
- Reference System: Associates purchases with organizations/users.
- Plugins: Checkout, Usage (Billing), Webhooks, and Customer Portal.
- 自动创建客户:将注册用户同步为Polar客户。
- 同步删除:当用户被删除时,同步删除Polar客户。
- 关联系统:将购买记录与组织/用户关联。
- 子插件:包含结账、使用量(计费)、Webhook和客户门户插件。
Installation
安装
bash
npm install better-auth @polar-sh/better-auth @polar-sh/sdkbash
npm install better-auth @polar-sh/better-auth @polar-sh/sdkor
or
yarn add better-auth @polar-sh/better-auth @polar-sh/sdk
yarn add better-auth @polar-sh/better-auth @polar-sh/sdk
or
or
pnpm add better-auth @polar-sh/better-auth @polar-sh/sdk
undefinedpnpm add better-auth @polar-sh/better-auth @polar-sh/sdk
undefinedServer Configuration
服务器配置
Initialize the Polar client and add the plugin to your Better Auth configuration.
初始化Polar客户端,并将该插件添加到你的Better Auth配置中。
Environment Variables
环境变量
bash
POLAR_ACCESS_TOKEN=polar_oat_...
POLAR_WEBHOOK_SECRET=...bash
POLAR_ACCESS_TOKEN=polar_oat_...
POLAR_WEBHOOK_SECRET=...Full Server Setup
完整服务器设置
typescript
import { betterAuth } from "better-auth";
import {
polar,
checkout,
portal,
usage,
webhooks,
} from "@polar-sh/better-auth";
import { Polar } from "@polar-sh/sdk";
const polarClient = new Polar({
accessToken: process.env.POLAR_ACCESS_TOKEN,
server: "sandbox", // Use 'sandbox' for testing, defaults to 'production'
});
const auth = betterAuth({
plugins: [
polar({
client: polarClient,
createCustomerOnSignUp: true, // Auto-create Polar customer
// Optional: Custom metadata for new customers
getCustomerCreateParams: ({ user }, request) => ({
metadata: { source: "better-auth" },
}),
use: [
// 1. Checkout Plugin
checkout({
products: [{ productId: "prod_123", slug: "pro" }],
successUrl: "/success?checkout_id={CHECKOUT_ID}",
authenticatedUsersOnly: true,
returnUrl: "https://myapp.com",
theme: "dark", // 'light' or 'dark'
}),
// 2. Customer Portal Plugin
portal({
returnUrl: "https://myapp.com",
}),
// 3. Usage Billing Plugin
usage(),
// 4. Webhooks Plugin
webhooks({
secret: process.env.POLAR_WEBHOOK_SECRET,
onOrderPaid: (payload) => console.log("💸 Order Paid:", payload),
onCustomerStateChanged: (payload) =>
console.log("👤 State Changed:", payload),
onPayload: (payload) => console.log("📨 Other Event:", payload),
}),
],
}),
],
});typescript
import { betterAuth } from "better-auth";
import {
polar,
checkout,
portal,
usage,
webhooks,
} from "@polar-sh/better-auth";
import { Polar } from "@polar-sh/sdk";
const polarClient = new Polar({
accessToken: process.env.POLAR_ACCESS_TOKEN,
server: "sandbox", // 测试环境使用'sandbox',默认是'production'
});
const auth = betterAuth({
plugins: [
polar({
client: polarClient,
createCustomerOnSignUp: true, // 注册时自动创建Polar客户
// 可选:为新客户添加自定义元数据
getCustomerCreateParams: ({ user }, request) => ({
metadata: { source: "better-auth" },
}),
use: [
// 1. 结账插件
checkout({
products: [{ productId: "prod_123", slug: "pro" }],
successUrl: "/success?checkout_id={CHECKOUT_ID}",
authenticatedUsersOnly: true,
returnUrl: "https://myapp.com",
theme: "dark", // 'light' 或 'dark'
}),
// 2. 客户门户插件
portal({
returnUrl: "https://myapp.com",
}),
// 3. 使用量计费插件
usage(),
// 4. Webhook插件
webhooks({
secret: process.env.POLAR_WEBHOOK_SECRET,
onOrderPaid: (payload) => console.log("💸 订单已支付:", payload),
onCustomerStateChanged: (payload) =>
console.log("👤 状态已更改:", payload),
onPayload: (payload) => console.log("📨 其他事件:", payload),
}),
],
}),
],
});Server Options Dictionary
服务器选项说明
| Option | Type | Description |
|---|---|---|
| | Required. The Polar SDK instance. |
| | Auto-create Polar customer on signup. |
| | Array of sub-plugins (checkout, portal, usage, webhooks). |
| | Returns metadata/params for interaction. |
| 选项 | 类型 | 描述 |
|---|---|---|
| | 必填项。 Polar SDK实例。 |
| | 注册时自动创建Polar客户。 |
| | 子插件数组(结账、门户、使用量、Webhook)。 |
| | 返回交互时使用的元数据/参数。 |
Client Configuration
客户端配置
typescript
import { createAuthClient } from "better-auth/react";
import { polarClient } from "@polar-sh/better-auth";
export const authClient = createAuthClient({
plugins: [polarClient()],
});typescript
import { createAuthClient } from "better-auth/react";
import { polarClient } from "@polar-sh/better-auth";
export const authClient = createAuthClient({
plugins: [polarClient()],
});Plugins Summary
子插件概述
1. Checkout Plugin
1. 结账插件
Enables creating checkout sessions directly from the client.
Configuration:
- : Array of
products. Allows referencing products by slug.{ productId, slug } - : Redirect URL after payment. Supports
successUrl.{CHECKOUT_ID} - :
authenticatedUsersOnlyforces user login before checkout.true - : Back button URL in checkout.
returnUrl - :
themeorlight.dark
Client Usage:
typescript
await authClient.checkout({
// Option A: Use slug defined in config
slug: "pro",
// Option B: Use direct Product ID
products: ["prod_123"],
// Optional: Link to an Organization (B2B)
referenceId: "org_123",
});支持直接从客户端创建结账会话。
配置项:
- :
products数组。允许通过slug引用产品。{ productId, slug } - : 支付成功后的重定向URL。支持
successUrl变量。{CHECKOUT_ID} - : 设置为
authenticatedUsersOnly时,强制用户先登录再结账。true - : 结账页面中返回按钮的跳转URL。
returnUrl - : 主题,可选
theme或light。dark
客户端使用示例:
typescript
await authClient.checkout({
// 方式A:使用配置中定义的slug
slug: "pro",
// 方式B:直接使用产品ID
products: ["prod_123"],
// 可选:关联到某个组织(B2B场景)
referenceId: "org_123",
});2. Usage Plugin (Billing)
2. 使用量计费插件
Handles Event Ingestion and Meter retrieval for Usage-Based Billing.
Client Usage:
A. Ingest Events:
typescript
await authClient.usage.ingestion({
event: "ai_generation", // Must match Meter definition in Dashboard
metadata: {
tokens: 156,
model: "gpt-4",
},
});Note: Automatically links event to the authenticated user.
B. List Meters:
typescript
const { data: meters } = await authClient.usage.meters.list({
query: { page: 1, limit: 10 },
});
// Returns: consumed units, credited units, current balance处理事件上报和计量数据查询,用于基于使用量的计费。
客户端使用示例:
A. 上报事件:
typescript
await authClient.usage.ingestion({
event: "ai_generation", // 必须与Polar后台中定义的计量项一致
metadata: {
tokens: 156,
model: "gpt-4",
},
});注意:会自动将事件与当前认证用户关联。
B. 查询计量项:
typescript
const { data: meters } = await authClient.usage.meters.list({
query: { page: 1, limit: 10 },
});
// 返回结果:已使用量、已充值量、当前余额3. Portal Plugin
3. 客户门户插件
Manages customer access to the hosted Customer Portal.
Client Usage:
A. Open Portal:
typescript
// Redirects user to Polar Customer Portal
await authClient.customer.portal();B. Get Customer State:
Returns active subscriptions, granted benefits, and meter balances.
typescript
const { data: state } = await authClient.customer.state();C. List Resources:
typescript
// List Active Subscriptions
const { data: subs } = await authClient.customer.subscriptions.list({
query: { active: true },
});
// List Orders (Purchases)
const { data: orders } = await authClient.customer.orders.list();
// List Benefits
const { data: benefits } = await authClient.customer.benefits.list();管理客户对Polar托管的客户门户的访问权限。
客户端使用示例:
A. 打开客户门户:
typescript
// 重定向用户到Polar客户门户
await authClient.customer.portal();B. 获取客户状态:
返回活跃订阅、已授予的权益以及计量项余额。
typescript
const { data: state } = await authClient.customer.state();C. 查询资源列表:
typescript
// 查询活跃订阅
const { data: subs } = await authClient.customer.subscriptions.list({
query: { active: true },
});
// 查询订单(购买记录)
const { data: orders } = await authClient.customer.orders.list();
// 查询权益
const { data: benefits } = await authClient.customer.benefits.list();4. Webhooks Plugin
4. Webhook插件
The plugin captures incoming events from your Polar organization.
webhooksSetup Steps:
- Configure Endpoint: Go to Polar Dashboard > Webhooks and set endpoint to .
/api/auth/polar/webhooks - Set Secret: Add to your environment variables.
POLAR_WEBHOOK_SECRET - Add Plugin:
typescript
import { polar, webhooks } from "@polar-sh/better-auth";
const auth = betterAuth({
plugins: [
polar({
client: polarClient,
use: [
webhooks({
secret: process.env.POLAR_WEBHOOK_SECRET,
// Handlers
onCustomerStateChanged: (payload) => {
console.log("Customer state changed:", payload);
},
onOrderPaid: (payload) => {
console.log("Order paid:", payload);
},
// ... over 25+ handlers available
onPayload: (payload) => {
console.log("Catch-all event:", payload);
},
}),
],
}),
],
});Supported Events:
- (Catch-all)
onPayload - ,
onCheckoutCreatedonCheckoutUpdated - ,
onOrderCreated,onOrderPaidonOrderRefunded - ,
onRefundCreatedonRefundUpdated - ,
onSubscriptionCreatedonSubscriptionUpdated - ,
onSubscriptionActive,onSubscriptionCanceledonSubscriptionRevoked - ,
onProductCreatedonProductUpdated - ,
onCustomerCreated,onCustomerUpdated,onCustomerDeletedonCustomerStateChanged - ,
onBenefitCreated,onBenefitGrantCreatedonBenefitGrantRevoked
webhooks设置步骤:
- 配置端点: 前往Polar后台 > Webhooks,将端点设置为。
/api/auth/polar/webhooks - 设置密钥: 将添加到你的环境变量中。
POLAR_WEBHOOK_SECRET - 添加插件:
typescript
import { polar, webhooks } from "@polar-sh/better-auth";
const auth = betterAuth({
plugins: [
polar({
client: polarClient,
use: [
webhooks({
secret: process.env.POLAR_WEBHOOK_SECRET,
// 事件处理器
onCustomerStateChanged: (payload) => {
console.log("客户状态已更改:", payload);
},
onOrderPaid: (payload) => {
console.log("订单已支付:", payload);
},
// ... 支持25+种处理器
onPayload: (payload) => {
console.log("通用事件捕获:", payload);
},
}),
],
}),
],
});支持的事件:
- (通用捕获)
onPayload - ,
onCheckoutCreatedonCheckoutUpdated - ,
onOrderCreated,onOrderPaidonOrderRefunded - ,
onRefundCreatedonRefundUpdated - ,
onSubscriptionCreatedonSubscriptionUpdated - ,
onSubscriptionActive,onSubscriptionCanceledonSubscriptionRevoked - ,
onProductCreatedonProductUpdated - ,
onCustomerCreated,onCustomerUpdated,onCustomerDeletedonCustomerStateChanged - ,
onBenefitCreated,onBenefitGrantCreatedonBenefitGrantRevoked
Common Workflows
常见工作流
Sync Customer Deletion
同步客户删除
To delete the Polar customer when a user is deleted in your database:
typescript
const auth = betterAuth({
user: {
deleteUser: {
enabled: true,
afterDelete: async (user) => {
await polarClient.customers.deleteExternal({
externalId: user.id,
});
},
},
},
});当你的数据库中删除用户时,同步删除对应的Polar客户:
typescript
const auth = betterAuth({
user: {
deleteUser: {
enabled: true,
afterDelete: async (user) => {
await polarClient.customers.deleteExternal({
externalId: user.id,
});
},
},
},
});Check Organization Access
检查组织访问权限
Check if a user has access via an Organization subscription (B2B):
typescript
const orgId = (await authClient.organization.list())?.data?.[0]?.id;
const { data: orders } = await authClient.customer.orders.list({
query: {
active: true,
referenceId: orgId, // Filter by Org ID
},
});
const hasAccess = orders.length > 0;检查用户是否通过组织订阅获得访问权限(B2B场景):
typescript
const orgId = (await authClient.organization.list())?.data?.[0]?.id;
const { data: orders } = await authClient.customer.orders.list({
query: {
active: true,
referenceId: orgId, // 按组织ID筛选
},
});
const hasAccess = orders.length > 0;