在 Encore.ts 中集成 Polar:支付、订阅与许可证密钥的完整接入指南
【免费下载链接】encoreThe infrastructure platform for the intelligence era项目地址: https://gitcode.com/GitHub_Trending/encor/encore
Polar 作为你的 Merchant of Record(记录商户),一站式处理支付、订阅与许可证密钥等商业化核心环节。本文将基于 Encore 开源仓库中的官方集成文档,完整演示如何在 Encore.ts 应用中接入 Polar:从 SDK 安装、Polar 后台配置、密钥管理、Checkout 会话创建,到 Webhook 事件处理与最终部署,并深入源码层讲解secret()、api.raw、ENCORE_ENVIRONMENT等 Encore 运行时机制,帮助你构建一套可上线的支付与订阅闭环。
适用前提:本指南面向 TypeScript 语言版本的 Encore 应用。若尚未安装 Encore,请先参阅仓库内的 安装指南,再继续后续步骤。
快速开始:从官方示例创建应用
如果你希望跳过手工搭建、直接获得一份可运行的 Polar 集成范例,可以使用 Encore CLI 基于官方示例模板创建新应用:
$ encore app create --example=ts/polar该命令会拉取一个已经配置好 Polar 客户端、Checkout 端点与 Webhook 处理的完整 TypeScript 示例项目。也可以按照下文步骤,把 Polar 逐步接入到已有的 Encore 应用中。
安装 Polar SDK
在 Encore.ts 项目根目录执行:
$ npm install @polar-sh/sdk@polar-sh/sdk是 Polar 官方的 TypeScript/JavaScript SDK,封装了 Checkout 会话创建、Webhook 校验、订单与订阅查询等能力,后续所有 Polar 交互都通过它完成。
Polar 后台配置
编写代码之前,需要先在 Polar 控制台完成三件事(开发阶段请使用 sandbox 沙箱环境,避免影响真实计费数据):
- 创建 Access Token(访问令牌):进入 Settings > Developers > Personal Access Tokens,新建一个令牌,用于服务端鉴权。
- 创建商品(Product):进入 Products 页面创建至少一个商品,并复制其product ID。后续创建 Checkout 会话时需要用它指定用户要购买的商品。
- 配置 Webhook(本地开发可延后):进入 Settings > Webhooks,将回调地址指向你的 API 地址加上
/webhooks/polar路径。本地开发时,可使用 ngrok 之类的隧道工具把本地服务暴露到公网,供 Polar 回调。
关于商品定价、订阅计划与 Webhook 事件类型的更多细节,可查阅 Polar 官方文档(本指南只介绍与 Encore 集成直接相关的部分)。
用 Encore Secrets 保存 Polar 凭据
Polar 的 Access Token 属于敏感凭据,绝不能硬编码进源码。Encore 提供内置的密钥管理机制,通过 CLI 设置:
$ encore secret set --type dev,local,pr,production PolarAccessToken--type指定该密钥生效的环境集合:dev(开发云)、local(本地)、pr(预览环境)与production(生产)。Encore 会为每个环境独立加密存储,环境之间互不共享。
本地开发时,密钥直接保存在你的机器上,并在运行encore run时自动注入到应用中——无需任何.env文件,也避免了.env文件被误提交进 Git 仓库的风险。
在源码中通过 Encore 的secret()函数读取密钥。以仓库中 runtimes/js/encore.dev/config/secrets.ts 的实现为例:secret(name)从运行时配置中获取该密钥的实现,返回一个可调用对象;本地开发(runtime.CloudProvider.Local)且密钥未设置时,它会返回空字符串而不是直接抛错,方便调试;而在非本地环境中,若密钥缺失会抛出secret <name> is not set错误。此外,该对象重写了toString()输出为Secret<name>(*********),确保日志中不会泄露明文。密钥值会被 Encore 周期性刷新,这意味着它可以安全轮换而无需重启服务。
初始化 Polar 客户端
新建polar.ts,用 Encore 的secret()读取令牌,并根据运行环境在 Polar 的sandbox(沙箱)与production(生产)服务器之间切换:
-- polar.ts -- import { Polar } from "@polar-sh/sdk"; import { secret } from "encore.dev/config"; const polarAccessToken = secret("PolarAccessToken"); const server = process.env.ENCORE_ENVIRONMENT === "production" ? "production" : "sandbox"; export const polar = new Polar({ accessToken: polarAccessToken(), server, });这里的ENCORE_ENVIRONMENT是 Encore 注入的环境变量:在生产环境部署时其值为production,其余情况(本地、预览、测试等)走 sandbox,从而保证开发与生产天然隔离。如果你需要更结构化的环境信息,Encore 还提供appMeta()API(见 runtimes/js/encore.dev/app_meta.ts),可读取environment.type、environment.cloud、apiBaseUrl等元数据。
创建 Checkout 会话
Checkout 会话是用户完成支付的关键入口。下面通过一个需要认证的 Encore 端点,创建 Checkout 会话并返回支付跳转链接:
-- checkout.ts -- import { api } from "encore.dev/api"; import { polar } from "./polar"; import { getAuthData } from "~encore/auth"; interface CreateCheckoutRequest { productId: string; } interface CreateCheckoutResponse { checkoutUrl: string; } export const createCheckout = api( { auth: true, expose: true, method: "POST", path: "/checkout" }, async (req: CreateCheckoutRequest): Promise<CreateCheckoutResponse> => { const authData = getAuthData()!; const baseUrl = process.env.ENCORE_API_URL || "http://localhost:4000"; const session = await polar.checkouts.create({ products: [req.productId], customerEmail: authData.email, successUrl: `${baseUrl}/?success=true`, }); return { checkoutUrl: session.url || "" }; } );对这段代码的要点拆解:
auth: true与getAuthData():auth: true声明该端点必须携带有效认证信息,否则 Encore 直接返回 401。认证数据通过~encore/auth的getAuthData()获取(内部实现在 runtimes/js/encore.dev/internal/auth/mod.ts,从当前请求上下文中取出认证数据),因此可以把用户的邮箱直接传给 Polar 作为customerEmail,实现"登录即下单"的体验。expose: true:把端点暴露到公网,使其可以被前端调用。未设置expose的端点默认只在服务内部网络可达。path: "/checkout":自定义路由路径。Encore 的api()声明在 runtimes/js/encore.dev/api/mod.ts 中,支持method、path、expose、auth、bodyLimit、sensitive等选项;路径中还可使用:id单段参数与*path通配多段参数。ENCORE_API_URL:Encore 注入的当前环境 API 基地址。本地开发时通常是http://localhost:4000,部署后则是对应环境的 API URL。这里用其拼接successUrl,保证用户在 Polar 完成支付后能正确跳回你的应用。
polar.checkouts.create()返回的session.url即用户在 Polar 侧完成支付的 Checkout 页面链接,前端拿到后直接跳转即可。
处理 Webhook:让支付事件驱动业务
支付是异步过程:用户可能在 Polar 侧完成支付或取消订阅,这些状态变化通过Webhook通知你的服务。Encore 的raw endpoint(原生端点)让你直接拿到 Node.js 风格的IncomingMessage请求对象,非常适合承接 Webhook 这类需要原始请求体的场景:
-- webhooks.ts -- import { api } from "encore.dev/api"; import log from "encore.dev/log"; export const handleWebhook = api.raw( { expose: true, path: "/webhooks/polar", method: "POST" }, async (req, res) => { const chunks: Buffer[] = []; for await (const chunk of req) { chunks.push(chunk); } const event = JSON.parse(Buffer.concat(chunks).toString()); log.info("Received Polar webhook", { type: event.type }); switch (event.type) { case "subscription.active": // Grant access to your product break; case "subscription.canceled": // Revoke access break; case "order.paid": // Fulfill the order break; } res.writeHead(200); res.end(); } );api.raw:Encore 提供的原生端点声明。req是stream.Readable类型的请求对象(实现在 runtimes/js/encore.dev/api/node_http.ts),可以用异步迭代器逐块读取请求体;res是ServerResponse兼容的响应对象(同一文件 L115-L310),支持writeHead、write、end等标准操作。由于完全兼容 Node.js HTTP 语义,它可以无缝对接 Express 等生态库。- 事件分发:示例按
event.type分派三类典型事件——subscription.active(订阅激活,授予产品访问权限)、subscription.canceled(订阅取消,收回权限)、order.paid(订单支付成功,履行订单)。你可以在switch中补充实际的业务逻辑,例如调用数据库 API 更新用户权益,或给用户发放许可证密钥。 - 确认响应:处理完成后返回 200,告知 Polar 事件已收到,避免 Polar 重复投递。
注册 Webhook 时,在 Polar 控制台的 Settings > Webhooks 中填写你的 Encore API URL 加/webhooks/polar,并勾选需要监听的事件(如subscription.active、subscription.canceled、order.paid)。
建议:生产环境务必校验 Webhook 请求的签名(Polar SDK 提供相应工具),并配合数据库做幂等处理,防止重复事件导致权益重复发放。
部署
当通过 Encore 部署应用时,Encore 会自动为应用提供并管理所需的全部基础设施:
- Secrets(密钥):按环境(preview、staging、production)独立加密存储,环境之间绝不共享。
- Databases(数据库):在 GCP 上自动预置为 Cloud SQL,在 AWS 上自动预置为 RDS。
- Networking(网络):包含 TLS 证书、负载均衡与 DNS 解析,开箱即用。
自托管部署
如果你希望把应用部署到自有基础设施,可以构建 Docker 镜像:
$ encore build docker my-app:latest构建产物是一个标准 Docker 镜像,可部署到任何支持 Docker 的环境。更详细的自托管说明见仓库内的 self-host 文档。
Encore Cloud
也可以直接推送到 Encore 的开发云,获得一个免费的 staging 环境:
$ git push encore main如果你想部署到自己的 AWS 或 GCP 账号,连接云账号后,Encore 会自动预置基础设施并代为管理密钥。具体步骤参考 连接云账号指南。
小结
把 Polar 与 Encore.ts 集成,本质上是三个动作的组合:用 Encore Secrets 安全托管 Polar Access Token、用类型安全的api()端点创建 Checkout 会话、用api.raw原生端点接收 Webhook 事件并驱动业务。Polar 承担了商户记录、支付合规、订阅计费与许可证发放等重活,Encore 则负责运行时配置、密钥注入、环境区分与一键部署,二者互补后,你得到的是一套具备生产级基础设施的支付订阅能力。仓库内的encore app create --example=ts/polar示例是快速上手的最佳起点,可直接在此基础上扩展你自己的业务逻辑。
【免费下载链接】encoreThe infrastructure platform for the intelligence era项目地址: https://gitcode.com/GitHub_Trending/encor/encore
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考