30分钟用Wave搭建带认证与计费的SaaS骨架
本文手把手教你使用基于 Laravel 的开源 Starter Kit——Wave,快速跑通一套包含用户认证、订阅计费、角色权限和后台管理的完整 SaaS 骨架。附带 Stripe 测试支付对接与自定义业务页面开发实战,助你省去重复基建时间,将精力聚焦于核心产品打磨。

30分钟用Wave搭建带认证与计费的SaaS骨架
做 SaaS 产品最耗时的往往不是核心业务逻辑,而是那些「每个应用都得有」的基础模块:用户注册登录、权限控制、订阅计费计划、后台管理面板。从零手写这些基建功能,不仅开发周期长,Stripe 或 Paddle 的 Webhook 回调调试也容易让人头疼。
本文以开源项目 Wave 为载体,带你一步步搭建一套能直接运行的 SaaS 骨架。学完本教程,你将获得一套包含完整认证、用户管理、计费系统和管理后台的 Laravel 项目,并掌握如何在此基础上快速接入自己的业务逻辑。
环境准备
Wave 本质上是基于 Laravel 10+ 构建的 Starter Kit,运行前请确保本地环境满足以下要求:
- PHP >= 8.1(推荐搭配 Laravel Herd 或 Laragon 一键配置)
- Composer(PHP 依赖管理工具)
- Node.js & NPM(用于 Tailwind CSS 和 Vite 前端资源编译)
- MySQL 或 SQLite(本地验证建议直接用 SQLite,零配置最省心)
- 具备基础的 Laravel 开发认知(熟悉 Artisan 命令、路由定义、Blade 模板语法即可)
如果你是 macOS 用户且使用了 Laravel Herd,可以直接执行 herd new --starter-kit=devdojo/wave 完成初始化。本文采用标准的 Composer 安装方式,确保所有开发者都能复现。
核心步骤:5 分钟拉起完整骨架
1. 初始化项目
打开终端,执行以下命令拉取项目并切换目录:
bash
composer create-project devdojo/wave my-saas-app
cd my-saas-app
Composer 会自动下载 Laravel 框架核心及 Wave 的 SaaS 功能模块。安装完成后,你会发现项目目录结构与标准 Laravel 一致,但多了大量预配置的认证、计费视图和中间件。
2. 配置环境变量
复制默认环境配置文件并生成应用加密 Key:
bash
cp .env.example .env
php artisan key:generate
编辑 .env 文件,将数据库连接切换为 SQLite,跳过繁琐的本地数据库创建过程:
env
DB_CONNECTION=sqlite
随后手动创建空数据库文件:
bash
touch database/database.sqlite
3. 迁移数据表与填充初始数据
Wave 已经为你预定义了用户表、订阅计划表、角色权限表等完整结构。运行迁移命令即可一键建表:
bash
php artisan migrate --seed
--seed 参数会向数据库中插入默认数据,例如预置的 Free 和 Pro 订阅计划。无需手动写 SQL 或 Migration 脚本。
4. 启动开发服务
bash
php artisan serve
浏览器访问 http://localhost:8000,你将直接看到 Wave 默认首页。点击右上角 Register 即可体验完整的注册、登录、密码找回流程。
至此,一套具备基础能力的 SaaS 应用已经跑通。
实战一:开发自定义业务仪表板
骨架跑通只是第一步。假设你正在开发一款「AI 写作助手」,用户登录后需要展示专属的使用量统计与写作面板。
创建控制器
使用 Artisan 生成控制器文件:
bash
php artisan make:controller DashboardController
编辑 app/Http/Controllers/DashboardController.php,加入用户认证校验与数据聚合逻辑:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function index()
{
// Wave 的 auth 中间件已处理未登录拦截,此处可直接获取用户实例
$user = auth()->user();
$plan = $user->plan()->first();
return view('wave::dashboard', [
'user' => $user,
'plan' => $plan,
'usage' => $this->getUsage($user),
]);
}
private function getUsage($user)
{
// 替换为你的实际业务统计逻辑(如数据库查询或 API 调用)
return [
'words_generated' => 1250,
'api_calls' => 48,
];
}
}
注册路由
在 routes/web.php 中添加受保护的路由组:
php
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])
->name('dashboard');
});
编写视图
Wave 的视图系统采用命名空间注册机制。通过 resources/views/vendor/wave/ 目录下的模板,你可以安全覆盖默认布局而不会影响后续框架升级。
创建 resources/views/vendor/wave/dashboard.blade.php:
blade
@extends('wave::app')
@section('content')
<div class="max-w-4xl mx-auto py-8">
<h1 class="text-2xl font-bold mb-4">欢迎回来,{{ $user->name }}!</h1>
<div class="bg-white rounded-lg shadow p-6">
<p>当前计划:<span class="font-semibold">{{ $plan->name ?? 'Free' }}</span></p>
<div class="mt-4 grid grid-cols-2 gap-4">
<div class="p-4 bg-gray-50 rounded">
<p class="text-sm text-gray-500">已生成字数</p>
<p class="text-xl font-bold">{{ number_format($usage['words_generated']) }}</p>
</div>
<div class="p-4 bg-gray-50 rounded">
<p class="text-sm text-gray-500">API 调用次数</p>
<p class="text-xl font-bold">{{ $usage['api_calls'] }}</p>
</div>
</div>
</div>
</div>
@endsection
刷新页面,访问 /dashboard 即可看到你定制的业务面板。
实战二:接入 Stripe 测试支付
Wave 内置了 Stripe 和 Paddle 的计费适配层。开发阶段务必使用测试模式,避免产生真实扣费。
- 登录 Stripe 开发者后台,复制测试环境的
Publishable Key和Secret Key。 - 在
.env中追加以下配置:
env
STRIPE_KEY=pk_test_xxxxxxxxxxxxxxxx
STRIPE_SECRET=sk_test_xxxxxxxxxxxxxxxx
BILLING_PROVIDER=stripe
Wave 的计费模块会自动读取环境变量。你可以直接在管理后台(/admin -> Billing -> Plans)可视化创建订阅计划,或使用 Tinker 快速生成:
bash
php artisan tinker
php
>>> \Wave\Plan::create([
... 'name' => 'Pro',
... 'price' => 19.99,
... 'interval' => 'month',
... 'features' => json_encode(['无限量写作', 'API 高优先级', '专属客服']),
... ]);
配置完成后,访问首页 Pricing 区域即可看到 Pro 计划。点击订阅将跳转至 Stripe Checkout 安全收银台。使用测试卡号 4242 4242 4242 4242(过期日期填未来任意时间,CVC 任意三位)即可模拟完整的支付成功流程。
开发避坑指南
在基于 Wave 进行二次开发时,以下几点能帮你节省大量调试时间:
- 前端样式未生效:记得运行
npm install && npm run dev。Vite 需要实时编译 Tailwind 工具类。若样式仍异常,检查vite.config.js的入口是否准确指向resources/css/app.css。 - 本地收不到 Stripe Webhook:生产环境配置真实域名即可,开发环境推荐使用 Stripe CLI 进行请求转发:
stripe listen --forward-to localhost:8000/webhook/stripe。这能让你在本地直接调试异步回调逻辑。 - 升级导致自定义视图丢失:绝对不要直接修改
vendor/devdojo/wave/resources/views下的文件。Composer 的 update 命令会彻底清空该目录。正确做法是将模板复制到resources/views/vendor/wave/后再进行修改,利用 Laravel 的视图覆盖优先级机制保持兼容。 - SQLite 外键约束报错:若在迁移时遇到外键限制,在
.env中设置DB_FOREIGN_KEYS=true,并在config/database.php的 SQLite 驱动配置中启用'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true)。
总结与建议
通过不到 10 分钟的环境配置与启动,加上几十分钟的自定义开发与支付联调,你现在手中已经握有一套功能完备的 SaaS 原型。Wave 帮你剥离了重复的底层基建,让你能够直接面对真实用户和核心业务。
接下来的演进路线建议:
- 注入核心逻辑:将 OpenAI API 调用、文档处理或你的专属算法接入到控制器中。
- 善用插件机制:尽量通过扩展或插件形式添加新功能,避免污染 Wave 核心代码,方便后续平滑升级。
- 异步任务处理:配置 Redis 或 Beanstalkd 队列,将订阅成功邮件、账单生成等耗时操作移出请求主线程。
- 生产环境部署:将 SQLite 替换为 MySQL 或 PostgreSQL,配置 Nginx 反向代理与 HTTPS,选择 VPS 或 Serverless 平台上线。
把节省下来的时间投入到产品体验打磨与用户反馈迭代中,才是独立开发者破局的关键。如果在对接过程中遇到任何报错,欢迎在评论区贴出具体的错误堆栈,我会协助排查。