Skip to main content
Glama
aegntic

Obsidian Elite RAG MCP Server

stripe-license-manager.ts10.6 kB
import Stripe from 'stripe'; import { SupabaseAuthManager } from './supabase-client.js'; export class StripeLicenseManager { private stripe: Stripe | null = null; private mockMode: boolean; private authManager: SupabaseAuthManager; // Pricing configuration private readonly PRICES = { pro: { monthly: process.env.STRIPE_PRO_PRICE_ID || 'price_pro_monthly', yearly: process.env.STRIPE_PRO_PRICE_YEARLY_ID || 'price_pro_yearly' }, enterprise: { monthly: process.env.STRIPE_ENTERPRISE_PRICE_ID || 'price_enterprise_monthly', yearly: process.env.STRIPE_ENTERPRISE_PRICE_YEARLY_ID || 'price_enterprise_yearly' } }; constructor(stripeKey?: string, authManager?: SupabaseAuthManager) { // Use the live key from environment const actualStripeKey = process.env.STRIPE_SECRET_KEY?.startsWith('sk_live_') ? process.env.STRIPE_SECRET_KEY : (stripeKey || process.env.STRIPE_SECRET_KEY); this.mockMode = !actualStripeKey || process.env.MOCK_PAYMENT_SERVICE === "true"; this.authManager = authManager || new SupabaseAuthManager( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); if (!this.mockMode && actualStripeKey) { this.stripe = new Stripe(actualStripeKey, { apiVersion: '2023-10-16', typescript: true }); } } async verifyFeatureAccess(email: string, feature: string): Promise<boolean> { // Get user from database const user = await this.authManager.getUserByEmail(email); if (!user) return false; // Check tier-based access return this.checkTierAccess(user.tier, feature); } async createSubscription(data: { email: string; tier: 'pro' | 'enterprise'; payment_method: string; billing_cycle?: 'monthly' | 'yearly'; }): Promise<any> { const user = await this.authManager.getUserByEmail(data.email); if (!user) { throw new Error('User not found'); } if (this.mockMode) { console.log(`📧 MOCK: Creating ${data.tier} subscription for ${data.email}`); // Update user tier in database await this.authManager.updateUserTier(data.email, data.tier); return { id: `sub_mock_${Date.now()}`, customer: `cus_mock_${Date.now()}`, status: 'active', current_period_end: Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60), items: { data: [{ price: { id: this.PRICES[data.tier][data.billing_cycle || 'monthly'] } }] } }; } if (!this.stripe) { throw new Error('Stripe not configured'); } try { // Create or get Stripe customer let customer: Stripe.Customer; if (user.stripe_customer_id) { customer = await this.stripe.customers.retrieve(user.stripe_customer_id) as Stripe.Customer; } else { customer = await this.stripe.customers.create({ email: data.email, name: user.name, metadata: { user_id: user.id, tier: data.tier } }); // Save customer ID await this.authManager.updateUser(data.email, { stripe_customer_id: customer.id }); } // Attach payment method await this.stripe.paymentMethods.attach(data.payment_method, { customer: customer.id }); // Set as default payment method await this.stripe.customers.update(customer.id, { invoice_settings: { default_payment_method: data.payment_method } }); // Create subscription const subscription = await this.stripe.subscriptions.create({ customer: customer.id, items: [{ price: this.PRICES[data.tier][data.billing_cycle || 'monthly'] }], metadata: { user_email: data.email, tier: data.tier } }); // Update user tier and subscription info in database await this.authManager.createSubscription({ user_id: user.id, stripe_subscription_id: subscription.id, tier: data.tier, status: subscription.status, current_period_end: new Date(subscription.current_period_end * 1000) }); await this.authManager.updateUserTier(data.email, data.tier); return subscription; } catch (error) { console.error('Stripe subscription error:', error); throw error; } } async cancelSubscription(email: string): Promise<void> { const user = await this.authManager.getUserByEmail(email); if (!user) { throw new Error('User not found'); } const subscription = await this.authManager.getUserSubscription(user.id); if (!subscription) { throw new Error('No active subscription found'); } if (this.mockMode) { console.log(`📧 MOCK: Canceling subscription for ${email}`); await this.authManager.updateUserTier(email, 'free'); return; } if (!this.stripe) { throw new Error('Stripe not configured'); } try { // Cancel at period end await this.stripe.subscriptions.update(subscription.stripe_subscription_id, { cancel_at_period_end: true }); // Update database await this.authManager.updateSubscriptionStatus( subscription.stripe_subscription_id, 'canceled' ); } catch (error) { console.error('Stripe cancellation error:', error); throw error; } } async updateSubscription(email: string, newTier: 'pro' | 'enterprise'): Promise<any> { const user = await this.authManager.getUserByEmail(email); if (!user) { throw new Error('User not found'); } const subscription = await this.authManager.getUserSubscription(user.id); if (!subscription) { throw new Error('No active subscription found'); } if (this.mockMode) { console.log(`📧 MOCK: Updating subscription to ${newTier} for ${email}`); await this.authManager.updateUserTier(email, newTier); return { id: subscription.stripe_subscription_id, status: 'active' }; } if (!this.stripe) { throw new Error('Stripe not configured'); } try { // Get current subscription const stripeSubscription = await this.stripe.subscriptions.retrieve( subscription.stripe_subscription_id ); // Update subscription const updated = await this.stripe.subscriptions.update( subscription.stripe_subscription_id, { items: [{ id: stripeSubscription.items.data[0].id, price: this.PRICES[newTier]['monthly'] }], metadata: { tier: newTier } } ); // Update database await this.authManager.updateUserTier(email, newTier); await this.authManager.updateSubscriptionTier( subscription.stripe_subscription_id, newTier ); return updated; } catch (error) { console.error('Stripe update error:', error); throw error; } } async createPaymentIntent(amount: number, currency: string = 'usd'): Promise<any> { if (this.mockMode) { return { id: `pi_mock_${Date.now()}`, client_secret: `pi_mock_secret_${Date.now()}`, amount, currency }; } if (!this.stripe) { throw new Error('Stripe not configured'); } return await this.stripe.paymentIntents.create({ amount, currency, automatic_payment_methods: { enabled: true } }); } private checkTierAccess(tier: string, feature: string): boolean { const tierFeatures = { free: [ 'basic_image_generation', 'basic_text_processing', 'limited_api_access' ], pro: [ 'advanced_image_generation', 'video_generation', 'batch_processing', 'custom_workflows', 'api_priority', 'all_free_features' ], enterprise: [ 'unlimited_access', 'custom_models', 'white_label', 'dedicated_support', 'all_features' ] }; if (tier === 'enterprise') return true; if (tier === 'pro') { return tierFeatures.pro.includes(feature) || tierFeatures.pro.includes('all_free_features') && tierFeatures.free.includes(feature); } return tierFeatures.free.includes(feature); } async handleWebhook(signature: string, payload: string): Promise<void> { if (!this.stripe || this.mockMode) { console.log('📧 MOCK: Webhook received'); return; } const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; if (!webhookSecret) { throw new Error('Webhook secret not configured'); } try { const event = this.stripe.webhooks.constructEvent( payload, signature, webhookSecret ); switch (event.type) { case 'customer.subscription.created': case 'customer.subscription.updated': await this.handleSubscriptionUpdate(event.data.object as Stripe.Subscription); break; case 'customer.subscription.deleted': await this.handleSubscriptionDeleted(event.data.object as Stripe.Subscription); break; case 'invoice.payment_failed': await this.handlePaymentFailed(event.data.object as Stripe.Invoice); break; } } catch (error) { console.error('Webhook error:', error); throw error; } } private async handleSubscriptionUpdate(subscription: Stripe.Subscription): Promise<void> { const email = subscription.metadata.user_email; if (!email) return; await this.authManager.updateSubscriptionStatus( subscription.id, subscription.status ); if (subscription.status === 'active') { const tier = subscription.metadata.tier as 'pro' | 'enterprise'; await this.authManager.updateUserTier(email, tier); } } private async handleSubscriptionDeleted(subscription: Stripe.Subscription): Promise<void> { const email = subscription.metadata.user_email; if (!email) return; await this.authManager.updateUserTier(email, 'free'); await this.authManager.updateSubscriptionStatus( subscription.id, 'canceled' ); } private async handlePaymentFailed(invoice: Stripe.Invoice): Promise<void> { // Log payment failure for follow-up console.error(`Payment failed for customer: ${invoice.customer}`); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aegntic/aegntic-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server