import type { NextApiRequest, NextApiResponse } from "next"; import { env } from "next-runtime-env"; import { z } from "zod"; import { createNextApiContext } from "@kan/api/trpc"; import * as workspaceRepo from "@kan/db/repository/workspace.repo"; import { createStripeClient } from "@kan/stripe"; const workspaceSlugSchema = z .string() .min(3) .max(24) .regex(/^(?![-]+$)[a-zA-Z0-9-]+$/); interface CheckoutSessionRequest { successUrl: string; cancelUrl: string; slug: string; workspacePublicId: string; stripeCustomerId: string; } export default async function handler( req: NextApiRequest, res: NextApiResponse, ) { const stripe = createStripeClient(); if (req.method !== "POST") { return res.status(405).json({ error: "Method not allowed" }); } try { const { user, db } = await createNextApiContext(req); if (!user) { return res.status(404).json({ error: "User not found" }); } const body = req.body as CheckoutSessionRequest; const { successUrl, cancelUrl, slug, workspacePublicId } = body; if (!successUrl || !cancelUrl || !slug || !workspacePublicId) { return res.status(400).json({ error: "Missing required fields" }); } const slugResult = workspaceSlugSchema.safeParse(slug); if (!slugResult.success) { return new Response(JSON.stringify({ error: "Invalid workspace slug" }), { status: 400, headers: { "Content-Type": "application/json" }, }); } const workspace = await workspaceRepo.getAllByUserId(db, user.id); const isMemberOfWorkspace = workspace.some( ({ workspace }) => workspace.publicId === body.workspacePublicId, ); if (!isMemberOfWorkspace) { return new Response(JSON.stringify({ error: "Unauthorized" }), { status: 403, headers: { "Content-Type": "application/json" }, }); } const session = await stripe.checkout.sessions.create({ mode: "subscription", line_items: [ { price: process.env.STRIPE_PRO_PLAN_PRICE_ID, quantity: 1, }, ], success_url: `${env("NEXT_PUBLIC_BASE_URL")}${successUrl}`, cancel_url: `${env("NEXT_PUBLIC_BASE_URL")}${cancelUrl}`, customer: user.stripeCustomerId ?? undefined, metadata: { workspaceSlug: slug, workspacePublicId, }, }); return res.status(200).json({ url: session.url }); } catch (error) { console.error("Error:", error); return res.status(500).json({ error: "Error creating checkout session" }); } }