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ự ánNEXT_PUBLIC_SUPABASE_ANON_KEY, anon keySUPABASE_SERVICE_ROLE_KEY, service role keyDATABASE_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.processingvàpayment.cancelled - Sự kiện đăng ký:
subscription.active,subscription.plan_changed,subscription.renewed,subscription.on_hold,subscription.cancelled,subscription.expiredvàsubscription.failed
DODO_WEBHOOK_SECRET.6
Create .env.local
Tạo một tệp Ứng dụng Next.js đọc mọi biến trong tệp này ngoại trừ
.env.local trong thư mục gốc:DODO_WEBHOOK_SECRET. Edge Function đọc DODO_WEBHOOK_SECRET từ Supabase secrets, được thiết lập khi bạn triển khai function.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 Script Response
dodo-webhook. Thay [your-project-ref] bằng project reference của bạn: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
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 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à 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:features và hiển thị từng mục.10
Run the Dev Server
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:generatevàdb:migratecho 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
Tệp và đường dẫn chính
Webhook handler, app routes và database schema nằm trong các tệp sau:- Edge Function
- Next.js Routes
- Database (Drizzle)
Environment Variables
Ứng dụng Next.js và Edge Function đọc các biến sau:Supabase
Supabase
.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 đó.Dodo Payments
Dodo Payments
Google OAuth
Google OAuth
Ứ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ố
Webhook signature invalid (400)
Webhook signature invalid (400)
- Đảm bảo secret
DODO_WEBHOOK_SECRETcủ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-webhookmới nhất. - Function xác minh các header
webhook-id,webhook-signaturevàwebhook-timestampcủa Standard Webhooks. Đảm bảo proxy không loại bỏ chúng.
Database push fails
Database push fails
- 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.
OAuth redirect mismatch
OAuth redirect mismatch
- 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.