GitHub Repository
简洁的 Next.js、Supabase 和 Dodo Payments 订阅 boilerplate。
Live Demo
探索已部署的 demo。
概述
Supabase 订阅入门项目是一个使用 Next.js 15 和 React 19 构建的应用,通过 Dodo Payments 销售订阅。Supabase 提供 Google OAuth 登录和 Postgres 数据库,Drizzle ORM 用于定义 schema。Supabase Edge Function 接收 Dodo Payments webhooks 并存储付款和订阅信息,基础 dashboard 会显示每位用户的套餐和发票。 如果你只需要为现有应用添加 checkout、Customer Portal 和 webhook 路由处理程序,请改用 framework adaptor:Next.js Adaptor
Express Adaptor
前置条件
开始之前,你需要准备:- Node.js 18 或更高版本,或 Bun 1.0 或更高版本。
- 一个 Supabase 项目。你需要它的 URL、anon key、service role key 和数据库连接字符串。
- 一个 Dodo Payments 账户,用于获取 API key 和 webhook signing secret。
- 一个 Google Cloud OAuth client,用于获取 Client ID 和 Client Secret。
快速开始
1
Clone and Install
克隆 repository,然后使用 Bun、npm 或 pnpm 安装依赖:
2
Create a Supabase Project
创建一个 Supabase 项目。后续步骤会使用它的 project reference,即
https://[your-project-ref].supabase.co 中的子域名。复制以下值:NEXT_PUBLIC_SUPABASE_URL,即项目 URLNEXT_PUBLIC_SUPABASE_ANON_KEY,即 anon keySUPABASE_SERVICE_ROLE_KEY,即 service role keyDATABASE_URL,即数据库连接字符串
3
Configure Google OAuth
在 Google Cloud 中,将此 authorized redirect URI 添加到 OAuth client:
https://[your-project-ref].supabase.co/auth/v1/callback。然后,在 Supabase Auth 中使用你的 Client ID 和 Client Secret 启用 Google provider。4
Configure Dodo Payments
在侧边栏中关闭 Live Mode 开关后,在 Dodo Payments dashboard 的 Developer → API Keys 下创建 API key。在开发期间,保持
DODO_PAYMENTS_ENVIRONMENT 设置为 test_mode。5
Add the Webhook in Dodo Payments
在 Developer → Webhooks 下,使用此 URL 添加 endpoint。你将在后续步骤中部署为其提供服务的 function。选择该 function 要处理的 payment 和 subscription 事件:
- Payment 事件:
payment.succeeded、payment.failed、payment.processing和payment.cancelled - Subscription 事件:
subscription.active、subscription.plan_changed、subscription.renewed、subscription.on_hold、subscription.cancelled、subscription.expired和subscription.failed
DODO_WEBHOOK_SECRET。6
Create .env.local
在根目录中创建一个 Next.js 应用会读取此文件中的每个变量,但
.env.local 文件:DODO_WEBHOOK_SECRET 除外。Edge Function 会从 Supabase secrets 中读取 DODO_WEBHOOK_SECRET,你将在部署它时设置该值。7
Provision the Database Schema
将 Drizzle schema 推送到 Supabase 数据库:
已创建的表:
users、subscriptions、payments。8
Deploy the Webhook Function
登录 Supabase,将 signing secret 保存为 function secret,然后部署 返回
dodo-webhook Edge Function。将 [your-project-ref] 替换为你的 project reference:deploy:webhook script 会运行 supabase functions deploy dodo-webhook --no-verify-jwt,因此 Dodo Payments 可以在没有 Supabase auth token 的情况下调用该 function。Supabase 默认会向该 function 提供 SUPABASE_URL 和 SUPABASE_SERVICE_ROLE_KEY。要检查部署情况,请发送一个未签名的 request:cURL
Invalid webhook signature 的 400 响应,表示 function 正在运行并且已配置 secret。返回 Server configuration error 的 500 响应,表示尚未设置 DODO_WEBHOOK_SECRET。要发送带签名的测试事件,请在 Developer → Webhooks 中打开 endpoint,并使用其 Testing 选项卡。9
Create Products and Features
在 Dodo Payments dashboard 的 Products 下,点击 Add Product,为每个套餐创建一个 subscription product。你也可以添加一个 metadata entry,其 key 为 Metadata 值可以是字符串、数字或布尔值,因此请将 array 存储为 JSON string。pricing UI 会解析
features,value 为字符串 JSON array,以便在应用中列出套餐功能。此时 product 的 metadata 如下所示:features 值并渲染每个项目。10
Run the Dev Server
现在,你已经拥有一个使用 Supabase 和 Dodo Payments 搭建的可用订阅 SaaS。要端到端确认其功能,请使用测试卡订阅一个套餐。webhook 到达后,dashboard 会显示你的新套餐。
包含内容
- 通过 Supabase 实现身份验证,并配置 Google OAuth
- 通过 Dodo Payments 实现 subscription checkout
- 用于处理 webhooks 的 Supabase Edge Function(
dodo-webhook) - Drizzle ORM schema,以及用于迁移的
db:generate和db:migratescripts - 包含发票、订阅状态和套餐功能的 dashboard
- 用于更改套餐、取消订阅和恢复已取消订阅的 server actions
关键文件和路径
webhook handler、应用路由和数据库 schema 位于以下文件中:- Edge Function
- Next.js Routes
- Database (Drizzle)
环境变量
Next.js 应用和 Edge Function 会读取以下变量:Supabase
Supabase
.env.example 中没有列出 SUPABASE_SERVICE_ROLE_KEY,但 lib/supabase/admin.ts 中的应用 admin client 需要它。请自行添加。Dodo Payments
Dodo Payments
Google OAuth
Google OAuth
应用不会从 environment variables 中读取 Google credentials。请在 Supabase Auth 的 Google provider 设置中输入 Client ID 和 Client Secret,并将此 redirect URI 添加到 Google Cloud 中的 OAuth client:
验证和故障排除
Webhook signature invalid (400)
Webhook signature invalid (400)
- 确保函数的
DODO_WEBHOOK_SECRETsecret 与 Dodo Payments 控制面板中 endpoint 的 signing secret 匹配。 - 确认你已部署最新的
dodo-webhook函数。 - 该函数会验证 Standard Webhooks 标头
webhook-id、webhook-signature和webhook-timestamp。确保代理不会移除这些标头。
Database push fails
Database push fails
- 检查
DATABASE_URL语法。 - 直接连接(
db.[project-ref].supabase.co:5432)使用 IPv6,除非你的项目已添加 IPv4 附加组件。在仅支持 IPv4 的网络上,请改用 session pooler 连接字符串(参见 Supabase 连接文档)。 - 创建项目后,等待 2–3 分钟再执行首次 push。
OAuth redirect mismatch
OAuth redirect mismatch
- redirect URI 必须是
https://[ref].supabase.co/auth/v1/callback。 - 在 Google Cloud 和 Supabase Auth provider 中使用相同的 URI。
有关原始 repository 和详细步骤,请参阅 dodo-supabase-subscription-starter。