Skip to main content

GitHub Repository

Boilerplate đăng ký tối giản cho Next.js, Supabase và Dodo Payments.

Live Demo

Khám phá bản demo đã triển khai.

Tổng quan

Bộ khởi đầu đăng ký Supabase là một ứng dụng Next.js 15 và React 19, dùng Dodo Payments để bán các gói đăng ký. Supabase cung cấp tính năng đăng nhập Google OAuth và cơ sở dữ liệu Postgres, còn Drizzle ORM định nghĩa schema. Supabase Edge Function nhận webhook từ Dodo Payments và lưu trữ các khoản thanh toán cũng như gói đăng ký; một dashboard cơ bản hiển thị gói và hóa đơn của từng người dùng. Nếu bạn chỉ cần các trình xử lý route cho checkout, Customer Portal và webhook trong một ứng dụng hiện có, hãy sử dụng framework adaptor thay thế:

Next.js Adaptor

Express Adaptor

Điều kiện tiên quyết

Trước khi bắt đầu, bạn cần:
  • Node.js 18 trở lên hoặc Bun 1.0 trở lên.
  • Một dự án Supabase. Bạn cần URL, anon key, service role key và chuỗi kết nối cơ sở dữ liệu của dự án.
  • Một tài khoản Dodo Payments để lấy API key và webhook signing secret.
  • Một OAuth client trên Google Cloud để lấy Client ID và Client Secret.

Bắt đầu nhanh

1

Clone and Install

Sao chép repository, sau đó cài đặt các dependency bằng Bun, npm hoặc pnpm:
2

Create a Supabase Project

Tạo một dự án Supabase. Các bước sau sử dụng project reference của dự án, tức subdomain trong https://[your-project-ref].supabase.co. Sao chép các giá trị sau:
  • NEXT_PUBLIC_SUPABASE_URL, URL của dự án
  • NEXT_PUBLIC_SUPABASE_ANON_KEY, anon key
  • SUPABASE_SERVICE_ROLE_KEY, service role key
  • DATABASE_URL, chuỗi kết nối cơ sở dữ liệu
3

Configure Google OAuth

Trong Google Cloud, thêm authorized redirect URI này vào OAuth client: https://[your-project-ref].supabase.co/auth/v1/callback. Sau đó, trong Supabase Auth, bật Google provider bằng Client ID và Client Secret của bạn.
4

Configure Dodo Payments

Khi công tắc Live Mode trong sidebar đang tắt, hãy tạo API key trong Developer → API Keys trên dashboard Dodo Payments. Giữ DODO_PAYMENTS_ENVIRONMENT ở giá trị test_mode trong quá trình phát triển.
5

Add the Webhook in Dodo Payments

Trong Developer → Webhooks, thêm một endpoint với URL này. Bạn sẽ triển khai function phục vụ endpoint đó ở bước sau.
Chọn các sự kiện thanh toán và đăng ký mà function sẽ xử lý:
  • Sự kiện thanh toán: INLINE_CODE_PLACEHOLDER_bfeed7a4ab5393d_END, payment.failed, payment.processing và payment.cancelled
  • Sự kiện đăng ký: subscription.active, subscription.plan_changed, subscription.renewed, subscription.on_hold, subscription.cancelled, subscription.expired và subscription.failed
Sao chép signing secret của endpoint. Đây là giá trị của DODO_WEBHOOK_SECRET.
6

Create .env.local

Tạo một tệp .env.local trong thư mục gốc:
Ứng dụng Next.js đọc mọi biến trong tệp này ngoại trừ DODO_WEBHOOK_SECRET. Edge Function đọc DODO_WEBHOOK_SECRET từ Supabase secrets, được thiết lập khi bạn triển khai function.
Không commit secrets. Trong các môi trường đã triển khai, hãy đặt chúng dưới dạng environment variables.
7

Provision the Database Schema

Đẩy Drizzle schema lên cơ sở dữ liệu Supabase:
Các bảng đã tạo: users, subscriptions, payments.
8

Deploy the Webhook Function

Đăng nhập vào Supabase, lưu signing secret dưới dạng function secret và triển khai Edge Function dodo-webhook. Thay [your-project-ref] bằng project reference của bạn:
Script deploy:webhook chạy supabase functions deploy dodo-webhook --no-verify-jwt, vì vậy Dodo Payments có thể gọi function mà không cần Supabase auth token. Theo mặc định, Supabase cung cấp SUPABASE_URL và SUPABASE_SERVICE_ROLE_KEY cho function.Để kiểm tra việc triển khai, gửi một request không có chữ ký:
cURL
Response 400 với Invalid webhook signature nghĩa là function đang chạy và đã có secret. Response 500 với Server configuration error nghĩa là DODO_WEBHOOK_SECRET chưa được thiết lập. Để gửi một test event có chữ ký, mở endpoint trong Developer → Webhooks và sử dụng tab Testing.
9

Create Products and Features

Trong Products trên dashboard Dodo Payments, nhấp Add Product để tạo một sản phẩm đăng ký cho mỗi gói. Nếu muốn liệt kê các tính năng của gói trong ứng dụng, hãy thêm một metadata entry với key features và một JSON array gồm các chuỗi làm value. Metadata của sản phẩm sẽ có dạng như sau:
Metadata values là chuỗi, số hoặc boolean, vì vậy hãy lưu array dưới dạng chuỗi JSON. Pricing UI phân tích giá trị features và hiển thị từng mục.
10

Run the Dev Server

Mở http://localhost:3000 và đăng nhập bằng Google.
Bây giờ bạn đã có một scaffold SaaS đăng ký hoạt động với Supabase và Dodo Payments. Để xác nhận toàn bộ quy trình, hãy đăng ký một gói bằng test card. Sau khi webhook đến, dashboard sẽ hiển thị gói mới của bạn.

Nội dung bao gồm

  • Xác thực qua Supabase, với Google OAuth đã được cấu hình
  • Checkout đăng ký qua Dodo Payments
  • Supabase Edge Function cho webhook (dodo-webhook)
  • Drizzle ORM schema, với các script db:generate và db:migrate cho migrations
  • Dashboard với hóa đơn, trạng thái đăng ký và tính năng của gói
  • Server actions để thay đổi gói, hủy đăng ký và khôi phục đăng ký đã hủy
Giữ DODO_PAYMENTS_ENVIRONMENT ở giá trị test_mode cho đến khi bạn hoàn tất các bài kiểm thử end-to-end. Để chuyển sang live, đặt giá trị này thành live_mode và sử dụng live mode API key.

Tệp và đường dẫn chính

Webhook handler, app routes và database schema nằm trong các tệp sau:

Environment Variables

Ứng dụng Next.js và Edge Function đọc các biến sau:
.env.example không liệt kê SUPABASE_SERVICE_ROLE_KEY, nhưng admin client của ứng dụng trong lib/supabase/admin.ts cần biến này. Hãy tự thêm biến đó.
Ứng dụng không đọc Google credentials từ environment variables. Nhập Client ID và Client Secret trong phần cài đặt Google provider của Supabase Auth, đồng thời thêm redirect URI này vào OAuth client trong Google Cloud:

Xác minh và khắc phục sự cố

  • Đảm bảo secret DODO_WEBHOOK_SECRET của function khớp với signing secret của endpoint trong dashboard Dodo Payments.
  • Xác nhận bạn đã triển khai function dodo-webhook mới nhất.
  • Function xác minh các header webhook-id, webhook-signature và webhook-timestamp của Standard Webhooks. Đảm bảo proxy không loại bỏ chúng.
  • Kiểm tra cú pháp DATABASE_URL.
  • Kết nối trực tiếp (db.[project-ref].supabase.co:5432) sử dụng IPv6, trừ khi project của bạn có IPv4 add-on. Trên mạng chỉ hỗ trợ IPv4, hãy sử dụng connection string của session pooler thay thế (tài liệu kết nối Supabase).
  • Chờ 2–3 phút sau khi tạo project rồi mới thực hiện lần push đầu tiên.
  • Redirect URI phải là https://[ref].supabase.co/auth/v1/callback.
  • Sử dụng cùng URI trong Google Cloud và trong nhà cung cấp Supabase Auth.
Để xem repository gốc và các bước chi tiết, hãy xem dodo-supabase-subscription-starter.
Lần sửa đổi cuối 26 tháng 9, 2026