0548a08cbb
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
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
/**
|
||
* Stripe product / price id 映射
|
||
*
|
||
* 为什么不直接存到 `subscription-plans.ts`:
|
||
* - product/price id 是部署环境配置(不同环境不同 product)
|
||
* - 套餐本身的 `name` / `price` / `highlight` 是业务常量(不随环境变)
|
||
* - 分离后,套餐表只包含业务字段,产品 id 走 env —— 避免硬编码 + 生产安全
|
||
*
|
||
* env 命名规范:
|
||
* - STRIPE_PRODUCT_<PLAN_ID_UPPER> → Product ID
|
||
* - STRIPE_PRICE_<PLAN_ID_UPPER> → Price ID
|
||
* - 例:STRIPE_PRODUCT_MONTHLY, STRIPE_PRICE_QUARTERLY
|
||
*/
|
||
import type { SubscriptionPlanId } from "@/data/constants/subscription-plans";
|
||
|
||
/**
|
||
* 获取 Stripe Product ID(从 env)
|
||
*
|
||
* @throws Error 如果 env 未配置(避免 silent failure)
|
||
*/
|
||
export function getPlanProductId(planId: SubscriptionPlanId): string {
|
||
const envKey = `STRIPE_PRODUCT_${planId.toUpperCase()}`;
|
||
const productId = process.env[envKey];
|
||
if (!productId || productId.startsWith("prod_replace_")) {
|
||
throw new Error(
|
||
`Stripe product id is not configured. Set ${envKey} in .env.local.`,
|
||
);
|
||
}
|
||
return productId;
|
||
}
|
||
|
||
/**
|
||
* 获取 Stripe Price ID(从 env)
|
||
*
|
||
* Price ID 是真正用在 `stripe.checkout.sessions.create({ line_items: [{ price: "price_xxx" }] })` 里的
|
||
*
|
||
* @throws Error 如果 env 未配置
|
||
*/
|
||
export function getPlanPriceId(planId: SubscriptionPlanId): string {
|
||
const envKey = `STRIPE_PRICE_${planId.toUpperCase()}`;
|
||
const priceId = process.env[envKey];
|
||
if (!priceId || priceId.startsWith("price_replace_")) {
|
||
throw new Error(
|
||
`Stripe price id is not configured. Set ${envKey} in .env.local.`,
|
||
);
|
||
}
|
||
return priceId;
|
||
}
|