> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Supabase 模板

> 克隆 Next.js、Supabase 和 Dodo Payments 订阅入门项目，其中包含 Google 登录、Drizzle schema、webhook Edge Function 和计费 dashboard。

> **[GitHub Repository](https://github.com/dodopayments/dodo-supabase-subscription-starter)**
>
> 简洁的 Next.js、Supabase 和 Dodo Payments 订阅 boilerplate。

> **[Live Demo](https://dodopayments-supabase-nextjs.vercel.app)**
>
> 探索已部署的 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](/developer-resources/nextjs-adaptor)**

> **[Express Adaptor](/developer-resources/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 安装依赖：

```bash theme={null}
git clone https://github.com/dodopayments/dodo-supabase-subscription-starter.git
cd dodo-supabase-subscription-starter
# choose one
bun install
# or
npm install
# or
pnpm install
```

**2. Create a Supabase Project**

创建一个 Supabase 项目。后续步骤会使用它的 project reference，即 `https://[your-project-ref].supabase.co` 中的子域名。复制以下值：

* `NEXT_PUBLIC_SUPABASE_URL`，即项目 URL
* `NEXT_PUBLIC_SUPABASE_ANON_KEY`，即 anon key
* `SUPABASE_SERVICE_ROLE_KEY`，即 service role key
* `DATABASE_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。

```text theme={null}
https://[your-project-ref].supabase.co/functions/v1/dodo-webhook
```

选择该 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`

复制 endpoint 的 signing secret。它的值为 `DODO_WEBHOOK_SECRET`。

**6. Create .env.local**

在根目录中创建一个 `.env.local` 文件：

```env theme={null}
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role

# Database
DATABASE_URL=postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres

# Dodo Payments
DODO_PAYMENTS_API_KEY=your-dodo-api-key
DODO_WEBHOOK_SECRET=your-webhook-secret
DODO_PAYMENTS_ENVIRONMENT=test_mode
```

Next.js 应用会读取此文件中的每个变量，但 `DODO_WEBHOOK_SECRET` 除外。Edge Function 会从 Supabase secrets 中读取 `DODO_WEBHOOK_SECRET`，你将在部署它时设置该值。

> [!WARNING]
>
> 不要提交 secrets。在已部署的环境中，将它们设置为 environment variables。

**7. Provision the Database Schema**

将 Drizzle schema 推送到 Supabase 数据库：

```bash theme={null}
bun run db:push
# or
npm run db:push
# or
pnpm run db:push
```

> [!TIP]
>
> 已创建的表：`users`、`subscriptions`、`payments`。

**8. Deploy the Webhook Function**

登录 Supabase，将 signing secret 保存为 function secret，然后部署 `dodo-webhook` Edge Function。将 `[your-project-ref]` 替换为你的 project reference：

```bash theme={null}
# login (one-time)
bunx supabase login
# or
npx supabase login

# store the Dodo Payments signing secret for the function
npx supabase secrets set DODO_WEBHOOK_SECRET=your-webhook-secret --project-ref [your-project-ref]

# deploy the edge function
bun run deploy:webhook --project-ref [your-project-ref]
# or
npm run deploy:webhook -- --project-ref [your-project-ref]
# or
pnpm run deploy:webhook --project-ref [your-project-ref]
```

`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：

```bash cURL theme={null}
curl -X POST \
  'https://[your-project-ref].supabase.co/functions/v1/dodo-webhook' \
  -H 'Content-Type: application/json' \
  -d '{"type":"payment.succeeded","data":{}}'
```

返回 `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 为 `features`，value 为字符串 JSON array，以便在应用中列出套餐功能。此时 product 的 metadata 如下所示：

```json theme={null}
{
  "features": "[\"Feature 1\", \"Feature 2\", \"Feature 3\"]"
}
```

Metadata 值可以是字符串、数字或布尔值，因此请将 array 存储为 JSON string。pricing UI 会解析 `features` 值并渲染每个项目。

**10. Run the Dev Server**

```bash theme={null}
bun run dev
# or
npm run dev
# or
pnpm run dev
```

打开 [http://localhost:3000](http://localhost:3000)，然后使用 Google 登录。

> [!TIP]
>
> 现在，你已经拥有一个使用 Supabase 和 Dodo Payments 搭建的可用订阅 SaaS。要端到端确认其功能，请使用[测试卡](/miscellaneous/testing-process)订阅一个套餐。webhook 到达后，dashboard 会显示你的新套餐。

## 包含内容

* 通过 Supabase 实现身份验证，并配置 Google OAuth
* 通过 Dodo Payments 实现 subscription checkout
* 用于处理 webhooks 的 Supabase Edge Function（`dodo-webhook`）
* Drizzle ORM schema，以及用于迁移的 `db:generate` 和 `db:migrate` scripts
* 包含发票、订阅状态和套餐功能的 dashboard
* 用于更改套餐、取消订阅和恢复已取消订阅的 server actions

> [!TIP]
>
> 在完成端到端测试之前，保持 `DODO_PAYMENTS_ENVIRONMENT` 设置为 `test_mode`。要上线，请将其设置为 `live_mode`，并使用 live mode API key。

## 关键文件和路径

webhook handler、应用路由和数据库 schema 位于以下文件中：

**Edge Function**

```text theme={null}
supabase/functions/dodo-webhook/
  index.ts            # verifies signatures, stores payments and subscriptions
  deno.json           # Deno configuration
```

**Next.js Routes**

```text theme={null}
app/page.tsx                    # redirects to /login or /dashboard
app/login/page.tsx              # Google sign-in page
app/dashboard/page.tsx          # plans, subscription, and invoices
app/checkout/route.ts           # checkout handler
app/api/auth/callback/route.ts  # OAuth callback
actions/*                       # server actions
```

**Database (Drizzle)**

```text theme={null}
lib/drizzle/schema.ts   # users, subscriptions, payments
lib/drizzle/client.ts   # client
```

## 环境变量

Next.js 应用和 Edge Function 会读取以下变量：

> **Supabase**
>
> ```env theme={null}
> NEXT_PUBLIC_SUPABASE_URL=
> NEXT_PUBLIC_SUPABASE_ANON_KEY=
> SUPABASE_SERVICE_ROLE_KEY=
> DATABASE_URL=
> ```
>
> `.env.example` 中没有列出 `SUPABASE_SERVICE_ROLE_KEY`，但 `lib/supabase/admin.ts` 中的应用 admin client 需要它。请自行添加。

> **Dodo Payments**
>
> ```env theme={null}
> DODO_PAYMENTS_API_KEY=
> DODO_WEBHOOK_SECRET=
> DODO_PAYMENTS_ENVIRONMENT=test_mode|live_mode
> ```

> **Google OAuth**
>
> 应用不会从 environment variables 中读取 Google credentials。请在 Supabase Auth 的 Google provider 设置中输入 Client ID 和 Client Secret，并将此 redirect URI 添加到 Google Cloud 中的 OAuth client：
>
> ```text theme={null}
> https://[your-project-ref].supabase.co/auth/v1/callback
> ```

## 验证和故障排除

> **Webhook signature invalid (400)**
>
> * 确保函数的 `DODO_WEBHOOK_SECRET` secret 与 Dodo Payments 控制面板中 endpoint 的 signing secret 匹配。
> * 确认你已部署最新的 `dodo-webhook` 函数。
> * 该函数会验证 [Standard Webhooks](https://standardwebhooks.com/) 标头 `webhook-id`、`webhook-signature` 和 `webhook-timestamp`。确保代理不会移除这些标头。

> **Database push fails**
>
> * 检查 `DATABASE_URL` 语法。
> * 直接连接（`db.[project-ref].supabase.co:5432`）使用 IPv6，除非你的项目已添加 IPv4 附加组件。在仅支持 IPv4 的网络上，请改用 session pooler 连接字符串（参见 [Supabase 连接文档](https://supabase.com/docs/guides/database/connecting-to-postgres)）。
> * 创建项目后，等待 2–3 分钟再执行首次 push。

> **OAuth redirect mismatch**
>
> * redirect URI 必须是 `https://[ref].supabase.co/auth/v1/callback`。
> * 在 Google Cloud 和 Supabase Auth provider 中使用相同的 URI。

> [!NOTE]
>
> 有关原始 repository 和详细步骤，请参阅 [dodo-supabase-subscription-starter](https://github.com/dodopayments/dodo-supabase-subscription-starter)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.