feat: integrate Stripe payment with subscription plans

Add Stripe payment integration across the project:

- Add @stripe/stripe-js dependency
- Configure Stripe environment variables (secret key, publishable key, webhook secret) for dev, local, and production environments
- Add Product/Price IDs for monthly, quarterly, and annual subscription tiers
- Extend subscription plan data with voiceMinutesPerDay quotas (30/45/60 minutes per tier)
- Update .gitignore to exclude implementation_plan.md
This commit is contained in:
2026-06-16 10:21:02 +08:00
parent 17741320ff
commit 0548a08cbb
25 changed files with 1220 additions and 26 deletions
+9 -1
View File
@@ -17,12 +17,20 @@ export const UserSchema = z.object({
personalityTraits: PersonalityTraitsSchema.default(PERSONALITY_TRAITS_DEFAULTS),
preferredLanguage: z.string().default(""),
createdAt: z.string().default(""),
// 后端**新**游客返回 null"还没发过消息"),`.default("")` **不**兜 null —— 需 nullable
// 后端游客返回 null"还没发过消息"),`.default("")` 兜 null —— 需 nullable
lastMessageAt: z.string().nullable().default(null),
avatarUrl: z.string().default(""),
loginProvider: z.string().default("email"),
isGuest: z.boolean().default(false),
/** 是否为 VIP 会员(订阅中或未过期) —— Stripe webhook 更新 */
isVip: z.boolean().default(false),
/** 语音聊天剩余分钟数(订阅生效后每天补充;用完为 0 不变) */
voiceMinutesRemaining: z.number().default(0),
/** Stripe Customer ID —— 首次 Checkout 完成后由 webhook 设置,用于 Customer Portal 自助管理 */
stripeCustomerId: z.string().nullable().default(null),
});
export type UserInput = z.input<typeof UserSchema>;
export type UserData = z.output<typeof UserSchema>;