@digilogiclabs/saas-factory-payments 1.2.0 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/native.js +1 -1
- package/dist/native.js.map +1 -1
- package/dist/native.mjs +1 -1
- package/dist/native.mjs.map +1 -1
- package/dist/web.js +1 -1
- package/dist/web.js.map +1 -1
- package/dist/web.mjs +1 -1
- package/dist/web.mjs.map +1 -1
- package/package.json +14 -23
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/shared/types/subscription.ts","../src/shared/types/errors.ts","../src/shared/constants.ts","../src/shared/utils/validation.ts","../src/shared/utils/formatting.ts","../src/shared/utils/env.ts","../src/providers/base/index.ts","../src/providers/stripe/index.ts","../src/providers/mock/index.ts","../src/providers/index.ts","../src/shared/providers/PaymentsProvider.tsx","../src/hooks/usePayments.ts","../src/shared/hooks/usePayments.ts","../src/web/components/CheckoutButton.tsx","../src/web/components/PricingTable.tsx","../src/web/components/PaymentForm.tsx","../src/web/components/SubscriptionManager.tsx"],"sourcesContent":["// Shared exports\nexport * from './shared/types';\nexport * from './shared/constants';\nexport * from './shared/utils/validation';\nexport * from './shared/utils/formatting';\nexport * from './shared/utils/env';\n\n// Utils that templates expect\nexport {\n formatCurrency,\n formatDate,\n calculateTax,\n formatTaxRate,\n formatAmountWithTax,\n} from './shared/utils/formatting';\nexport {\n validateCard,\n validateEmail,\n validateAmount,\n validatePricingPlan,\n validatePaymentsConfig,\n} from './shared/utils/validation';\n\n// Providers\nexport { PaymentProviderFactory } from './providers';\nexport * from './providers/stripe';\nexport * from './providers/mock';\n\n// New providers (temporarily commented out due to build issues)\n// export * from './providers/paypal';\n// export * from './providers/applepay';\n\n// Hooks\nexport {\n PaymentsProvider,\n usePaymentsContext,\n} from './shared/providers/PaymentsProvider';\nexport { usePayments } from './shared/hooks/usePayments';\n\n// Analytics hooks (temporarily commented out due to build issues)\n// export { useSubscriptionAnalytics } from './shared/hooks/useSubscriptionAnalytics';\n// export { useRevenueAnalytics } from './shared/hooks/useRevenueAnalytics';\n\n// Re-export commonly used components from web for convenience\nexport {\n StripePaymentForm,\n SubscriptionManager,\n PricingTable,\n type StripePaymentFormProps,\n type SubscriptionManagerProps,\n} from './web/components';\n\n// Platform-specific exports are handled by package.json exports field\n// Users will import from:\n// - '@digilogiclabs/saas-factory-payments/web' for web components\n// - '@digilogiclabs/saas-factory-payments/native' for React Native components\n// - '@digilogiclabs/saas-factory-payments/server' for server-side utilities\n","export enum SubscriptionStatus {\n ACTIVE = 'active',\n CANCELED = 'canceled',\n PAST_DUE = 'past_due',\n UNPAID = 'unpaid',\n INCOMPLETE = 'incomplete',\n INCOMPLETE_EXPIRED = 'incomplete_expired',\n TRIALING = 'trialing',\n ENDED = 'ended', // Custom status for ended subscriptions\n ALL = 'all', // For filtering purposes\n}\n\nexport interface SubscriptionItem {\n id: string;\n priceId: string;\n quantity: number;\n metadata?: Record<string, string>;\n}\n\nexport interface Subscription {\n id: string;\n customerId: string;\n customer_id?: string; // For compatibility\n status: SubscriptionStatus;\n items?: SubscriptionItem[];\n price_id?: string; // For single-item subscriptions\n currentPeriodStart: Date;\n current_period_start?: Date; // For compatibility\n currentPeriodEnd: Date;\n current_period_end?: Date; // For compatibility\n cancelAtPeriodEnd: boolean;\n cancel_at_period_end?: boolean; // For compatibility\n trialEnd?: Date;\n trial_end?: Date; // For compatibility\n trialStart?: Date;\n trial_start?: Date; // For compatibility\n canceledAt?: Date;\n canceled_at?: Date; // For compatibility\n endedAt?: Date;\n metadata?: Record<string, string>;\n created: Date;\n updated?: Date;\n // Additional fields for analytics\n amount?: number;\n currency?: string;\n interval?: string;\n interval_unit?: string;\n planName?: string;\n planId?: string;\n}\n\nexport interface SubscriptionCreateParams {\n customerId: string;\n items?: { priceId: string; quantity?: number }[];\n priceId?: string; // For single-item subscriptions\n trialPeriodDays?: number;\n metadata?: Record<string, string>;\n paymentBehavior?:\n | 'default_incomplete'\n | 'error_if_incomplete'\n | 'allow_incomplete';\n // Additional fields for multi-provider support\n customerEmail?: string;\n customerName?: string;\n successUrl?: string;\n cancelUrl?: string;\n}\n\nexport interface SubscriptionUpdateParams {\n items?: { priceId: string; quantity?: number }[];\n priceId?: string; // For single-item subscriptions\n quantity?: number;\n cancelAtPeriodEnd?: boolean;\n metadata?: Record<string, string>;\n}\n\n// More specific status type unions for better TypeScript support\nexport type ActiveSubscriptionStatus =\n | SubscriptionStatus.ACTIVE\n | SubscriptionStatus.TRIALING;\nexport type InactiveSubscriptionStatus =\n | SubscriptionStatus.CANCELED\n | SubscriptionStatus.ENDED;\nexport type ProblematicSubscriptionStatus =\n | SubscriptionStatus.PAST_DUE\n | SubscriptionStatus.UNPAID;\nexport type IncompleteSubscriptionStatus =\n | SubscriptionStatus.INCOMPLETE\n | SubscriptionStatus.INCOMPLETE_EXPIRED;\n\n// Status groups for filtering and UI logic\nexport const ACTIVE_STATUSES: ActiveSubscriptionStatus[] = [\n SubscriptionStatus.ACTIVE,\n SubscriptionStatus.TRIALING,\n];\n\nexport const INACTIVE_STATUSES: InactiveSubscriptionStatus[] = [\n SubscriptionStatus.CANCELED,\n SubscriptionStatus.ENDED,\n];\n\nexport const PROBLEMATIC_STATUSES: ProblematicSubscriptionStatus[] = [\n SubscriptionStatus.PAST_DUE,\n SubscriptionStatus.UNPAID,\n];\n\nexport const INCOMPLETE_STATUSES: IncompleteSubscriptionStatus[] = [\n SubscriptionStatus.INCOMPLETE,\n SubscriptionStatus.INCOMPLETE_EXPIRED,\n];\n\n// Helper functions for subscription status checks\nexport const isActiveSubscription = (\n status: SubscriptionStatus\n): status is ActiveSubscriptionStatus => {\n return ACTIVE_STATUSES.includes(status as ActiveSubscriptionStatus);\n};\n\nexport const isInactiveSubscription = (\n status: SubscriptionStatus\n): status is InactiveSubscriptionStatus => {\n return INACTIVE_STATUSES.includes(status as InactiveSubscriptionStatus);\n};\n\nexport const isProblematicSubscription = (\n status: SubscriptionStatus\n): status is ProblematicSubscriptionStatus => {\n return PROBLEMATIC_STATUSES.includes(status as ProblematicSubscriptionStatus);\n};\n\nexport const isIncompleteSubscription = (\n status: SubscriptionStatus\n): status is IncompleteSubscriptionStatus => {\n return INCOMPLETE_STATUSES.includes(status as IncompleteSubscriptionStatus);\n};\n","export enum PaymentErrorType {\n CARD_DECLINED = 'CARD_DECLINED',\n INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS',\n CUSTOMER_NOT_FOUND = 'CUSTOMER_NOT_FOUND',\n SUBSCRIPTION_NOT_FOUND = 'SUBSCRIPTION_NOT_FOUND',\n NETWORK_ERROR = 'NETWORK_ERROR',\n CONFIGURATION_ERROR = 'CONFIGURATION_ERROR',\n WEBHOOK_ERROR = 'WEBHOOK_ERROR',\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n PROVIDER_NOT_CONFIGURED = 'PROVIDER_NOT_CONFIGURED',\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n INITIALIZATION_ERROR = 'INITIALIZATION_ERROR',\n AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR',\n NOT_FOUND = 'NOT_FOUND',\n INVALID_REQUEST = 'INVALID_REQUEST',\n API_ERROR = 'API_ERROR',\n PERMISSION_DENIED = 'PERMISSION_DENIED',\n WEBHOOK_VERIFICATION_FAILED = 'WEBHOOK_VERIFICATION_FAILED',\n}\n\nexport interface PaymentError extends Error {\n type: PaymentErrorType;\n code?: string;\n details?: Record<string, unknown>;\n}\n\nexport class PaymentsError extends Error implements PaymentError {\n public type: PaymentErrorType;\n public code?: string;\n public details?: Record<string, unknown>;\n\n constructor(\n type: PaymentErrorType,\n message: string,\n code?: string,\n details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'PaymentsError';\n this.type = type;\n this.code = code;\n this.details = details;\n Object.setPrototypeOf(this, PaymentsError.prototype);\n }\n}\n","export const STRIPE_API_VERSION = '2023-10-16';\n\nexport const PAYMENT_METHODS = {\n CARD: 'card',\n BANK_ACCOUNT: 'bank_account',\n SEPA_DEBIT: 'sepa_debit',\n IDEAL: 'ideal',\n SOFORT: 'sofort',\n} as const;\n\nexport const SUBSCRIPTION_STATUS = {\n ACTIVE: 'active',\n CANCELED: 'canceled',\n PAST_DUE: 'past_due',\n UNPAID: 'unpaid',\n INCOMPLETE: 'incomplete',\n INCOMPLETE_EXPIRED: 'incomplete_expired',\n TRIALING: 'trialing',\n} as const;\n\nexport const INVOICE_STATUS = {\n DRAFT: 'draft',\n OPEN: 'open',\n PAID: 'paid',\n UNCOLLECTIBLE: 'uncollectible',\n VOID: 'void',\n} as const;\n\nexport const CHECKOUT_MODE = {\n PAYMENT: 'payment',\n SUBSCRIPTION: 'subscription',\n SETUP: 'setup',\n} as const;\n\nexport const BILLING_INTERVALS = {\n DAY: 'day',\n WEEK: 'week',\n MONTH: 'month',\n YEAR: 'year',\n} as const;\n\nexport const CURRENCY_SYMBOLS = {\n USD: '$',\n EUR: '€',\n GBP: '£',\n JPY: '¥',\n CAD: 'C$',\n AUD: 'A$',\n CHF: 'CHF',\n CNY: '¥',\n SEK: 'kr',\n NZD: 'NZ$',\n} as const;\n\nexport const DEFAULT_CURRENCY = 'USD';\n\nexport const WEBHOOK_EVENTS = {\n CUSTOMER_SUBSCRIPTION_CREATED: 'customer.subscription.created',\n CUSTOMER_SUBSCRIPTION_UPDATED: 'customer.subscription.updated',\n CUSTOMER_SUBSCRIPTION_DELETED: 'customer.subscription.deleted',\n INVOICE_PAYMENT_SUCCEEDED: 'invoice.payment_succeeded',\n INVOICE_PAYMENT_FAILED: 'invoice.payment_failed',\n CHECKOUT_SESSION_COMPLETED: 'checkout.session.completed',\n PAYMENT_INTENT_SUCCEEDED: 'payment_intent.succeeded',\n PAYMENT_INTENT_PAYMENT_FAILED: 'payment_intent.payment_failed',\n} as const;\n\nexport const ERROR_MESSAGES = {\n PROVIDER_NOT_CONFIGURED: 'Payments provider is not properly configured',\n STRIPE_NOT_LOADED: 'Stripe has not been loaded yet',\n INVALID_PRICE_ID: 'Invalid price ID provided',\n INVALID_CUSTOMER_ID: 'Invalid customer ID provided',\n CHECKOUT_FAILED: 'Checkout session creation failed',\n PAYMENT_FAILED: 'Payment processing failed',\n SUBSCRIPTION_NOT_FOUND: 'Subscription not found',\n CUSTOMER_NOT_FOUND: 'Customer not found',\n} as const;\n","import { PaymentsConfig, PricingPlan } from '../types';\n\nexport const validateEmail = (email: string): boolean => {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n};\n\nexport const validatePhoneNumber = (phone: string): boolean => {\n // Basic phone number validation - can be enhanced based on requirements\n const phoneRegex = /^\\+?[\\d\\s-()]{10,}$/;\n return phoneRegex.test(phone);\n};\n\nexport const validatePaymentsConfig = (\n config: PaymentsConfig\n): { isValid: boolean; errors: string[] } => {\n const errors: string[] = [];\n\n if (!config.publishableKey) {\n errors.push('publishableKey is required');\n }\n\n if (!config.provider) {\n errors.push('provider is required');\n }\n\n if (config.provider !== 'stripe') {\n errors.push('Only stripe provider is currently supported');\n }\n\n if (!config.environment) {\n errors.push('environment is required');\n }\n\n if (\n config.environment &&\n !['development', 'production'].includes(config.environment)\n ) {\n errors.push('environment must be either \"development\" or \"production\"');\n }\n\n if (config.publishableKey && !config.publishableKey.startsWith('pk_')) {\n errors.push('publishableKey must start with \"pk_\"');\n }\n\n if (config.secretKey && !config.secretKey.startsWith('sk_')) {\n errors.push('secretKey must start with \"sk_\"');\n }\n\n if (config.webhookSecret && !config.webhookSecret.startsWith('whsec_')) {\n errors.push('webhookSecret must start with \"whsec_\"');\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n};\n\nexport const validatePricingPlan = (\n plan: PricingPlan\n): { isValid: boolean; errors: string[] } => {\n const errors: string[] = [];\n\n if (!plan.id) {\n errors.push('id is required');\n }\n\n if (!plan.name) {\n errors.push('name is required');\n }\n\n if (typeof plan.price !== 'number' || plan.price < 0) {\n errors.push('price must be a non-negative number');\n }\n\n if (!plan.currency) {\n errors.push('currency is required');\n }\n\n if (!plan.interval) {\n errors.push('interval is required');\n }\n\n if (!['day', 'week', 'month', 'year'].includes(plan.interval)) {\n errors.push('interval must be one of: day, week, month, year');\n }\n\n if (!plan.stripePriceId) {\n errors.push('stripePriceId is required');\n }\n\n if (plan.stripePriceId && !plan.stripePriceId.startsWith('price_')) {\n errors.push('stripePriceId must start with \"price_\"');\n }\n\n if (!Array.isArray(plan.features)) {\n errors.push('features must be an array');\n }\n\n if (\n plan.intervalCount &&\n (typeof plan.intervalCount !== 'number' || plan.intervalCount < 1)\n ) {\n errors.push('intervalCount must be a positive number');\n }\n\n if (\n plan.trialPeriodDays &&\n (typeof plan.trialPeriodDays !== 'number' || plan.trialPeriodDays < 0)\n ) {\n errors.push('trialPeriodDays must be a non-negative number');\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n};\n\nexport const validateStripeId = (\n id: string,\n type: 'customer' | 'subscription' | 'price' | 'product' | 'payment_intent'\n): boolean => {\n const prefixes = {\n customer: 'cus_',\n subscription: 'sub_',\n price: 'price_',\n product: 'prod_',\n payment_intent: 'pi_',\n };\n\n return id.startsWith(prefixes[type]);\n};\n\nexport const validateAmount = (\n amount: number,\n currency: string\n): { isValid: boolean; error?: string } => {\n if (typeof amount !== 'number') {\n return { isValid: false, error: 'Amount must be a number' };\n }\n\n if (amount < 0) {\n return { isValid: false, error: 'Amount must be non-negative' };\n }\n\n // Stripe minimum amounts by currency\n const minimumAmounts: Record<string, number> = {\n USD: 50, // $0.50\n EUR: 50, // €0.50\n GBP: 30, // £0.30\n JPY: 50, // ¥50\n CAD: 50, // C$0.50\n AUD: 50, // A$0.50\n };\n\n const minAmount = minimumAmounts[currency.toUpperCase()] || 50;\n\n if (amount < minAmount) {\n return {\n isValid: false,\n error: `Amount must be at least ${minAmount} ${currency.toLowerCase()} cents`,\n };\n }\n\n return { isValid: true };\n};\n\nexport const validateCard = (cardDetails: {\n number: string;\n expMonth: number;\n expYear: number;\n cvc: string;\n}): { isValid: boolean; errors: string[] } => {\n const errors: string[] = [];\n\n // Validate card number (basic Luhn algorithm)\n const cleanNumber = cardDetails.number.replace(/\\s/g, '');\n if (!cleanNumber || cleanNumber.length < 13 || cleanNumber.length > 19) {\n errors.push('Card number must be between 13 and 19 digits');\n } else if (!luhnCheck(cleanNumber)) {\n errors.push('Invalid card number');\n }\n\n // Validate expiration month\n if (!cardDetails.expMonth || cardDetails.expMonth < 1 || cardDetails.expMonth > 12) {\n errors.push('Expiration month must be between 1 and 12');\n }\n\n // Validate expiration year\n const currentYear = new Date().getFullYear();\n if (!cardDetails.expYear || cardDetails.expYear < currentYear || cardDetails.expYear > currentYear + 20) {\n errors.push('Invalid expiration year');\n }\n\n // Check if card is expired\n if (cardDetails.expMonth && cardDetails.expYear) {\n const expirationDate = new Date(cardDetails.expYear, cardDetails.expMonth - 1, 1);\n const currentDate = new Date();\n if (expirationDate < currentDate) {\n errors.push('Card has expired');\n }\n }\n\n // Validate CVC\n if (!cardDetails.cvc || cardDetails.cvc.length < 3 || cardDetails.cvc.length > 4) {\n errors.push('CVC must be 3 or 4 digits');\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n};\n\n// Luhn algorithm for credit card validation\nconst luhnCheck = (cardNumber: string): boolean => {\n let sum = 0;\n let alternate = false;\n\n for (let i = cardNumber.length - 1; i >= 0; i--) {\n let n = parseInt(cardNumber.charAt(i), 10);\n\n if (alternate) {\n n *= 2;\n if (n > 9) {\n n = (n % 10) + 1;\n }\n }\n\n sum += n;\n alternate = !alternate;\n }\n\n return sum % 10 === 0;\n};\n","import { CURRENCY_SYMBOLS, DEFAULT_CURRENCY } from '../constants';\nimport { PricingPlan, SubscriptionStatus } from '../types';\n\nexport const formatCurrency = (\n amount: number,\n currency: string = DEFAULT_CURRENCY,\n options: {\n showSymbol?: boolean;\n showCents?: boolean;\n locale?: string;\n } = {}\n): string => {\n const { showSymbol = true, showCents = true, locale = 'en-US' } = options;\n\n const currencyCode = currency.toUpperCase();\n\n // Convert from cents to dollars for most currencies\n const isZeroDecimalCurrency = ['JPY', 'KRW', 'VND', 'CLP'].includes(\n currencyCode\n );\n const displayAmount = isZeroDecimalCurrency ? amount : amount / 100;\n\n if (showSymbol) {\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: showCents && !isZeroDecimalCurrency ? 2 : 0,\n maximumFractionDigits: showCents && !isZeroDecimalCurrency ? 2 : 0,\n }).format(displayAmount);\n } catch {\n // Fallback to manual formatting if Intl.NumberFormat fails\n const symbol =\n CURRENCY_SYMBOLS[currencyCode as keyof typeof CURRENCY_SYMBOLS] ||\n currencyCode;\n const formattedAmount =\n showCents && !isZeroDecimalCurrency\n ? displayAmount.toFixed(2)\n : Math.round(displayAmount).toString();\n return `${symbol}${formattedAmount}`;\n }\n }\n\n return showCents && !isZeroDecimalCurrency\n ? displayAmount.toFixed(2)\n : Math.round(displayAmount).toString();\n};\n\nexport const formatPricingPlan = (plan: PricingPlan): string => {\n const price = formatCurrency(plan.price, plan.currency);\n const interval =\n plan.intervalCount && plan.intervalCount > 1\n ? `${plan.intervalCount} ${plan.interval}s`\n : plan.interval;\n\n return `${price}/${interval}`;\n};\n\nexport const formatSubscriptionStatus = (\n status: SubscriptionStatus\n): string => {\n const statusMap: Record<SubscriptionStatus, string> = {\n [SubscriptionStatus.ACTIVE]: 'Active',\n [SubscriptionStatus.CANCELED]: 'Canceled',\n [SubscriptionStatus.PAST_DUE]: 'Past Due',\n [SubscriptionStatus.UNPAID]: 'Unpaid',\n [SubscriptionStatus.INCOMPLETE]: 'Incomplete',\n [SubscriptionStatus.INCOMPLETE_EXPIRED]: 'Incomplete (Expired)',\n [SubscriptionStatus.TRIALING]: 'Trial',\n [SubscriptionStatus.ENDED]: 'Ended',\n [SubscriptionStatus.ALL]: 'All',\n };\n\n return statusMap[status] || status;\n};\n\nexport const formatDate = (\n date: Date | string | number,\n options: {\n format?: 'short' | 'medium' | 'long' | 'full';\n locale?: string;\n timeZone?: string;\n } = {}\n): string => {\n const { format = 'medium', locale = 'en-US', timeZone } = options;\n\n const dateObj =\n typeof date === 'string' || typeof date === 'number'\n ? new Date(date)\n : date;\n\n const formatOptions: Intl.DateTimeFormatOptions = {\n timeZone,\n };\n\n switch (format) {\n case 'short':\n formatOptions.dateStyle = 'short';\n break;\n case 'medium':\n formatOptions.dateStyle = 'medium';\n break;\n case 'long':\n formatOptions.dateStyle = 'long';\n break;\n case 'full':\n formatOptions.dateStyle = 'full';\n break;\n }\n\n try {\n return new Intl.DateTimeFormat(locale, formatOptions).format(dateObj);\n } catch {\n // Fallback to basic formatting\n return dateObj.toLocaleDateString();\n }\n};\n\nexport const formatRelativeTime = (\n date: Date | string | number,\n options: {\n locale?: string;\n numeric?: 'always' | 'auto';\n } = {}\n): string => {\n const { locale = 'en-US', numeric = 'auto' } = options;\n\n const dateObj =\n typeof date === 'string' || typeof date === 'number'\n ? new Date(date)\n : date;\n const now = new Date();\n const diffInSeconds = Math.floor((now.getTime() - dateObj.getTime()) / 1000);\n\n try {\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric });\n\n if (Math.abs(diffInSeconds) < 60) {\n return rtf.format(-diffInSeconds, 'second');\n } else if (Math.abs(diffInSeconds) < 3600) {\n return rtf.format(-Math.floor(diffInSeconds / 60), 'minute');\n } else if (Math.abs(diffInSeconds) < 86400) {\n return rtf.format(-Math.floor(diffInSeconds / 3600), 'hour');\n } else if (Math.abs(diffInSeconds) < 2592000) {\n return rtf.format(-Math.floor(diffInSeconds / 86400), 'day');\n } else if (Math.abs(diffInSeconds) < 31536000) {\n return rtf.format(-Math.floor(diffInSeconds / 2592000), 'month');\n } else {\n return rtf.format(-Math.floor(diffInSeconds / 31536000), 'year');\n }\n } catch {\n // Fallback to basic relative time\n if (Math.abs(diffInSeconds) < 60) {\n return 'just now';\n } else if (Math.abs(diffInSeconds) < 3600) {\n const minutes = Math.floor(Math.abs(diffInSeconds) / 60);\n return diffInSeconds < 0\n ? `in ${minutes} minutes`\n : `${minutes} minutes ago`;\n } else if (Math.abs(diffInSeconds) < 86400) {\n const hours = Math.floor(Math.abs(diffInSeconds) / 3600);\n return diffInSeconds < 0 ? `in ${hours} hours` : `${hours} hours ago`;\n } else {\n const days = Math.floor(Math.abs(diffInSeconds) / 86400);\n return diffInSeconds < 0 ? `in ${days} days` : `${days} days ago`;\n }\n }\n};\n\nexport const formatBillingInterval = (\n interval: string,\n count: number = 1\n): string => {\n const intervalMap: Record<string, string> = {\n day: count === 1 ? 'daily' : `every ${count} days`,\n week: count === 1 ? 'weekly' : `every ${count} weeks`,\n month: count === 1 ? 'monthly' : `every ${count} months`,\n year: count === 1 ? 'yearly' : `every ${count} years`,\n };\n\n return intervalMap[interval] || interval;\n};\n\nexport const formatTrialPeriod = (days: number): string => {\n if (days === 0) return 'No trial';\n if (days === 1) return '1 day trial';\n if (days < 7) return `${days} days trial`;\n if (days === 7) return '1 week trial';\n if (days < 30) return `${Math.floor(days / 7)} weeks trial`;\n if (days === 30) return '1 month trial';\n return `${Math.floor(days / 30)} months trial`;\n};\n\nexport const truncateText = (text: string, maxLength: number): string => {\n if (text.length <= maxLength) return text;\n return `${text.substring(0, maxLength - 3)}...`;\n};\n\nexport const formatCardBrand = (brand: string): string => {\n const brandMap: Record<string, string> = {\n visa: 'Visa',\n mastercard: 'Mastercard',\n amex: 'American Express',\n discover: 'Discover',\n jcb: 'JCB',\n diners: 'Diners Club',\n unionpay: 'UnionPay',\n };\n\n return brandMap[brand.toLowerCase()] || brand;\n};\n\nexport const formatPaymentMethodDisplay = (paymentMethod: {\n type: string;\n card?: { brand: string; last4: string };\n bankAccount?: { last4: string; bankName?: string };\n}): string => {\n if (paymentMethod.type === 'card' && paymentMethod.card) {\n return `${formatCardBrand(paymentMethod.card.brand)} •••• ${paymentMethod.card.last4}`;\n }\n\n if (paymentMethod.type === 'bank_account' && paymentMethod.bankAccount) {\n const bankName = paymentMethod.bankAccount.bankName || 'Bank';\n return `${bankName} •••• ${paymentMethod.bankAccount.last4}`;\n }\n\n return paymentMethod.type;\n};\n\nexport const calculateTax = (\n amount: number,\n taxRate: number,\n options: {\n inclusive?: boolean;\n roundTo?: number;\n } = {}\n): { subtotal: number; tax: number; total: number } => {\n const { inclusive = false, roundTo = 2 } = options;\n\n let subtotal: number;\n let tax: number;\n let total: number;\n\n if (inclusive) {\n // Tax is included in the amount\n total = amount;\n subtotal = amount / (1 + taxRate / 100);\n tax = amount - subtotal;\n } else {\n // Tax is added to the amount\n subtotal = amount;\n tax = amount * (taxRate / 100);\n total = amount + tax;\n }\n\n // Round to specified decimal places\n const multiplier = Math.pow(10, roundTo);\n return {\n subtotal: Math.round(subtotal * multiplier) / multiplier,\n tax: Math.round(tax * multiplier) / multiplier,\n total: Math.round(total * multiplier) / multiplier,\n };\n};\n\nexport const formatTaxRate = (rate: number): string => {\n return `${rate.toFixed(2)}%`;\n};\n\nexport const formatAmountWithTax = (\n amount: number,\n taxRate: number,\n currency: string = DEFAULT_CURRENCY,\n options: {\n inclusive?: boolean;\n showBreakdown?: boolean;\n locale?: string;\n } = {}\n): string => {\n const { inclusive = false, showBreakdown = false, locale = 'en-US' } = options;\n const taxCalculation = calculateTax(amount, taxRate, { inclusive });\n\n if (showBreakdown) {\n const subtotalFormatted = formatCurrency(taxCalculation.subtotal, currency, { locale });\n const taxFormatted = formatCurrency(taxCalculation.tax, currency, { locale });\n const totalFormatted = formatCurrency(taxCalculation.total, currency, { locale });\n\n return `${subtotalFormatted} + ${taxFormatted} tax = ${totalFormatted}`;\n }\n\n return formatCurrency(taxCalculation.total, currency, { locale });\n};\n","/**\n * Environment validation utilities for SaaS Factory Payments\n */\n\nexport interface EnvironmentConfig {\n stripePublishableKey: string;\n stripeSecretKey?: string;\n stripeWebhookSecret?: string;\n environment: 'development' | 'production';\n appUrl?: string;\n}\n\nexport const validateEnvironment = (\n config: Partial<EnvironmentConfig>\n): {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n} => {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Required fields\n if (!config.stripePublishableKey) {\n errors.push('STRIPE_PUBLISHABLE_KEY is required');\n } else if (!config.stripePublishableKey.startsWith('pk_')) {\n errors.push('STRIPE_PUBLISHABLE_KEY must start with \"pk_\"');\n }\n\n if (!config.environment) {\n errors.push('Environment must be specified (development or production)');\n } else if (!['development', 'production'].includes(config.environment)) {\n errors.push('Environment must be either \"development\" or \"production\"');\n }\n\n // Environment-specific validation\n if (config.environment === 'production') {\n if (config.stripePublishableKey?.includes('test')) {\n warnings.push('Using test keys in production environment');\n }\n\n if (!config.appUrl) {\n warnings.push('APP_URL should be set in production for proper redirects');\n } else if (!config.appUrl.startsWith('https://')) {\n warnings.push('APP_URL should use HTTPS in production');\n }\n }\n\n // Server-side validation\n if (typeof window === 'undefined') {\n if (!config.stripeSecretKey) {\n warnings.push(\n 'STRIPE_SECRET_KEY is recommended for server-side operations'\n );\n } else if (!config.stripeSecretKey.startsWith('sk_')) {\n errors.push('STRIPE_SECRET_KEY must start with \"sk_\"');\n }\n\n if (!config.stripeWebhookSecret) {\n warnings.push(\n 'STRIPE_WEBHOOK_SECRET is recommended for webhook verification'\n );\n } else if (!config.stripeWebhookSecret.startsWith('whsec_')) {\n errors.push('STRIPE_WEBHOOK_SECRET must start with \"whsec_\"');\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n};\n\nexport const getEnvironmentConfig = (): EnvironmentConfig => {\n const isServer = typeof window === 'undefined';\n\n // Client-side configuration\n const config: EnvironmentConfig = {\n stripePublishableKey:\n process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ||\n process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY ||\n '',\n environment:\n (process.env.NODE_ENV as 'development' | 'production') || 'development',\n appUrl: process.env.NEXT_PUBLIC_APP_URL,\n };\n\n // Server-side configuration\n if (isServer) {\n config.stripeSecretKey = process.env.STRIPE_SECRET_KEY;\n config.stripeWebhookSecret = process.env.STRIPE_WEBHOOK_SECRET;\n }\n\n return config;\n};\n\nexport const validateCurrentEnvironment = () => {\n const config = getEnvironmentConfig();\n const validation = validateEnvironment(config);\n\n if (!validation.isValid) {\n console.error('❌ Environment validation failed:');\n validation.errors.forEach(error => console.error(` - ${error}`));\n\n if (typeof window === 'undefined') {\n // Server-side: throw error\n throw new Error(\n `Environment validation failed: ${validation.errors.join(', ')}`\n );\n }\n }\n\n if (validation.warnings.length > 0) {\n console.warn('⚠️ Environment warnings:');\n validation.warnings.forEach(warning => console.warn(` - ${warning}`));\n }\n\n return validation;\n};\n\n// Helper to check if we're in development mode\nexport const isDevelopment = () => {\n return process.env.NODE_ENV === 'development';\n};\n\n// Helper to check if we're in production mode\nexport const isProduction = () => {\n return process.env.NODE_ENV === 'production';\n};\n\n// Helper to check if we're on the server\nexport const isServer = () => {\n return typeof window === 'undefined';\n};\n\n// Helper to check if we're on the client\nexport const isClient = () => {\n return typeof window !== 'undefined';\n};\n","import { PaymentProvider } from '../../shared/types/provider';\nimport { PaymentsConfig } from '../../shared/types/config';\nimport { PaymentsError, PaymentErrorType } from '../../shared/types/errors';\nimport { CheckoutParams, CheckoutSession } from '../../shared/types/checkout';\nimport { Customer, CustomerCreateParams } from '../../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../../shared/types/subscription';\n\nexport abstract class BasePaymentProvider implements PaymentProvider {\n public abstract name: string;\n protected config: PaymentsConfig;\n\n constructor(config: PaymentsConfig) {\n this.config = config;\n }\n\n public abstract initialize(): Promise<void>;\n public abstract createCheckoutSession(\n params: CheckoutParams\n ): Promise<CheckoutSession>;\n public abstract retrieveCheckoutSession(\n sessionId: string\n ): Promise<CheckoutSession>;\n public abstract createCustomer(\n params: CustomerCreateParams\n ): Promise<Customer>;\n public abstract retrieveCustomer(\n customerId: string\n ): Promise<Customer | null>;\n public abstract createSubscription(\n params: SubscriptionCreateParams\n ): Promise<Subscription>;\n public abstract cancelSubscription(subscriptionId: string): Promise<void>;\n public abstract reactivateSubscription(subscriptionId: string): Promise<void>;\n public abstract listSubscriptions(\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]>;\n public abstract retrieveSubscription(\n subscriptionId: string\n ): Promise<Subscription | null>;\n public abstract updateSubscription(\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ): Promise<Subscription>;\n\n protected handleError(\n error: unknown,\n type: PaymentErrorType = PaymentErrorType.UNKNOWN_ERROR\n ): PaymentsError {\n if (error instanceof PaymentsError) {\n return error;\n }\n\n let message = 'An unknown error occurred';\n let code: string | undefined;\n let details: Record<string, unknown> | undefined;\n\n if (typeof error === 'object' && error !== null) {\n if (\n 'message' in error &&\n typeof (error as { message: unknown }).message === 'string'\n ) {\n message = (error as { message: string }).message;\n }\n if (\n 'code' in error &&\n typeof (error as { code: unknown }).code === 'string'\n ) {\n code = (error as { code: string }).code;\n }\n details = { ...(error as Record<string, unknown>) };\n }\n\n return new PaymentsError(type, message, code, details);\n }\n}\n","import { BasePaymentProvider } from '../base';\nimport { PaymentsConfig } from '../../shared/types/config';\nimport { CheckoutParams, CheckoutSession } from '../../shared/types/checkout';\nimport { Customer, CustomerCreateParams } from '../../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../../shared/types/subscription';\nimport { PaymentsError, PaymentErrorType } from '../../shared/types/errors';\nimport Stripe from 'stripe';\n\nexport class StripePaymentProvider extends BasePaymentProvider {\n public name = 'stripe';\n private stripeClient: Stripe;\n\n constructor(config: PaymentsConfig) {\n super(config);\n if (!config.stripeConfig?.publishableKey) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Stripe publishable key is missing in config.'\n );\n }\n if (!process.env.STRIPE_SECRET_KEY) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'STRIPE_SECRET_KEY environment variable is not set.'\n );\n }\n this.stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY, {\n apiVersion: '2024-06-20',\n });\n }\n\n public async initialize(): Promise<void> {\n // No specific client-side initialization needed for server-side Stripe operations\n\n console.log('StripePaymentProvider initialized (server-side)');\n }\n\n public async createCheckoutSession(\n params: CheckoutParams\n ): Promise<CheckoutSession> {\n try {\n const session = await this.stripeClient.checkout.sessions.create({\n payment_method_types: ['card'],\n line_items: [\n {\n price: params.priceId,\n quantity: 1,\n },\n ],\n mode: params.mode || 'payment',\n success_url:\n params.successUrl ||\n `${process.env.NEXT_PUBLIC_BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,\n cancel_url:\n params.cancelUrl || `${process.env.NEXT_PUBLIC_BASE_URL}/cancel`,\n customer_email: params.customerEmail,\n allow_promotion_codes: params.allowPromotionCodes,\n metadata: params.metadata,\n });\n\n if (!session.url) {\n throw new PaymentsError(\n PaymentErrorType.UNKNOWN_ERROR,\n 'Stripe checkout session URL is missing.'\n );\n }\n\n return {\n id: session.id,\n url: session.url,\n status: session.status as CheckoutSession['status'],\n amountTotal: session.amount_total || undefined,\n currency: session.currency || undefined,\n customerEmail: session.customer_details?.email || undefined,\n subscriptionId: session.subscription?.toString() || undefined,\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async createCustomer(params: CustomerCreateParams): Promise<Customer> {\n try {\n const customer = await this.stripeClient.customers.create({\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n return {\n id: customer.id,\n email: customer.email || params.email,\n name: customer.name || params.name,\n phone: null, // Stripe API does not directly return phone for customer creation\n stripeCustomerId: customer.id,\n subscriptions: [], // Subscriptions are fetched separately\n paymentMethods: [], // Payment methods are fetched separately\n defaultPaymentMethodId: null, // Default payment method is set separately\n metadata: customer.metadata,\n created: new Date(customer.created * 1000),\n updated: new Date(customer.created * 1000), // Stripe customer object doesn't have an 'updated' timestamp directly\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async retrieveCustomer(customerId: string): Promise<Customer | null> {\n try {\n const customer = await this.stripeClient.customers.retrieve(customerId);\n if (customer.deleted) {\n return null;\n }\n return {\n id: customer.id,\n email: customer.email || '',\n name: customer.name || undefined,\n phone: customer.phone || undefined,\n stripeCustomerId: customer.id,\n subscriptions: [], // Subscriptions are fetched separately\n paymentMethods: [], // Payment methods are fetched separately\n defaultPaymentMethodId:\n customer.invoice_settings?.default_payment_method?.toString() ||\n undefined,\n metadata: customer.metadata,\n created: new Date(customer.created * 1000),\n updated: new Date(customer.created * 1000), // Stripe customer object doesn't have an 'updated' timestamp directly\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async createSubscription(\n params: SubscriptionCreateParams\n ): Promise<Subscription> {\n try {\n const subscription = await this.stripeClient.subscriptions.create({\n customer: params.customerId,\n items: (params.items || (params.priceId ? [{ priceId: params.priceId, quantity: 1 }] : [])).map(\n (item: { priceId: string; quantity?: number }) => ({\n price: item.priceId,\n quantity: item.quantity || 1,\n })\n ),\n trial_period_days: params.trialPeriodDays,\n metadata: params.metadata,\n expand: ['latest_invoice.payment_intent'],\n });\n\n return this.mapStripeSubscriptionToSubscription(subscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async cancelSubscription(subscriptionId: string): Promise<void> {\n try {\n await this.stripeClient.subscriptions.cancel(subscriptionId);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async reactivateSubscription(subscriptionId: string): Promise<void> {\n try {\n const subscription =\n await this.stripeClient.subscriptions.retrieve(subscriptionId);\n if (\n subscription.status === SubscriptionStatus.CANCELED &&\n subscription.cancel_at_period_end\n ) {\n await this.stripeClient.subscriptions.update(subscriptionId, {\n cancel_at_period_end: false,\n });\n } else {\n throw new PaymentsError(\n PaymentErrorType.VALIDATION_ERROR,\n 'Subscription cannot be reactivated.'\n );\n }\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async retrieveCheckoutSession(\n sessionId: string\n ): Promise<CheckoutSession> {\n try {\n const session =\n await this.stripeClient.checkout.sessions.retrieve(sessionId);\n if (!session.url) {\n throw new PaymentsError(\n PaymentErrorType.UNKNOWN_ERROR,\n 'Stripe checkout session URL is missing.'\n );\n }\n return {\n id: session.id,\n url: session.url,\n status: session.status as CheckoutSession['status'],\n amountTotal: session.amount_total || undefined,\n currency: session.currency || undefined,\n customerEmail: session.customer_details?.email || undefined,\n subscriptionId: session.subscription?.toString() || undefined,\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async listSubscriptions(\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]> {\n try {\n const subscriptions = await this.stripeClient.subscriptions.list({\n customer: customerId,\n status: status === SubscriptionStatus.ALL ? undefined : status,\n });\n return subscriptions.data.map(this.mapStripeSubscriptionToSubscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async retrieveSubscription(\n subscriptionId: string\n ): Promise<Subscription | null> {\n try {\n const subscription =\n await this.stripeClient.subscriptions.retrieve(subscriptionId);\n return this.mapStripeSubscriptionToSubscription(subscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async updateSubscription(\n subscriptionId: string,\n params: Partial<SubscriptionUpdateParams>\n ): Promise<Subscription> {\n try {\n const currentSubscription =\n await this.stripeClient.subscriptions.retrieve(subscriptionId);\n const items = params.items\n ? params.items.map((item: { priceId: string; quantity?: number }) => ({\n id: currentSubscription.items.data.find(\n i => i.price?.id === item.priceId\n )?.id,\n price: item.priceId,\n quantity: item.quantity || 1,\n }))\n : undefined;\n\n const subscription = await this.stripeClient.subscriptions.update(\n subscriptionId,\n {\n items,\n metadata: params.metadata,\n }\n );\n return this.mapStripeSubscriptionToSubscription(subscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n private mapStripeSubscriptionToSubscription(\n stripeSubscription: Stripe.Subscription\n ): Subscription {\n return {\n id: stripeSubscription.id,\n customerId: stripeSubscription.customer.toString(),\n status: stripeSubscription.status as SubscriptionStatus,\n items: stripeSubscription.items.data.map(item => ({\n id: item.id,\n priceId: item.price?.id || '',\n quantity: item.quantity || 1,\n })),\n currentPeriodStart: new Date(\n stripeSubscription.current_period_start * 1000\n ),\n currentPeriodEnd: new Date(stripeSubscription.current_period_end * 1000),\n cancelAtPeriodEnd: stripeSubscription.cancel_at_period_end,\n trialStart: stripeSubscription.trial_start\n ? new Date(stripeSubscription.trial_start * 1000)\n : undefined,\n trialEnd: stripeSubscription.trial_end\n ? new Date(stripeSubscription.trial_end * 1000)\n : undefined,\n metadata: stripeSubscription.metadata,\n created: new Date(stripeSubscription.created * 1000),\n updated: new Date(stripeSubscription.created * 1000), // Stripe subscription object doesn't have an 'updated' timestamp directly\n };\n }\n}\n","import { CheckoutParams, CheckoutSession } from '../../shared/types/checkout';\nimport {\n Customer,\n CustomerCreateParams,\n PaymentMethod,\n} from '../../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../../shared/types/subscription';\nimport { PaymentProvider } from '../../shared/types/provider';\nimport { PaymentsError, PaymentErrorType } from '../../shared/types/errors';\nimport { PaymentsConfig } from '../../shared/types/config';\nimport { BasePaymentProvider } from '../base';\n\n/**\n * A mock payment provider for testing and development purposes.\n * It simulates payment operations without actual API calls.\n */\nexport class MockPaymentProvider\n extends BasePaymentProvider\n implements PaymentProvider\n{\n name = 'MockPaymentProvider';\n private customers: Customer[] = [];\n private subscriptions: Subscription[] = [];\n private nextCustomerId = 1;\n private nextSubscriptionId = 1;\n\n constructor(config: Omit<PaymentsConfig, 'provider'>) {\n super({ ...config, provider: 'mock' });\n\n console.log('MockPaymentProvider initialized');\n }\n\n async initialize(): Promise<void> {\n console.log('MockPaymentProvider initialized');\n }\n\n async createCheckoutSession(\n params: CheckoutParams\n ): Promise<CheckoutSession> {\n console.log('Mock: createCheckoutSession', params);\n return {\n id: 'mock_cs_123',\n clientSecret: 'mock_client_secret',\n url: 'https://mock-checkout.example.com/success', // Changed from redirectUrl to url\n status: 'open', // Changed from 'pending' to 'open'\n };\n }\n\n async retrieveCheckoutSession(id: string): Promise<CheckoutSession> {\n console.log('Mock: retrieveCheckoutSession', id);\n if (id === 'mock_cs_123') {\n return {\n id: 'mock_cs_123',\n clientSecret: 'mock_client_secret',\n url: 'https://mock-checkout.example.com/success', // Changed from redirectUrl to url\n status: 'complete',\n };\n }\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock checkout session ${id} not found`\n );\n }\n\n async createCustomer(params: CustomerCreateParams): Promise<Customer> {\n console.log('Mock: createCustomer', params);\n const newCustomer: Customer = {\n id: `mock_cus_${this.nextCustomerId++}`,\n email: params.email,\n name: params.name || null,\n phone: params.phone || null,\n stripeCustomerId: null,\n subscriptions: [],\n defaultPaymentMethodId: null,\n paymentMethods: [], // Added paymentMethods\n metadata: params.metadata || {},\n created: new Date(),\n updated: new Date(),\n };\n this.customers.push(newCustomer);\n return newCustomer;\n }\n\n async retrieveCustomer(id: string): Promise<Customer> {\n console.log('Mock: retrieveCustomer', id);\n const customer = this.customers.find(c => c.id === id);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${id} not found`\n );\n }\n return customer;\n }\n\n async updateCustomer(\n id: string,\n params: CustomerCreateParams\n ): Promise<Customer> {\n console.log('Mock: updateCustomer', id, params);\n const customer = this.customers.find(c => c.id === id);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${id} not found`\n );\n }\n if (params.email) customer.email = params.email;\n if (params.name) customer.name = params.name;\n if (params.phone) customer.phone = params.phone;\n if (params.metadata)\n customer.metadata = { ...customer.metadata, ...params.metadata };\n customer.updated = new Date();\n return customer;\n }\n\n async deleteCustomer(id: string): Promise<void> {\n console.log('Mock: deleteCustomer', id);\n const initialLength = this.customers.length;\n this.customers = this.customers.filter(c => c.id !== id);\n if (this.customers.length === initialLength) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${id} not found`\n );\n }\n }\n\n async listPaymentMethods(customerId: string): Promise<PaymentMethod[]> {\n console.log('Mock: listPaymentMethods', customerId);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n return customer.paymentMethods || [];\n }\n\n async attachPaymentMethod(\n customerId: string,\n paymentMethodId: string\n ): Promise<PaymentMethod> {\n console.log('Mock: attachPaymentMethod', customerId, paymentMethodId);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n const newPaymentMethod: PaymentMethod = {\n id: paymentMethodId,\n type: 'card',\n card: {\n brand: 'visa',\n last4: '4242',\n expMonth: 12,\n expYear: 2025,\n country: 'US',\n },\n isDefault: false,\n created: new Date(),\n };\n customer.paymentMethods.push(newPaymentMethod);\n return newPaymentMethod;\n }\n\n async detachPaymentMethod(\n customerId: string,\n paymentMethodId: string\n ): Promise<void> {\n console.log('Mock: detachPaymentMethod', customerId, paymentMethodId);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n const initialLength = customer.paymentMethods.length;\n customer.paymentMethods = customer.paymentMethods.filter(\n (pm: PaymentMethod) => pm.id !== paymentMethodId\n );\n if (customer.paymentMethods.length === initialLength) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock payment method ${paymentMethodId} not found for customer ${customerId}`\n );\n }\n }\n\n async createSubscription(\n params: SubscriptionCreateParams\n ): Promise<Subscription> {\n console.log('Mock: createSubscription', params);\n const customer = this.customers.find(c => c.id === params.customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${params.customerId} not found`\n );\n }\n const newSubscription: Subscription = {\n id: `mock_sub_${this.nextSubscriptionId++}`,\n customerId: params.customerId,\n status: SubscriptionStatus.ACTIVE,\n items: (params.items || (params.priceId ? [{ priceId: params.priceId, quantity: 1 }] : [])).map(\n (item: { priceId: string; quantity?: number }) => ({\n id: `mock_sub_item_${Math.random().toString(36).substring(7)}`,\n priceId: item.priceId,\n quantity: item.quantity || 1,\n })\n ),\n currentPeriodStart: new Date(),\n currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days from now\n cancelAtPeriodEnd: false,\n created: new Date(),\n updated: new Date(),\n };\n this.subscriptions.push(newSubscription);\n customer.subscriptions.push(newSubscription);\n return newSubscription;\n }\n\n async retrieveSubscription(id: string): Promise<Subscription> {\n console.log('Mock: retrieveSubscription', id);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n return subscription;\n }\n\n async updateSubscription(\n id: string,\n params: SubscriptionUpdateParams\n ): Promise<Subscription> {\n console.log('Mock: updateSubscription', id, params);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n if (params.cancelAtPeriodEnd !== undefined) {\n subscription.cancelAtPeriodEnd = params.cancelAtPeriodEnd;\n subscription.status = params.cancelAtPeriodEnd\n ? SubscriptionStatus.CANCELED\n : SubscriptionStatus.ACTIVE;\n }\n if (params.items) {\n subscription.items = params.items.map(\n (item: { priceId: string; quantity?: number }) => ({\n id: `mock_sub_item_${Math.random().toString(36).substring(7)}`,\n priceId: item.priceId,\n quantity: item.quantity || 1,\n })\n );\n }\n subscription.updated = new Date();\n return subscription;\n }\n\n async cancelSubscription(id: string): Promise<void> {\n console.log('Mock: cancelSubscription', id);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n subscription.status = SubscriptionStatus.CANCELED;\n subscription.cancelAtPeriodEnd = true;\n subscription.updated = new Date();\n }\n\n async reactivateSubscription(id: string): Promise<void> {\n console.log('Mock: reactivateSubscription', id);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n subscription.status = SubscriptionStatus.ACTIVE;\n subscription.cancelAtPeriodEnd = false;\n subscription.updated = new Date();\n }\n\n async listSubscriptions(\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]> {\n console.log('Mock: listSubscriptions', customerId, status);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n let subs = customer.subscriptions;\n if (status && status !== SubscriptionStatus.ALL) {\n subs = subs.filter(s => s.status === status);\n }\n return subs;\n }\n}\n","import { PaymentsConfig, PaymentProviderType } from '../shared/types/config';\nimport { PaymentsError, PaymentErrorType } from '../shared/types/errors';\nimport { PaymentProvider } from '../shared/types/provider';\nimport { StripePaymentProvider } from './stripe';\n// import { PayPalPaymentProvider } from './paypal';\n// import { ApplePayPaymentProvider } from './applepay';\nimport { MockPaymentProvider } from './mock';\n\nexport class PaymentProviderFactory {\n public static create(config: PaymentsConfig): PaymentProvider {\n switch (config.provider) {\n case 'stripe':\n return new StripePaymentProvider(config);\n case 'paypal':\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n 'PayPal provider is not yet available in this build'\n );\n case 'applepay':\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n 'Apple Pay provider is not yet available in this build'\n );\n case 'mock':\n return new MockPaymentProvider(config);\n default:\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n `Unsupported payment provider: ${config.provider}`\n );\n }\n }\n\n public static autodetect(): PaymentsConfig {\n // Check for Stripe configuration first (most common)\n if (\n process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY &&\n process.env.STRIPE_SECRET_KEY\n ) {\n return {\n provider: 'stripe',\n publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'development',\n stripeConfig: {\n publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,\n },\n };\n }\n\n // Check for PayPal configuration\n if (\n process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID &&\n process.env.PAYPAL_CLIENT_SECRET\n ) {\n return {\n provider: 'paypal',\n publishableKey: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'development',\n paypalConfig: {\n clientId: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,\n clientSecret: process.env.PAYPAL_CLIENT_SECRET,\n environment: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',\n currency: process.env.PAYPAL_CURRENCY || 'USD',\n },\n };\n }\n\n // Check for Apple Pay configuration\n if (\n process.env.NEXT_PUBLIC_APPLE_PAY_MERCHANT_ID &&\n typeof window !== 'undefined' &&\n window.ApplePaySession\n ) {\n return {\n provider: 'applepay',\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'development',\n applePayConfig: {\n merchantId: process.env.NEXT_PUBLIC_APPLE_PAY_MERCHANT_ID,\n merchantName: process.env.NEXT_PUBLIC_APPLE_PAY_MERCHANT_NAME || 'Your Store',\n countryCode: process.env.NEXT_PUBLIC_APPLE_PAY_COUNTRY_CODE || 'US',\n currencyCode: process.env.NEXT_PUBLIC_APPLE_PAY_CURRENCY_CODE || 'USD',\n environment: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',\n },\n };\n }\n\n // For development/testing, allow mock provider if no other is detected\n if (\n process.env.NODE_ENV !== 'production' ||\n process.env.VERCEL_ENV === 'preview'\n ) {\n console.warn(\n 'No payment provider detected, defaulting to MockPaymentProvider for development/preview environment.'\n );\n return {\n provider: 'mock',\n environment: 'development',\n };\n }\n\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Could not auto-detect payment provider. Please provide explicit configuration.'\n );\n }\n\n // Helper method to get all available providers based on environment\n public static getAvailableProviders(): PaymentProviderType[] {\n const providers: PaymentProviderType[] = [];\n\n // Check Stripe\n if (process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY) {\n providers.push('stripe');\n }\n\n // Check PayPal\n if (process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID) {\n providers.push('paypal');\n }\n\n // Check Apple Pay (client-side only)\n if (typeof window !== 'undefined' && window.ApplePaySession?.canMakePayments()) {\n providers.push('applepay');\n }\n\n // Always include mock for development\n if (process.env.NODE_ENV !== 'production') {\n providers.push('mock');\n }\n\n return providers;\n }\n\n // Method to create multiple providers for fallback scenarios\n public static createMultiple(configs: PaymentsConfig[]): PaymentProvider[] {\n return configs.map(config => this.create(config));\n }\n}\n","import React, { useEffect, createContext, useContext, useRef } from 'react';\nimport { usePayments } from '../../hooks/usePayments';\nimport { PaymentsConfig } from '../types/config';\nimport { PaymentEvent } from '../types/events';\nimport { PaymentError } from '../types/errors';\n\nimport { Customer, CustomerCreateParams } from '../types/customer';\nimport {\n Subscription,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../types/subscription';\nimport { CheckoutParams, CheckoutSession } from '../types/checkout';\n\ninterface PaymentsContextType {\n config: PaymentsConfig | null;\n initialized: boolean;\n loading: boolean;\n error: PaymentError | null;\n customer: Customer | null;\n subscriptions: Subscription[];\n activeSubscription: Subscription | null;\n createCustomer: (params: CustomerCreateParams) => Promise<Customer>;\n createCheckoutSession: (params: CheckoutParams) => Promise<CheckoutSession>;\n cancelSubscription: (subscriptionId: string) => Promise<void>;\n reactivateSubscription: (subscriptionId: string) => Promise<void>;\n updateSubscription: (\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ) => Promise<Subscription>;\n refreshCustomer: (customerId: string) => Promise<void>;\n refreshSubscriptions: (\n customerId: string,\n status?: SubscriptionStatus\n ) => Promise<void>;\n reset: () => void;\n}\n\nconst PaymentsContext = createContext<PaymentsContextType | undefined>(\n undefined\n);\n\ninterface PaymentsProviderProps {\n children: React.ReactNode;\n config?: PaymentsConfig;\n onPaymentSuccess?: (event: PaymentEvent) => void;\n onPaymentError?: (error: PaymentError) => void;\n}\n\nexport const PaymentsProvider: React.FC<PaymentsProviderProps> = ({\n children,\n config,\n onPaymentSuccess,\n onPaymentError,\n}) => {\n const store = usePayments();\n const {\n initialize,\n initialized,\n loading,\n error,\n customer,\n subscriptions,\n activeSubscription,\n } = store;\n\n const onPaymentSuccessRef = useRef(onPaymentSuccess);\n const onPaymentErrorRef = useRef(onPaymentError);\n\n useEffect(() => {\n onPaymentSuccessRef.current = onPaymentSuccess;\n }, [onPaymentSuccess]);\n\n useEffect(() => {\n onPaymentErrorRef.current = onPaymentError;\n }, [onPaymentError]);\n\n useEffect(() => {\n if (!initialized && !loading && !error) {\n initialize(config).catch(err => {\n console.error('PaymentsProvider initialization failed:', err);\n if (onPaymentErrorRef.current) {\n onPaymentErrorRef.current(err);\n }\n });\n }\n }, [initialized, loading, error, config, initialize]);\n\n const contextValue: PaymentsContextType = {\n config: store.config,\n initialized,\n loading,\n error,\n customer,\n subscriptions,\n activeSubscription,\n createCustomer: store.createCustomer,\n createCheckoutSession: store.createCheckoutSession,\n cancelSubscription: store.cancelSubscription,\n reactivateSubscription: store.reactivateSubscription,\n updateSubscription: store.updateSubscription,\n refreshCustomer: store.refreshCustomer,\n refreshSubscriptions: store.refreshSubscriptions,\n reset: store.reset,\n };\n\n return (\n <PaymentsContext.Provider value={contextValue}>\n {children}\n </PaymentsContext.Provider>\n );\n};\n\nexport const usePaymentsContext = () => {\n const context = useContext(PaymentsContext);\n if (context === undefined) {\n throw new Error(\n 'usePaymentsContext must be used within a PaymentsProvider'\n );\n }\n return context;\n};\n","import { create } from 'zustand';\nimport { immer } from 'zustand/middleware/immer';\nimport { PaymentsStore, PaymentsProviderState } from '../shared/types/provider';\nimport { PaymentsConfig } from '../shared/types/config';\nimport { PaymentErrorType, PaymentsError } from '../shared/types/errors';\nimport { Customer, CustomerCreateParams } from '../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../shared/types/subscription';\nimport { CheckoutParams, CheckoutSession } from '../shared/types/checkout';\nimport { PaymentProviderFactory } from '../providers';\nimport { PaymentProvider } from '../shared/types/provider';\n\nconst initialState: PaymentsProviderState = {\n customer: null,\n subscriptions: [],\n activeSubscription: null,\n loading: false,\n error: null,\n initialized: false,\n config: null, // Add config to the state\n // Backward compatibility getters (will be computed)\n isLoading: false,\n isError: false,\n};\n\nexport const usePayments = create<PaymentsStore>()(\n immer((set, get) => ({\n ...initialState,\n\n // Override getters to always return computed values\n get isLoading() {\n return get().loading;\n },\n get isError() {\n return !!get().error;\n },\n\n initialize: async (config?: PaymentsConfig) => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n let resolvedConfig: PaymentsConfig;\n if (config) {\n resolvedConfig = config;\n } else {\n resolvedConfig = PaymentProviderFactory.autodetect();\n }\n\n const provider: PaymentProvider =\n PaymentProviderFactory.create(resolvedConfig);\n await provider.initialize();\n\n set((state: PaymentsProviderState) => {\n state.initialized = true;\n state.loading = false;\n state.config = resolvedConfig; // Store the resolved config in the state\n });\n } catch (error: unknown) {\n set(state => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to initialize payments provider.';\n state.error = new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n createCustomer: async (params: CustomerCreateParams): Promise<Customer> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const customer = await provider.createCustomer(params);\n set((state: PaymentsProviderState) => {\n state.customer = customer;\n state.loading = false;\n });\n return customer;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to create customer.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n retrieveCustomer: async (customerId: string): Promise<Customer | null> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const customer = await provider.retrieveCustomer(customerId);\n set((state: PaymentsProviderState) => {\n state.customer = customer;\n state.loading = false;\n });\n return customer;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to retrieve customer.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n createCheckoutSession: async (\n params: CheckoutParams\n ): Promise<CheckoutSession> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const session = await provider.createCheckoutSession(params);\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return session;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to create checkout session.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n retrieveCheckoutSession: async (\n sessionId: string\n ): Promise<CheckoutSession> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const session = await provider.retrieveCheckoutSession(sessionId);\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return session;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to retrieve checkout session.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n createSubscription: async (\n params: SubscriptionCreateParams\n ): Promise<Subscription> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const newSubscription = await provider.createSubscription(params);\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return newSubscription;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to create subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n cancelSubscription: async (subscriptionId: string): Promise<void> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n await provider.cancelSubscription(subscriptionId);\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to cancel subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n reactivateSubscription: async (subscriptionId: string): Promise<void> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n await provider.reactivateSubscription(subscriptionId);\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to reactivate subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n updateSubscription: async (\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ): Promise<Subscription> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const updatedSubscription = await provider.updateSubscription(\n subscriptionId,\n params\n );\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return updatedSubscription;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to update subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n listSubscriptions: async (\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const subscriptions = await provider.listSubscriptions(\n customerId,\n status\n );\n set((state: PaymentsProviderState) => {\n state.subscriptions = subscriptions;\n state.loading = false;\n });\n return subscriptions;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to list subscriptions.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n retrieveSubscription: async (\n subscriptionId: string\n ): Promise<Subscription | null> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const subscription =\n await provider.retrieveSubscription(subscriptionId);\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return subscription;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to retrieve subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n refreshCustomer: async (customerId: string) => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const customer = await provider.retrieveCustomer(customerId);\n set((state: PaymentsProviderState) => {\n state.customer = customer;\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to refresh customer.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n }\n },\n\n refreshSubscriptions: async (\n customerId: string,\n status?: SubscriptionStatus\n ) => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const subscriptions = await provider.listSubscriptions(\n customerId,\n status\n );\n const activeSubscription =\n subscriptions.find(\n (sub: Subscription) =>\n sub.status === SubscriptionStatus.ACTIVE ||\n sub.status === SubscriptionStatus.TRIALING\n ) || null;\n set((state: PaymentsProviderState) => {\n state.subscriptions = subscriptions;\n state.activeSubscription = activeSubscription;\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to refresh subscriptions.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n }\n },\n\n reset: () => {\n set((state: PaymentsProviderState) => {\n Object.assign(state, initialState);\n });\n },\n }))\n);\n","import { useState, useEffect, useCallback } from 'react';\nimport {\n Customer,\n CustomerCreateParams,\n Subscription,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n CheckoutParams,\n CheckoutSession,\n} from '../types';\nimport { PaymentsConfig } from '../types/config';\nimport { PaymentProviderFactory } from '../../providers';\nimport { PaymentsError, PaymentErrorType } from '../types/errors';\nimport { ERROR_MESSAGES } from '../constants';\nimport { PaymentProvider } from '../types/provider';\n\ninterface UsePaymentsStore {\n config: PaymentsConfig | null;\n provider: PaymentProvider | null;\n initialized: boolean;\n loading: boolean;\n error: PaymentsError | null;\n // Backward compatibility getters\n isLoading: boolean; // Maps to loading\n isError: boolean; // Maps to !!error\n customer: Customer | null;\n subscriptions: Subscription[];\n activeSubscription: Subscription | null;\n initialize: (config?: PaymentsConfig) => Promise<void>;\n createCustomer: (params: CustomerCreateParams) => Promise<Customer>;\n retrieveCustomer: (customerId: string) => Promise<Customer | null>;\n createCheckoutSession: (params: CheckoutParams) => Promise<CheckoutSession>;\n retrieveCheckoutSession: (sessionId: string) => Promise<CheckoutSession>;\n createSubscription: (params: {\n priceId: string;\n quantity?: number;\n }) => Promise<Subscription>;\n cancelSubscription: (subscriptionId: string) => Promise<void>;\n reactivateSubscription: (subscriptionId: string) => Promise<void>;\n listSubscriptions: (\n customerId: string,\n status?: SubscriptionStatus\n ) => Promise<Subscription[]>;\n retrieveSubscription: (\n subscriptionId: string\n ) => Promise<Subscription | null>;\n updateSubscription: (\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ) => Promise<Subscription>;\n refreshCustomer: (customerId: string) => Promise<void>;\n refreshSubscriptions: (\n customerId: string,\n status?: SubscriptionStatus\n ) => Promise<void>;\n reset: () => void;\n}\n\nexport const usePayments = (): UsePaymentsStore => {\n const [config, setConfig] = useState<PaymentsConfig | null>(null);\n const [provider, setProvider] = useState<PaymentProvider | null>(null);\n const [initialized, setInitialized] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<PaymentsError | null>(null);\n const [customer, setCustomer] = useState<Customer | null>(null);\n const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);\n\n const handleError = useCallback((err: PaymentsError) => {\n setError(err);\n console.error('Payments error:', err);\n }, []);\n\n const refreshSubscriptions = useCallback(\n async (customerId: string, status?: SubscriptionStatus) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const fetchedSubscriptions = await provider.listSubscriptions(\n customerId,\n status\n );\n setSubscriptions(fetchedSubscriptions);\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const initialize = useCallback(\n async (initialConfig?: PaymentsConfig) => {\n setLoading(true);\n setError(null);\n try {\n const resolvedConfig =\n initialConfig || PaymentProviderFactory.autodetect();\n const newProvider = PaymentProviderFactory.create(resolvedConfig);\n setConfig(resolvedConfig);\n setProvider(newProvider);\n setInitialized(true);\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n } finally {\n setLoading(false);\n }\n },\n [handleError]\n );\n\n const retrieveCustomer = useCallback(\n async (customerId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const newCustomer = await provider.retrieveCustomer(customerId);\n setCustomer(newCustomer);\n return newCustomer;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const createCustomer = useCallback(\n async (params: CustomerCreateParams) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const newCustomer = await provider.createCustomer(params);\n setCustomer(newCustomer);\n return newCustomer;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const createSubscription = useCallback(\n async (params: { priceId: string; quantity?: number }) => {\n if (!provider || !customer) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const newSubscription = await provider.createSubscription({\n customerId: customer.id,\n items: [{ priceId: params.priceId, quantity: params.quantity }],\n });\n await refreshSubscriptions(customer.id);\n return newSubscription;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const listSubscriptions = useCallback(\n async (customerId: string, status?: SubscriptionStatus) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const subs = await provider.listSubscriptions(customerId, status);\n setSubscriptions(subs);\n return subs;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const retrieveSubscription = useCallback(\n async (subscriptionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const sub = await provider.retrieveSubscription(subscriptionId);\n // Optionally refresh the list of subscriptions\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n return sub;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const createCheckoutSession = useCallback(\n async (params: CheckoutParams) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const session = await provider.createCheckoutSession(params);\n return session;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const retrieveCheckoutSession = useCallback(\n async (sessionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const session = await provider.retrieveCheckoutSession(sessionId);\n return session;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const cancelSubscription = useCallback(\n async (subscriptionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n await provider.cancelSubscription(subscriptionId);\n // Refresh subscriptions after cancellation\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const reactivateSubscription = useCallback(\n async (subscriptionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n await provider.reactivateSubscription(subscriptionId);\n // Refresh subscriptions after reactivation\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const updateSubscription = useCallback(\n async (subscriptionId: string, params: SubscriptionUpdateParams) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const updatedSubscription = await provider.updateSubscription(\n subscriptionId,\n params\n );\n // Refresh subscriptions after update\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n return updatedSubscription;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const refreshCustomer = useCallback(\n async (customerId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const fetchedCustomer = await provider.retrieveCustomer(customerId);\n setCustomer(fetchedCustomer);\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const reset = useCallback(() => {\n setConfig(null);\n setProvider(null);\n setInitialized(false);\n setLoading(false);\n setError(null);\n setCustomer(null);\n setSubscriptions([]);\n }, []);\n\n const activeSubscription =\n subscriptions.find(s => s.status === 'active' || s.status === 'trialing') ||\n null;\n\n // Initial fetch for customer and subscriptions if a customerId is provided\n useEffect(() => {\n // This useEffect should be triggered by the PaymentsProvider, not directly here\n // The PaymentsProvider will call `initialize` with the config.\n // If a customer ID is available in the config or passed to initialize,\n // then refreshCustomer and refreshSubscriptions can be called.\n // For now, removing the auto-fetch logic from here to avoid circular dependencies\n // and to align with the PaymentsProvider's role in initialization.\n }, []);\n\n return {\n config,\n provider,\n initialized,\n loading,\n error,\n // Backward compatibility getters\n isLoading: loading,\n isError: !!error,\n customer,\n subscriptions,\n activeSubscription,\n initialize,\n createCustomer,\n retrieveCustomer,\n createCheckoutSession,\n retrieveCheckoutSession,\n createSubscription,\n cancelSubscription,\n reactivateSubscription,\n listSubscriptions,\n retrieveSubscription,\n updateSubscription,\n refreshCustomer,\n refreshSubscriptions,\n reset,\n };\n};\n","import React, { useState } from 'react';\nimport { useStripe } from '@stripe/react-stripe-js';\nimport { usePaymentsContext } from '../../shared/providers/PaymentsProvider';\nimport { ERROR_MESSAGES } from '../../shared/constants';\nimport { validateStripeId } from '../../shared/utils/validation';\n\ninterface CheckoutButtonProps {\n priceId: string;\n customerId?: string;\n customerEmail?: string;\n successUrl?: string;\n cancelUrl?: string;\n children: React.ReactNode;\n className?: string;\n disabled?: boolean;\n allowPromotionCodes?: boolean;\n billingAddressCollection?: 'auto' | 'required';\n metadata?: Record<string, string>;\n trialPeriodDays?: number;\n onSuccess?: () => void;\n onError?: (error: string) => void;\n onLoading?: (loading: boolean) => void;\n}\n\nexport const CheckoutButton: React.FC<CheckoutButtonProps> = ({\n priceId,\n customerId,\n customerEmail,\n successUrl = typeof window !== 'undefined'\n ? `${window.location.origin}/success`\n : '/success',\n cancelUrl = typeof window !== 'undefined'\n ? `${window.location.origin}/cancel`\n : '/cancel',\n children,\n className = '',\n disabled = false,\n allowPromotionCodes = true,\n billingAddressCollection = 'auto',\n metadata,\n trialPeriodDays,\n onSuccess,\n onError,\n onLoading,\n}) => {\n const stripe = useStripe();\n const { initialized } = usePaymentsContext();\n const [loading, setLoading] = useState(false);\n\n const handleCheckout = async () => {\n if (!stripe) {\n const error = ERROR_MESSAGES.STRIPE_NOT_LOADED;\n onError?.(error);\n console.error(error);\n return;\n }\n\n if (!initialized) {\n const error = ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED;\n onError?.(error);\n console.error(error);\n return;\n }\n\n if (!validateStripeId(priceId, 'price')) {\n const error = ERROR_MESSAGES.INVALID_PRICE_ID;\n onError?.(error);\n console.error(error);\n return;\n }\n\n if (customerId && !validateStripeId(customerId, 'customer')) {\n const error = ERROR_MESSAGES.INVALID_CUSTOMER_ID;\n onError?.(error);\n console.error(error);\n return;\n }\n\n setLoading(true);\n onLoading?.(true);\n\n try {\n const response = await fetch('/api/payments/create-checkout-session', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n priceId,\n customerId,\n customerEmail,\n successUrl,\n cancelUrl,\n allowPromotionCodes,\n billingAddressCollection,\n metadata,\n trialPeriodDays,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response\n .json()\n .catch(() => ({ error: 'Network error' }));\n throw new Error(errorData.error || ERROR_MESSAGES.CHECKOUT_FAILED);\n }\n\n const { sessionId } = await response.json();\n\n if (!sessionId) {\n throw new Error('No session ID returned from server');\n }\n\n const result = await stripe.redirectToCheckout({ sessionId });\n\n if (result.error) {\n throw new Error(result.error.message || ERROR_MESSAGES.CHECKOUT_FAILED);\n }\n\n onSuccess?.();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : ERROR_MESSAGES.CHECKOUT_FAILED;\n onError?.(errorMessage);\n console.error('Checkout error:', error);\n } finally {\n setLoading(false);\n onLoading?.(false);\n }\n };\n\n const isDisabled = !stripe || loading || disabled || !initialized;\n\n return (\n <button\n onClick={handleCheckout}\n disabled={isDisabled}\n className={`\n inline-flex items-center justify-center px-4 py-2 \n border border-transparent text-sm font-medium rounded-md \n text-white bg-blue-600 hover:bg-blue-700 \n focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\n disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors duration-200\n ${className}\n `}\n aria-label={typeof children === 'string' ? children : 'Checkout'}\n >\n {loading ? (\n <>\n <svg\n className=\"animate-spin -ml-1 mr-3 h-4 w-4 text-white\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n Processing...\n </>\n ) : (\n children\n )}\n </button>\n );\n};\n\nexport default CheckoutButton;\n","import React from 'react';\nimport { PricingPlan } from '../../shared/types';\nimport {\n formatPricingPlan,\n formatTrialPeriod,\n} from '../../shared/utils/formatting';\nimport { CheckoutButton } from './CheckoutButton';\n\ninterface PricingTableProps {\n plans: PricingPlan[];\n customerId?: string;\n customerEmail?: string;\n successUrl?: string;\n cancelUrl?: string;\n className?: string;\n onCheckoutSuccess?: (plan: PricingPlan) => void;\n onCheckoutError?: (plan: PricingPlan, error: string) => void;\n showFeatures?: boolean;\n showTrialInfo?: boolean;\n layout?: 'grid' | 'list';\n maxColumns?: number;\n}\n\nexport const PricingTable: React.FC<PricingTableProps> = ({\n plans,\n customerId,\n customerEmail,\n successUrl,\n cancelUrl,\n className = '',\n onCheckoutSuccess,\n onCheckoutError,\n showFeatures = true,\n showTrialInfo = true,\n layout = 'grid',\n maxColumns = 3,\n}) => {\n if (!plans || plans.length === 0) {\n return (\n <div className=\"text-center py-8 text-gray-500\">\n No pricing plans available\n </div>\n );\n }\n\n const gridCols = Math.min(plans.length, maxColumns);\n const gridClass =\n layout === 'grid'\n ? `grid gap-6 ${gridCols === 1 ? 'grid-cols-1' : gridCols === 2 ? 'grid-cols-1 md:grid-cols-2' : 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3'}`\n : 'space-y-6';\n\n return (\n <div className={`pricing-table ${className}`}>\n <div className={gridClass}>\n {plans.map(plan => (\n <PricingCard\n key={plan.id}\n plan={plan}\n customerId={customerId}\n customerEmail={customerEmail}\n successUrl={successUrl}\n cancelUrl={cancelUrl}\n onCheckoutSuccess={() => onCheckoutSuccess?.(plan)}\n onCheckoutError={error => onCheckoutError?.(plan, error)}\n showFeatures={showFeatures}\n showTrialInfo={showTrialInfo}\n />\n ))}\n </div>\n </div>\n );\n};\n\ninterface PricingCardProps {\n plan: PricingPlan;\n customerId?: string;\n customerEmail?: string;\n successUrl?: string;\n cancelUrl?: string;\n onCheckoutSuccess?: () => void;\n onCheckoutError?: (error: string) => void;\n showFeatures?: boolean;\n showTrialInfo?: boolean;\n}\n\nconst PricingCard: React.FC<PricingCardProps> = ({\n plan,\n customerId,\n customerEmail,\n successUrl,\n cancelUrl,\n onCheckoutSuccess,\n onCheckoutError,\n showFeatures = true,\n showTrialInfo = true,\n}) => {\n const isPopular = plan.popular;\n\n return (\n <div\n className={`\n relative bg-white rounded-lg shadow-lg overflow-hidden\n ${isPopular ? 'ring-2 ring-blue-500 ring-opacity-50' : 'border border-gray-200'}\n transition-transform duration-200 hover:scale-105\n `}\n >\n {isPopular && (\n <div className=\"absolute top-0 left-0 right-0 bg-blue-500 text-white text-center py-2 text-sm font-medium\">\n Most Popular\n </div>\n )}\n\n <div className={`p-6 ${isPopular ? 'pt-12' : ''}`}>\n {/* Plan Header */}\n <div className=\"text-center mb-6\">\n <h3 className=\"text-xl font-semibold text-gray-900 mb-2\">\n {plan.name}\n </h3>\n {plan.description && (\n <p className=\"text-gray-600 text-sm mb-4\">{plan.description}</p>\n )}\n <div className=\"mb-4\">\n <span className=\"text-3xl font-bold text-gray-900\">\n {formatPricingPlan(plan)}\n </span>\n </div>\n {showTrialInfo &&\n plan.trialPeriodDays &&\n plan.trialPeriodDays > 0 && (\n <div className=\"text-sm text-green-600 font-medium\">\n {formatTrialPeriod(plan.trialPeriodDays)}\n </div>\n )}\n </div>\n\n {/* Features List */}\n {showFeatures && plan.features && plan.features.length > 0 && (\n <div className=\"mb-6\">\n <ul className=\"space-y-3\">\n {plan.features.map((feature, index) => (\n <li key={index} className=\"flex items-start\">\n <svg\n className=\"flex-shrink-0 w-5 h-5 text-green-500 mt-0.5 mr-3\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n <span className=\"text-gray-700 text-sm\">{feature}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* CTA Button */}\n <div className=\"mt-6\">\n <CheckoutButton\n priceId={plan.stripePriceId}\n customerId={customerId}\n customerEmail={customerEmail}\n successUrl={successUrl}\n cancelUrl={cancelUrl}\n trialPeriodDays={plan.trialPeriodDays}\n metadata={plan.metadata}\n onSuccess={onCheckoutSuccess}\n onError={onCheckoutError}\n className={`\n w-full justify-center py-3 px-4 text-base font-medium\n ${\n isPopular\n ? 'bg-blue-600 hover:bg-blue-700 text-white'\n : 'bg-gray-100 hover:bg-gray-200 text-gray-900 border border-gray-300'\n }\n `}\n >\n Get Started\n </CheckoutButton>\n </div>\n </div>\n </div>\n );\n};\n\nexport default PricingTable;\n","import React, { useState } from 'react';\nimport {\n useStripe,\n useElements,\n CardElement,\n PaymentElement,\n} from '@stripe/react-stripe-js';\nimport { usePaymentsContext } from '../../shared/providers/PaymentsProvider';\nimport { PaymentIntent } from '@stripe/stripe-js';\nimport { ERROR_MESSAGES } from '../../shared/constants';\nimport { validateEmail } from '../../shared/utils/validation';\n\nexport interface PaymentFormProps {\n clientSecret?: string;\n customerId?: string;\n customerEmail?: string;\n amount?: number;\n currency?: string;\n description?: string;\n metadata?: Record<string, string>;\n onSuccess?: (paymentIntent: PaymentIntent) => void;\n onError?: (error: string) => void;\n onLoading?: (loading: boolean) => void;\n className?: string;\n showBillingDetails?: boolean;\n elementType?: 'card' | 'payment';\n}\n\nexport const PaymentForm: React.FC<PaymentFormProps> = ({\n clientSecret,\n customerId,\n customerEmail,\n amount,\n currency = 'usd',\n description,\n metadata,\n onSuccess,\n onError,\n onLoading,\n className = '',\n showBillingDetails = true,\n elementType = 'payment',\n}) => {\n const stripe = useStripe();\n const elements = useElements();\n const { initialized } = usePaymentsContext();\n\n const [loading, setLoading] = useState(false);\n const [email, setEmail] = useState(customerEmail || '');\n const [billingDetails, setBillingDetails] = useState({\n name: '',\n email: customerEmail || '',\n phone: '',\n address: {\n line1: '',\n line2: '',\n city: '',\n state: '',\n postal_code: '',\n country: 'US',\n },\n });\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n\n if (!stripe || !elements) {\n const error = ERROR_MESSAGES.STRIPE_NOT_LOADED;\n onError?.(error);\n return;\n }\n\n if (!initialized) {\n const error = ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED;\n onError?.(error);\n return;\n }\n\n if (showBillingDetails && email && !validateEmail(email)) {\n onError?.('Please enter a valid email address');\n return;\n }\n\n setLoading(true);\n onLoading?.(true);\n\n try {\n let result;\n\n if (elementType === 'payment' && clientSecret) {\n // Use Payment Element with existing Payment Intent\n result = await stripe.confirmPayment({\n elements,\n confirmParams: {\n return_url: window.location.href,\n receipt_email: email || billingDetails.email,\n },\n redirect: 'if_required',\n });\n } else if (elementType === 'card') {\n // Use Card Element\n const cardElement = elements.getElement(CardElement);\n\n if (!cardElement) {\n throw new Error('Card element not found');\n }\n\n if (clientSecret) {\n // Confirm existing Payment Intent\n result = await stripe.confirmCardPayment(clientSecret, {\n payment_method: {\n card: cardElement,\n billing_details: showBillingDetails\n ? {\n name: billingDetails.name || undefined,\n email: billingDetails.email || undefined,\n phone: billingDetails.phone || undefined,\n address: billingDetails.address.line1\n ? billingDetails.address\n : undefined,\n }\n : undefined,\n },\n });\n } else if (amount) {\n // Create new Payment Intent\n const response = await fetch('/api/payments/create-payment-intent', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n amount,\n currency,\n customerId,\n description,\n metadata,\n }),\n });\n\n if (!response.ok) {\n throw new Error('Failed to create payment intent');\n }\n\n const { client_secret } = await response.json();\n\n result = await stripe.confirmCardPayment(client_secret, {\n payment_method: {\n card: cardElement,\n billing_details: showBillingDetails\n ? {\n name: billingDetails.name || undefined,\n email: billingDetails.email || undefined,\n phone: billingDetails.phone || undefined,\n address: billingDetails.address.line1\n ? billingDetails.address\n : undefined,\n }\n : undefined,\n },\n });\n } else {\n throw new Error('Either clientSecret or amount is required');\n }\n }\n\n if (result?.error) {\n throw new Error(result.error.message || ERROR_MESSAGES.PAYMENT_FAILED);\n }\n\n if (result?.paymentIntent?.status === 'succeeded') {\n onSuccess?.(result.paymentIntent);\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : ERROR_MESSAGES.PAYMENT_FAILED;\n onError?.(errorMessage);\n console.error('Payment error:', error);\n } finally {\n setLoading(false);\n onLoading?.(false);\n }\n };\n\n const cardElementOptions = {\n style: {\n base: {\n fontSize: '16px',\n color: '#424770',\n '::placeholder': {\n color: '#aab7c4',\n },\n },\n invalid: {\n color: '#9e2146',\n },\n },\n };\n\n return (\n <form onSubmit={handleSubmit} className={`payment-form ${className}`}>\n {showBillingDetails && (\n <div className=\"mb-6 space-y-4\">\n <div>\n <label\n htmlFor=\"email\"\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n Email\n </label>\n <input\n type=\"email\"\n id=\"email\"\n value={email}\n onChange={e => {\n setEmail(e.target.value);\n setBillingDetails(prev => ({ ...prev, email: e.target.value }));\n }}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"your@email.com\"\n required\n />\n </div>\n\n <div>\n <label\n htmlFor=\"name\"\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n Full Name\n </label>\n <input\n type=\"text\"\n id=\"name\"\n value={billingDetails.name}\n onChange={e =>\n setBillingDetails(prev => ({ ...prev, name: e.target.value }))\n }\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"John Doe\"\n />\n </div>\n </div>\n )}\n\n <div className=\"mb-6\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n Payment Information\n </label>\n <div className=\"p-3 border border-gray-300 rounded-md\">\n {elementType === 'payment' ? (\n <PaymentElement />\n ) : (\n <CardElement options={cardElementOptions} />\n )}\n </div>\n </div>\n\n <button\n type=\"submit\"\n disabled={!stripe || loading}\n className=\"w-full bg-blue-600 text-white py-3 px-4 rounded-md font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200\"\n >\n {loading ? (\n <>\n <svg\n className=\"animate-spin -ml-1 mr-3 h-4 w-4 text-white inline\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n Processing...\n </>\n ) : (\n `Pay ${amount ? `$${(amount / 100).toFixed(2)}` : ''}`\n )}\n </button>\n </form>\n );\n};\n\nexport default PaymentForm;\n","import React, { useState } from 'react';\n\nexport type SubscriptionStatus =\n | 'active'\n | 'canceled'\n | 'past_due'\n | 'unpaid'\n | 'incomplete';\n\nexport interface Subscription {\n id: string;\n planId: string;\n planName: string;\n status: SubscriptionStatus;\n currentPeriodStart: Date;\n currentPeriodEnd: Date;\n cancelAtPeriodEnd: boolean;\n amount: number;\n currency: string;\n interval: 'month' | 'year';\n}\n\nexport type SubscriptionAction = 'upgrade' | 'downgrade' | 'pause' | 'resume';\n\nexport interface SubscriptionManagerProps {\n subscription: Subscription;\n onSubscriptionChange: (action: SubscriptionAction) => void;\n onCancel: () => void;\n className?: string;\n}\n\nexport const SubscriptionManager: React.FC<SubscriptionManagerProps> = ({\n subscription,\n onSubscriptionChange,\n onCancel,\n className = '',\n}) => {\n const [loading, setLoading] = useState(false);\n\n const formatDate = (date: Date) => {\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n }).format(date);\n };\n\n const formatAmount = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(amount / 100);\n };\n\n const getStatusColor = (status: SubscriptionStatus) => {\n switch (status) {\n case 'active':\n return '#10b981';\n case 'canceled':\n return '#ef4444';\n case 'past_due':\n return '#f59e0b';\n case 'unpaid':\n return '#ef4444';\n case 'incomplete':\n return '#6b7280';\n default:\n return '#6b7280';\n }\n };\n\n const getStatusText = (status: SubscriptionStatus) => {\n switch (status) {\n case 'active':\n return 'Active';\n case 'canceled':\n return 'Canceled';\n case 'past_due':\n return 'Past Due';\n case 'unpaid':\n return 'Unpaid';\n case 'incomplete':\n return 'Incomplete';\n default:\n return status;\n }\n };\n\n const handleAction = async (action: SubscriptionAction) => {\n setLoading(true);\n try {\n await onSubscriptionChange(action);\n } finally {\n setLoading(false);\n }\n };\n\n const handleCancel = async () => {\n setLoading(true);\n try {\n await onCancel();\n } finally {\n setLoading(false);\n }\n };\n\n const styles = {\n container: {\n width: '100%',\n } as React.CSSProperties,\n card: {\n border: '1px solid #e5e7eb',\n borderRadius: '12px',\n padding: '2rem',\n background: 'white',\n boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',\n } as React.CSSProperties,\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: '1.5rem',\n } as React.CSSProperties,\n info: {\n flex: 1,\n } as React.CSSProperties,\n planName: {\n fontSize: '1.5rem',\n fontWeight: 700,\n color: '#1f2937',\n margin: '0 0 0.5rem 0',\n } as React.CSSProperties,\n details: {\n display: 'flex',\n alignItems: 'baseline',\n gap: '0.25rem',\n } as React.CSSProperties,\n amount: {\n fontSize: '1.25rem',\n fontWeight: 600,\n color: '#3b82f6',\n } as React.CSSProperties,\n interval: {\n fontSize: '1rem',\n color: '#6b7280',\n } as React.CSSProperties,\n statusBadge: {\n padding: '0.5rem 1rem',\n borderRadius: '20px',\n color: 'white',\n fontSize: '0.875rem',\n fontWeight: 600,\n } as React.CSSProperties,\n dates: {\n marginBottom: '2rem',\n padding: '1rem',\n background: '#f9fafb',\n borderRadius: '8px',\n } as React.CSSProperties,\n dateLabel: {\n fontSize: '0.875rem',\n color: '#6b7280',\n fontWeight: 500,\n } as React.CSSProperties,\n dateValue: {\n fontSize: '0.875rem',\n color: '#1f2937',\n } as React.CSSProperties,\n cancellationNotice: {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n marginTop: '1rem',\n padding: '0.75rem',\n background: '#fef3c7',\n borderRadius: '6px',\n fontSize: '0.875rem',\n color: '#92400e',\n } as React.CSSProperties,\n actions: {\n display: 'flex',\n gap: '1rem',\n flexWrap: 'wrap' as const,\n } as React.CSSProperties,\n button: {\n padding: '0.75rem 1.5rem',\n border: 'none',\n borderRadius: '8px',\n fontWeight: 600,\n fontSize: '0.875rem',\n cursor: 'pointer',\n transition: 'all 0.3s ease',\n flex: 1,\n minWidth: '120px',\n } as React.CSSProperties,\n buttonPrimary: {\n background: '#3b82f6',\n color: 'white',\n } as React.CSSProperties,\n buttonSecondary: {\n background: '#f3f4f6',\n color: '#374151',\n border: '1px solid #d1d5db',\n } as React.CSSProperties,\n buttonDanger: {\n background: '#ef4444',\n color: 'white',\n } as React.CSSProperties,\n buttonDisabled: {\n opacity: 0.6,\n cursor: 'not-allowed',\n } as React.CSSProperties,\n };\n\n return (\n <div style={styles.container} className={className}>\n <div style={styles.card}>\n <div style={styles.header}>\n <div style={styles.info}>\n <h3 style={styles.planName}>{subscription.planName}</h3>\n <div style={styles.details}>\n <span style={styles.amount}>\n {formatAmount(subscription.amount, subscription.currency)}\n </span>\n <span style={styles.interval}>/{subscription.interval}</span>\n </div>\n </div>\n <div>\n <span\n style={{\n ...styles.statusBadge,\n backgroundColor: getStatusColor(subscription.status),\n }}\n >\n {getStatusText(subscription.status)}\n </span>\n </div>\n </div>\n\n <div style={styles.dates}>\n <div>\n <div style={styles.dateLabel}>Current period:</div>\n <div style={styles.dateValue}>\n {formatDate(subscription.currentPeriodStart)} -{' '}\n {formatDate(subscription.currentPeriodEnd)}\n </div>\n </div>\n {subscription.cancelAtPeriodEnd && (\n <div style={styles.cancellationNotice}>\n <span>⚠️</span>\n <span>\n Your subscription will be canceled at the end of the current\n period.\n </span>\n </div>\n )}\n </div>\n\n <div style={styles.actions}>\n {subscription.status === 'active' &&\n !subscription.cancelAtPeriodEnd && (\n <>\n <button\n style={{\n ...styles.button,\n ...styles.buttonSecondary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('upgrade')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Upgrade Plan'}\n </button>\n <button\n style={{\n ...styles.button,\n ...styles.buttonSecondary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('downgrade')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Downgrade Plan'}\n </button>\n <button\n style={{\n ...styles.button,\n ...styles.buttonDanger,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={handleCancel}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Cancel Subscription'}\n </button>\n </>\n )}\n\n {subscription.status === 'active' &&\n subscription.cancelAtPeriodEnd && (\n <button\n style={{\n ...styles.button,\n ...styles.buttonPrimary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('resume')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Resume Subscription'}\n </button>\n )}\n\n {subscription.status === 'past_due' && (\n <button\n style={{\n ...styles.button,\n ...styles.buttonPrimary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('resume')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Update Payment Method'}\n </button>\n )}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":["src_exports","__export","ACTIVE_STATUSES","BILLING_INTERVALS","CHECKOUT_MODE","CURRENCY_SYMBOLS","DEFAULT_CURRENCY","ERROR_MESSAGES","INACTIVE_STATUSES","INCOMPLETE_STATUSES","INVOICE_STATUS","MockPaymentProvider","PAYMENT_METHODS","PROBLEMATIC_STATUSES","PaymentErrorType","PaymentProviderFactory","PaymentsError","PaymentsProvider","PricingTable","STRIPE_API_VERSION","SUBSCRIPTION_STATUS","PaymentForm","StripePaymentProvider","SubscriptionManager","SubscriptionStatus","WEBHOOK_EVENTS","calculateTax","formatAmountWithTax","formatBillingInterval","formatCardBrand","formatCurrency","formatDate","formatPaymentMethodDisplay","formatPricingPlan","formatRelativeTime","formatSubscriptionStatus","formatTaxRate","formatTrialPeriod","getEnvironmentConfig","isActiveSubscription","isClient","isDevelopment","isInactiveSubscription","isIncompleteSubscription","isProblematicSubscription","isProduction","isServer","truncateText","usePayments","usePaymentsContext","validateAmount","validateCard","validateCurrentEnvironment","validateEmail","validateEnvironment","validatePaymentsConfig","validatePhoneNumber","validatePricingPlan","validateStripeId","__toCommonJS","SubscriptionStatus","ACTIVE_STATUSES","INACTIVE_STATUSES","PROBLEMATIC_STATUSES","INCOMPLETE_STATUSES","isActiveSubscription","status","isInactiveSubscription","isProblematicSubscription","isIncompleteSubscription","PaymentErrorType","PaymentsError","_PaymentsError","type","message","code","details","STRIPE_API_VERSION","PAYMENT_METHODS","SUBSCRIPTION_STATUS","INVOICE_STATUS","CHECKOUT_MODE","BILLING_INTERVALS","CURRENCY_SYMBOLS","DEFAULT_CURRENCY","WEBHOOK_EVENTS","ERROR_MESSAGES","validateEmail","email","validatePhoneNumber","phone","validatePaymentsConfig","config","errors","validatePricingPlan","plan","validateStripeId","id","type","prefixes","validateAmount","amount","currency","minAmount","validateCard","cardDetails","cleanNumber","luhnCheck","currentYear","cardNumber","sum","alternate","formatCurrency","amount","currency","DEFAULT_CURRENCY","options","showSymbol","showCents","locale","currencyCode","isZeroDecimalCurrency","displayAmount","symbol","CURRENCY_SYMBOLS","formattedAmount","formatPricingPlan","plan","price","interval","formatSubscriptionStatus","status","formatDate","date","format","timeZone","dateObj","formatOptions","formatRelativeTime","numeric","diffInSeconds","rtf","minutes","hours","days","formatBillingInterval","count","formatTrialPeriod","truncateText","text","maxLength","formatCardBrand","brand","formatPaymentMethodDisplay","paymentMethod","calculateTax","taxRate","inclusive","roundTo","subtotal","tax","total","multiplier","formatTaxRate","rate","formatAmountWithTax","showBreakdown","taxCalculation","subtotalFormatted","taxFormatted","totalFormatted","validateEnvironment","config","errors","warnings","getEnvironmentConfig","isServer","validateCurrentEnvironment","validation","error","warning","isDevelopment","isProduction","isClient","BasePaymentProvider","config","error","type","PaymentsError","message","code","details","import_stripe","StripePaymentProvider","BasePaymentProvider","config","PaymentsError","Stripe","params","session","error","customer","customerId","subscription","item","subscriptionId","sessionId","status","currentSubscription","items","i","stripeSubscription","MockPaymentProvider","BasePaymentProvider","config","params","id","PaymentsError","newCustomer","customer","c","initialLength","customerId","paymentMethodId","newPaymentMethod","pm","newSubscription","item","subscription","s","status","subs","PaymentProviderFactory","config","StripePaymentProvider","PaymentsError","MockPaymentProvider","providers","configs","import_react","import_zustand","import_immer","initialState","usePayments","set","get","config","state","resolvedConfig","PaymentProviderFactory","error","message","PaymentsError","params","customer","customerId","session","sessionId","newSubscription","subscriptionId","updatedSubscription","status","subscriptions","subscription","activeSubscription","sub","import_jsx_runtime","PaymentsContext","PaymentsProvider","children","config","onPaymentSuccess","onPaymentError","store","usePayments","initialize","initialized","loading","error","customer","subscriptions","activeSubscription","onPaymentSuccessRef","onPaymentErrorRef","err","contextValue","usePaymentsContext","context","import_react","usePayments","config","setConfig","provider","setProvider","initialized","setInitialized","loading","setLoading","error","setError","customer","setCustomer","subscriptions","setSubscriptions","handleError","err","refreshSubscriptions","customerId","status","PaymentsError","ERROR_MESSAGES","fetchedSubscriptions","initialize","initialConfig","resolvedConfig","PaymentProviderFactory","newProvider","retrieveCustomer","newCustomer","createCustomer","params","createSubscription","newSubscription","listSubscriptions","subs","retrieveSubscription","subscriptionId","sub","createCheckoutSession","retrieveCheckoutSession","sessionId","cancelSubscription","reactivateSubscription","updateSubscription","updatedSubscription","refreshCustomer","fetchedCustomer","reset","activeSubscription","s","import_react","import_react_stripe_js","import_jsx_runtime","CheckoutButton","priceId","customerId","customerEmail","successUrl","cancelUrl","children","className","disabled","allowPromotionCodes","billingAddressCollection","metadata","trialPeriodDays","onSuccess","onError","onLoading","stripe","initialized","usePaymentsContext","loading","setLoading","error","ERROR_MESSAGES","validateStripeId","response","errorData","sessionId","result","errorMessage","import_jsx_runtime","PricingTable","plans","customerId","customerEmail","successUrl","cancelUrl","className","onCheckoutSuccess","onCheckoutError","showFeatures","showTrialInfo","layout","maxColumns","gridCols","gridClass","plan","PricingCard","error","isPopular","formatPricingPlan","formatTrialPeriod","feature","index","CheckoutButton","import_react","import_react_stripe_js","import_jsx_runtime","PaymentForm","clientSecret","customerId","customerEmail","amount","currency","description","metadata","onSuccess","onError","onLoading","className","showBillingDetails","elementType","stripe","elements","initialized","usePaymentsContext","loading","setLoading","email","setEmail","billingDetails","setBillingDetails","handleSubmit","event","error","ERROR_MESSAGES","validateEmail","result","cardElement","response","client_secret","errorMessage","cardElementOptions","e","prev","import_react","import_jsx_runtime","SubscriptionManager","subscription","onSubscriptionChange","onCancel","className","loading","setLoading","formatDate","date","formatAmount","amount","currency","getStatusColor","status","getStatusText","handleAction","action","handleCancel","styles"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/shared/types/subscription.ts","../src/shared/types/errors.ts","../src/shared/constants.ts","../src/shared/utils/validation.ts","../src/shared/utils/formatting.ts","../src/shared/utils/env.ts","../src/providers/base/index.ts","../src/providers/stripe/index.ts","../src/providers/mock/index.ts","../src/providers/index.ts","../src/shared/providers/PaymentsProvider.tsx","../src/hooks/usePayments.ts","../src/shared/hooks/usePayments.ts","../src/web/components/CheckoutButton.tsx","../src/web/components/PricingTable.tsx","../src/web/components/PaymentForm.tsx","../src/web/components/SubscriptionManager.tsx"],"sourcesContent":["// Shared exports\nexport * from './shared/types';\nexport * from './shared/constants';\nexport * from './shared/utils/validation';\nexport * from './shared/utils/formatting';\nexport * from './shared/utils/env';\n\n// Utils that templates expect\nexport {\n formatCurrency,\n formatDate,\n calculateTax,\n formatTaxRate,\n formatAmountWithTax,\n} from './shared/utils/formatting';\nexport {\n validateCard,\n validateEmail,\n validateAmount,\n validatePricingPlan,\n validatePaymentsConfig,\n} from './shared/utils/validation';\n\n// Providers\nexport { PaymentProviderFactory } from './providers';\nexport * from './providers/stripe';\nexport * from './providers/mock';\n\n// New providers (temporarily commented out due to build issues)\n// export * from './providers/paypal';\n// export * from './providers/applepay';\n\n// Hooks\nexport {\n PaymentsProvider,\n usePaymentsContext,\n} from './shared/providers/PaymentsProvider';\nexport { usePayments } from './shared/hooks/usePayments';\n\n// Analytics hooks (temporarily commented out due to build issues)\n// export { useSubscriptionAnalytics } from './shared/hooks/useSubscriptionAnalytics';\n// export { useRevenueAnalytics } from './shared/hooks/useRevenueAnalytics';\n\n// Re-export commonly used components from web for convenience\nexport {\n StripePaymentForm,\n SubscriptionManager,\n PricingTable,\n type StripePaymentFormProps,\n type SubscriptionManagerProps,\n} from './web/components';\n\n// Platform-specific exports are handled by package.json exports field\n// Users will import from:\n// - '@digilogiclabs/saas-factory-payments/web' for web components\n// - '@digilogiclabs/saas-factory-payments/native' for React Native components\n// - '@digilogiclabs/saas-factory-payments/server' for server-side utilities\n","export enum SubscriptionStatus {\n ACTIVE = 'active',\n CANCELED = 'canceled',\n PAST_DUE = 'past_due',\n UNPAID = 'unpaid',\n INCOMPLETE = 'incomplete',\n INCOMPLETE_EXPIRED = 'incomplete_expired',\n TRIALING = 'trialing',\n ENDED = 'ended', // Custom status for ended subscriptions\n ALL = 'all', // For filtering purposes\n}\n\nexport interface SubscriptionItem {\n id: string;\n priceId: string;\n quantity: number;\n metadata?: Record<string, string>;\n}\n\nexport interface Subscription {\n id: string;\n customerId: string;\n customer_id?: string; // For compatibility\n status: SubscriptionStatus;\n items?: SubscriptionItem[];\n price_id?: string; // For single-item subscriptions\n currentPeriodStart: Date;\n current_period_start?: Date; // For compatibility\n currentPeriodEnd: Date;\n current_period_end?: Date; // For compatibility\n cancelAtPeriodEnd: boolean;\n cancel_at_period_end?: boolean; // For compatibility\n trialEnd?: Date;\n trial_end?: Date; // For compatibility\n trialStart?: Date;\n trial_start?: Date; // For compatibility\n canceledAt?: Date;\n canceled_at?: Date; // For compatibility\n endedAt?: Date;\n metadata?: Record<string, string>;\n created: Date;\n updated?: Date;\n // Additional fields for analytics\n amount?: number;\n currency?: string;\n interval?: string;\n interval_unit?: string;\n planName?: string;\n planId?: string;\n}\n\nexport interface SubscriptionCreateParams {\n customerId: string;\n items?: { priceId: string; quantity?: number }[];\n priceId?: string; // For single-item subscriptions\n trialPeriodDays?: number;\n metadata?: Record<string, string>;\n paymentBehavior?:\n | 'default_incomplete'\n | 'error_if_incomplete'\n | 'allow_incomplete';\n // Additional fields for multi-provider support\n customerEmail?: string;\n customerName?: string;\n successUrl?: string;\n cancelUrl?: string;\n}\n\nexport interface SubscriptionUpdateParams {\n items?: { priceId: string; quantity?: number }[];\n priceId?: string; // For single-item subscriptions\n quantity?: number;\n cancelAtPeriodEnd?: boolean;\n metadata?: Record<string, string>;\n}\n\n// More specific status type unions for better TypeScript support\nexport type ActiveSubscriptionStatus =\n | SubscriptionStatus.ACTIVE\n | SubscriptionStatus.TRIALING;\nexport type InactiveSubscriptionStatus =\n | SubscriptionStatus.CANCELED\n | SubscriptionStatus.ENDED;\nexport type ProblematicSubscriptionStatus =\n | SubscriptionStatus.PAST_DUE\n | SubscriptionStatus.UNPAID;\nexport type IncompleteSubscriptionStatus =\n | SubscriptionStatus.INCOMPLETE\n | SubscriptionStatus.INCOMPLETE_EXPIRED;\n\n// Status groups for filtering and UI logic\nexport const ACTIVE_STATUSES: ActiveSubscriptionStatus[] = [\n SubscriptionStatus.ACTIVE,\n SubscriptionStatus.TRIALING,\n];\n\nexport const INACTIVE_STATUSES: InactiveSubscriptionStatus[] = [\n SubscriptionStatus.CANCELED,\n SubscriptionStatus.ENDED,\n];\n\nexport const PROBLEMATIC_STATUSES: ProblematicSubscriptionStatus[] = [\n SubscriptionStatus.PAST_DUE,\n SubscriptionStatus.UNPAID,\n];\n\nexport const INCOMPLETE_STATUSES: IncompleteSubscriptionStatus[] = [\n SubscriptionStatus.INCOMPLETE,\n SubscriptionStatus.INCOMPLETE_EXPIRED,\n];\n\n// Helper functions for subscription status checks\nexport const isActiveSubscription = (\n status: SubscriptionStatus\n): status is ActiveSubscriptionStatus => {\n return ACTIVE_STATUSES.includes(status as ActiveSubscriptionStatus);\n};\n\nexport const isInactiveSubscription = (\n status: SubscriptionStatus\n): status is InactiveSubscriptionStatus => {\n return INACTIVE_STATUSES.includes(status as InactiveSubscriptionStatus);\n};\n\nexport const isProblematicSubscription = (\n status: SubscriptionStatus\n): status is ProblematicSubscriptionStatus => {\n return PROBLEMATIC_STATUSES.includes(status as ProblematicSubscriptionStatus);\n};\n\nexport const isIncompleteSubscription = (\n status: SubscriptionStatus\n): status is IncompleteSubscriptionStatus => {\n return INCOMPLETE_STATUSES.includes(status as IncompleteSubscriptionStatus);\n};\n","export enum PaymentErrorType {\n CARD_DECLINED = 'CARD_DECLINED',\n INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS',\n CUSTOMER_NOT_FOUND = 'CUSTOMER_NOT_FOUND',\n SUBSCRIPTION_NOT_FOUND = 'SUBSCRIPTION_NOT_FOUND',\n NETWORK_ERROR = 'NETWORK_ERROR',\n CONFIGURATION_ERROR = 'CONFIGURATION_ERROR',\n WEBHOOK_ERROR = 'WEBHOOK_ERROR',\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n PROVIDER_NOT_CONFIGURED = 'PROVIDER_NOT_CONFIGURED',\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n INITIALIZATION_ERROR = 'INITIALIZATION_ERROR',\n AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR',\n NOT_FOUND = 'NOT_FOUND',\n INVALID_REQUEST = 'INVALID_REQUEST',\n API_ERROR = 'API_ERROR',\n PERMISSION_DENIED = 'PERMISSION_DENIED',\n WEBHOOK_VERIFICATION_FAILED = 'WEBHOOK_VERIFICATION_FAILED',\n}\n\nexport interface PaymentError extends Error {\n type: PaymentErrorType;\n code?: string;\n details?: Record<string, unknown>;\n}\n\nexport class PaymentsError extends Error implements PaymentError {\n public type: PaymentErrorType;\n public code?: string;\n public details?: Record<string, unknown>;\n\n constructor(\n type: PaymentErrorType,\n message: string,\n code?: string,\n details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'PaymentsError';\n this.type = type;\n this.code = code;\n this.details = details;\n Object.setPrototypeOf(this, PaymentsError.prototype);\n }\n}\n","export const STRIPE_API_VERSION = '2023-10-16';\n\nexport const PAYMENT_METHODS = {\n CARD: 'card',\n BANK_ACCOUNT: 'bank_account',\n SEPA_DEBIT: 'sepa_debit',\n IDEAL: 'ideal',\n SOFORT: 'sofort',\n} as const;\n\nexport const SUBSCRIPTION_STATUS = {\n ACTIVE: 'active',\n CANCELED: 'canceled',\n PAST_DUE: 'past_due',\n UNPAID: 'unpaid',\n INCOMPLETE: 'incomplete',\n INCOMPLETE_EXPIRED: 'incomplete_expired',\n TRIALING: 'trialing',\n} as const;\n\nexport const INVOICE_STATUS = {\n DRAFT: 'draft',\n OPEN: 'open',\n PAID: 'paid',\n UNCOLLECTIBLE: 'uncollectible',\n VOID: 'void',\n} as const;\n\nexport const CHECKOUT_MODE = {\n PAYMENT: 'payment',\n SUBSCRIPTION: 'subscription',\n SETUP: 'setup',\n} as const;\n\nexport const BILLING_INTERVALS = {\n DAY: 'day',\n WEEK: 'week',\n MONTH: 'month',\n YEAR: 'year',\n} as const;\n\nexport const CURRENCY_SYMBOLS = {\n USD: '$',\n EUR: '€',\n GBP: '£',\n JPY: '¥',\n CAD: 'C$',\n AUD: 'A$',\n CHF: 'CHF',\n CNY: '¥',\n SEK: 'kr',\n NZD: 'NZ$',\n} as const;\n\nexport const DEFAULT_CURRENCY = 'USD';\n\nexport const WEBHOOK_EVENTS = {\n CUSTOMER_SUBSCRIPTION_CREATED: 'customer.subscription.created',\n CUSTOMER_SUBSCRIPTION_UPDATED: 'customer.subscription.updated',\n CUSTOMER_SUBSCRIPTION_DELETED: 'customer.subscription.deleted',\n INVOICE_PAYMENT_SUCCEEDED: 'invoice.payment_succeeded',\n INVOICE_PAYMENT_FAILED: 'invoice.payment_failed',\n CHECKOUT_SESSION_COMPLETED: 'checkout.session.completed',\n PAYMENT_INTENT_SUCCEEDED: 'payment_intent.succeeded',\n PAYMENT_INTENT_PAYMENT_FAILED: 'payment_intent.payment_failed',\n} as const;\n\nexport const ERROR_MESSAGES = {\n PROVIDER_NOT_CONFIGURED: 'Payments provider is not properly configured',\n STRIPE_NOT_LOADED: 'Stripe has not been loaded yet',\n INVALID_PRICE_ID: 'Invalid price ID provided',\n INVALID_CUSTOMER_ID: 'Invalid customer ID provided',\n CHECKOUT_FAILED: 'Checkout session creation failed',\n PAYMENT_FAILED: 'Payment processing failed',\n SUBSCRIPTION_NOT_FOUND: 'Subscription not found',\n CUSTOMER_NOT_FOUND: 'Customer not found',\n} as const;\n","import { PaymentsConfig, PricingPlan } from '../types';\n\nexport const validateEmail = (email: string): boolean => {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n};\n\nexport const validatePhoneNumber = (phone: string): boolean => {\n // Basic phone number validation - can be enhanced based on requirements\n const phoneRegex = /^\\+?[\\d\\s-()]{10,}$/;\n return phoneRegex.test(phone);\n};\n\nexport const validatePaymentsConfig = (\n config: PaymentsConfig\n): { isValid: boolean; errors: string[] } => {\n const errors: string[] = [];\n\n if (!config.publishableKey) {\n errors.push('publishableKey is required');\n }\n\n if (!config.provider) {\n errors.push('provider is required');\n }\n\n if (config.provider !== 'stripe') {\n errors.push('Only stripe provider is currently supported');\n }\n\n if (!config.environment) {\n errors.push('environment is required');\n }\n\n if (\n config.environment &&\n !['development', 'production'].includes(config.environment)\n ) {\n errors.push('environment must be either \"development\" or \"production\"');\n }\n\n if (config.publishableKey && !config.publishableKey.startsWith('pk_')) {\n errors.push('publishableKey must start with \"pk_\"');\n }\n\n if (config.secretKey && !config.secretKey.startsWith('sk_')) {\n errors.push('secretKey must start with \"sk_\"');\n }\n\n if (config.webhookSecret && !config.webhookSecret.startsWith('whsec_')) {\n errors.push('webhookSecret must start with \"whsec_\"');\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n};\n\nexport const validatePricingPlan = (\n plan: PricingPlan\n): { isValid: boolean; errors: string[] } => {\n const errors: string[] = [];\n\n if (!plan.id) {\n errors.push('id is required');\n }\n\n if (!plan.name) {\n errors.push('name is required');\n }\n\n if (typeof plan.price !== 'number' || plan.price < 0) {\n errors.push('price must be a non-negative number');\n }\n\n if (!plan.currency) {\n errors.push('currency is required');\n }\n\n if (!plan.interval) {\n errors.push('interval is required');\n }\n\n if (!['day', 'week', 'month', 'year'].includes(plan.interval)) {\n errors.push('interval must be one of: day, week, month, year');\n }\n\n if (!plan.stripePriceId) {\n errors.push('stripePriceId is required');\n }\n\n if (plan.stripePriceId && !plan.stripePriceId.startsWith('price_')) {\n errors.push('stripePriceId must start with \"price_\"');\n }\n\n if (!Array.isArray(plan.features)) {\n errors.push('features must be an array');\n }\n\n if (\n plan.intervalCount &&\n (typeof plan.intervalCount !== 'number' || plan.intervalCount < 1)\n ) {\n errors.push('intervalCount must be a positive number');\n }\n\n if (\n plan.trialPeriodDays &&\n (typeof plan.trialPeriodDays !== 'number' || plan.trialPeriodDays < 0)\n ) {\n errors.push('trialPeriodDays must be a non-negative number');\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n};\n\nexport const validateStripeId = (\n id: string,\n type: 'customer' | 'subscription' | 'price' | 'product' | 'payment_intent'\n): boolean => {\n const prefixes = {\n customer: 'cus_',\n subscription: 'sub_',\n price: 'price_',\n product: 'prod_',\n payment_intent: 'pi_',\n };\n\n return id.startsWith(prefixes[type]);\n};\n\nexport const validateAmount = (\n amount: number,\n currency: string\n): { isValid: boolean; error?: string } => {\n if (typeof amount !== 'number') {\n return { isValid: false, error: 'Amount must be a number' };\n }\n\n if (amount < 0) {\n return { isValid: false, error: 'Amount must be non-negative' };\n }\n\n // Stripe minimum amounts by currency\n const minimumAmounts: Record<string, number> = {\n USD: 50, // $0.50\n EUR: 50, // €0.50\n GBP: 30, // £0.30\n JPY: 50, // ¥50\n CAD: 50, // C$0.50\n AUD: 50, // A$0.50\n };\n\n const minAmount = minimumAmounts[currency.toUpperCase()] || 50;\n\n if (amount < minAmount) {\n return {\n isValid: false,\n error: `Amount must be at least ${minAmount} ${currency.toLowerCase()} cents`,\n };\n }\n\n return { isValid: true };\n};\n\nexport const validateCard = (cardDetails: {\n number: string;\n expMonth: number;\n expYear: number;\n cvc: string;\n}): { isValid: boolean; errors: string[] } => {\n const errors: string[] = [];\n\n // Validate card number (basic Luhn algorithm)\n const cleanNumber = cardDetails.number.replace(/\\s/g, '');\n if (!cleanNumber || cleanNumber.length < 13 || cleanNumber.length > 19) {\n errors.push('Card number must be between 13 and 19 digits');\n } else if (!luhnCheck(cleanNumber)) {\n errors.push('Invalid card number');\n }\n\n // Validate expiration month\n if (\n !cardDetails.expMonth ||\n cardDetails.expMonth < 1 ||\n cardDetails.expMonth > 12\n ) {\n errors.push('Expiration month must be between 1 and 12');\n }\n\n // Validate expiration year\n const currentYear = new Date().getFullYear();\n if (\n !cardDetails.expYear ||\n cardDetails.expYear < currentYear ||\n cardDetails.expYear > currentYear + 20\n ) {\n errors.push('Invalid expiration year');\n }\n\n // Check if card is expired\n if (cardDetails.expMonth && cardDetails.expYear) {\n const expirationDate = new Date(\n cardDetails.expYear,\n cardDetails.expMonth - 1,\n 1\n );\n const currentDate = new Date();\n if (expirationDate < currentDate) {\n errors.push('Card has expired');\n }\n }\n\n // Validate CVC\n if (\n !cardDetails.cvc ||\n cardDetails.cvc.length < 3 ||\n cardDetails.cvc.length > 4\n ) {\n errors.push('CVC must be 3 or 4 digits');\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n};\n\n// Luhn algorithm for credit card validation\nconst luhnCheck = (cardNumber: string): boolean => {\n let sum = 0;\n let alternate = false;\n\n for (let i = cardNumber.length - 1; i >= 0; i--) {\n let n = parseInt(cardNumber.charAt(i), 10);\n\n if (alternate) {\n n *= 2;\n if (n > 9) {\n n = (n % 10) + 1;\n }\n }\n\n sum += n;\n alternate = !alternate;\n }\n\n return sum % 10 === 0;\n};\n","import { CURRENCY_SYMBOLS, DEFAULT_CURRENCY } from '../constants';\nimport { PricingPlan, SubscriptionStatus } from '../types';\n\nexport const formatCurrency = (\n amount: number,\n currency: string = DEFAULT_CURRENCY,\n options: {\n showSymbol?: boolean;\n showCents?: boolean;\n locale?: string;\n } = {}\n): string => {\n const { showSymbol = true, showCents = true, locale = 'en-US' } = options;\n\n const currencyCode = currency.toUpperCase();\n\n // Convert from cents to dollars for most currencies\n const isZeroDecimalCurrency = ['JPY', 'KRW', 'VND', 'CLP'].includes(\n currencyCode\n );\n const displayAmount = isZeroDecimalCurrency ? amount : amount / 100;\n\n if (showSymbol) {\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: showCents && !isZeroDecimalCurrency ? 2 : 0,\n maximumFractionDigits: showCents && !isZeroDecimalCurrency ? 2 : 0,\n }).format(displayAmount);\n } catch {\n // Fallback to manual formatting if Intl.NumberFormat fails\n const symbol =\n CURRENCY_SYMBOLS[currencyCode as keyof typeof CURRENCY_SYMBOLS] ||\n currencyCode;\n const formattedAmount =\n showCents && !isZeroDecimalCurrency\n ? displayAmount.toFixed(2)\n : Math.round(displayAmount).toString();\n return `${symbol}${formattedAmount}`;\n }\n }\n\n return showCents && !isZeroDecimalCurrency\n ? displayAmount.toFixed(2)\n : Math.round(displayAmount).toString();\n};\n\nexport const formatPricingPlan = (plan: PricingPlan): string => {\n const price = formatCurrency(plan.price, plan.currency);\n const interval =\n plan.intervalCount && plan.intervalCount > 1\n ? `${plan.intervalCount} ${plan.interval}s`\n : plan.interval;\n\n return `${price}/${interval}`;\n};\n\nexport const formatSubscriptionStatus = (\n status: SubscriptionStatus\n): string => {\n const statusMap: Record<SubscriptionStatus, string> = {\n [SubscriptionStatus.ACTIVE]: 'Active',\n [SubscriptionStatus.CANCELED]: 'Canceled',\n [SubscriptionStatus.PAST_DUE]: 'Past Due',\n [SubscriptionStatus.UNPAID]: 'Unpaid',\n [SubscriptionStatus.INCOMPLETE]: 'Incomplete',\n [SubscriptionStatus.INCOMPLETE_EXPIRED]: 'Incomplete (Expired)',\n [SubscriptionStatus.TRIALING]: 'Trial',\n [SubscriptionStatus.ENDED]: 'Ended',\n [SubscriptionStatus.ALL]: 'All',\n };\n\n return statusMap[status] || status;\n};\n\nexport const formatDate = (\n date: Date | string | number,\n options: {\n format?: 'short' | 'medium' | 'long' | 'full';\n locale?: string;\n timeZone?: string;\n } = {}\n): string => {\n const { format = 'medium', locale = 'en-US', timeZone } = options;\n\n const dateObj =\n typeof date === 'string' || typeof date === 'number'\n ? new Date(date)\n : date;\n\n const formatOptions: Intl.DateTimeFormatOptions = {\n timeZone,\n };\n\n switch (format) {\n case 'short':\n formatOptions.dateStyle = 'short';\n break;\n case 'medium':\n formatOptions.dateStyle = 'medium';\n break;\n case 'long':\n formatOptions.dateStyle = 'long';\n break;\n case 'full':\n formatOptions.dateStyle = 'full';\n break;\n }\n\n try {\n return new Intl.DateTimeFormat(locale, formatOptions).format(dateObj);\n } catch {\n // Fallback to basic formatting\n return dateObj.toLocaleDateString();\n }\n};\n\nexport const formatRelativeTime = (\n date: Date | string | number,\n options: {\n locale?: string;\n numeric?: 'always' | 'auto';\n } = {}\n): string => {\n const { locale = 'en-US', numeric = 'auto' } = options;\n\n const dateObj =\n typeof date === 'string' || typeof date === 'number'\n ? new Date(date)\n : date;\n const now = new Date();\n const diffInSeconds = Math.floor((now.getTime() - dateObj.getTime()) / 1000);\n\n try {\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric });\n\n if (Math.abs(diffInSeconds) < 60) {\n return rtf.format(-diffInSeconds, 'second');\n } else if (Math.abs(diffInSeconds) < 3600) {\n return rtf.format(-Math.floor(diffInSeconds / 60), 'minute');\n } else if (Math.abs(diffInSeconds) < 86400) {\n return rtf.format(-Math.floor(diffInSeconds / 3600), 'hour');\n } else if (Math.abs(diffInSeconds) < 2592000) {\n return rtf.format(-Math.floor(diffInSeconds / 86400), 'day');\n } else if (Math.abs(diffInSeconds) < 31536000) {\n return rtf.format(-Math.floor(diffInSeconds / 2592000), 'month');\n } else {\n return rtf.format(-Math.floor(diffInSeconds / 31536000), 'year');\n }\n } catch {\n // Fallback to basic relative time\n if (Math.abs(diffInSeconds) < 60) {\n return 'just now';\n } else if (Math.abs(diffInSeconds) < 3600) {\n const minutes = Math.floor(Math.abs(diffInSeconds) / 60);\n return diffInSeconds < 0\n ? `in ${minutes} minutes`\n : `${minutes} minutes ago`;\n } else if (Math.abs(diffInSeconds) < 86400) {\n const hours = Math.floor(Math.abs(diffInSeconds) / 3600);\n return diffInSeconds < 0 ? `in ${hours} hours` : `${hours} hours ago`;\n } else {\n const days = Math.floor(Math.abs(diffInSeconds) / 86400);\n return diffInSeconds < 0 ? `in ${days} days` : `${days} days ago`;\n }\n }\n};\n\nexport const formatBillingInterval = (\n interval: string,\n count: number = 1\n): string => {\n const intervalMap: Record<string, string> = {\n day: count === 1 ? 'daily' : `every ${count} days`,\n week: count === 1 ? 'weekly' : `every ${count} weeks`,\n month: count === 1 ? 'monthly' : `every ${count} months`,\n year: count === 1 ? 'yearly' : `every ${count} years`,\n };\n\n return intervalMap[interval] || interval;\n};\n\nexport const formatTrialPeriod = (days: number): string => {\n if (days === 0) return 'No trial';\n if (days === 1) return '1 day trial';\n if (days < 7) return `${days} days trial`;\n if (days === 7) return '1 week trial';\n if (days < 30) return `${Math.floor(days / 7)} weeks trial`;\n if (days === 30) return '1 month trial';\n return `${Math.floor(days / 30)} months trial`;\n};\n\nexport const truncateText = (text: string, maxLength: number): string => {\n if (text.length <= maxLength) return text;\n return `${text.substring(0, maxLength - 3)}...`;\n};\n\nexport const formatCardBrand = (brand: string): string => {\n const brandMap: Record<string, string> = {\n visa: 'Visa',\n mastercard: 'Mastercard',\n amex: 'American Express',\n discover: 'Discover',\n jcb: 'JCB',\n diners: 'Diners Club',\n unionpay: 'UnionPay',\n };\n\n return brandMap[brand.toLowerCase()] || brand;\n};\n\nexport const formatPaymentMethodDisplay = (paymentMethod: {\n type: string;\n card?: { brand: string; last4: string };\n bankAccount?: { last4: string; bankName?: string };\n}): string => {\n if (paymentMethod.type === 'card' && paymentMethod.card) {\n return `${formatCardBrand(paymentMethod.card.brand)} •••• ${paymentMethod.card.last4}`;\n }\n\n if (paymentMethod.type === 'bank_account' && paymentMethod.bankAccount) {\n const bankName = paymentMethod.bankAccount.bankName || 'Bank';\n return `${bankName} •••• ${paymentMethod.bankAccount.last4}`;\n }\n\n return paymentMethod.type;\n};\n\nexport const calculateTax = (\n amount: number,\n taxRate: number,\n options: {\n inclusive?: boolean;\n roundTo?: number;\n } = {}\n): { subtotal: number; tax: number; total: number } => {\n const { inclusive = false, roundTo = 2 } = options;\n\n let subtotal: number;\n let tax: number;\n let total: number;\n\n if (inclusive) {\n // Tax is included in the amount\n total = amount;\n subtotal = amount / (1 + taxRate / 100);\n tax = amount - subtotal;\n } else {\n // Tax is added to the amount\n subtotal = amount;\n tax = amount * (taxRate / 100);\n total = amount + tax;\n }\n\n // Round to specified decimal places\n const multiplier = Math.pow(10, roundTo);\n return {\n subtotal: Math.round(subtotal * multiplier) / multiplier,\n tax: Math.round(tax * multiplier) / multiplier,\n total: Math.round(total * multiplier) / multiplier,\n };\n};\n\nexport const formatTaxRate = (rate: number): string => {\n return `${rate.toFixed(2)}%`;\n};\n\nexport const formatAmountWithTax = (\n amount: number,\n taxRate: number,\n currency: string = DEFAULT_CURRENCY,\n options: {\n inclusive?: boolean;\n showBreakdown?: boolean;\n locale?: string;\n } = {}\n): string => {\n const {\n inclusive = false,\n showBreakdown = false,\n locale = 'en-US',\n } = options;\n const taxCalculation = calculateTax(amount, taxRate, { inclusive });\n\n if (showBreakdown) {\n const subtotalFormatted = formatCurrency(\n taxCalculation.subtotal,\n currency,\n { locale }\n );\n const taxFormatted = formatCurrency(taxCalculation.tax, currency, {\n locale,\n });\n const totalFormatted = formatCurrency(taxCalculation.total, currency, {\n locale,\n });\n\n return `${subtotalFormatted} + ${taxFormatted} tax = ${totalFormatted}`;\n }\n\n return formatCurrency(taxCalculation.total, currency, { locale });\n};\n","/**\n * Environment validation utilities for SaaS Factory Payments\n */\n\nexport interface EnvironmentConfig {\n stripePublishableKey: string;\n stripeSecretKey?: string;\n stripeWebhookSecret?: string;\n environment: 'development' | 'production';\n appUrl?: string;\n}\n\nexport const validateEnvironment = (\n config: Partial<EnvironmentConfig>\n): {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n} => {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Required fields\n if (!config.stripePublishableKey) {\n errors.push('STRIPE_PUBLISHABLE_KEY is required');\n } else if (!config.stripePublishableKey.startsWith('pk_')) {\n errors.push('STRIPE_PUBLISHABLE_KEY must start with \"pk_\"');\n }\n\n if (!config.environment) {\n errors.push('Environment must be specified (development or production)');\n } else if (!['development', 'production'].includes(config.environment)) {\n errors.push('Environment must be either \"development\" or \"production\"');\n }\n\n // Environment-specific validation\n if (config.environment === 'production') {\n if (config.stripePublishableKey?.includes('test')) {\n warnings.push('Using test keys in production environment');\n }\n\n if (!config.appUrl) {\n warnings.push('APP_URL should be set in production for proper redirects');\n } else if (!config.appUrl.startsWith('https://')) {\n warnings.push('APP_URL should use HTTPS in production');\n }\n }\n\n // Server-side validation\n if (typeof window === 'undefined') {\n if (!config.stripeSecretKey) {\n warnings.push(\n 'STRIPE_SECRET_KEY is recommended for server-side operations'\n );\n } else if (!config.stripeSecretKey.startsWith('sk_')) {\n errors.push('STRIPE_SECRET_KEY must start with \"sk_\"');\n }\n\n if (!config.stripeWebhookSecret) {\n warnings.push(\n 'STRIPE_WEBHOOK_SECRET is recommended for webhook verification'\n );\n } else if (!config.stripeWebhookSecret.startsWith('whsec_')) {\n errors.push('STRIPE_WEBHOOK_SECRET must start with \"whsec_\"');\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n};\n\nexport const getEnvironmentConfig = (): EnvironmentConfig => {\n const isServer = typeof window === 'undefined';\n\n // Client-side configuration\n const config: EnvironmentConfig = {\n stripePublishableKey:\n process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ||\n process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY ||\n '',\n environment:\n (process.env.NODE_ENV as 'development' | 'production') || 'development',\n appUrl: process.env.NEXT_PUBLIC_APP_URL,\n };\n\n // Server-side configuration\n if (isServer) {\n config.stripeSecretKey = process.env.STRIPE_SECRET_KEY;\n config.stripeWebhookSecret = process.env.STRIPE_WEBHOOK_SECRET;\n }\n\n return config;\n};\n\nexport const validateCurrentEnvironment = () => {\n const config = getEnvironmentConfig();\n const validation = validateEnvironment(config);\n\n if (!validation.isValid) {\n console.error('❌ Environment validation failed:');\n validation.errors.forEach(error => console.error(` - ${error}`));\n\n if (typeof window === 'undefined') {\n // Server-side: throw error\n throw new Error(\n `Environment validation failed: ${validation.errors.join(', ')}`\n );\n }\n }\n\n if (validation.warnings.length > 0) {\n console.warn('⚠️ Environment warnings:');\n validation.warnings.forEach(warning => console.warn(` - ${warning}`));\n }\n\n return validation;\n};\n\n// Helper to check if we're in development mode\nexport const isDevelopment = () => {\n return process.env.NODE_ENV === 'development';\n};\n\n// Helper to check if we're in production mode\nexport const isProduction = () => {\n return process.env.NODE_ENV === 'production';\n};\n\n// Helper to check if we're on the server\nexport const isServer = () => {\n return typeof window === 'undefined';\n};\n\n// Helper to check if we're on the client\nexport const isClient = () => {\n return typeof window !== 'undefined';\n};\n","import { PaymentProvider } from '../../shared/types/provider';\nimport { PaymentsConfig } from '../../shared/types/config';\nimport { PaymentsError, PaymentErrorType } from '../../shared/types/errors';\nimport { CheckoutParams, CheckoutSession } from '../../shared/types/checkout';\nimport { Customer, CustomerCreateParams } from '../../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../../shared/types/subscription';\n\nexport abstract class BasePaymentProvider implements PaymentProvider {\n public abstract name: string;\n protected config: PaymentsConfig;\n\n constructor(config: PaymentsConfig) {\n this.config = config;\n }\n\n public abstract initialize(): Promise<void>;\n public abstract createCheckoutSession(\n params: CheckoutParams\n ): Promise<CheckoutSession>;\n public abstract retrieveCheckoutSession(\n sessionId: string\n ): Promise<CheckoutSession>;\n public abstract createCustomer(\n params: CustomerCreateParams\n ): Promise<Customer>;\n public abstract retrieveCustomer(\n customerId: string\n ): Promise<Customer | null>;\n public abstract createSubscription(\n params: SubscriptionCreateParams\n ): Promise<Subscription>;\n public abstract cancelSubscription(subscriptionId: string): Promise<void>;\n public abstract reactivateSubscription(subscriptionId: string): Promise<void>;\n public abstract listSubscriptions(\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]>;\n public abstract retrieveSubscription(\n subscriptionId: string\n ): Promise<Subscription | null>;\n public abstract updateSubscription(\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ): Promise<Subscription>;\n\n protected handleError(\n error: unknown,\n type: PaymentErrorType = PaymentErrorType.UNKNOWN_ERROR\n ): PaymentsError {\n if (error instanceof PaymentsError) {\n return error;\n }\n\n let message = 'An unknown error occurred';\n let code: string | undefined;\n let details: Record<string, unknown> | undefined;\n\n if (typeof error === 'object' && error !== null) {\n if (\n 'message' in error &&\n typeof (error as { message: unknown }).message === 'string'\n ) {\n message = (error as { message: string }).message;\n }\n if (\n 'code' in error &&\n typeof (error as { code: unknown }).code === 'string'\n ) {\n code = (error as { code: string }).code;\n }\n details = { ...(error as Record<string, unknown>) };\n }\n\n return new PaymentsError(type, message, code, details);\n }\n}\n","import { BasePaymentProvider } from '../base';\nimport { PaymentsConfig } from '../../shared/types/config';\nimport { CheckoutParams, CheckoutSession } from '../../shared/types/checkout';\nimport { Customer, CustomerCreateParams } from '../../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../../shared/types/subscription';\nimport { PaymentsError, PaymentErrorType } from '../../shared/types/errors';\nimport Stripe from 'stripe';\n\nexport class StripePaymentProvider extends BasePaymentProvider {\n public name = 'stripe';\n private stripeClient: Stripe;\n\n constructor(config: PaymentsConfig) {\n super(config);\n if (!config.stripeConfig?.publishableKey) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Stripe publishable key is missing in config.'\n );\n }\n if (!process.env.STRIPE_SECRET_KEY) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'STRIPE_SECRET_KEY environment variable is not set.'\n );\n }\n this.stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY, {\n apiVersion: '2024-06-20',\n });\n }\n\n public async initialize(): Promise<void> {\n // No specific client-side initialization needed for server-side Stripe operations\n\n console.log('StripePaymentProvider initialized (server-side)');\n }\n\n public async createCheckoutSession(\n params: CheckoutParams\n ): Promise<CheckoutSession> {\n try {\n const session = await this.stripeClient.checkout.sessions.create({\n payment_method_types: ['card'],\n line_items: [\n {\n price: params.priceId,\n quantity: 1,\n },\n ],\n mode: params.mode || 'payment',\n success_url:\n params.successUrl ||\n `${process.env.NEXT_PUBLIC_BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,\n cancel_url:\n params.cancelUrl || `${process.env.NEXT_PUBLIC_BASE_URL}/cancel`,\n customer_email: params.customerEmail,\n allow_promotion_codes: params.allowPromotionCodes,\n metadata: params.metadata,\n });\n\n if (!session.url) {\n throw new PaymentsError(\n PaymentErrorType.UNKNOWN_ERROR,\n 'Stripe checkout session URL is missing.'\n );\n }\n\n return {\n id: session.id,\n url: session.url,\n status: session.status as CheckoutSession['status'],\n amountTotal: session.amount_total || undefined,\n currency: session.currency || undefined,\n customerEmail: session.customer_details?.email || undefined,\n subscriptionId: session.subscription?.toString() || undefined,\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async createCustomer(params: CustomerCreateParams): Promise<Customer> {\n try {\n const customer = await this.stripeClient.customers.create({\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n return {\n id: customer.id,\n email: customer.email || params.email,\n name: customer.name || params.name,\n phone: null, // Stripe API does not directly return phone for customer creation\n stripeCustomerId: customer.id,\n subscriptions: [], // Subscriptions are fetched separately\n paymentMethods: [], // Payment methods are fetched separately\n defaultPaymentMethodId: null, // Default payment method is set separately\n metadata: customer.metadata,\n created: new Date(customer.created * 1000),\n updated: new Date(customer.created * 1000), // Stripe customer object doesn't have an 'updated' timestamp directly\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async retrieveCustomer(customerId: string): Promise<Customer | null> {\n try {\n const customer = await this.stripeClient.customers.retrieve(customerId);\n if (customer.deleted) {\n return null;\n }\n return {\n id: customer.id,\n email: customer.email || '',\n name: customer.name || undefined,\n phone: customer.phone || undefined,\n stripeCustomerId: customer.id,\n subscriptions: [], // Subscriptions are fetched separately\n paymentMethods: [], // Payment methods are fetched separately\n defaultPaymentMethodId:\n customer.invoice_settings?.default_payment_method?.toString() ||\n undefined,\n metadata: customer.metadata,\n created: new Date(customer.created * 1000),\n updated: new Date(customer.created * 1000), // Stripe customer object doesn't have an 'updated' timestamp directly\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async createSubscription(\n params: SubscriptionCreateParams\n ): Promise<Subscription> {\n try {\n const subscription = await this.stripeClient.subscriptions.create({\n customer: params.customerId,\n items: (\n params.items ||\n (params.priceId ? [{ priceId: params.priceId, quantity: 1 }] : [])\n ).map((item: { priceId: string; quantity?: number }) => ({\n price: item.priceId,\n quantity: item.quantity || 1,\n })),\n trial_period_days: params.trialPeriodDays,\n metadata: params.metadata,\n expand: ['latest_invoice.payment_intent'],\n });\n\n return this.mapStripeSubscriptionToSubscription(subscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async cancelSubscription(subscriptionId: string): Promise<void> {\n try {\n await this.stripeClient.subscriptions.cancel(subscriptionId);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async reactivateSubscription(subscriptionId: string): Promise<void> {\n try {\n const subscription =\n await this.stripeClient.subscriptions.retrieve(subscriptionId);\n if (\n subscription.status === SubscriptionStatus.CANCELED &&\n subscription.cancel_at_period_end\n ) {\n await this.stripeClient.subscriptions.update(subscriptionId, {\n cancel_at_period_end: false,\n });\n } else {\n throw new PaymentsError(\n PaymentErrorType.VALIDATION_ERROR,\n 'Subscription cannot be reactivated.'\n );\n }\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async retrieveCheckoutSession(\n sessionId: string\n ): Promise<CheckoutSession> {\n try {\n const session =\n await this.stripeClient.checkout.sessions.retrieve(sessionId);\n if (!session.url) {\n throw new PaymentsError(\n PaymentErrorType.UNKNOWN_ERROR,\n 'Stripe checkout session URL is missing.'\n );\n }\n return {\n id: session.id,\n url: session.url,\n status: session.status as CheckoutSession['status'],\n amountTotal: session.amount_total || undefined,\n currency: session.currency || undefined,\n customerEmail: session.customer_details?.email || undefined,\n subscriptionId: session.subscription?.toString() || undefined,\n };\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async listSubscriptions(\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]> {\n try {\n const subscriptions = await this.stripeClient.subscriptions.list({\n customer: customerId,\n status: status === SubscriptionStatus.ALL ? undefined : status,\n });\n return subscriptions.data.map(this.mapStripeSubscriptionToSubscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async retrieveSubscription(\n subscriptionId: string\n ): Promise<Subscription | null> {\n try {\n const subscription =\n await this.stripeClient.subscriptions.retrieve(subscriptionId);\n return this.mapStripeSubscriptionToSubscription(subscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n public async updateSubscription(\n subscriptionId: string,\n params: Partial<SubscriptionUpdateParams>\n ): Promise<Subscription> {\n try {\n const currentSubscription =\n await this.stripeClient.subscriptions.retrieve(subscriptionId);\n const items = params.items\n ? params.items.map((item: { priceId: string; quantity?: number }) => ({\n id: currentSubscription.items.data.find(\n i => i.price?.id === item.priceId\n )?.id,\n price: item.priceId,\n quantity: item.quantity || 1,\n }))\n : undefined;\n\n const subscription = await this.stripeClient.subscriptions.update(\n subscriptionId,\n {\n items,\n metadata: params.metadata,\n }\n );\n return this.mapStripeSubscriptionToSubscription(subscription);\n } catch (error: unknown) {\n throw this.handleError(error, PaymentErrorType.NETWORK_ERROR);\n }\n }\n\n private mapStripeSubscriptionToSubscription(\n stripeSubscription: Stripe.Subscription\n ): Subscription {\n return {\n id: stripeSubscription.id,\n customerId: stripeSubscription.customer.toString(),\n status: stripeSubscription.status as SubscriptionStatus,\n items: stripeSubscription.items.data.map(item => ({\n id: item.id,\n priceId: item.price?.id || '',\n quantity: item.quantity || 1,\n })),\n currentPeriodStart: new Date(\n stripeSubscription.current_period_start * 1000\n ),\n currentPeriodEnd: new Date(stripeSubscription.current_period_end * 1000),\n cancelAtPeriodEnd: stripeSubscription.cancel_at_period_end,\n trialStart: stripeSubscription.trial_start\n ? new Date(stripeSubscription.trial_start * 1000)\n : undefined,\n trialEnd: stripeSubscription.trial_end\n ? new Date(stripeSubscription.trial_end * 1000)\n : undefined,\n metadata: stripeSubscription.metadata,\n created: new Date(stripeSubscription.created * 1000),\n updated: new Date(stripeSubscription.created * 1000), // Stripe subscription object doesn't have an 'updated' timestamp directly\n };\n }\n}\n","import { CheckoutParams, CheckoutSession } from '../../shared/types/checkout';\nimport {\n Customer,\n CustomerCreateParams,\n PaymentMethod,\n} from '../../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../../shared/types/subscription';\nimport { PaymentProvider } from '../../shared/types/provider';\nimport { PaymentsError, PaymentErrorType } from '../../shared/types/errors';\nimport { PaymentsConfig } from '../../shared/types/config';\nimport { BasePaymentProvider } from '../base';\n\n/**\n * A mock payment provider for testing and development purposes.\n * It simulates payment operations without actual API calls.\n */\nexport class MockPaymentProvider\n extends BasePaymentProvider\n implements PaymentProvider\n{\n name = 'MockPaymentProvider';\n private customers: Customer[] = [];\n private subscriptions: Subscription[] = [];\n private nextCustomerId = 1;\n private nextSubscriptionId = 1;\n\n constructor(config: Omit<PaymentsConfig, 'provider'>) {\n super({ ...config, provider: 'mock' });\n\n console.log('MockPaymentProvider initialized');\n }\n\n async initialize(): Promise<void> {\n console.log('MockPaymentProvider initialized');\n }\n\n async createCheckoutSession(\n params: CheckoutParams\n ): Promise<CheckoutSession> {\n console.log('Mock: createCheckoutSession', params);\n return {\n id: 'mock_cs_123',\n clientSecret: 'mock_client_secret',\n url: 'https://mock-checkout.example.com/success', // Changed from redirectUrl to url\n status: 'open', // Changed from 'pending' to 'open'\n };\n }\n\n async retrieveCheckoutSession(id: string): Promise<CheckoutSession> {\n console.log('Mock: retrieveCheckoutSession', id);\n if (id === 'mock_cs_123') {\n return {\n id: 'mock_cs_123',\n clientSecret: 'mock_client_secret',\n url: 'https://mock-checkout.example.com/success', // Changed from redirectUrl to url\n status: 'complete',\n };\n }\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock checkout session ${id} not found`\n );\n }\n\n async createCustomer(params: CustomerCreateParams): Promise<Customer> {\n console.log('Mock: createCustomer', params);\n const newCustomer: Customer = {\n id: `mock_cus_${this.nextCustomerId++}`,\n email: params.email,\n name: params.name || null,\n phone: params.phone || null,\n stripeCustomerId: null,\n subscriptions: [],\n defaultPaymentMethodId: null,\n paymentMethods: [], // Added paymentMethods\n metadata: params.metadata || {},\n created: new Date(),\n updated: new Date(),\n };\n this.customers.push(newCustomer);\n return newCustomer;\n }\n\n async retrieveCustomer(id: string): Promise<Customer> {\n console.log('Mock: retrieveCustomer', id);\n const customer = this.customers.find(c => c.id === id);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${id} not found`\n );\n }\n return customer;\n }\n\n async updateCustomer(\n id: string,\n params: CustomerCreateParams\n ): Promise<Customer> {\n console.log('Mock: updateCustomer', id, params);\n const customer = this.customers.find(c => c.id === id);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${id} not found`\n );\n }\n if (params.email) customer.email = params.email;\n if (params.name) customer.name = params.name;\n if (params.phone) customer.phone = params.phone;\n if (params.metadata)\n customer.metadata = { ...customer.metadata, ...params.metadata };\n customer.updated = new Date();\n return customer;\n }\n\n async deleteCustomer(id: string): Promise<void> {\n console.log('Mock: deleteCustomer', id);\n const initialLength = this.customers.length;\n this.customers = this.customers.filter(c => c.id !== id);\n if (this.customers.length === initialLength) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${id} not found`\n );\n }\n }\n\n async listPaymentMethods(customerId: string): Promise<PaymentMethod[]> {\n console.log('Mock: listPaymentMethods', customerId);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n return customer.paymentMethods || [];\n }\n\n async attachPaymentMethod(\n customerId: string,\n paymentMethodId: string\n ): Promise<PaymentMethod> {\n console.log('Mock: attachPaymentMethod', customerId, paymentMethodId);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n const newPaymentMethod: PaymentMethod = {\n id: paymentMethodId,\n type: 'card',\n card: {\n brand: 'visa',\n last4: '4242',\n expMonth: 12,\n expYear: 2025,\n country: 'US',\n },\n isDefault: false,\n created: new Date(),\n };\n customer.paymentMethods.push(newPaymentMethod);\n return newPaymentMethod;\n }\n\n async detachPaymentMethod(\n customerId: string,\n paymentMethodId: string\n ): Promise<void> {\n console.log('Mock: detachPaymentMethod', customerId, paymentMethodId);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n const initialLength = customer.paymentMethods.length;\n customer.paymentMethods = customer.paymentMethods.filter(\n (pm: PaymentMethod) => pm.id !== paymentMethodId\n );\n if (customer.paymentMethods.length === initialLength) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock payment method ${paymentMethodId} not found for customer ${customerId}`\n );\n }\n }\n\n async createSubscription(\n params: SubscriptionCreateParams\n ): Promise<Subscription> {\n console.log('Mock: createSubscription', params);\n const customer = this.customers.find(c => c.id === params.customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${params.customerId} not found`\n );\n }\n const newSubscription: Subscription = {\n id: `mock_sub_${this.nextSubscriptionId++}`,\n customerId: params.customerId,\n status: SubscriptionStatus.ACTIVE,\n items: (\n params.items ||\n (params.priceId ? [{ priceId: params.priceId, quantity: 1 }] : [])\n ).map((item: { priceId: string; quantity?: number }) => ({\n id: `mock_sub_item_${Math.random().toString(36).substring(7)}`,\n priceId: item.priceId,\n quantity: item.quantity || 1,\n })),\n currentPeriodStart: new Date(),\n currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days from now\n cancelAtPeriodEnd: false,\n created: new Date(),\n updated: new Date(),\n };\n this.subscriptions.push(newSubscription);\n customer.subscriptions.push(newSubscription);\n return newSubscription;\n }\n\n async retrieveSubscription(id: string): Promise<Subscription> {\n console.log('Mock: retrieveSubscription', id);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n return subscription;\n }\n\n async updateSubscription(\n id: string,\n params: SubscriptionUpdateParams\n ): Promise<Subscription> {\n console.log('Mock: updateSubscription', id, params);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n if (params.cancelAtPeriodEnd !== undefined) {\n subscription.cancelAtPeriodEnd = params.cancelAtPeriodEnd;\n subscription.status = params.cancelAtPeriodEnd\n ? SubscriptionStatus.CANCELED\n : SubscriptionStatus.ACTIVE;\n }\n if (params.items) {\n subscription.items = params.items.map(\n (item: { priceId: string; quantity?: number }) => ({\n id: `mock_sub_item_${Math.random().toString(36).substring(7)}`,\n priceId: item.priceId,\n quantity: item.quantity || 1,\n })\n );\n }\n subscription.updated = new Date();\n return subscription;\n }\n\n async cancelSubscription(id: string): Promise<void> {\n console.log('Mock: cancelSubscription', id);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n subscription.status = SubscriptionStatus.CANCELED;\n subscription.cancelAtPeriodEnd = true;\n subscription.updated = new Date();\n }\n\n async reactivateSubscription(id: string): Promise<void> {\n console.log('Mock: reactivateSubscription', id);\n const subscription = this.subscriptions.find(s => s.id === id);\n if (!subscription) {\n throw new PaymentsError(\n PaymentErrorType.SUBSCRIPTION_NOT_FOUND,\n `Mock subscription ${id} not found`\n );\n }\n subscription.status = SubscriptionStatus.ACTIVE;\n subscription.cancelAtPeriodEnd = false;\n subscription.updated = new Date();\n }\n\n async listSubscriptions(\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]> {\n console.log('Mock: listSubscriptions', customerId, status);\n const customer = this.customers.find(c => c.id === customerId);\n if (!customer) {\n throw new PaymentsError(\n PaymentErrorType.CUSTOMER_NOT_FOUND,\n `Mock customer ${customerId} not found`\n );\n }\n let subs = customer.subscriptions;\n if (status && status !== SubscriptionStatus.ALL) {\n subs = subs.filter(s => s.status === status);\n }\n return subs;\n }\n}\n","import { PaymentsConfig, PaymentProviderType } from '../shared/types/config';\nimport { PaymentsError, PaymentErrorType } from '../shared/types/errors';\nimport { PaymentProvider } from '../shared/types/provider';\nimport { StripePaymentProvider } from './stripe';\n// import { PayPalPaymentProvider } from './paypal';\n// import { ApplePayPaymentProvider } from './applepay';\nimport { MockPaymentProvider } from './mock';\n\nexport class PaymentProviderFactory {\n public static create(config: PaymentsConfig): PaymentProvider {\n switch (config.provider) {\n case 'stripe':\n return new StripePaymentProvider(config);\n case 'paypal':\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n 'PayPal provider is not yet available in this build'\n );\n case 'applepay':\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n 'Apple Pay provider is not yet available in this build'\n );\n case 'mock':\n return new MockPaymentProvider(config);\n default:\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n `Unsupported payment provider: ${config.provider}`\n );\n }\n }\n\n public static autodetect(): PaymentsConfig {\n // Check for Stripe configuration first (most common)\n if (\n process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY &&\n process.env.STRIPE_SECRET_KEY\n ) {\n return {\n provider: 'stripe',\n publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'development',\n stripeConfig: {\n publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,\n },\n };\n }\n\n // Check for PayPal configuration\n if (\n process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID &&\n process.env.PAYPAL_CLIENT_SECRET\n ) {\n return {\n provider: 'paypal',\n publishableKey: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'development',\n paypalConfig: {\n clientId: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,\n clientSecret: process.env.PAYPAL_CLIENT_SECRET,\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',\n currency: process.env.PAYPAL_CURRENCY || 'USD',\n },\n };\n }\n\n // Check for Apple Pay configuration\n if (\n process.env.NEXT_PUBLIC_APPLE_PAY_MERCHANT_ID &&\n typeof window !== 'undefined' &&\n window.ApplePaySession\n ) {\n return {\n provider: 'applepay',\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'development',\n applePayConfig: {\n merchantId: process.env.NEXT_PUBLIC_APPLE_PAY_MERCHANT_ID,\n merchantName:\n process.env.NEXT_PUBLIC_APPLE_PAY_MERCHANT_NAME || 'Your Store',\n countryCode: process.env.NEXT_PUBLIC_APPLE_PAY_COUNTRY_CODE || 'US',\n currencyCode:\n process.env.NEXT_PUBLIC_APPLE_PAY_CURRENCY_CODE || 'USD',\n environment:\n process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',\n },\n };\n }\n\n // For development/testing, allow mock provider if no other is detected\n if (\n process.env.NODE_ENV !== 'production' ||\n process.env.VERCEL_ENV === 'preview'\n ) {\n console.warn(\n 'No payment provider detected, defaulting to MockPaymentProvider for development/preview environment.'\n );\n return {\n provider: 'mock',\n environment: 'development',\n };\n }\n\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Could not auto-detect payment provider. Please provide explicit configuration.'\n );\n }\n\n // Helper method to get all available providers based on environment\n public static getAvailableProviders(): PaymentProviderType[] {\n const providers: PaymentProviderType[] = [];\n\n // Check Stripe\n if (process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY) {\n providers.push('stripe');\n }\n\n // Check PayPal\n if (process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID) {\n providers.push('paypal');\n }\n\n // Check Apple Pay (client-side only)\n if (\n typeof window !== 'undefined' &&\n window.ApplePaySession?.canMakePayments()\n ) {\n providers.push('applepay');\n }\n\n // Always include mock for development\n if (process.env.NODE_ENV !== 'production') {\n providers.push('mock');\n }\n\n return providers;\n }\n\n // Method to create multiple providers for fallback scenarios\n public static createMultiple(configs: PaymentsConfig[]): PaymentProvider[] {\n return configs.map(config => this.create(config));\n }\n}\n","import React, { useEffect, createContext, useContext, useRef } from 'react';\nimport { usePayments } from '../../hooks/usePayments';\nimport { PaymentsConfig } from '../types/config';\nimport { PaymentEvent } from '../types/events';\nimport { PaymentError } from '../types/errors';\n\nimport { Customer, CustomerCreateParams } from '../types/customer';\nimport {\n Subscription,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../types/subscription';\nimport { CheckoutParams, CheckoutSession } from '../types/checkout';\n\ninterface PaymentsContextType {\n config: PaymentsConfig | null;\n initialized: boolean;\n loading: boolean;\n error: PaymentError | null;\n customer: Customer | null;\n subscriptions: Subscription[];\n activeSubscription: Subscription | null;\n createCustomer: (params: CustomerCreateParams) => Promise<Customer>;\n createCheckoutSession: (params: CheckoutParams) => Promise<CheckoutSession>;\n cancelSubscription: (subscriptionId: string) => Promise<void>;\n reactivateSubscription: (subscriptionId: string) => Promise<void>;\n updateSubscription: (\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ) => Promise<Subscription>;\n refreshCustomer: (customerId: string) => Promise<void>;\n refreshSubscriptions: (\n customerId: string,\n status?: SubscriptionStatus\n ) => Promise<void>;\n reset: () => void;\n}\n\nconst PaymentsContext = createContext<PaymentsContextType | undefined>(\n undefined\n);\n\ninterface PaymentsProviderProps {\n children: React.ReactNode;\n config?: PaymentsConfig;\n onPaymentSuccess?: (event: PaymentEvent) => void;\n onPaymentError?: (error: PaymentError) => void;\n}\n\nexport const PaymentsProvider: React.FC<PaymentsProviderProps> = ({\n children,\n config,\n onPaymentSuccess,\n onPaymentError,\n}) => {\n const store = usePayments();\n const {\n initialize,\n initialized,\n loading,\n error,\n customer,\n subscriptions,\n activeSubscription,\n } = store;\n\n const onPaymentSuccessRef = useRef(onPaymentSuccess);\n const onPaymentErrorRef = useRef(onPaymentError);\n\n useEffect(() => {\n onPaymentSuccessRef.current = onPaymentSuccess;\n }, [onPaymentSuccess]);\n\n useEffect(() => {\n onPaymentErrorRef.current = onPaymentError;\n }, [onPaymentError]);\n\n useEffect(() => {\n if (!initialized && !loading && !error) {\n initialize(config).catch(err => {\n console.error('PaymentsProvider initialization failed:', err);\n if (onPaymentErrorRef.current) {\n onPaymentErrorRef.current(err);\n }\n });\n }\n }, [initialized, loading, error, config, initialize]);\n\n const contextValue: PaymentsContextType = {\n config: store.config,\n initialized,\n loading,\n error,\n customer,\n subscriptions,\n activeSubscription,\n createCustomer: store.createCustomer,\n createCheckoutSession: store.createCheckoutSession,\n cancelSubscription: store.cancelSubscription,\n reactivateSubscription: store.reactivateSubscription,\n updateSubscription: store.updateSubscription,\n refreshCustomer: store.refreshCustomer,\n refreshSubscriptions: store.refreshSubscriptions,\n reset: store.reset,\n };\n\n return (\n <PaymentsContext.Provider value={contextValue}>\n {children}\n </PaymentsContext.Provider>\n );\n};\n\nexport const usePaymentsContext = () => {\n const context = useContext(PaymentsContext);\n if (context === undefined) {\n throw new Error(\n 'usePaymentsContext must be used within a PaymentsProvider'\n );\n }\n return context;\n};\n","import { create } from 'zustand';\nimport { immer } from 'zustand/middleware/immer';\nimport { PaymentsStore, PaymentsProviderState } from '../shared/types/provider';\nimport { PaymentsConfig } from '../shared/types/config';\nimport { PaymentErrorType, PaymentsError } from '../shared/types/errors';\nimport { Customer, CustomerCreateParams } from '../shared/types/customer';\nimport {\n Subscription,\n SubscriptionCreateParams,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n} from '../shared/types/subscription';\nimport { CheckoutParams, CheckoutSession } from '../shared/types/checkout';\nimport { PaymentProviderFactory } from '../providers';\nimport { PaymentProvider } from '../shared/types/provider';\n\nconst initialState: PaymentsProviderState = {\n customer: null,\n subscriptions: [],\n activeSubscription: null,\n loading: false,\n error: null,\n initialized: false,\n config: null, // Add config to the state\n // Backward compatibility getters (will be computed)\n isLoading: false,\n isError: false,\n};\n\nexport const usePayments = create<PaymentsStore>()(\n immer((set, get) => ({\n ...initialState,\n\n // Override getters to always return computed values\n get isLoading() {\n return get().loading;\n },\n get isError() {\n return !!get().error;\n },\n\n initialize: async (config?: PaymentsConfig) => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n let resolvedConfig: PaymentsConfig;\n if (config) {\n resolvedConfig = config;\n } else {\n resolvedConfig = PaymentProviderFactory.autodetect();\n }\n\n const provider: PaymentProvider =\n PaymentProviderFactory.create(resolvedConfig);\n await provider.initialize();\n\n set((state: PaymentsProviderState) => {\n state.initialized = true;\n state.loading = false;\n state.config = resolvedConfig; // Store the resolved config in the state\n });\n } catch (error: unknown) {\n set(state => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to initialize payments provider.';\n state.error = new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n createCustomer: async (params: CustomerCreateParams): Promise<Customer> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const customer = await provider.createCustomer(params);\n set((state: PaymentsProviderState) => {\n state.customer = customer;\n state.loading = false;\n });\n return customer;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to create customer.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n retrieveCustomer: async (customerId: string): Promise<Customer | null> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const customer = await provider.retrieveCustomer(customerId);\n set((state: PaymentsProviderState) => {\n state.customer = customer;\n state.loading = false;\n });\n return customer;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to retrieve customer.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n createCheckoutSession: async (\n params: CheckoutParams\n ): Promise<CheckoutSession> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const session = await provider.createCheckoutSession(params);\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return session;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to create checkout session.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n retrieveCheckoutSession: async (\n sessionId: string\n ): Promise<CheckoutSession> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const session = await provider.retrieveCheckoutSession(sessionId);\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return session;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to retrieve checkout session.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n createSubscription: async (\n params: SubscriptionCreateParams\n ): Promise<Subscription> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const newSubscription = await provider.createSubscription(params);\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return newSubscription;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to create subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n cancelSubscription: async (subscriptionId: string): Promise<void> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n await provider.cancelSubscription(subscriptionId);\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to cancel subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n reactivateSubscription: async (subscriptionId: string): Promise<void> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n await provider.reactivateSubscription(subscriptionId);\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to reactivate subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n updateSubscription: async (\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ): Promise<Subscription> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const updatedSubscription = await provider.updateSubscription(\n subscriptionId,\n params\n );\n await get().refreshSubscriptions(get().customer?.id || '');\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return updatedSubscription;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to update subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n listSubscriptions: async (\n customerId: string,\n status?: SubscriptionStatus\n ): Promise<Subscription[]> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const subscriptions = await provider.listSubscriptions(\n customerId,\n status\n );\n set((state: PaymentsProviderState) => {\n state.subscriptions = subscriptions;\n state.loading = false;\n });\n return subscriptions;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to list subscriptions.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n retrieveSubscription: async (\n subscriptionId: string\n ): Promise<Subscription | null> => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const subscription =\n await provider.retrieveSubscription(subscriptionId);\n set((state: PaymentsProviderState) => {\n state.loading = false;\n });\n return subscription;\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to retrieve subscription.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n throw error;\n }\n },\n\n refreshCustomer: async (customerId: string) => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const customer = await provider.retrieveCustomer(customerId);\n set((state: PaymentsProviderState) => {\n state.customer = customer;\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to refresh customer.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n }\n },\n\n refreshSubscriptions: async (\n customerId: string,\n status?: SubscriptionStatus\n ) => {\n set((state: PaymentsProviderState) => {\n state.loading = true;\n state.error = null;\n });\n try {\n if (!get().config) {\n throw new PaymentsError(\n PaymentErrorType.CONFIGURATION_ERROR,\n 'Payments provider not initialized. Call initialize() first.'\n );\n }\n const provider = PaymentProviderFactory.create(\n get().config as PaymentsConfig\n );\n const subscriptions = await provider.listSubscriptions(\n customerId,\n status\n );\n const activeSubscription =\n subscriptions.find(\n (sub: Subscription) =>\n sub.status === SubscriptionStatus.ACTIVE ||\n sub.status === SubscriptionStatus.TRIALING\n ) || null;\n set((state: PaymentsProviderState) => {\n state.subscriptions = subscriptions;\n state.activeSubscription = activeSubscription;\n state.loading = false;\n });\n } catch (error: unknown) {\n set((state: PaymentsProviderState) => {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to refresh subscriptions.';\n state.error = new PaymentsError(\n PaymentErrorType.NETWORK_ERROR,\n message\n );\n state.loading = false;\n });\n }\n },\n\n reset: () => {\n set((state: PaymentsProviderState) => {\n Object.assign(state, initialState);\n });\n },\n }))\n);\n","import { useState, useEffect, useCallback } from 'react';\nimport {\n Customer,\n CustomerCreateParams,\n Subscription,\n SubscriptionUpdateParams,\n SubscriptionStatus,\n CheckoutParams,\n CheckoutSession,\n} from '../types';\nimport { PaymentsConfig } from '../types/config';\nimport { PaymentProviderFactory } from '../../providers';\nimport { PaymentsError, PaymentErrorType } from '../types/errors';\nimport { ERROR_MESSAGES } from '../constants';\nimport { PaymentProvider } from '../types/provider';\n\ninterface UsePaymentsStore {\n config: PaymentsConfig | null;\n provider: PaymentProvider | null;\n initialized: boolean;\n loading: boolean;\n error: PaymentsError | null;\n // Backward compatibility getters\n isLoading: boolean; // Maps to loading\n isError: boolean; // Maps to !!error\n customer: Customer | null;\n subscriptions: Subscription[];\n activeSubscription: Subscription | null;\n initialize: (config?: PaymentsConfig) => Promise<void>;\n createCustomer: (params: CustomerCreateParams) => Promise<Customer>;\n retrieveCustomer: (customerId: string) => Promise<Customer | null>;\n createCheckoutSession: (params: CheckoutParams) => Promise<CheckoutSession>;\n retrieveCheckoutSession: (sessionId: string) => Promise<CheckoutSession>;\n createSubscription: (params: {\n priceId: string;\n quantity?: number;\n }) => Promise<Subscription>;\n cancelSubscription: (subscriptionId: string) => Promise<void>;\n reactivateSubscription: (subscriptionId: string) => Promise<void>;\n listSubscriptions: (\n customerId: string,\n status?: SubscriptionStatus\n ) => Promise<Subscription[]>;\n retrieveSubscription: (\n subscriptionId: string\n ) => Promise<Subscription | null>;\n updateSubscription: (\n subscriptionId: string,\n params: SubscriptionUpdateParams\n ) => Promise<Subscription>;\n refreshCustomer: (customerId: string) => Promise<void>;\n refreshSubscriptions: (\n customerId: string,\n status?: SubscriptionStatus\n ) => Promise<void>;\n reset: () => void;\n}\n\nexport const usePayments = (): UsePaymentsStore => {\n const [config, setConfig] = useState<PaymentsConfig | null>(null);\n const [provider, setProvider] = useState<PaymentProvider | null>(null);\n const [initialized, setInitialized] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<PaymentsError | null>(null);\n const [customer, setCustomer] = useState<Customer | null>(null);\n const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);\n\n const handleError = useCallback((err: PaymentsError) => {\n setError(err);\n console.error('Payments error:', err);\n }, []);\n\n const refreshSubscriptions = useCallback(\n async (customerId: string, status?: SubscriptionStatus) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const fetchedSubscriptions = await provider.listSubscriptions(\n customerId,\n status\n );\n setSubscriptions(fetchedSubscriptions);\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const initialize = useCallback(\n async (initialConfig?: PaymentsConfig) => {\n setLoading(true);\n setError(null);\n try {\n const resolvedConfig =\n initialConfig || PaymentProviderFactory.autodetect();\n const newProvider = PaymentProviderFactory.create(resolvedConfig);\n setConfig(resolvedConfig);\n setProvider(newProvider);\n setInitialized(true);\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n } finally {\n setLoading(false);\n }\n },\n [handleError]\n );\n\n const retrieveCustomer = useCallback(\n async (customerId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const newCustomer = await provider.retrieveCustomer(customerId);\n setCustomer(newCustomer);\n return newCustomer;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const createCustomer = useCallback(\n async (params: CustomerCreateParams) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const newCustomer = await provider.createCustomer(params);\n setCustomer(newCustomer);\n return newCustomer;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const createSubscription = useCallback(\n async (params: { priceId: string; quantity?: number }) => {\n if (!provider || !customer) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const newSubscription = await provider.createSubscription({\n customerId: customer.id,\n items: [{ priceId: params.priceId, quantity: params.quantity }],\n });\n await refreshSubscriptions(customer.id);\n return newSubscription;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const listSubscriptions = useCallback(\n async (customerId: string, status?: SubscriptionStatus) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const subs = await provider.listSubscriptions(customerId, status);\n setSubscriptions(subs);\n return subs;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const retrieveSubscription = useCallback(\n async (subscriptionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const sub = await provider.retrieveSubscription(subscriptionId);\n // Optionally refresh the list of subscriptions\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n return sub;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const createCheckoutSession = useCallback(\n async (params: CheckoutParams) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const session = await provider.createCheckoutSession(params);\n return session;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const retrieveCheckoutSession = useCallback(\n async (sessionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const session = await provider.retrieveCheckoutSession(sessionId);\n return session;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const cancelSubscription = useCallback(\n async (subscriptionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n await provider.cancelSubscription(subscriptionId);\n // Refresh subscriptions after cancellation\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const reactivateSubscription = useCallback(\n async (subscriptionId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n await provider.reactivateSubscription(subscriptionId);\n // Refresh subscriptions after reactivation\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const updateSubscription = useCallback(\n async (subscriptionId: string, params: SubscriptionUpdateParams) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const updatedSubscription = await provider.updateSubscription(\n subscriptionId,\n params\n );\n // Refresh subscriptions after update\n if (customer?.id) {\n await refreshSubscriptions(customer.id);\n }\n return updatedSubscription;\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, customer, handleError, refreshSubscriptions]\n );\n\n const refreshCustomer = useCallback(\n async (customerId: string) => {\n if (!provider) {\n throw new PaymentsError(\n PaymentErrorType.PROVIDER_NOT_CONFIGURED,\n ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED\n );\n }\n setLoading(true);\n setError(null);\n try {\n const fetchedCustomer = await provider.retrieveCustomer(customerId);\n setCustomer(fetchedCustomer);\n } catch (err: unknown) {\n handleError(err as PaymentsError);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [provider, handleError]\n );\n\n const reset = useCallback(() => {\n setConfig(null);\n setProvider(null);\n setInitialized(false);\n setLoading(false);\n setError(null);\n setCustomer(null);\n setSubscriptions([]);\n }, []);\n\n const activeSubscription =\n subscriptions.find(s => s.status === 'active' || s.status === 'trialing') ||\n null;\n\n // Initial fetch for customer and subscriptions if a customerId is provided\n useEffect(() => {\n // This useEffect should be triggered by the PaymentsProvider, not directly here\n // The PaymentsProvider will call `initialize` with the config.\n // If a customer ID is available in the config or passed to initialize,\n // then refreshCustomer and refreshSubscriptions can be called.\n // For now, removing the auto-fetch logic from here to avoid circular dependencies\n // and to align with the PaymentsProvider's role in initialization.\n }, []);\n\n return {\n config,\n provider,\n initialized,\n loading,\n error,\n // Backward compatibility getters\n isLoading: loading,\n isError: !!error,\n customer,\n subscriptions,\n activeSubscription,\n initialize,\n createCustomer,\n retrieveCustomer,\n createCheckoutSession,\n retrieveCheckoutSession,\n createSubscription,\n cancelSubscription,\n reactivateSubscription,\n listSubscriptions,\n retrieveSubscription,\n updateSubscription,\n refreshCustomer,\n refreshSubscriptions,\n reset,\n };\n};\n","import React, { useState } from 'react';\nimport { useStripe } from '@stripe/react-stripe-js';\nimport { usePaymentsContext } from '../../shared/providers/PaymentsProvider';\nimport { ERROR_MESSAGES } from '../../shared/constants';\nimport { validateStripeId } from '../../shared/utils/validation';\n\ninterface CheckoutButtonProps {\n priceId: string;\n customerId?: string;\n customerEmail?: string;\n successUrl?: string;\n cancelUrl?: string;\n children: React.ReactNode;\n className?: string;\n disabled?: boolean;\n allowPromotionCodes?: boolean;\n billingAddressCollection?: 'auto' | 'required';\n metadata?: Record<string, string>;\n trialPeriodDays?: number;\n onSuccess?: () => void;\n onError?: (error: string) => void;\n onLoading?: (loading: boolean) => void;\n}\n\nexport const CheckoutButton: React.FC<CheckoutButtonProps> = ({\n priceId,\n customerId,\n customerEmail,\n successUrl = typeof window !== 'undefined'\n ? `${window.location.origin}/success`\n : '/success',\n cancelUrl = typeof window !== 'undefined'\n ? `${window.location.origin}/cancel`\n : '/cancel',\n children,\n className = '',\n disabled = false,\n allowPromotionCodes = true,\n billingAddressCollection = 'auto',\n metadata,\n trialPeriodDays,\n onSuccess,\n onError,\n onLoading,\n}) => {\n const stripe = useStripe();\n const { initialized } = usePaymentsContext();\n const [loading, setLoading] = useState(false);\n\n const handleCheckout = async () => {\n if (!stripe) {\n const error = ERROR_MESSAGES.STRIPE_NOT_LOADED;\n onError?.(error);\n console.error(error);\n return;\n }\n\n if (!initialized) {\n const error = ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED;\n onError?.(error);\n console.error(error);\n return;\n }\n\n if (!validateStripeId(priceId, 'price')) {\n const error = ERROR_MESSAGES.INVALID_PRICE_ID;\n onError?.(error);\n console.error(error);\n return;\n }\n\n if (customerId && !validateStripeId(customerId, 'customer')) {\n const error = ERROR_MESSAGES.INVALID_CUSTOMER_ID;\n onError?.(error);\n console.error(error);\n return;\n }\n\n setLoading(true);\n onLoading?.(true);\n\n try {\n const response = await fetch('/api/payments/create-checkout-session', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n priceId,\n customerId,\n customerEmail,\n successUrl,\n cancelUrl,\n allowPromotionCodes,\n billingAddressCollection,\n metadata,\n trialPeriodDays,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response\n .json()\n .catch(() => ({ error: 'Network error' }));\n throw new Error(errorData.error || ERROR_MESSAGES.CHECKOUT_FAILED);\n }\n\n const { sessionId } = await response.json();\n\n if (!sessionId) {\n throw new Error('No session ID returned from server');\n }\n\n const result = await stripe.redirectToCheckout({ sessionId });\n\n if (result.error) {\n throw new Error(result.error.message || ERROR_MESSAGES.CHECKOUT_FAILED);\n }\n\n onSuccess?.();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : ERROR_MESSAGES.CHECKOUT_FAILED;\n onError?.(errorMessage);\n console.error('Checkout error:', error);\n } finally {\n setLoading(false);\n onLoading?.(false);\n }\n };\n\n const isDisabled = !stripe || loading || disabled || !initialized;\n\n return (\n <button\n onClick={handleCheckout}\n disabled={isDisabled}\n className={`\n inline-flex items-center justify-center px-4 py-2 \n border border-transparent text-sm font-medium rounded-md \n text-white bg-blue-600 hover:bg-blue-700 \n focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\n disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors duration-200\n ${className}\n `}\n aria-label={typeof children === 'string' ? children : 'Checkout'}\n >\n {loading ? (\n <>\n <svg\n className=\"animate-spin -ml-1 mr-3 h-4 w-4 text-white\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n Processing...\n </>\n ) : (\n children\n )}\n </button>\n );\n};\n\nexport default CheckoutButton;\n","import React from 'react';\nimport { PricingPlan } from '../../shared/types';\nimport {\n formatPricingPlan,\n formatTrialPeriod,\n} from '../../shared/utils/formatting';\nimport { CheckoutButton } from './CheckoutButton';\n\ninterface PricingTableProps {\n plans: PricingPlan[];\n customerId?: string;\n customerEmail?: string;\n successUrl?: string;\n cancelUrl?: string;\n className?: string;\n onCheckoutSuccess?: (plan: PricingPlan) => void;\n onCheckoutError?: (plan: PricingPlan, error: string) => void;\n showFeatures?: boolean;\n showTrialInfo?: boolean;\n layout?: 'grid' | 'list';\n maxColumns?: number;\n}\n\nexport const PricingTable: React.FC<PricingTableProps> = ({\n plans,\n customerId,\n customerEmail,\n successUrl,\n cancelUrl,\n className = '',\n onCheckoutSuccess,\n onCheckoutError,\n showFeatures = true,\n showTrialInfo = true,\n layout = 'grid',\n maxColumns = 3,\n}) => {\n if (!plans || plans.length === 0) {\n return (\n <div className=\"text-center py-8 text-gray-500\">\n No pricing plans available\n </div>\n );\n }\n\n const gridCols = Math.min(plans.length, maxColumns);\n const gridClass =\n layout === 'grid'\n ? `grid gap-6 ${gridCols === 1 ? 'grid-cols-1' : gridCols === 2 ? 'grid-cols-1 md:grid-cols-2' : 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3'}`\n : 'space-y-6';\n\n return (\n <div className={`pricing-table ${className}`}>\n <div className={gridClass}>\n {plans.map(plan => (\n <PricingCard\n key={plan.id}\n plan={plan}\n customerId={customerId}\n customerEmail={customerEmail}\n successUrl={successUrl}\n cancelUrl={cancelUrl}\n onCheckoutSuccess={() => onCheckoutSuccess?.(plan)}\n onCheckoutError={error => onCheckoutError?.(plan, error)}\n showFeatures={showFeatures}\n showTrialInfo={showTrialInfo}\n />\n ))}\n </div>\n </div>\n );\n};\n\ninterface PricingCardProps {\n plan: PricingPlan;\n customerId?: string;\n customerEmail?: string;\n successUrl?: string;\n cancelUrl?: string;\n onCheckoutSuccess?: () => void;\n onCheckoutError?: (error: string) => void;\n showFeatures?: boolean;\n showTrialInfo?: boolean;\n}\n\nconst PricingCard: React.FC<PricingCardProps> = ({\n plan,\n customerId,\n customerEmail,\n successUrl,\n cancelUrl,\n onCheckoutSuccess,\n onCheckoutError,\n showFeatures = true,\n showTrialInfo = true,\n}) => {\n const isPopular = plan.popular;\n\n return (\n <div\n className={`\n relative bg-white rounded-lg shadow-lg overflow-hidden\n ${isPopular ? 'ring-2 ring-blue-500 ring-opacity-50' : 'border border-gray-200'}\n transition-transform duration-200 hover:scale-105\n `}\n >\n {isPopular && (\n <div className=\"absolute top-0 left-0 right-0 bg-blue-500 text-white text-center py-2 text-sm font-medium\">\n Most Popular\n </div>\n )}\n\n <div className={`p-6 ${isPopular ? 'pt-12' : ''}`}>\n {/* Plan Header */}\n <div className=\"text-center mb-6\">\n <h3 className=\"text-xl font-semibold text-gray-900 mb-2\">\n {plan.name}\n </h3>\n {plan.description && (\n <p className=\"text-gray-600 text-sm mb-4\">{plan.description}</p>\n )}\n <div className=\"mb-4\">\n <span className=\"text-3xl font-bold text-gray-900\">\n {formatPricingPlan(plan)}\n </span>\n </div>\n {showTrialInfo &&\n plan.trialPeriodDays &&\n plan.trialPeriodDays > 0 && (\n <div className=\"text-sm text-green-600 font-medium\">\n {formatTrialPeriod(plan.trialPeriodDays)}\n </div>\n )}\n </div>\n\n {/* Features List */}\n {showFeatures && plan.features && plan.features.length > 0 && (\n <div className=\"mb-6\">\n <ul className=\"space-y-3\">\n {plan.features.map((feature, index) => (\n <li key={index} className=\"flex items-start\">\n <svg\n className=\"flex-shrink-0 w-5 h-5 text-green-500 mt-0.5 mr-3\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n <span className=\"text-gray-700 text-sm\">{feature}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* CTA Button */}\n <div className=\"mt-6\">\n <CheckoutButton\n priceId={plan.stripePriceId}\n customerId={customerId}\n customerEmail={customerEmail}\n successUrl={successUrl}\n cancelUrl={cancelUrl}\n trialPeriodDays={plan.trialPeriodDays}\n metadata={plan.metadata}\n onSuccess={onCheckoutSuccess}\n onError={onCheckoutError}\n className={`\n w-full justify-center py-3 px-4 text-base font-medium\n ${\n isPopular\n ? 'bg-blue-600 hover:bg-blue-700 text-white'\n : 'bg-gray-100 hover:bg-gray-200 text-gray-900 border border-gray-300'\n }\n `}\n >\n Get Started\n </CheckoutButton>\n </div>\n </div>\n </div>\n );\n};\n\nexport default PricingTable;\n","import React, { useState } from 'react';\nimport {\n useStripe,\n useElements,\n CardElement,\n PaymentElement,\n} from '@stripe/react-stripe-js';\nimport { usePaymentsContext } from '../../shared/providers/PaymentsProvider';\nimport { PaymentIntent } from '@stripe/stripe-js';\nimport { ERROR_MESSAGES } from '../../shared/constants';\nimport { validateEmail } from '../../shared/utils/validation';\n\nexport interface PaymentFormProps {\n clientSecret?: string;\n customerId?: string;\n customerEmail?: string;\n amount?: number;\n currency?: string;\n description?: string;\n metadata?: Record<string, string>;\n onSuccess?: (paymentIntent: PaymentIntent) => void;\n onError?: (error: string) => void;\n onLoading?: (loading: boolean) => void;\n className?: string;\n showBillingDetails?: boolean;\n elementType?: 'card' | 'payment';\n}\n\nexport const PaymentForm: React.FC<PaymentFormProps> = ({\n clientSecret,\n customerId,\n customerEmail,\n amount,\n currency = 'usd',\n description,\n metadata,\n onSuccess,\n onError,\n onLoading,\n className = '',\n showBillingDetails = true,\n elementType = 'payment',\n}) => {\n const stripe = useStripe();\n const elements = useElements();\n const { initialized } = usePaymentsContext();\n\n const [loading, setLoading] = useState(false);\n const [email, setEmail] = useState(customerEmail || '');\n const [billingDetails, setBillingDetails] = useState({\n name: '',\n email: customerEmail || '',\n phone: '',\n address: {\n line1: '',\n line2: '',\n city: '',\n state: '',\n postal_code: '',\n country: 'US',\n },\n });\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n\n if (!stripe || !elements) {\n const error = ERROR_MESSAGES.STRIPE_NOT_LOADED;\n onError?.(error);\n return;\n }\n\n if (!initialized) {\n const error = ERROR_MESSAGES.PROVIDER_NOT_CONFIGURED;\n onError?.(error);\n return;\n }\n\n if (showBillingDetails && email && !validateEmail(email)) {\n onError?.('Please enter a valid email address');\n return;\n }\n\n setLoading(true);\n onLoading?.(true);\n\n try {\n let result;\n\n if (elementType === 'payment' && clientSecret) {\n // Use Payment Element with existing Payment Intent\n result = await stripe.confirmPayment({\n elements,\n confirmParams: {\n return_url: window.location.href,\n receipt_email: email || billingDetails.email,\n },\n redirect: 'if_required',\n });\n } else if (elementType === 'card') {\n // Use Card Element\n const cardElement = elements.getElement(CardElement);\n\n if (!cardElement) {\n throw new Error('Card element not found');\n }\n\n if (clientSecret) {\n // Confirm existing Payment Intent\n result = await stripe.confirmCardPayment(clientSecret, {\n payment_method: {\n card: cardElement,\n billing_details: showBillingDetails\n ? {\n name: billingDetails.name || undefined,\n email: billingDetails.email || undefined,\n phone: billingDetails.phone || undefined,\n address: billingDetails.address.line1\n ? billingDetails.address\n : undefined,\n }\n : undefined,\n },\n });\n } else if (amount) {\n // Create new Payment Intent\n const response = await fetch('/api/payments/create-payment-intent', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n amount,\n currency,\n customerId,\n description,\n metadata,\n }),\n });\n\n if (!response.ok) {\n throw new Error('Failed to create payment intent');\n }\n\n const { client_secret } = await response.json();\n\n result = await stripe.confirmCardPayment(client_secret, {\n payment_method: {\n card: cardElement,\n billing_details: showBillingDetails\n ? {\n name: billingDetails.name || undefined,\n email: billingDetails.email || undefined,\n phone: billingDetails.phone || undefined,\n address: billingDetails.address.line1\n ? billingDetails.address\n : undefined,\n }\n : undefined,\n },\n });\n } else {\n throw new Error('Either clientSecret or amount is required');\n }\n }\n\n if (result?.error) {\n throw new Error(result.error.message || ERROR_MESSAGES.PAYMENT_FAILED);\n }\n\n if (result?.paymentIntent?.status === 'succeeded') {\n onSuccess?.(result.paymentIntent);\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : ERROR_MESSAGES.PAYMENT_FAILED;\n onError?.(errorMessage);\n console.error('Payment error:', error);\n } finally {\n setLoading(false);\n onLoading?.(false);\n }\n };\n\n const cardElementOptions = {\n style: {\n base: {\n fontSize: '16px',\n color: '#424770',\n '::placeholder': {\n color: '#aab7c4',\n },\n },\n invalid: {\n color: '#9e2146',\n },\n },\n };\n\n return (\n <form onSubmit={handleSubmit} className={`payment-form ${className}`}>\n {showBillingDetails && (\n <div className=\"mb-6 space-y-4\">\n <div>\n <label\n htmlFor=\"email\"\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n Email\n </label>\n <input\n type=\"email\"\n id=\"email\"\n value={email}\n onChange={e => {\n setEmail(e.target.value);\n setBillingDetails(prev => ({ ...prev, email: e.target.value }));\n }}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"your@email.com\"\n required\n />\n </div>\n\n <div>\n <label\n htmlFor=\"name\"\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n Full Name\n </label>\n <input\n type=\"text\"\n id=\"name\"\n value={billingDetails.name}\n onChange={e =>\n setBillingDetails(prev => ({ ...prev, name: e.target.value }))\n }\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"John Doe\"\n />\n </div>\n </div>\n )}\n\n <div className=\"mb-6\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n Payment Information\n </label>\n <div className=\"p-3 border border-gray-300 rounded-md\">\n {elementType === 'payment' ? (\n <PaymentElement />\n ) : (\n <CardElement options={cardElementOptions} />\n )}\n </div>\n </div>\n\n <button\n type=\"submit\"\n disabled={!stripe || loading}\n className=\"w-full bg-blue-600 text-white py-3 px-4 rounded-md font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200\"\n >\n {loading ? (\n <>\n <svg\n className=\"animate-spin -ml-1 mr-3 h-4 w-4 text-white inline\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n Processing...\n </>\n ) : (\n `Pay ${amount ? `$${(amount / 100).toFixed(2)}` : ''}`\n )}\n </button>\n </form>\n );\n};\n\nexport default PaymentForm;\n","import React, { useState } from 'react';\n\nexport type SubscriptionStatus =\n | 'active'\n | 'canceled'\n | 'past_due'\n | 'unpaid'\n | 'incomplete';\n\nexport interface Subscription {\n id: string;\n planId: string;\n planName: string;\n status: SubscriptionStatus;\n currentPeriodStart: Date;\n currentPeriodEnd: Date;\n cancelAtPeriodEnd: boolean;\n amount: number;\n currency: string;\n interval: 'month' | 'year';\n}\n\nexport type SubscriptionAction = 'upgrade' | 'downgrade' | 'pause' | 'resume';\n\nexport interface SubscriptionManagerProps {\n subscription: Subscription;\n onSubscriptionChange: (action: SubscriptionAction) => void;\n onCancel: () => void;\n className?: string;\n}\n\nexport const SubscriptionManager: React.FC<SubscriptionManagerProps> = ({\n subscription,\n onSubscriptionChange,\n onCancel,\n className = '',\n}) => {\n const [loading, setLoading] = useState(false);\n\n const formatDate = (date: Date) => {\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n }).format(date);\n };\n\n const formatAmount = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(amount / 100);\n };\n\n const getStatusColor = (status: SubscriptionStatus) => {\n switch (status) {\n case 'active':\n return '#10b981';\n case 'canceled':\n return '#ef4444';\n case 'past_due':\n return '#f59e0b';\n case 'unpaid':\n return '#ef4444';\n case 'incomplete':\n return '#6b7280';\n default:\n return '#6b7280';\n }\n };\n\n const getStatusText = (status: SubscriptionStatus) => {\n switch (status) {\n case 'active':\n return 'Active';\n case 'canceled':\n return 'Canceled';\n case 'past_due':\n return 'Past Due';\n case 'unpaid':\n return 'Unpaid';\n case 'incomplete':\n return 'Incomplete';\n default:\n return status;\n }\n };\n\n const handleAction = async (action: SubscriptionAction) => {\n setLoading(true);\n try {\n await onSubscriptionChange(action);\n } finally {\n setLoading(false);\n }\n };\n\n const handleCancel = async () => {\n setLoading(true);\n try {\n await onCancel();\n } finally {\n setLoading(false);\n }\n };\n\n const styles = {\n container: {\n width: '100%',\n } as React.CSSProperties,\n card: {\n border: '1px solid #e5e7eb',\n borderRadius: '12px',\n padding: '2rem',\n background: 'white',\n boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',\n } as React.CSSProperties,\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: '1.5rem',\n } as React.CSSProperties,\n info: {\n flex: 1,\n } as React.CSSProperties,\n planName: {\n fontSize: '1.5rem',\n fontWeight: 700,\n color: '#1f2937',\n margin: '0 0 0.5rem 0',\n } as React.CSSProperties,\n details: {\n display: 'flex',\n alignItems: 'baseline',\n gap: '0.25rem',\n } as React.CSSProperties,\n amount: {\n fontSize: '1.25rem',\n fontWeight: 600,\n color: '#3b82f6',\n } as React.CSSProperties,\n interval: {\n fontSize: '1rem',\n color: '#6b7280',\n } as React.CSSProperties,\n statusBadge: {\n padding: '0.5rem 1rem',\n borderRadius: '20px',\n color: 'white',\n fontSize: '0.875rem',\n fontWeight: 600,\n } as React.CSSProperties,\n dates: {\n marginBottom: '2rem',\n padding: '1rem',\n background: '#f9fafb',\n borderRadius: '8px',\n } as React.CSSProperties,\n dateLabel: {\n fontSize: '0.875rem',\n color: '#6b7280',\n fontWeight: 500,\n } as React.CSSProperties,\n dateValue: {\n fontSize: '0.875rem',\n color: '#1f2937',\n } as React.CSSProperties,\n cancellationNotice: {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n marginTop: '1rem',\n padding: '0.75rem',\n background: '#fef3c7',\n borderRadius: '6px',\n fontSize: '0.875rem',\n color: '#92400e',\n } as React.CSSProperties,\n actions: {\n display: 'flex',\n gap: '1rem',\n flexWrap: 'wrap' as const,\n } as React.CSSProperties,\n button: {\n padding: '0.75rem 1.5rem',\n border: 'none',\n borderRadius: '8px',\n fontWeight: 600,\n fontSize: '0.875rem',\n cursor: 'pointer',\n transition: 'all 0.3s ease',\n flex: 1,\n minWidth: '120px',\n } as React.CSSProperties,\n buttonPrimary: {\n background: '#3b82f6',\n color: 'white',\n } as React.CSSProperties,\n buttonSecondary: {\n background: '#f3f4f6',\n color: '#374151',\n border: '1px solid #d1d5db',\n } as React.CSSProperties,\n buttonDanger: {\n background: '#ef4444',\n color: 'white',\n } as React.CSSProperties,\n buttonDisabled: {\n opacity: 0.6,\n cursor: 'not-allowed',\n } as React.CSSProperties,\n };\n\n return (\n <div style={styles.container} className={className}>\n <div style={styles.card}>\n <div style={styles.header}>\n <div style={styles.info}>\n <h3 style={styles.planName}>{subscription.planName}</h3>\n <div style={styles.details}>\n <span style={styles.amount}>\n {formatAmount(subscription.amount, subscription.currency)}\n </span>\n <span style={styles.interval}>/{subscription.interval}</span>\n </div>\n </div>\n <div>\n <span\n style={{\n ...styles.statusBadge,\n backgroundColor: getStatusColor(subscription.status),\n }}\n >\n {getStatusText(subscription.status)}\n </span>\n </div>\n </div>\n\n <div style={styles.dates}>\n <div>\n <div style={styles.dateLabel}>Current period:</div>\n <div style={styles.dateValue}>\n {formatDate(subscription.currentPeriodStart)} -{' '}\n {formatDate(subscription.currentPeriodEnd)}\n </div>\n </div>\n {subscription.cancelAtPeriodEnd && (\n <div style={styles.cancellationNotice}>\n <span>⚠️</span>\n <span>\n Your subscription will be canceled at the end of the current\n period.\n </span>\n </div>\n )}\n </div>\n\n <div style={styles.actions}>\n {subscription.status === 'active' &&\n !subscription.cancelAtPeriodEnd && (\n <>\n <button\n style={{\n ...styles.button,\n ...styles.buttonSecondary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('upgrade')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Upgrade Plan'}\n </button>\n <button\n style={{\n ...styles.button,\n ...styles.buttonSecondary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('downgrade')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Downgrade Plan'}\n </button>\n <button\n style={{\n ...styles.button,\n ...styles.buttonDanger,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={handleCancel}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Cancel Subscription'}\n </button>\n </>\n )}\n\n {subscription.status === 'active' &&\n subscription.cancelAtPeriodEnd && (\n <button\n style={{\n ...styles.button,\n ...styles.buttonPrimary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('resume')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Resume Subscription'}\n </button>\n )}\n\n {subscription.status === 'past_due' && (\n <button\n style={{\n ...styles.button,\n ...styles.buttonPrimary,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n onClick={() => handleAction('resume')}\n disabled={loading}\n >\n {loading ? 'Loading...' : 'Update Payment Method'}\n </button>\n )}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":["src_exports","__export","ACTIVE_STATUSES","BILLING_INTERVALS","CHECKOUT_MODE","CURRENCY_SYMBOLS","DEFAULT_CURRENCY","ERROR_MESSAGES","INACTIVE_STATUSES","INCOMPLETE_STATUSES","INVOICE_STATUS","MockPaymentProvider","PAYMENT_METHODS","PROBLEMATIC_STATUSES","PaymentErrorType","PaymentProviderFactory","PaymentsError","PaymentsProvider","PricingTable","STRIPE_API_VERSION","SUBSCRIPTION_STATUS","PaymentForm","StripePaymentProvider","SubscriptionManager","SubscriptionStatus","WEBHOOK_EVENTS","calculateTax","formatAmountWithTax","formatBillingInterval","formatCardBrand","formatCurrency","formatDate","formatPaymentMethodDisplay","formatPricingPlan","formatRelativeTime","formatSubscriptionStatus","formatTaxRate","formatTrialPeriod","getEnvironmentConfig","isActiveSubscription","isClient","isDevelopment","isInactiveSubscription","isIncompleteSubscription","isProblematicSubscription","isProduction","isServer","truncateText","usePayments","usePaymentsContext","validateAmount","validateCard","validateCurrentEnvironment","validateEmail","validateEnvironment","validatePaymentsConfig","validatePhoneNumber","validatePricingPlan","validateStripeId","__toCommonJS","SubscriptionStatus","ACTIVE_STATUSES","INACTIVE_STATUSES","PROBLEMATIC_STATUSES","INCOMPLETE_STATUSES","isActiveSubscription","status","isInactiveSubscription","isProblematicSubscription","isIncompleteSubscription","PaymentErrorType","PaymentsError","_PaymentsError","type","message","code","details","STRIPE_API_VERSION","PAYMENT_METHODS","SUBSCRIPTION_STATUS","INVOICE_STATUS","CHECKOUT_MODE","BILLING_INTERVALS","CURRENCY_SYMBOLS","DEFAULT_CURRENCY","WEBHOOK_EVENTS","ERROR_MESSAGES","validateEmail","email","validatePhoneNumber","phone","validatePaymentsConfig","config","errors","validatePricingPlan","plan","validateStripeId","id","type","prefixes","validateAmount","amount","currency","minAmount","validateCard","cardDetails","cleanNumber","luhnCheck","currentYear","cardNumber","sum","alternate","formatCurrency","amount","currency","DEFAULT_CURRENCY","options","showSymbol","showCents","locale","currencyCode","isZeroDecimalCurrency","displayAmount","symbol","CURRENCY_SYMBOLS","formattedAmount","formatPricingPlan","plan","price","interval","formatSubscriptionStatus","status","formatDate","date","format","timeZone","dateObj","formatOptions","formatRelativeTime","numeric","diffInSeconds","rtf","minutes","hours","days","formatBillingInterval","count","formatTrialPeriod","truncateText","text","maxLength","formatCardBrand","brand","formatPaymentMethodDisplay","paymentMethod","calculateTax","taxRate","inclusive","roundTo","subtotal","tax","total","multiplier","formatTaxRate","rate","formatAmountWithTax","showBreakdown","taxCalculation","subtotalFormatted","taxFormatted","totalFormatted","validateEnvironment","config","errors","warnings","getEnvironmentConfig","isServer","validateCurrentEnvironment","validation","error","warning","isDevelopment","isProduction","isClient","BasePaymentProvider","config","error","type","PaymentsError","message","code","details","import_stripe","StripePaymentProvider","BasePaymentProvider","config","PaymentsError","Stripe","params","session","error","customer","customerId","subscription","item","subscriptionId","sessionId","status","currentSubscription","items","i","stripeSubscription","MockPaymentProvider","BasePaymentProvider","config","params","id","PaymentsError","newCustomer","customer","c","initialLength","customerId","paymentMethodId","newPaymentMethod","pm","newSubscription","item","subscription","s","status","subs","PaymentProviderFactory","config","StripePaymentProvider","PaymentsError","MockPaymentProvider","providers","configs","import_react","import_zustand","import_immer","initialState","usePayments","set","get","config","state","resolvedConfig","PaymentProviderFactory","error","message","PaymentsError","params","customer","customerId","session","sessionId","newSubscription","subscriptionId","updatedSubscription","status","subscriptions","subscription","activeSubscription","sub","import_jsx_runtime","PaymentsContext","PaymentsProvider","children","config","onPaymentSuccess","onPaymentError","store","usePayments","initialize","initialized","loading","error","customer","subscriptions","activeSubscription","onPaymentSuccessRef","onPaymentErrorRef","err","contextValue","usePaymentsContext","context","import_react","usePayments","config","setConfig","provider","setProvider","initialized","setInitialized","loading","setLoading","error","setError","customer","setCustomer","subscriptions","setSubscriptions","handleError","err","refreshSubscriptions","customerId","status","PaymentsError","ERROR_MESSAGES","fetchedSubscriptions","initialize","initialConfig","resolvedConfig","PaymentProviderFactory","newProvider","retrieveCustomer","newCustomer","createCustomer","params","createSubscription","newSubscription","listSubscriptions","subs","retrieveSubscription","subscriptionId","sub","createCheckoutSession","retrieveCheckoutSession","sessionId","cancelSubscription","reactivateSubscription","updateSubscription","updatedSubscription","refreshCustomer","fetchedCustomer","reset","activeSubscription","s","import_react","import_react_stripe_js","import_jsx_runtime","CheckoutButton","priceId","customerId","customerEmail","successUrl","cancelUrl","children","className","disabled","allowPromotionCodes","billingAddressCollection","metadata","trialPeriodDays","onSuccess","onError","onLoading","stripe","initialized","usePaymentsContext","loading","setLoading","error","ERROR_MESSAGES","validateStripeId","response","errorData","sessionId","result","errorMessage","import_jsx_runtime","PricingTable","plans","customerId","customerEmail","successUrl","cancelUrl","className","onCheckoutSuccess","onCheckoutError","showFeatures","showTrialInfo","layout","maxColumns","gridCols","gridClass","plan","PricingCard","error","isPopular","formatPricingPlan","formatTrialPeriod","feature","index","CheckoutButton","import_react","import_react_stripe_js","import_jsx_runtime","PaymentForm","clientSecret","customerId","customerEmail","amount","currency","description","metadata","onSuccess","onError","onLoading","className","showBillingDetails","elementType","stripe","elements","initialized","usePaymentsContext","loading","setLoading","email","setEmail","billingDetails","setBillingDetails","handleSubmit","event","error","ERROR_MESSAGES","validateEmail","result","cardElement","response","client_secret","errorMessage","cardElementOptions","e","prev","import_react","import_jsx_runtime","SubscriptionManager","subscription","onSubscriptionChange","onCancel","className","loading","setLoading","formatDate","date","formatAmount","amount","currency","getStatusColor","status","getStatusText","handleAction","action","handleCancel","styles"]}
|