AeThex-OS/temp-forge-extract/aethex-forge-main/api/subscriptions/create-checkout.ts
MrPiglr b3c308b2c8 Add functional marketplace modules, bottom nav bar, root terminal, arcade games
- ModuleManager: Central tracking for installed marketplace modules
- DataAnalyzerWidget: Real-time CPU/RAM/Battery/Storage widget (unlocked by Data Analyzer module)
- BottomNavBar: Navigation bar for Projects/Chat/Marketplace/Settings
- RootShell: Real root command execution utility
- TerminalActivity: Full root shell with neofetch, sysinfo, real Linux commands
- Terminal Pro module: Adds aliases (ll, la, h), command history
- ArcadeActivity + SnakeGame: Pixel Arcade module unlocks retro games
- fade_in/fade_out animations for smooth transitions
2026-02-18 22:03:50 -07:00

138 lines
3.7 KiB
TypeScript

import type { VercelRequest, VercelResponse } from "@vercel/node";
import Stripe from "stripe";
import { getAdminClient } from "../_supabase.js";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", {
apiVersion: "2024-04-10",
});
const SUBSCRIPTION_TIERS = {
pro: {
name: "Pro",
priceMonthly: 900,
priceId: process.env.STRIPE_PRO_PRICE_ID || "",
},
council: {
name: "Council",
priceMonthly: 2900,
priceId: process.env.STRIPE_COUNCIL_PRICE_ID || "",
},
} as const;
type TierKey = keyof typeof SUBSCRIPTION_TIERS;
export default async function handler(req: VercelRequest, res: VercelResponse) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const admin = getAdminClient();
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).json({ error: "Unauthorized" });
}
const token = authHeader.replace("Bearer ", "");
const {
data: { user },
error: authError,
} = await admin.auth.getUser(token);
if (authError || !user) {
return res.status(401).json({ error: "Invalid token" });
}
try {
const { tier, successUrl, cancelUrl } = req.body;
if (!tier || !["pro", "council"].includes(tier)) {
return res.status(400).json({
error: "Invalid tier. Must be 'pro' or 'council'",
});
}
const tierKey = tier as TierKey;
const tierConfig = SUBSCRIPTION_TIERS[tierKey];
const { data: profile } = await admin
.from("user_profiles")
.select("stripe_customer_id, tier, full_name")
.eq("id", user.id)
.single();
if (profile?.tier === tier || profile?.tier === "council") {
return res.status(400).json({
error:
profile?.tier === "council"
? "You already have the highest tier"
: "You already have this subscription",
});
}
let customerId = profile?.stripe_customer_id;
if (!customerId) {
const customer = await stripe.customers.create({
email: user.email,
name: profile?.full_name || user.email,
metadata: {
userId: user.id,
},
});
customerId = customer.id;
await admin
.from("user_profiles")
.update({ stripe_customer_id: customerId })
.eq("id", user.id);
}
const baseUrl =
process.env.VITE_APP_URL || process.env.REPLIT_DEV_DOMAIN
? `https://${process.env.REPLIT_DEV_DOMAIN}`
: "https://aethex.dev";
const session = await stripe.checkout.sessions.create({
customer: customerId,
mode: "subscription",
payment_method_types: ["card"],
line_items: [
{
price_data: {
currency: "usd",
product_data: {
name: `AeThex ${tierConfig.name} Subscription`,
description: `Monthly ${tierConfig.name} tier subscription for AeThex`,
},
unit_amount: tierConfig.priceMonthly,
recurring: {
interval: "month",
},
},
quantity: 1,
},
],
success_url: successUrl || `${baseUrl}/dashboard?subscription=success`,
cancel_url: cancelUrl || `${baseUrl}/pricing?subscription=cancelled`,
metadata: {
userId: user.id,
tier: tierKey,
},
subscription_data: {
metadata: {
userId: user.id,
tier: tierKey,
},
},
});
return res.status(200).json({
sessionId: session.id,
url: session.url,
});
} catch (error: any) {
console.error("Checkout session error:", error);
return res.status(500).json({ error: error?.message || "Server error" });
}
}