mcpField
F
framework-adapters

framework-adapters

github.com/dodopayments开发13200 次安装3 周前更新
代码仓库

关于 framework-adapters

面向在 Web 框架中集成 Dodo Payments 的开发者,介绍官方适配器如何提供结账、客户门户和 Webhook 路由处理器。覆盖多种框架,并说明环境变量、请求处理和安全配置要点。

主要功能

  1. 01提供多框架官方适配器
  2. 02创建结账路由处理器
  3. 03生成客户门户会话链接
  4. 04验证 Webhook 签名并分发事件
  5. 05映射环境变量和请求响应格式

适用场景

  1. 01在 Web 框架中添加支付结账路由
  2. 02创建需身份验证的客户门户入口
  3. 03接收并验证支付 Webhook
  4. 04按框架选择适配器和处理器模式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dodopayments/skills --skill framework-adapters

安装后在 Claude Code 中输入/framework-adapters确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
astro.md
bun.md
convex.md
express.md
fastify.md
hono.md
nuxt.md
remix.md
sveltekit.md
tanstack-start.md

详细介绍

框架适配器

当你需要使用官方适配器包将 Dodo Payments 集成到 Web 框架时,请使用此技能。框架适配器负责路由配置、环境配置和处理程序设置,因此你无需从头构建结账、门户和 Webhook 路由。

何时使用此技能

  • 你正在使用 Next.js、Express、Fastify、Hono、Astro、Remix、SvelteKit、Nuxt、TanStack、Bun 或 Convex 构建结账流程。
  • 你需要设置客户门户会话端点。
  • 你要添加用于验证签名并分发事件的 Webhook 处理程序。
  • 你希望采用符合框架惯例的路由位置和环境变量处理方式。
  • 你需要在静态、动态或会话结账模式之间进行选择。

框架适配器的功能

Dodo 发布了 @dodopayments/* 包,用框架专用的路由处理程序封装核心 SDK。你无需编写自己的 HTTP 处理程序,只需导入适配器的处理程序并直接挂载到路由中。

每个适配器都提供三类处理程序:

  • Checkout: 静态(仅 GET)、动态(POST,通过已弃用的 POST /payments / POST /subscriptions 端点创建付款或订阅——仅适用于现有集成),或会话(POST,附带结账会话负载——新集成请使用此模式)。
  • CustomerPortal: 生成有时效限制的门户会话链接。
  • Webhooks: 验证 Webhook 签名并分发类型化事件。

安全性——CustomerPortal 不进行身份验证。 每个 CustomerPortal 处理程序都会为其接收到的任何 ?customer_id= 打开门户。若直接挂载,任何访客都可以通过猜测或枚举 ID 打开任意客户的门户。请将此路由置于你自己的身份验证机制之后,并在服务端根据已登录会话解析客户 ID;切勿从客户端接收客户 ID。下方的门户示例采用了这种做法。

各适配器的导出名称并不统一。 大多数适配器导出 Checkout / CustomerPortal / Webhooks,但有两个适配器不同,返回值的形状也各不相同。编写导入语句前请查看此表:

适配器Checkout 导出项Portal 导出项处理程序形状
nextjs、hono、astro、bun、remix、tanstackCheckoutCustomerPortal返回一个请求处理程序
expresscheckoutHandler(小写)CustomerPortal返回 (req, res)
fastifyCheckoutCustomerPortal返回 { getHandler, postHandler }
sveltekitCheckoutCustomerPortal返回 { GET, POST } / { GET }
nuxtcheckoutHandler(自动导入)customerPortalHandler无需导入语句
convexcheckout(来自 dodo.api())customerPortal(来自 dodo.api(),使用 identify)createDodoWebhookHandler

适配器会处理 Webhook 验证所需的原始请求体保留、环境变量映射,以及框架专用的请求/响应形状。结账负载的设计属于 checkout-integration 技能;Webhook 业务逻辑属于 webhook-integration;门户行为属于 customer-management。

框架选择与安装

框架包安装
Next.js@dodopayments/nextjsnpm install @dodopayments/nextjs
Express@dodopayments/expressnpm install @dodopayments/express
Fastify@dodopayments/fastifynpm install @dodopayments/fastify
Hono@dodopayments/hononpm install @dodopayments/hono
Astro@dodopayments/astronpm install @dodopayments/astro
Remix@dodopayments/remixnpm install @dodopayments/remix
SvelteKit@dodopayments/sveltekitnpm install @dodopayments/sveltekit
Nuxt@dodopayments/nuxtnpm install @dodopayments/nuxt
TanStack Start@dodopayments/tanstacknpm install @dodopayments/tanstack
Bun@dodopayments/bunbun add @dodopayments/bun
Convex@dodopayments/convexnpm install @dodopayments/convex

环境变量

大多数适配器使用以下标准名称:

DODO_PAYMENTS_API_KEY=dodo_test_...
DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
DODO_PAYMENTS_ENVIRONMENT=test_mode
DODO_PAYMENTS_RETURN_URL=https://yourdomain.com/checkout/success

Nuxt 使用私有运行时配置前缀:

NUXT_PRIVATE_BEARER_TOKEN=dodo_test_...
NUXT_PRIVATE_WEBHOOK_KEY=your-webhook-secret
NUXT_PRIVATE_ENVIRONMENT=test_mode
NUXT_PRIVATE_RETURN_URL=https://yourdomain.com/checkout/success

Convex 使用控制面板环境变量(而非本地 .env):

DODO_PAYMENTS_API_KEY=dodo_test_...
DODO_PAYMENTS_ENVIRONMENT=test_mode
DODO_PAYMENTS_WEBHOOK_SECRET=your-webhook-secret

**Webhook 密钥命名:**有些适配器引用 DODO_PAYMENTS_WEBHOOK_KEY,另一些使用 DODO_PAYMENTS_WEBHOOK_SECRET。请查看框架的适配器文档和控制面板配置,确认正确的变量名称。

缩窄 environment 类型

适配器配置将 environment 的类型定义为 Pick<ClientOptions, "environment">,即字面量联合类型 "test_mode" | "live_mode"。process.env.X 的类型是 string | undefined,不能赋值给它——直接传入会在所有适配器中导致类型错误。

定义一次此辅助函数,并在构造适配器配置的地方导入:

// lib/dodo-env.ts
export const dodoEnvironment =
  process.env.DODO_PAYMENTS_ENVIRONMENT === "live_mode" ? "live_mode" : "test_mode";

默认使用 test_mode 是有意为之:缺失或拼写错误的变量绝不能静默地解析为实时模式。以下示例均使用 dodoEnvironment。

Next.js

包:@dodopayments/nextjs
路由位置:app/api/checkout/route.ts、app/api/customer-portal/route.ts、app/api/webhook/route.ts

结账(每个路由选择一种模式)
// app/api/checkout/route.ts
import { Checkout } from "@dodopayments/nextjs";
import { dodoEnvironment } from "@/lib/dodo-env";

export const GET = Checkout({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
  environment: dodoEnvironment,
  type: "static",
});

export const POST = Checkout({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
  environment: dodoEnvironment,
  type: "session",
});
客户门户
// app/api/customer-portal/route.ts
import { NextRequest } from "next/server";
import { CustomerPortal } from "@dodopayments/nextjs";
import { dodoEnvironment } from "@/lib/dodo-env";
// your auth helper
import { getSessionUser } from "@/lib/auth";

const portal = CustomerPortal({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: dodoEnvironment,
});

export async function GET(req: NextRequest) {
  const user = await getSessionUser(req);
  if (!user?.dodoCustomerId) return new Response("Unauthorized", { status: 401 });

  // Overwrite any client-supplied ?customer_id= with the signed-in user's ID.
  const url = new URL(req.url);
  url.searchParams.set("customer_id", user.dodoCustomerId);
  return portal(new NextRequest(url, req));
}
Webhook
// app/api/webhook/route.ts
import { Webhooks } from "@dodopayments/nextjs";

export const POST = Webhooks({
  webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
  onPayload: async (payload) => {
    console.log("Webhook received:", payload.type);
  },
});

Express

完整指南:references/express.md。

涵盖:

  • 结账
  • 客户门户
  • Webhook

Fastify

完整指南:references/fastify.md。

涵盖:

  • 结账
  • Webhook

Hono

完整指南:references/hono.md。

涵盖:

  • 结账
  • 客户门户
  • Webhook

Astro

完整指南:references/astro.md。

涵盖:

  • 结账
  • Webhook

Remix

完整指南:references/remix.md。

涵盖:

  • 结账
  • 客户门户
  • Webhook

SvelteKit

完整指南:references/sveltekit.md。

涵盖:

  • 结账
  • Webhook

Nuxt

完整指南:references/nuxt.md。

涵盖:

  • 结账
  • Webhook

TanStack Start

完整指南:references/tanstack-start.md。

涵盖:

  • 结账

Bun

完整指南:references/bun.md。

涵盖:

  • 结账和门户

Convex

完整指南:references/convex.md。

常见错误

  1. 重复的 POST 处理程序: Next.js 和 Astro 文档中展示了两个 export const POST 声明。每条路由选择一种结账模式,或添加路由逻辑以在两者之间进行分发。

  2. Webhook 变量名称错误: 检查你的适配器使用的是 DODO_PAYMENTS_WEBHOOK_KEY 还是 DODO_PAYMENTS_WEBHOOK_SECRET。文档中的名称不一致;请使用你的适配器实际引用的名称。

  3. 未保留原始请求正文: Webhook 处理程序必须接收原始请求正文,而不是重新解析后的 JSON 对象。Fastify 需要显式的字符串正文解析器;其他框架会自动处理。**Express 是例外:**它的 Webhooks 处理程序会根据已解析的 req.body 进行验证,因此请在路由之前注册 express.json(),不要使用 express.raw(),否则每次验证都会失败。webhook-integration 技能涵盖了 Webhook 签名验证。

  4. 混用框架约定: 每个框架都有自己的请求/响应格式。不要尝试在 Express 中使用 Next.js 处理程序,反之亦然。请使用适用于你所用框架的适配器。

  5. 硬编码密钥: 始终从环境变量读取 API 密钥和 Webhook 密钥,绝不要将它们写入代码或配置文件。

  6. 跳过环境设置: 缺少 DODO_PAYMENTS_API_KEY 和 DODO_PAYMENTS_ENVIRONMENT 时,适配器将无法工作。请在测试前设置这些变量。

  7. 未验证身份便开放 CustomerPortal: 门户处理程序会信任请求中的 ?customer_id=。请像上面的示例一样,在服务端从已登录会话中解析 ID,否则任何人都能打开任意客户的门户。

  8. 直接使用 @dodopayments/core: 核心包是内部依赖,并非有文档说明的公共入口点。请使用适用于你所用技术栈的框架适配器。

资源

评论

支持 Markdown