fix stripe
This commit is contained in:
parent
81b33f85f2
commit
c765368382
3
package-lock.json
generated
3
package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^6.12.0",
|
"@prisma/client": "^6.13.0",
|
||||||
"@stripe/stripe-js": "^7.8.0",
|
"@stripe/stripe-js": "^7.8.0",
|
||||||
"@supabase/auth-ui-react": "^0.4.7",
|
"@supabase/auth-ui-react": "^0.4.7",
|
||||||
"@supabase/auth-ui-shared": "^0.1.8",
|
"@supabase/auth-ui-shared": "^0.1.8",
|
||||||
@ -1445,6 +1445,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz",
|
||||||
"integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==",
|
"integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.18"
|
"node": ">=18.18"
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"seed": "tsx prisma/seed.ts"
|
"seed": "tsx prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^6.12.0",
|
"@prisma/client": "^6.13.0",
|
||||||
"@stripe/stripe-js": "^7.8.0",
|
"@stripe/stripe-js": "^7.8.0",
|
||||||
"@supabase/auth-ui-react": "^0.4.7",
|
"@supabase/auth-ui-react": "^0.4.7",
|
||||||
"@supabase/auth-ui-shared": "^0.1.8",
|
"@supabase/auth-ui-shared": "^0.1.8",
|
||||||
|
@ -40,6 +40,7 @@ model User {
|
|||||||
subscriptionPlan SubscriptionPlan @relation(fields: [subscriptionPlanId], references: [id])
|
subscriptionPlan SubscriptionPlan @relation(fields: [subscriptionPlanId], references: [id])
|
||||||
prompts Prompt[]
|
prompts Prompt[]
|
||||||
credits Credit[]
|
credits Credit[]
|
||||||
|
subscriptions Subscription[]
|
||||||
|
|
||||||
@@map("users")
|
@@map("users")
|
||||||
}
|
}
|
||||||
@ -66,6 +67,7 @@ model SubscriptionPlan {
|
|||||||
|
|
||||||
// 关联关系
|
// 关联关系
|
||||||
users User[]
|
users User[]
|
||||||
|
subscriptions Subscription[]
|
||||||
|
|
||||||
@@map("subscription_plans")
|
@@map("subscription_plans")
|
||||||
}
|
}
|
||||||
@ -173,3 +175,32 @@ model Credit {
|
|||||||
|
|
||||||
@@map("credits")
|
@@map("credits")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 订阅记录模型
|
||||||
|
model Subscription {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
userId String // 用户 ID
|
||||||
|
subscriptionPlanId String // 订阅套餐 ID
|
||||||
|
stripeSubscriptionId String? @unique // Stripe 订阅 ID
|
||||||
|
stripeCustomerId String? // Stripe 客户 ID(冗余存储,便于查询)
|
||||||
|
|
||||||
|
// 订阅状态和时间
|
||||||
|
isActive Boolean @default(false) // 是否有效
|
||||||
|
startDate DateTime? // 开始时间(订阅激活时设置)
|
||||||
|
endDate DateTime? // 结束时间(订阅激活时设置)
|
||||||
|
|
||||||
|
// 订阅状态
|
||||||
|
status String @default("pending") // "pending", "active", "canceled", "expired", "failed"
|
||||||
|
|
||||||
|
// 元数据
|
||||||
|
metadata Json? // 额外的元数据(如 Stripe 的原始数据)
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// 关联关系
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
subscriptionPlan SubscriptionPlan @relation(fields: [subscriptionPlanId], references: [id])
|
||||||
|
|
||||||
|
@@map("subscriptions")
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { createServerClient } from '@supabase/ssr'
|
|||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
import { createOrGetStripeCustomer, createSubscriptionSession } from '@/lib/stripe'
|
import { createOrGetStripeCustomer, createSubscriptionSession } from '@/lib/stripe'
|
||||||
import { prisma } from '@/lib/prisma'
|
import { prisma } from '@/lib/prisma'
|
||||||
|
import { SubscriptionService } from '@/lib/subscription-service'
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
@ -55,12 +56,14 @@ export async function POST(request: NextRequest) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 创建订阅会话
|
// 创建订阅会话
|
||||||
|
console.log('🛒 Creating subscription session for customer:', customer.id, 'price:', priceId)
|
||||||
const session = await createSubscriptionSession(
|
const session = await createSubscriptionSession(
|
||||||
customer.id,
|
customer.id,
|
||||||
priceId,
|
priceId,
|
||||||
`${process.env.NEXT_PUBLIC_APP_URL}/subscription?success=true`,
|
`${process.env.NEXT_PUBLIC_APP_URL}/subscription?success=true`,
|
||||||
`${process.env.NEXT_PUBLIC_APP_URL}/pricing?canceled=true`
|
`${process.env.NEXT_PUBLIC_APP_URL}/pricing?canceled=true`
|
||||||
)
|
)
|
||||||
|
console.log('✅ Created session:', session.id, 'mode:', session.mode)
|
||||||
|
|
||||||
// 保存 Stripe 客户 ID 到数据库
|
// 保存 Stripe 客户 ID 到数据库
|
||||||
await prisma.user.update({
|
await prisma.user.update({
|
||||||
@ -68,6 +71,14 @@ export async function POST(request: NextRequest) {
|
|||||||
data: { stripeCustomerId: customer.id }
|
data: { stripeCustomerId: customer.id }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 创建初始的订阅记录(待激活状态)
|
||||||
|
await SubscriptionService.createPendingSubscription(
|
||||||
|
user.id,
|
||||||
|
plan.id,
|
||||||
|
undefined, // Stripe 订阅 ID 将在 webhook 中设置
|
||||||
|
customer.id
|
||||||
|
)
|
||||||
|
|
||||||
return NextResponse.json({ sessionId: session.id, url: session.url })
|
return NextResponse.json({ sessionId: session.id, url: session.url })
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -6,11 +6,13 @@ import { SubscriptionService } from '@/lib/subscription-service'
|
|||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
console.log('🔔 Webhook received')
|
||||||
const body = await request.text()
|
const body = await request.text()
|
||||||
const headersList = await headers()
|
const headersList = await headers()
|
||||||
const signature = headersList.get('stripe-signature')
|
const signature = headersList.get('stripe-signature')
|
||||||
|
|
||||||
if (!signature) {
|
if (!signature) {
|
||||||
|
console.log('❌ No signature found')
|
||||||
return NextResponse.json({ error: 'No signature' }, { status: 400 })
|
return NextResponse.json({ error: 'No signature' }, { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,6 +23,8 @@ export async function POST(request: NextRequest) {
|
|||||||
STRIPE_CONFIG.webhookSecret
|
STRIPE_CONFIG.webhookSecret
|
||||||
)
|
)
|
||||||
|
|
||||||
|
console.log(`📨 Processing event: ${event.type}`)
|
||||||
|
|
||||||
// 处理不同类型的事件
|
// 处理不同类型的事件
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case 'checkout.session.completed':
|
case 'checkout.session.completed':
|
||||||
@ -61,29 +65,47 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
async function handleCheckoutSessionCompleted(session: Record<string, unknown>) {
|
async function handleCheckoutSessionCompleted(session: Record<string, unknown>) {
|
||||||
try {
|
try {
|
||||||
|
console.log('🛒 Processing checkout session completed')
|
||||||
|
console.log('Session data:', JSON.stringify(session, null, 2))
|
||||||
|
|
||||||
const subscriptionId = session.subscription as string
|
const subscriptionId = session.subscription as string
|
||||||
|
console.log('Subscription ID from session:', subscriptionId)
|
||||||
|
|
||||||
if (!subscriptionId) {
|
if (!subscriptionId) {
|
||||||
|
console.log('❌ No subscription ID found in checkout session')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取订阅详情
|
// 获取订阅详情
|
||||||
|
console.log('📞 Retrieving subscription from Stripe...')
|
||||||
const subscription = await stripe.subscriptions.retrieve(subscriptionId)
|
const subscription = await stripe.subscriptions.retrieve(subscriptionId)
|
||||||
|
console.log('✅ Retrieved subscription:', subscription.id, 'status:', subscription.status)
|
||||||
|
|
||||||
// 处理订阅更新
|
// 处理订阅更新
|
||||||
await handleSubscriptionUpdate(subscription as unknown as Record<string, unknown>)
|
await handleSubscriptionUpdate(subscription as unknown as Record<string, unknown>)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error handling checkout session completed:', error)
|
console.error('❌ Error handling checkout session completed:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSubscriptionUpdate(subscription: Record<string, unknown>) {
|
async function handleSubscriptionUpdate(subscription: Record<string, unknown>) {
|
||||||
try {
|
try {
|
||||||
|
console.log('🔄 Processing subscription update')
|
||||||
const customerId = subscription.customer as string
|
const customerId = subscription.customer as string
|
||||||
const status = subscription.status as string
|
const status = subscription.status as string
|
||||||
|
const stripeSubscriptionId = subscription.id as string
|
||||||
const items = subscription.items as { data: Array<{ price: { id: string } }> }
|
const items = subscription.items as { data: Array<{ price: { id: string } }> }
|
||||||
const priceId = items?.data[0]?.price?.id
|
const priceId = items?.data[0]?.price?.id
|
||||||
|
const currentPeriodStart = subscription.current_period_start as number
|
||||||
|
const currentPeriodEnd = subscription.current_period_end as number
|
||||||
|
|
||||||
|
console.log(`📊 Subscription details:`, {
|
||||||
|
customerId,
|
||||||
|
status,
|
||||||
|
stripeSubscriptionId,
|
||||||
|
priceId
|
||||||
|
})
|
||||||
|
|
||||||
// 查找用户
|
// 查找用户
|
||||||
const user = await prisma.user.findFirst({
|
const user = await prisma.user.findFirst({
|
||||||
@ -91,21 +113,79 @@ async function handleSubscriptionUpdate(subscription: Record<string, unknown>) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.error('User not found for customer:', customerId)
|
console.error('❌ User not found for customer:', customerId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据订阅状态确定套餐
|
console.log(`👤 Found user: ${user.id}`)
|
||||||
let planId = 'free'
|
|
||||||
if (status === 'active' || status === 'trialing') {
|
if (status === 'active' || status === 'trialing') {
|
||||||
// 根据 Stripe 价格 ID 获取套餐 ID
|
// 根据 Stripe 价格 ID 获取套餐 ID
|
||||||
planId = await SubscriptionService.getPlanIdByStripePriceId(priceId)
|
const planId = await SubscriptionService.getPlanIdByStripePriceId(priceId)
|
||||||
|
|
||||||
|
// 检查是否已有待激活的订阅记录(通过用户 ID 查找)
|
||||||
|
const existingSubscription = await prisma.subscription.findFirst({
|
||||||
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
status: 'pending',
|
||||||
|
subscriptionPlanId: planId
|
||||||
|
},
|
||||||
|
orderBy: { createdAt: 'desc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (existingSubscription) {
|
||||||
|
// 激活现有的订阅记录,并设置 Stripe 订阅 ID
|
||||||
|
await prisma.subscription.update({
|
||||||
|
where: { id: existingSubscription.id },
|
||||||
|
data: {
|
||||||
|
stripeSubscriptionId,
|
||||||
|
isActive: true,
|
||||||
|
status: 'active',
|
||||||
|
startDate: new Date(currentPeriodStart * 1000),
|
||||||
|
endDate: new Date(currentPeriodEnd * 1000),
|
||||||
|
metadata: subscription ? JSON.parse(JSON.stringify(subscription)) : undefined,
|
||||||
|
updatedAt: new Date()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log(`✅ Activated existing subscription ${existingSubscription.id} for user ${user.id}`)
|
||||||
|
} else {
|
||||||
|
// 检查是否是续订(已有活跃订阅)
|
||||||
|
const activeSubscription = await SubscriptionService.getUserActiveSubscription(user.id)
|
||||||
|
|
||||||
|
if (activeSubscription) {
|
||||||
|
// 这是续订,创建新的订阅记录
|
||||||
|
await SubscriptionService.createRenewalSubscription(
|
||||||
|
user.id,
|
||||||
|
planId,
|
||||||
|
stripeSubscriptionId,
|
||||||
|
new Date(currentPeriodStart * 1000),
|
||||||
|
new Date(currentPeriodEnd * 1000),
|
||||||
|
customerId,
|
||||||
|
subscription
|
||||||
|
)
|
||||||
|
console.log(`Created renewal subscription for user ${user.id}`)
|
||||||
|
} else {
|
||||||
|
// 直接创建并激活订阅(可能是通过其他方式创建的订阅)
|
||||||
|
await SubscriptionService.createRenewalSubscription(
|
||||||
|
user.id,
|
||||||
|
planId,
|
||||||
|
stripeSubscriptionId,
|
||||||
|
new Date(currentPeriodStart * 1000),
|
||||||
|
new Date(currentPeriodEnd * 1000),
|
||||||
|
customerId,
|
||||||
|
subscription
|
||||||
|
)
|
||||||
|
console.log(`Created new subscription for user ${user.id}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新用户订阅套餐
|
// 更新用户的默认订阅套餐(保持向后兼容)
|
||||||
|
const planId = status === 'active' || status === 'trialing'
|
||||||
|
? await SubscriptionService.getPlanIdByStripePriceId(priceId)
|
||||||
|
: 'free'
|
||||||
await SubscriptionService.updateUserSubscriptionPlan(user.id, planId)
|
await SubscriptionService.updateUserSubscriptionPlan(user.id, planId)
|
||||||
|
|
||||||
console.log(`Updated user ${user.id} subscription to plan: ${planId}`)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error handling subscription update:', error)
|
console.error('Error handling subscription update:', error)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { prisma } from '@/lib/prisma'
|
import { prisma } from '@/lib/prisma'
|
||||||
import { getCustomerSubscriptions } from '@/lib/stripe'
|
|
||||||
import type { SubscriptionPlan } from '@prisma/client'
|
import type { SubscriptionPlan } from '@prisma/client'
|
||||||
import { isPlanPro } from '@/lib/subscription-utils'
|
import { isPlanPro } from '@/lib/subscription-utils'
|
||||||
|
|
||||||
@ -102,83 +101,119 @@ export class SubscriptionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户的当前订阅状态(从 Stripe 实时获取)
|
* 获取用户的当前订阅状态(从订阅表查询)
|
||||||
*/
|
*/
|
||||||
static async getUserSubscriptionStatus(userId: string): Promise<SubscriptionStatus> {
|
static async getUserSubscriptionStatus(userId: string): Promise<SubscriptionStatus> {
|
||||||
const user = await prisma.user.findUnique({
|
// 查找用户当前有效的订阅
|
||||||
where: { id: userId },
|
const activeSubscription = await this.getUserActiveSubscription(userId)
|
||||||
select: {
|
|
||||||
stripeCustomerId: true,
|
|
||||||
subscriptionPlanId: true,
|
|
||||||
subscriptionPlan: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new Error('User not found')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果 plan 没有 stripePriceId,则直接返回当前套餐有效
|
|
||||||
// 无需从 Stripe 实时获取
|
|
||||||
if (!user.subscriptionPlan?.stripePriceId) {
|
|
||||||
return {
|
|
||||||
isActive: true,
|
|
||||||
planId: user.subscriptionPlanId || 'free'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有匹配到上述规则,则需要从 Stripe 获取实时状态
|
|
||||||
// 如果此时没有 Stripe 客户 ID,则返免费套餐状态
|
|
||||||
if (!user.stripeCustomerId) {
|
|
||||||
return {
|
|
||||||
isActive: true,
|
|
||||||
planId: 'free'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 从 Stripe 获取实时订阅状态
|
|
||||||
const subscriptions = await getCustomerSubscriptions(user.stripeCustomerId)
|
|
||||||
const activeSubscription = subscriptions.find(sub =>
|
|
||||||
sub.status === 'active' || sub.status === 'trialing'
|
|
||||||
)
|
|
||||||
|
|
||||||
if (activeSubscription) {
|
if (activeSubscription) {
|
||||||
// 根据 Stripe 价格 ID 确定套餐
|
|
||||||
const items = activeSubscription.items?.data || []
|
|
||||||
const priceId = items[0]?.price?.id
|
|
||||||
|
|
||||||
// 查找对应的套餐
|
|
||||||
const plan = await prisma.subscriptionPlan.findFirst({
|
|
||||||
where: { stripePriceId: priceId }
|
|
||||||
})
|
|
||||||
|
|
||||||
const subData = activeSubscription as unknown as Record<string, unknown>
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
planId: plan?.id || 'free',
|
planId: activeSubscription.subscriptionPlanId,
|
||||||
stripeSubscriptionId: activeSubscription.id,
|
stripeSubscriptionId: activeSubscription.stripeSubscriptionId || undefined,
|
||||||
currentPeriodStart: new Date((subData.current_period_start as number) * 1000),
|
currentPeriodStart: activeSubscription.startDate || undefined,
|
||||||
currentPeriodEnd: new Date((subData.current_period_end as number) * 1000),
|
currentPeriodEnd: activeSubscription.endDate || undefined,
|
||||||
cancelAtPeriodEnd: subData.cancel_at_period_end as boolean,
|
|
||||||
status: activeSubscription.status
|
status: activeSubscription.status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有活跃订阅,返回免费套餐
|
// 没有有效订阅,返回免费套餐
|
||||||
return {
|
return {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
planId: 'free'
|
planId: 'free'
|
||||||
}
|
}
|
||||||
} catch (error) {
|
}
|
||||||
console.error('Error fetching subscription status from Stripe:', error)
|
|
||||||
// Stripe 错误时,返回用户当前套餐状态
|
/**
|
||||||
return {
|
* 获取用户当前有效的订阅记录
|
||||||
|
*/
|
||||||
|
static async getUserActiveSubscription(userId: string) {
|
||||||
|
const now = new Date()
|
||||||
|
|
||||||
|
return await prisma.subscription.findFirst({
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
planId: user.subscriptionPlanId || 'free'
|
status: 'active',
|
||||||
|
startDate: { lte: now },
|
||||||
|
endDate: { gte: now }
|
||||||
|
},
|
||||||
|
orderBy: { createdAt: 'desc' }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的订阅记录(用户点击订阅时)
|
||||||
|
*/
|
||||||
|
static async createPendingSubscription(
|
||||||
|
userId: string,
|
||||||
|
planId: string,
|
||||||
|
stripeSubscriptionId?: string,
|
||||||
|
stripeCustomerId?: string
|
||||||
|
) {
|
||||||
|
return await prisma.subscription.create({
|
||||||
|
data: {
|
||||||
|
userId,
|
||||||
|
subscriptionPlanId: planId,
|
||||||
|
stripeSubscriptionId,
|
||||||
|
stripeCustomerId,
|
||||||
|
isActive: false,
|
||||||
|
status: 'pending'
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 激活订阅(Stripe 订阅成功回调时)
|
||||||
|
*/
|
||||||
|
static async activateSubscription(
|
||||||
|
stripeSubscriptionId: string,
|
||||||
|
startDate: Date,
|
||||||
|
endDate: Date,
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
) {
|
||||||
|
return await prisma.subscription.updateMany({
|
||||||
|
where: {
|
||||||
|
stripeSubscriptionId,
|
||||||
|
status: 'pending'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
isActive: true,
|
||||||
|
status: 'active',
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
metadata: metadata ? JSON.parse(JSON.stringify(metadata)) : undefined,
|
||||||
|
updatedAt: new Date()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建续订记录(Stripe 续订成功时)
|
||||||
|
*/
|
||||||
|
static async createRenewalSubscription(
|
||||||
|
userId: string,
|
||||||
|
planId: string,
|
||||||
|
stripeSubscriptionId: string,
|
||||||
|
startDate: Date,
|
||||||
|
endDate: Date,
|
||||||
|
stripeCustomerId?: string,
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
) {
|
||||||
|
return await prisma.subscription.create({
|
||||||
|
data: {
|
||||||
|
userId,
|
||||||
|
subscriptionPlanId: planId,
|
||||||
|
stripeSubscriptionId,
|
||||||
|
stripeCustomerId,
|
||||||
|
isActive: true,
|
||||||
|
status: 'active',
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
metadata: metadata ? JSON.parse(JSON.stringify(metadata)) : undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user