项目概述
这是一个可复用的 SaaS 基础框架,包含所有 SaaS 产品必备的基础设施:
- 认证系统:邮箱注册、Google/GitHub OAuth
- 订阅管理:免费版、Pro 版、企业版三档
- 支付集成:Stripe 订阅、Webhook 处理
- 权限控制:基于订阅计划的功能限制
- 用户仪表盘:使用量统计、账单管理
订阅计划设计
const PLANS = {
free: {
name: '免费版',
price: 0,
limits: {
apiCalls: 100, // 每月 API 调用次数
projects: 3, // 最多项目数
storage: 100, // MB
},
features: ['基础功能', '社区支持'],
},
pro: {
name: 'Pro 版',
price: 29, // 美元/月
stripePriceId: 'price_xxx',
limits: {
apiCalls: 10000,
projects: 50,
storage: 10240, // 10GB
},
features: ['全部功能', '优先支持', 'API 访问'],
},
enterprise: {
name: '企业版',
price: 99,
stripePriceId: 'price_yyy',
limits: {
apiCalls: -1, // 无限制
projects: -1,
storage: -1,
},
features: ['无限使用', '专属客服', 'SLA 保障', '自定义集成'],
},
};核心功能实现
权限中间件
// middleware/checkPlan.ts
export function requirePlan(minPlan: 'free' | 'pro' | 'enterprise') {
return async (req: Request, res: Response, next: NextFunction) => {
const user = await prisma.user.findUnique({
where: { id: req.user.id },
include: { subscription: true },
});
const planOrder = { free: 0, pro: 1, enterprise: 2 };
const userPlan = user?.subscription?.plan ?? 'free';
if (planOrder[userPlan] < planOrder[minPlan]) {
return res.status(403).json({
error: 'PLAN_REQUIRED',
message: `此功能需要 ${minPlan} 及以上套餐`,
upgradeUrl: '/pricing',
});
}
next();
};
}
// 使用示例
router.post('/api/export', requirePlan('pro'), exportHandler);Stripe Webhook 处理
app.post('/api/webhooks/stripe',
express.raw({ type: 'application/json' }),
async (req, res) => {
const sig = req.headers['stripe-signature']!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
} catch {
return res.status(400).send('Webhook signature verification failed');
}
switch (event.type) {
case 'customer.subscription.created':
case 'customer.subscription.updated':
await handleSubscriptionChange(event.data.object as Stripe.Subscription);
break;
case 'customer.subscription.deleted':
await handleSubscriptionCancelled(event.data.object as Stripe.Subscription);
break;
case 'invoice.payment_failed':
await handlePaymentFailed(event.data.object as Stripe.Invoice);
break;
}
res.json({ received: true });
}
);关键提示词
提示词:使用量限制检查
实现一个使用量检查中间件:
1. 每次 API 调用时,检查用户本月已使用次数
2. 如果超过当前套餐限制,返回 429 错误和升级提示
3. 使用 Redis 缓存计数,key 格式:usage:{userId}:{year}:{month}
4. 每月 1 日自动重置计数
5. 在响应头中返回剩余次数:X-RateLimit-Remaining
技术栈:Express + Redis (ioredis) + Prisma