201 lines
4.3 KiB
Markdown
201 lines
4.3 KiB
Markdown
# Pro 套餐配置指南
|
||
|
||
## 概述
|
||
|
||
系统现在完全从数据库动态获取 Pro 套餐的配置,不再依赖环境变量 `NEXT_PUBLIC_STRIPE_PRO_PRICE_ID`。
|
||
|
||
## 核心原理
|
||
|
||
1. **动态查找**: 系统通过查找数据库中 `name = 'pro'` 的套餐来确定 Pro 套餐
|
||
2. **价格判定**: 任何价格超过 $19 的套餐都被视为 Pro 级别
|
||
3. **实时获取**: 订阅时动态获取 Pro 套餐的 Stripe 价格 ID
|
||
|
||
## 配置步骤
|
||
|
||
### 1. 确保 Pro 套餐存在
|
||
|
||
运行种子脚本会自动创建 Pro 套餐:
|
||
|
||
```bash
|
||
npm run db:seed
|
||
```
|
||
|
||
或者手动创建:
|
||
|
||
```sql
|
||
INSERT INTO subscription_plans (
|
||
id, name, "displayName", description, price, currency, interval,
|
||
"stripePriceId", "isActive", "sortOrder", features, limits,
|
||
"createdAt", "updatedAt"
|
||
) VALUES (
|
||
'pro', 'pro', 'Pro Plan', 'Advanced features for power users',
|
||
19.9, 'usd', 'month', NULL, true, 2,
|
||
'{"promptLimit": true, "versionsPerPrompt": true, "prioritySupport": true}',
|
||
'{"maxVersionLimit": 10, "promptLimit": 5000, "creditMonthly": 20}',
|
||
NOW(), NOW()
|
||
);
|
||
```
|
||
|
||
### 2. 设置 Stripe 价格 ID
|
||
|
||
在 Stripe Dashboard 中创建价格后,更新数据库:
|
||
|
||
```sql
|
||
UPDATE subscription_plans
|
||
SET "stripePriceId" = 'price_your_actual_stripe_price_id'
|
||
WHERE name = 'pro';
|
||
```
|
||
|
||
### 3. 验证配置
|
||
|
||
运行测试脚本验证配置:
|
||
|
||
```bash
|
||
npx tsx scripts/test-pro-plan-detection.ts
|
||
```
|
||
|
||
## API 端点
|
||
|
||
### 获取 Pro 价格 ID
|
||
|
||
```http
|
||
GET /api/subscription/pro-price-id
|
||
```
|
||
|
||
**成功响应**:
|
||
```json
|
||
{
|
||
"priceId": "price_1RryBL9mNQExFr2OpYGPdBVJ"
|
||
}
|
||
```
|
||
|
||
**错误响应**:
|
||
```json
|
||
{
|
||
"error": "Pro plan not found or not configured"
|
||
}
|
||
```
|
||
|
||
## 前端集成
|
||
|
||
### QuickUpgradeButton 组件
|
||
|
||
```typescript
|
||
import { QuickUpgradeButton } from '@/components/subscription/SubscribeButton'
|
||
|
||
// 自动获取 Pro 套餐价格 ID
|
||
<QuickUpgradeButton className="btn-primary">
|
||
Upgrade to Pro
|
||
</QuickUpgradeButton>
|
||
```
|
||
|
||
### 定价页面
|
||
|
||
定价页面会自动从数据库获取所有套餐,包括 Pro 套餐的价格 ID。
|
||
|
||
## 服务端方法
|
||
|
||
### SubscriptionService 方法
|
||
|
||
```typescript
|
||
import { SubscriptionService } from '@/lib/subscription-service'
|
||
|
||
// 获取 Pro 套餐
|
||
const proPlan = await SubscriptionService.getProPlan()
|
||
|
||
// 获取 Pro 价格 ID
|
||
const proPriceId = await SubscriptionService.getProPriceId()
|
||
|
||
// 判断套餐是否为 Pro
|
||
const isPro = SubscriptionService.isPlanPro(plan)
|
||
|
||
// 判断用户是否为 Pro
|
||
const isUserPro = await SubscriptionService.isUserPro(userId)
|
||
```
|
||
|
||
## 故障排除
|
||
|
||
### 问题:订阅创建失败
|
||
|
||
**原因**: Pro 套餐未配置或 Stripe 价格 ID 未设置
|
||
|
||
**解决方案**:
|
||
1. 检查数据库中是否存在 `name = 'pro'` 的套餐
|
||
2. 确认该套餐的 `stripePriceId` 字段不为空
|
||
3. 验证 Stripe 价格 ID 是否有效
|
||
|
||
### 问题:API 返回 404
|
||
|
||
**原因**: 找不到名称为 "pro" 的套餐
|
||
|
||
**解决方案**:
|
||
```sql
|
||
-- 检查套餐名称
|
||
SELECT id, name, "displayName" FROM subscription_plans WHERE "isActive" = true;
|
||
|
||
-- 如果名称不正确,更新为 "pro"
|
||
UPDATE subscription_plans SET name = 'pro' WHERE id = 'pro';
|
||
```
|
||
|
||
### 问题:前端显示 "Pro plan unavailable"
|
||
|
||
**原因**: API 无法获取 Pro 价格 ID
|
||
|
||
**解决方案**:
|
||
1. 检查 API 端点 `/api/subscription/pro-price-id` 是否正常
|
||
2. 确认数据库连接正常
|
||
3. 验证 Pro 套餐配置
|
||
|
||
## 测试工具
|
||
|
||
### 检测脚本
|
||
|
||
```bash
|
||
# 测试 Pro 套餐检测
|
||
npx tsx scripts/test-pro-plan-detection.ts
|
||
|
||
# 修复 Pro 套餐名称
|
||
npx tsx scripts/fix-pro-plan-name.ts
|
||
```
|
||
|
||
### 手动测试
|
||
|
||
```bash
|
||
# 测试 API 端点
|
||
curl http://localhost:3000/api/subscription/pro-price-id
|
||
|
||
# 检查数据库
|
||
npx prisma studio
|
||
```
|
||
|
||
## 迁移指南
|
||
|
||
### 从环境变量迁移
|
||
|
||
如果你之前使用 `NEXT_PUBLIC_STRIPE_PRO_PRICE_ID`:
|
||
|
||
1. 将价格 ID 更新到数据库:
|
||
```sql
|
||
UPDATE subscription_plans
|
||
SET "stripePriceId" = 'your_old_price_id'
|
||
WHERE name = 'pro';
|
||
```
|
||
|
||
2. 移除环境变量:
|
||
```bash
|
||
# 从 .env 文件中删除这一行
|
||
# NEXT_PUBLIC_STRIPE_PRO_PRICE_ID="price_..."
|
||
```
|
||
|
||
3. 重新构建应用:
|
||
```bash
|
||
npm run build
|
||
```
|
||
|
||
## 优势
|
||
|
||
1. **灵活性**: 可以在数据库中动态修改 Pro 套餐配置
|
||
2. **安全性**: 价格 ID 不再暴露在客户端环境变量中
|
||
3. **可扩展性**: 支持多个 Pro 级别套餐
|
||
4. **一致性**: 所有套餐配置都在数据库中统一管理
|