# @convex-dev/polar 中文文档

规范地址：https://npmcn.com/package/%40convex-dev/polar/

版本：0\.9\.2
npm 元数据更新时间：2026-10-07T00:51:45.168Z
中文译文更新时间：2026-11-10T17:53:06.970Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40convex-dev/polar
原文对照：https://npmcn.com/package/%40convex-dev/polar/?lang=original
项目主页：https://github.com/get-convex/polar#readme
源码仓库：https://github.com/get-convex/polar

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：480 kB，67 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：4 个
- peer 依赖：react ^18 \|\| ^19，convex ^1\.29\.0，react-dom ^18 \|\| ^19，@polar-sh/sdk \>=0\.45\.0，@polar-sh/checkout \>=0\.1\.10
- 首次发布：2025-04-05T00:19:10.320Z
- 最新版本发布：2026-06-25T00:09:25.364Z
- 近 30 天下载量：49304（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：19（近 12 个月 8 个）

## 中文简介

Convex 的极性组件 .

## 安装

```sh
npm install @convex-dev/polar
```

也可以使用：`pnpm add @convex-dev/polar`、`yarn add @convex-dev/polar`、`bun add @convex-dev/polar`

## README

# Convex 极地组件 [![npm version](https://badge.fury.io/js/@convex-dev%2Fpolar.svg)](https://badge.fury.io/js/@convex-dev%2Fpolar)

在您的 Convex 应用程序中添加订阅和账单 [极点](https://polar.sh/)。 。 。 .

**看看这个 [示例应用程序](https://npmcn.com/package/%40convex-dev/polar/example) 一个完整的例子.**

```tsx
// Get subscription details for the current user
// Note: getCurrentSubscription is for apps that only allow one active
// subscription per user. If you need to support multiple active
// subscriptions, use listUserSubscriptions instead.
const {
  productKey,
  status,
  currentPeriodEnd,
  currentPeriodStart,
  ...
} = await polar.getCurrentSubscription(ctx, {
  userId: user._id,
});

// Show available plans
<CheckoutLink
  polarApi={api.example}
  productIds={[products.premiumMonthly.id, products.premiumYearly.id]}
  // Optional: turn off embedding to link to a checkout page
  embed={false}
>
  Upgrade to Premium
</CheckoutLink>

// Manage existing subscriptions
<CustomerPortalLink polarApi={api.example}>
  Manage Subscription
</CustomerPortalLink>
```

## 先决条件

### Convex 应用程序

你需要一个Convex App来使用组件. 跟着任何 [Convex 快速启动](https://docs.convex.dev/home) 来设置一个.

### 极账户

-   [创建极账户](https://polar.sh/)
-   创建一个组织并创建一个组织标志,并有权限:
    -   `products:read`
    -   `products:write`
    -   `subscriptions:read`
    -   `subscriptions:write`
    -   `customers:read`
    -   `customers:write`
    -   `checkouts:read`
    -   `checkouts:write`
    -   `checkout_links:read`
    -   `checkout_links:write`
    -   `customer_portal:read`
    -   `customer_portal:write`
    -   `customer_sessions:write`

## 安装

安装组件包 :

```ts
npm install @convex-dev/polar
```

创建一个 `convex.config.ts` 应用程序中的文件 `convex/` 文件夹并安装 通过调用 `app.use`数字 :

```ts
// convex/convex.config.ts
import { defineApp } from "convex/server";
import polar from "@convex-dev/polar/convex.config.js";

const app = defineApp();
app.use(polar);

export default app;
```

设置您的极组织符号 :

```sh
npx convex env set POLAR_ORGANIZATION_TOKEN xxxxx
```

## 使用量

### 设置极地网点

极地组件使用webhooks保持订阅数据同步. 你会需要的 改为:

1.  在极地仪表板上创建一则网钩和网钩秘密,使用您 [Convex 站点 URL](https://docs.convex.dev/production/environment-variables#system-environment-variables) + 键 `/polar/events` 作为网点。 应该是这样的 `https://verb-noun-123.convex.site/polar/events`
    
    启用以下事件 :
    
    -   `product.created`
    -   `product.updated`
    -   `subscription.created`
    -   `subscription.updated`
2.  设置您的 Convex 环境中的 Webhook 密钥 :
    

```sh
npx convex env set POLAR_WEBHOOK_SECRET xxxxx
```

3.  在您的网页处理器中注册 `convex/http.ts`数字 :

```ts
import { httpRouter } from "convex/server";
import { polar } from "./example";

const http = httpRouter();

// Register the webhook handler at /polar/events
polar.registerRoutes(http as any);

export default http;
```

您也可以通过该程序为任何极地 Webhook 事件提供类型安全处理器 `events` 选项。 手提箱接收基于以下特性的已打出的全部事件有效载荷: 事件密钥 :

```ts
polar.registerRoutes(http, {
  // Optional custom path, default is "/polar/events"
  path: "/polar/events",
  events: {
    "subscription.updated": async (ctx, event) => {
      // event.data is typed as Subscription
      if (event.data.customerCancellationReason) {
        console.log("Customer cancelled:", event.data.customerCancellationReason);
      }
    },
    "order.created": async (ctx, event) => {
      // event.data is typed as Order
      console.log("New order:", event.data.id);
    },
  },
});
```

4.  一定要运行 `npx convex dev` 用极点启动您的 Convex 应用程序 启用组件, 它将将 Webhook 处理器部署到您的 Convex 举个例子.

### 在极地创建产品

在极地仪表板上为您想要的每个定价计划创建产品 提供。 产品数据将自动同步到您的 Convex 应用程序 .

该组件支持所有极地价格类型:固定、免费、自定义 (付费 -什么 -你需要), 座椅,和计量吸入器。 产品还可包括: 在极地仪表板或 离职时间.

使用此组件前创建的产品需要与 Convex 同步 使用 `syncProducts` 函数.

### 初始化极端客户端

在 Convex 后端创建极端客户端 :

```ts
// convex/example.ts
import { Polar } from "@convex-dev/polar";
import { api, components } from "./_generated/api";
import { DataModel } from "./_generated/dataModel";

export const polar = new Polar<DataModel>(components.polar, {
  // Required: provide a function the component can use to get the current user's ID and
  // email - this will be used for retrieving the correct subscription data for the
  // current user. The function should return an object with `userId` and `email`
  // properties.
  getUserInfo: async (ctx) => {
    const user = await ctx.runQuery(api.example.getCurrentUser);
    return {
      userId: user._id,
      email: user.email,
    };
  },
  // Optional: Configure static keys for referencing your products.
  // Alternatively you can use the `listAllProducts` function to get
  // the product data and sort it out in your UI however you like
  // (eg., by price, name, recurrence, etc.).
  // Map your product keys to Polar product IDs (you can also use env vars for this)
  // Replace these keys with whatever is useful for your app (eg., "pro", "proMonthly",
  // whatever you want), and replace the values with the actual product IDs from your
  // Polar dashboard
  products: {
    premiumMonthly: "product_id_from_polar",
    premiumYearly: "product_id_from_polar",
    premiumPlusMonthly: "product_id_from_polar",
    premiumPlusYearly: "product_id_from_polar",
  },
  // Optional: Set Polar configuration directly in code
  organizationToken: "your_organization_token", // Defaults to POLAR_ORGANIZATION_TOKEN env var
  webhookSecret: "your_webhook_secret", // Defaults to POLAR_WEBHOOK_SECRET env var
  server: "sandbox", // Optional: "sandbox" or "production", defaults to POLAR_SERVER env var
});

// Export API functions from the Polar client
export const {
  changeCurrentSubscription,
  cancelCurrentSubscription,
  getConfiguredProducts,
  listAllProducts,
  listAllSubscriptions,
  generateCheckoutLink,
  generateCustomerPortalUrl,
} = polar.api();
```

### 显示产品和价格

使用导出 `getConfiguredProducts` 或者说 `listAllProducts` 要显示的函数 您的产品及其价格:

#### `getConfiguredProducts`

```tsx
// Simple example of displaying products and prices if you've configured
// products by key in the Polar constructor
function PricingTable() {
  const products = useQuery(api.example.getConfiguredProducts);
  if (!products) return null;

  return (
    <div>
      {products.premiumMonthly && (
        <div>
          <h3>{products.premiumMonthly.name}</h3>
          <p>
            ${(products.premiumMonthly.prices[0].priceAmount ?? 0) / 100}/month
          </p>
        </div>
      )}
      {products.premiumYearly && (
        <div>
          <h3>{products.premiumYearly.name}</h3>
          <p>
            ${(products.premiumYearly.prices[0].priceAmount ?? 0) / 100}/year
          </p>
        </div>
      )}
    </div>
  );
}
```

#### `listAllProducts`

```tsx
// Simple example of displaying products and prices if you haven't configured
// products by key in the Polar constructor
function PricingTable() {
  const products = useQuery(api.example.listAllProducts);
  if (!products) return null;

  // You can sort through products in the client as below, or you can use
  // `polar.listAllProducts` in your own Convex query and return your desired
  // products to display in the UI.
  const proMonthly = products.find(
    (p) => p.prices[0].recurringInterval === "month",
  );
  const proYearly = products.find(
    (p) => p.prices[0].recurringInterval === "year",
  );
  return (
    <div>
      {proMonthly && (
        <div>
          <h3>{proMonthly.name}</h3>
          <p>
            ${(proMonthly.prices[0].priceAmount ?? 0) / 100}/
            {proMonthly.prices[0].recurringInterval}
          </p>
        </div>
      )}
      {proYearly && (
        <div>
          <h3>{proYearly.name}</h3>
          <p>${(proYearly.prices[0].priceAmount ?? 0) / 100}/year</p>
        </div>
      )}
    </div>
  );
}
```

每种产品包括:

-   `id`:极地产品ID
-   `name`: 产品名称
-   `description`: 产品说明
-   `isRecurring`: 产品是否为订阅
-   `recurringInterval`:计费间隔(如"月份","年份"等)
-   `trialInterval`: 试验时间间隔(如果配置)
-   `trialIntervalCount`: 审判间隔次数(如果配置)
-   `benefits`: 产品效益矩阵(说明、类型等)
-   `prices`: 价格矩阵,每组都有 `amountType` 确定可用字段:
    -   **已固定**数字 : `priceAmount` (以美分计), `priceCurrency`
    -   **免费**: 无量字段
    -   **自定义**数字 : `minimumAmount`, (中文(简体) ), `maximumAmount`, (中文(简体) ), `presetAmount`, (中文(简体) ), `priceCurrency`
    -   **座标( b)**数字 : `seatTiers` (数目 `{ minSeats, maxSeats, pricePerSeat }`, (中文(简体) ), `priceCurrency`
    -   **计算单位**数字 : `unitAmount`, (中文(简体) ), `capAmount`, (中文(简体) ), `meterId`, (中文(简体) ), `meter` (单位:千美元)`{ id, name }`, (中文(简体) ), `priceCurrency`

### 添加订阅 UI 组件

使用提供的 React 组件为您的应用程序添加订阅功能 :

```tsx
import { CheckoutLink, CustomerPortalLink } from "@convex-dev/polar/react";
import { api } from "../convex/_generated/api";

// For new subscriptions
<CheckoutLink
  // For our example, the api.example object includes the generateCheckoutLink
  // function. You can also pass any object that includes this function.
  polarApi={api.example}
  productIds={[products.premiumMonthly.id, products.premiumYearly.id]}
  // Optional: turn off embedding to link to a checkout page
  embed={false}
>
  Upgrade to Premium
</CheckoutLink>

// With a free trial
<CheckoutLink
  polarApi={api.example}
  productIds={[products.premiumMonthly.id]}
  trialInterval="day"
  trialIntervalCount={7}
>
  Start 7-day free trial
</CheckoutLink>

// Lazy mode: generates checkout URL on click instead of on mount.
// Useful when rendering many checkout links to avoid rate limits.
<CheckoutLink
  polarApi={api.example}
  productIds={[products.premiumMonthly.id]}
  lazy
>
  Subscribe
</CheckoutLink>

// For managing existing subscriptions
<CustomerPortalLink
  polarApi={{
    generateCustomerPortalUrl: api.example.generateCustomerPortalUrl,
  }}
>
  Manage Subscription
</CustomerPortalLink>
```

### 处理订阅更改

极地组件提供处理用户更改的功能 当前用户.

**说明:** 强烈建议在 改变他们的订阅方式!

```ts
// Change subscription
const changeSubscription = useAction(api.example.changeCurrentSubscription);
await changeSubscription({ productId: "new_product_id" });

// Cancel subscription (works for both active and trialing subscriptions)
const cancelSubscription = useAction(api.example.cancelCurrentSubscription);
await cancelSubscription({ revokeImmediately: true });
```

### 访问订阅数据

在您的应用程序中查询订阅信息 :

```ts
// convex/example.ts

// A query that returns a user with their subscription details
export const getCurrentUser = query({
  handler: async (ctx) => {
    const user = await ctx.db.query("users").first();
    if (!user) throw new Error("No user found");

    const subscription = await polar.getCurrentSubscription(ctx, {
      userId: user._id,
    });

    return {
      ...user,
      subscription,
      isFree: !subscription,
      isPremium:
        subscription?.productKey === "premiumMonthly" ||
        subscription?.productKey === "premiumYearly",
    };
  },
});
```

## API 参考

### 极端客户端

这个 `Polar` 类 接受配置对象 :

-   `getUserInfo`: 获取当前用户ID和电子邮件的函数
-   `products`: (可选) 任意命名的极地产品ID密钥地图
-   `organizationToken`: (可选)你的极地组织标志. 倒计时 `POLAR_ORGANIZATION_TOKEN` 环境 var
-   `webhookSecret`: (可选)你的极地网球秘诀. 倒计时 `POLAR_WEBHOOK_SECRET` 环境 var
-   `server`: (可选)极地服务器环境:"sandbox"或"生产". 倒计时 `POLAR_SERVER` 环境 var

### 反应组件

#### 退出链接

道具 :

-   `polarApi`: 含有 `generateCheckoutLink` 函数
-   `productIds`: 复选时要显示的产品标识组
-   `children`: 反应儿童(按钮内容)
-   `embed`: (可选)是否嵌入出票. 默认为 `true`。 。 。 .
-   `lazy`: (可选) 推迟检出 URL 生成直到点击. 有用时 提供许多链接。 默认为 `false`。 。 。 .
-   `theme`: (可选)嵌入式取出主题: `"dark"` 或者说 `"light"`默认 改为 `"dark"`。 。 。 .
-   `trialInterval`: (可选) 审判时间间隔: `"day"`, (中文(简体) ), `"week"`, (中文(简体) ), `"month"`,或 `"year"`。 。 。 .
-   `trialIntervalCount`: (备选) 审判间隔次数(例如, `7` 7个 (日数).
-   `className`: (可选) CSS 类名
-   `subscriptionId`: (可选)订阅升级的ID. 这一定是在 免费定价.
-   `metadata`: (可选) 离职附加信息的元数据
-   `locale`: (可选) 退出页面的语言(例如,), `"fr"`, (中文(简体) ), `"de"`(中文(简体) )

#### 客户端端链接

道具 :

-   `polarApi`: 含有 `generateCustomerPortalUrl` 函数
-   `children`: 反应儿童(按钮内容)
-   `className`: (可选) CSS 类名

### API 函数

下面的功能是: `Polar` 实例,用于您 Convex后端代码. 相应的对应名称(通过 `polar.api()`)显示于 [初始化部分](https://npmcn.com/package/%40convex-dev/polar/#readme-initialize-the-polar-client) 见上文.

#### 更改当前订阅

更改对新计划的现有订阅 :

```ts
await changeSubscription({ productId: "new_product_id" });
```

#### 取消当前订阅

取消正在或正在试验的订阅 :

```ts
await cancelSubscription({ revokeImmediately: true });
```

#### 获取当前订阅

获取当前用户的活动订阅 。 回返 `null` 如果没有活动 订阅已存在 。 过期的审判不包括在内.

```ts
const subscription = await polar.getCurrentSubscription(ctx, { userId });
```

#### 列表用户订阅

对于支持每个用户多个活动订阅的应用程序. 返回活动 订阅,不包括已终止的订阅和已到期的审判.

```ts
const subscriptions = await polar.listUserSubscriptions(ctx, { userId });
```

#### 列表 全部用户订阅

返回用户的所有订阅,包括已结束和已过期的试验。 有用 用于显示订阅历史或区分“从未订阅” 和"审判期满".

```ts
const allSubscriptions = await polar.listAllUserSubscriptions(ctx, { userId });
```

#### 生产

以极地产品ID获得单一产品:

```ts
const product = await polar.getProduct(ctx, { productId });
```

#### 获取客户端

为用户获取极地客户记录 :

```ts
const customer = await polar.getCustomerByUserId(ctx, userId);
```

#### 产品

列出所有现有产品及其价格:

```ts
const products = await polar.listProducts(ctx);
```

#### 登记册

登记极地组件的 Webhook 处理器 :

```ts
polar.registerRoutes(http, {
  // Optional: customize the webhook endpoint path (defaults to "/polar/events")
  path: "/custom/webhook/path",
  // Optional: typesafe handlers for any Polar webhook event
  events: {
    "order.created": async (ctx, event) => {
      // event.data is typed as Order
    },
  },
});
```

这个 `events` 选项为 30+ 中的任意一个接受处理器 极地网点事件 类型对事件有效载荷有完整的TypeScript推断。 内置装卸 (长期订阅和产品)总是自动运行,无论 其中你处理的事件.

Webhook 处理器使用 `webhookSecret` 从极端客户端配置 或 `POLAR_WEBHOOK_SECRET` 环境变量.

#### 同步产品

同步来自极地的现有产品( 必须在动作内运行) :

```ts
export const syncProducts = action({
  args: {},
  handler: async (ctx) => {
    await polar.syncProducts(ctx);
  },
});
```

## 常见问题

### @convex-dev/polar 是什么？

Convex 的极性组件 \.

### 如何安装 @convex-dev/polar？

在项目目录运行 npm install @convex-dev/polar，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^18 \|\| ^19）、convex（^1\.29\.0）、react-dom（^18 \|\| ^19）、@polar-sh/sdk（\>=0\.45\.0）、@polar-sh/checkout（\>=0\.1\.10）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @convex-dev/polar 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @convex-dev/polar 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @convex-dev/polar 可以商用吗？

@convex-dev/polar 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @convex-dev/polar 的下载量有多少？

根据 npm 官方下载统计，@convex-dev/polar 在 2026/10/11 – 2026/11/09 这 30 天内被下载 49,304 次，日均约 1,643 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @convex-dev/polar 还在维护吗？

最新版本 0\.9\.2 发布于 2026/06/25（4 个月前）；至今共发布 19 个版本，其中过去 12 个月发布了 8 个；首次发布于 2025/04/05。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

