@flopay/js 0.2.1 → 0.3.1

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.cjs CHANGED
@@ -173,7 +173,7 @@ var StripeAdapter = class {
173
173
  }
174
174
  return {};
175
175
  }
176
- async createPaymentMethod() {
176
+ async createPaymentMethod(billingDetails) {
177
177
  if (!this.stripe || !this.elements) {
178
178
  return {
179
179
  paymentMethodId: null,
@@ -181,11 +181,28 @@ var StripeAdapter = class {
181
181
  };
182
182
  }
183
183
  const cardNumberEl = this.elements.getElement("cardNumber");
184
+ const stripeBilling = billingDetails ? {
185
+ billing_details: {
186
+ ...billingDetails.name ? { name: billingDetails.name } : {},
187
+ ...billingDetails.address ? {
188
+ address: {
189
+ ...billingDetails.address.country ? { country: billingDetails.address.country } : {},
190
+ ...billingDetails.address.postal_code ? { postal_code: billingDetails.address.postal_code } : {},
191
+ ...billingDetails.address.city ? { city: billingDetails.address.city } : {},
192
+ ...billingDetails.address.line1 ? { line1: billingDetails.address.line1 } : {},
193
+ ...billingDetails.address.line2 ? { line2: billingDetails.address.line2 } : {},
194
+ ...billingDetails.address.state ? { state: billingDetails.address.state } : {}
195
+ }
196
+ } : {}
197
+ }
198
+ } : {};
184
199
  const { error, paymentMethod } = cardNumberEl ? await this.stripe.createPaymentMethod({
185
200
  type: "card",
186
- card: cardNumberEl
201
+ card: cardNumberEl,
202
+ ...stripeBilling
187
203
  }) : await this.stripe.createPaymentMethod({
188
- elements: this.elements
204
+ elements: this.elements,
205
+ ...stripeBilling
189
206
  });
190
207
  if (error) {
191
208
  return {
@@ -729,8 +746,8 @@ var FloPay = class {
729
746
  return this.provider.submitElements();
730
747
  }
731
748
  /** Create a payment method from the current elements (tokenize card). */
732
- async createPaymentMethod() {
733
- return this.provider.createPaymentMethod();
749
+ async createPaymentMethod(billingDetails) {
750
+ return this.provider.createPaymentMethod(billingDetails);
734
751
  }
735
752
  /** Confirm a card payment with a known client secret and payment method ID. */
736
753
  async confirmCardPayment(params) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/load.ts","../src/stripe-adapter.ts","../src/flopay.ts","../src/elements.ts","../src/payment-api.ts","../src/create-checkout-session.ts"],"sourcesContent":["export { loadFloPay } from './load.js';\nexport { FloPay } from './flopay.js';\nexport { FloPayElements } from './elements.js';\nexport { StripeAdapter } from './stripe-adapter.js';\nexport { PaymentAPI } from './payment-api.js';\nexport { createCheckoutSession, createCheckoutSessionWithRetries } from './create-checkout-session.js';\n","import type { FloPayConfig } from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\nimport { StripeAdapter } from './stripe-adapter.js';\nimport { FloPay } from './flopay.js';\n\n/** Cache to avoid re-initializing for the same key. */\nlet cachedInstance: FloPay | null = null;\nlet cachedKey: string | null = null;\n\n/**\n * Loads and initializes the FloPay SDK.\n *\n * This is the primary entry point for consumer applications.\n * It initializes the underlying payment provider (currently Stripe)\n * and returns a ready-to-use `FloPay` instance.\n *\n * @example\n * ```ts\n * import { loadFloPay } from '@flopay/js';\n *\n * const flopay = await loadFloPay('pk_test_...');\n * const elements = flopay.elements();\n * const cardElement = await elements.create('card');\n * cardElement.mount('#card-container');\n * ```\n */\nexport async function loadFloPay(\n publishableKey: string,\n options?: Omit<FloPayConfig, 'publishableKey'>,\n): Promise<FloPay> {\n if (!publishableKey) {\n throw new FloPayError(\n 'A publishable key is required to initialize FloPay.',\n 'validation_error',\n { param: 'publishableKey' },\n );\n }\n\n // Return cached instance if key matches\n if (cachedInstance && cachedKey === publishableKey) {\n return cachedInstance;\n }\n\n // Clean up previous instance\n if (cachedInstance) {\n cachedInstance.destroy();\n }\n\n const config: FloPayConfig = {\n publishableKey,\n ...options,\n };\n\n // Currently only Stripe is supported. The adapter pattern allows\n // adding Chargebee, Recurly, or other providers in the future.\n const adapter = new StripeAdapter();\n await adapter.initialize(config);\n\n const instance = new FloPay(adapter, config);\n\n cachedKey = publishableKey;\n cachedInstance = instance;\n\n return instance;\n}\n","import type { Stripe, StripeElements, StripeElementType } from '@stripe/stripe-js';\nimport type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementType,\n ElementOptions,\n MountedElement,\n ConfirmPaymentParams,\n PaymentResult,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Maps FloPay element types to Stripe element types.\n * FloPay uses camelCase; Stripe uses lowercase with hyphens or specific names.\n */\nfunction toStripeElementType(type: ElementType): StripeElementType {\n const map: Record<ElementType, string> = {\n payment: 'payment',\n card: 'card',\n cardNumber: 'cardNumber',\n cardExpiry: 'cardExpiry',\n cardCvc: 'cardCvc',\n address: 'address',\n };\n return map[type] as StripeElementType;\n}\n\n/**\n * Wraps a Stripe element instance in the FloPay MountedElement interface.\n *\n * TODO: In a future phase, this wrapper will render the Stripe element inside\n * an iframe hosted on the FloPay domain for PCI DSS SAQ-A compliance.\n * For now, it delegates directly to the Stripe element.\n */\n/** Minimal interface shared by all Stripe element types. */\ninterface StripeElementLike {\n mount(domElement: string | HTMLElement): void;\n unmount(): void;\n destroy(): void;\n update(options?: Record<string, unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void): void;\n off(event: string, handler?: (...args: unknown[]) => void): void;\n}\n\nfunction wrapStripeElement(\n stripeElement: StripeElementLike,\n): MountedElement {\n const el = stripeElement;\n\n return {\n mount(container: HTMLElement) {\n el.mount(container);\n },\n unmount() {\n el.unmount();\n },\n update(options: Partial<ElementOptions>) {\n el.update(options as Record<string, unknown>);\n },\n on(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['on']?.(event, handler);\n },\n off(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['off']?.(event, handler);\n },\n destroy() {\n el.destroy();\n },\n };\n}\n\n/**\n * Payment provider adapter backed by Stripe.\n *\n * Implements the `PaymentProviderAdapter` interface so that FloPay consumers\n * interact with a stable API regardless of the upstream provider.\n */\nexport class StripeAdapter implements PaymentProviderAdapter {\n readonly name = 'stripe';\n private stripe: Stripe | null = null;\n private elements: StripeElements | null = null;\n\n async initialize(config: FloPayConfig): Promise<void> {\n // loadStripe only works in the browser — skip initialization during SSR/SSG\n if (typeof window === 'undefined') {\n return;\n }\n\n const { loadStripe } = await import('@stripe/stripe-js');\n const stripe = await loadStripe(config.publishableKey, {\n locale: (config.locale as 'auto') ?? 'auto',\n });\n\n if (!stripe) {\n throw new FloPayError(\n 'Failed to initialize Stripe. Check your publishable key.',\n 'authentication_error',\n );\n }\n\n this.stripe = stripe;\n }\n\n /** Lazily creates the Stripe Elements group for the given options. */\n private getElements(options?: ElementOptions): StripeElements {\n if (!this.stripe) {\n throw new FloPayError(\n 'StripeAdapter not initialized. Call initialize() first.',\n 'api_error',\n );\n }\n\n if (!this.elements) {\n let elementsOptions: Record<string, unknown>;\n\n if (options?.clientSecret) {\n // Server-side intent already exists — pass its client secret\n elementsOptions = { clientSecret: options.clientSecret };\n } else {\n // No server-side intent yet — use deferred mode with manual payment method creation.\n // This matches checkout/StripeCardForm: mode='payment', paymentMethodCreation='manual'.\n elementsOptions = {\n mode: 'payment' as const,\n amount: options?.amount ?? 0,\n currency: (options?.currency ?? 'usd').toLowerCase(),\n paymentMethodCreation: options?.paymentMethodCreation ?? ('manual' as const),\n };\n }\n\n if (options?.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n this.elements = this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n return this.elements;\n }\n\n async createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement> {\n const elements = this.getElements(options);\n const stripeType = toStripeElementType(type);\n\n const elementOptions: Record<string, unknown> = {};\n if (options.layout) {\n elementOptions['layout'] = options.layout;\n }\n if (options.defaultValues) {\n elementOptions['defaultValues'] = options.defaultValues;\n }\n if (options.readOnly) {\n elementOptions['readOnly'] = options.readOnly;\n }\n if (options.mode) {\n elementOptions['mode'] = options.mode;\n }\n if (options.style) {\n elementOptions['style'] = options.style;\n }\n\n const stripeElement = elements.create(stripeType as 'card', elementOptions) as unknown as StripeElementLike;\n return wrapStripeElement(stripeElement);\n }\n\n getElement(type: ElementType): MountedElement | null {\n if (!this.elements) return null;\n const stripeType = toStripeElementType(type);\n const existing = this.elements.getElement(stripeType as 'card') as unknown as StripeElementLike | null;\n if (!existing) return null;\n return wrapStripeElement(existing);\n }\n\n async submitElements(): Promise<{ error?: FloPayError }> {\n if (!this.stripe || !this.elements) {\n return { error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n const { error } = await this.elements.submit();\n if (error) {\n return {\n error: new FloPayError(error.message ?? 'Validation failed', 'validation_error'),\n };\n }\n return {};\n }\n\n async createPaymentMethod(): Promise<CreatePaymentMethodResult> {\n if (!this.stripe || !this.elements) {\n return {\n paymentMethodId: null,\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n // Detect split card fields vs unified PaymentElement.\n // With split fields (cardNumber + cardExpiry + cardCvc), Stripe requires\n // passing the specific cardNumber element with type: 'card'.\n // With unified PaymentElement, pass the elements group.\n const cardNumberEl = this.elements.getElement('cardNumber' as 'card');\n\n const { error, paymentMethod } = cardNumberEl\n ? await this.stripe.createPaymentMethod({\n type: 'card',\n card: cardNumberEl,\n })\n : await this.stripe.createPaymentMethod({\n elements: this.elements,\n });\n\n if (error) {\n return {\n paymentMethodId: null,\n error: new FloPayError(\n error.message ?? 'Failed to create payment method',\n 'api_error',\n { code: error.code },\n ),\n };\n }\n\n return { paymentMethodId: paymentMethod.id };\n }\n\n async confirmCardPayment(\n params: ConfirmCardPaymentParams,\n ): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return {\n status: 'failed',\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n const { error, paymentIntent } = await this.stripe.confirmCardPayment(\n params.clientSecret,\n { payment_method: params.paymentMethodId },\n );\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n { code: error.code, declineCode: error.decline_code },\n ),\n };\n }\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n };\n }\n\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n if (!this.stripe || !this.elements) {\n throw new FloPayError(\n 'StripeAdapter not initialized or no elements created.',\n 'api_error',\n );\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n elements: this.elements,\n clientSecret: params.clientSecret,\n confirmParams: {\n return_url: params.returnUrl ?? window.location.href,\n },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n {\n code: error.code,\n declineCode: error.decline_code,\n },\n ),\n };\n }\n\n if (!paymentIntent) {\n return { status: 'failed', error: new FloPayError('No payment intent returned', 'api_error') };\n }\n\n const statusMap: Record<string, PaymentResult['status']> = {\n succeeded: 'succeeded',\n processing: 'processing',\n requires_action: 'requires_action',\n requires_payment_method: 'failed',\n canceled: 'failed',\n };\n\n return {\n status: statusMap[paymentIntent.status] ?? 'failed',\n paymentIntentId: paymentIntent.id,\n };\n }\n\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return { status: 'failed', error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n\n const baseUrl = params.billingApiUrl.replace(/\\/+$/, '');\n\n // 1. Create a PayPal PaymentMethod upfront — backend needs pm_xxx\n // Mirrors checkout/StripeCardForm: stripe.createPaymentMethod({ type: 'paypal' })\n const createPM = this.stripe.createPaymentMethod as unknown as (\n params: { type: string },\n ) => Promise<{ error?: { message?: string }; paymentMethod?: { id: string } }>;\n\n const { error: pmError, paymentMethod } = await createPM({ type: 'paypal' });\n\n if (pmError) {\n console.warn('[FloPay] Could not create PayPal PM upfront:', pmError.message);\n }\n\n // 2. Create PaymentIntent via billing API with pm_xxx (or 'paypal' fallback)\n // isPaypal MUST be string 'true', not boolean — backend checks === 'true'\n const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId: params.sessionId,\n email: params.email,\n paymentMethodType: paymentMethod?.id ?? 'paypal',\n isPaypal: 'true',\n }),\n });\n\n if (!intentResponse.ok) {\n return { status: 'failed', error: new FloPayError('Failed to create PayPal payment intent', 'api_error') };\n }\n\n const intentJson = await intentResponse.json() as { data?: { id?: string } };\n const intentClientSecret = intentJson.data?.id;\n if (!intentClientSecret) {\n return { status: 'failed', error: new FloPayError('No client_secret in response', 'api_error') };\n }\n\n // 3. Confirm — pass payment_method if we have it (avoids setupFutureUsage mismatch)\n // Matches checkout: stripe.confirmPayment({ clientSecret, confirmParams: { payment_method, return_url } })\n const confirmParams: Record<string, unknown> = {\n return_url: params.returnUrl,\n };\n if (paymentMethod?.id) {\n confirmParams['payment_method'] = paymentMethod.id;\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n clientSecret: intentClientSecret,\n confirmParams: confirmParams as { return_url: string },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'PayPal payment failed', 'api_error', { code: error.code }),\n };\n }\n\n const pmId = typeof paymentIntent?.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent?.payment_method?.id;\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n paymentMethodId: pmId,\n };\n }\n\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n if (!this.stripe || typeof window === 'undefined') return null;\n\n const params = new URLSearchParams(window.location.search);\n const paymentIntentId = params.get('payment_intent');\n const clientSecret = params.get('payment_intent_client_secret');\n const redirectStatus = params.get('redirect_status');\n\n if (!paymentIntentId || !clientSecret) return null;\n\n if (redirectStatus === 'failed') {\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was declined. Please try again.', 'api_error'),\n };\n }\n\n const { paymentIntent, error } = await this.stripe.retrievePaymentIntent(clientSecret);\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'Failed to retrieve PayPal payment', 'api_error'),\n };\n }\n\n if (paymentIntent && (paymentIntent.status === 'requires_capture' || paymentIntent.status === 'succeeded')) {\n const pmId = typeof paymentIntent.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent.payment_method?.id;\n\n // Clean up URL params\n const url = new URL(window.location.href);\n url.searchParams.delete('payment_intent');\n url.searchParams.delete('payment_intent_client_secret');\n url.searchParams.delete('redirect_status');\n window.history.replaceState({}, '', url.toString());\n\n return {\n status: paymentIntent.status as ConfirmCardPaymentResult['status'],\n paymentIntentId: paymentIntent.id,\n paymentMethodId: pmId,\n };\n }\n\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was not completed. Please try again.', 'api_error'),\n };\n }\n\n getRawProvider(): unknown {\n return this.stripe;\n }\n\n createPayPalElements(options: ElementOptions): unknown {\n if (!this.stripe) return null;\n\n const elementsOptions: Record<string, unknown> = {\n mode: 'payment' as const,\n amount: options.amount ?? 0,\n currency: (options.currency ?? 'usd').toLowerCase(),\n captureMethod: 'manual' as const,\n };\n\n if (options.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n return this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n destroy(): void {\n this.elements = null;\n this.stripe = null;\n }\n}\n","import type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementOptions,\n ConfirmPaymentParams,\n PaymentResult,\n CheckoutSession,\n NormalizedCheckoutSession,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError, resolveBillingApiUrl } from '@flopay/shared';\nimport { FloPayElements } from './elements.js';\nimport { PaymentAPI } from './payment-api.js';\n\n/**\n * The main FloPay SDK instance.\n *\n * Created via `loadFloPay(publishableKey)`. Provides element management,\n * payment confirmation, and session retrieval.\n */\nexport class FloPay {\n private readonly provider: PaymentProviderAdapter;\n private readonly config: FloPayConfig;\n private currentElements: FloPayElements | null = null;\n\n constructor(provider: PaymentProviderAdapter, config: FloPayConfig) {\n this.provider = provider;\n this.config = config;\n }\n\n /**\n * Creates a new `FloPayElements` group for mounting payment fields.\n *\n * Only one elements group is active at a time. Creating a new one\n * destroys the previous group.\n */\n elements(options?: ElementOptions): FloPayElements {\n if (this.currentElements) {\n this.currentElements.destroy();\n }\n this.currentElements = new FloPayElements(this.provider, {\n appearance: this.config.appearance,\n ...options,\n });\n return this.currentElements;\n }\n\n /** Submit elements for validation. */\n async submitElements(): Promise<{ error?: import('@flopay/shared').FloPayError }> {\n return this.provider.submitElements();\n }\n\n /** Create a payment method from the current elements (tokenize card). */\n async createPaymentMethod(): Promise<CreatePaymentMethodResult> {\n return this.provider.createPaymentMethod();\n }\n\n /** Confirm a card payment with a known client secret and payment method ID. */\n async confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmCardPayment(params);\n }\n\n /** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmPayPalPayment(params);\n }\n\n /** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n return this.provider.resumePayPalPayment();\n }\n\n /** Confirms a payment using the mounted elements. */\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n return this.provider.confirmPayment(params);\n }\n\n /**\n * Retrieves a checkout session by ID via the billing API.\n *\n * Returns the normalized `CheckoutSession` with amount, currency,\n * customer data, and status.\n *\n * Requires `billingApiUrl` to be set — either via `loadFloPay(key, { billingApiUrl })`\n * or passed directly as the second argument.\n */\n async retrieveSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<CheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required to retrieve a session.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n const unified = await api.getUnifiedCheckoutSession(sessionId);\n if (!unified.data.session) {\n throw new FloPayError('Session not found', 'api_error');\n }\n return unified.data.session;\n }\n\n /**\n * Retrieves and normalizes a checkout session, including provider-specific\n * data (Stripe clientSecret/publishableKey, Chargebee site, etc.).\n *\n * The billing API URL is resolved from: explicit param → `loadFloPay()` config\n * → `NEXT_PUBLIC_FLOPAY_ENV` env var → `configureFlopay()` → staging fallback.\n */\n async retrieveUnifiedSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<NormalizedCheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n return api.getUnifiedCheckoutSession(sessionId);\n }\n\n /**\n * Returns the raw underlying provider instance (e.g. Stripe object).\n * Used internally by components that need direct provider access,\n * such as PayPal which requires its own Elements instance.\n */\n getRawProvider(): unknown {\n return this.provider.getRawProvider();\n }\n\n /** Tears down the SDK instance and releases resources. */\n destroy(): void {\n this.currentElements?.destroy();\n this.currentElements = null;\n this.provider.destroy();\n }\n}\n","import type {\n PaymentProviderAdapter,\n ElementType,\n ElementOptions,\n MountedElement,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Manages the creation and lifecycle of payment elements.\n *\n * Each `FloPayElements` instance is bound to a single provider adapter\n * and tracks all created elements for cleanup.\n */\nexport class FloPayElements {\n private readonly provider: PaymentProviderAdapter;\n private readonly elementMap = new Map<ElementType, MountedElement>();\n private readonly baseOptions: ElementOptions;\n\n constructor(provider: PaymentProviderAdapter, options?: ElementOptions) {\n this.provider = provider;\n this.baseOptions = options ?? {};\n }\n\n /**\n * Creates a new element of the given type.\n * If an element of that type already exists, it is destroyed first.\n */\n async create(\n type: ElementType,\n options?: ElementOptions,\n ): Promise<MountedElement> {\n // Check if the provider already has this element (e.g. after React\n // Strict Mode unmount+remount cycle). Reuse it instead of creating\n // a duplicate, which Stripe would reject.\n const providerExisting = this.provider.getElement(type);\n if (providerExisting) {\n this.elementMap.set(type, providerExisting);\n return providerExisting;\n }\n\n const existing = this.elementMap.get(type);\n if (existing) {\n existing.destroy();\n }\n\n const merged: ElementOptions = { ...this.baseOptions, ...options };\n const element = await this.provider.createElement(type, merged);\n this.elementMap.set(type, element);\n return element;\n }\n\n /** Returns a previously created element, or `null`. */\n getElement(type: ElementType): MountedElement | null {\n return this.elementMap.get(type) ?? null;\n }\n\n /**\n * Submits all mounted elements for validation.\n *\n * Returns an object with an optional error if validation fails.\n * This does NOT confirm the payment — call `floPay.confirmPayment()` for that.\n */\n async submit(): Promise<{ error?: FloPayError }> {\n // Walk through all mounted elements and check for incomplete state.\n // The actual validation is handled by the provider's element implementation.\n // For Stripe, the Elements.submit() method is called during confirmPayment.\n // This method exists to match the Stripe Elements API surface.\n return {};\n }\n\n /** Destroys all created elements and clears the internal map. */\n destroy(): void {\n for (const element of this.elementMap.values()) {\n element.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import type {\n CheckoutSession,\n NormalizedCheckoutSession,\n ProcessPaymentParams,\n TokenizedBody,\n BillingProvider,\n InlineSessionParams,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/** Raw billing API response wrapper. */\ninterface BillingResponse<T> {\n data: T;\n}\n\n/** Raw checkout session from the billing API (includes gateway field). */\ninterface RawCheckoutSession {\n uuid: string;\n nonce: string;\n gateway?: BillingProvider;\n status: 'pending' | 'completed';\n successUrl: string;\n cancelUrl: string;\n createdAt?: string;\n checkoutUrl?: string;\n items: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerItemId: string;\n providerItemName: string;\n providerItemDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n metadata?: Record<string, unknown> | null;\n }>;\n subscriptions: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerPlanId: string;\n providerPlanName: string;\n providerPlanDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n isUpdate?: boolean;\n metadata?: Record<string, unknown> | null;\n }>;\n coupons?: string[];\n checkoutMode?: 'full' | 'auto' | 'confirm';\n gatewayData: {\n publishableKey?: string | null;\n };\n accountData: {\n userId: string;\n firstName: string;\n lastName: string;\n email: string;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: string | null;\n };\n tagsData: {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n };\n}\n\n/**\n * Client-side payment API service.\n *\n * Mirrors the `PaymentAPI` class from the checkout project's\n * `src/service/api.ts`. All methods call the billing API endpoints\n * that the checkout backend exposes.\n */\nexport class PaymentAPI {\n private readonly baseUrl: string;\n\n constructor(billingApiUrl: string) {\n this.baseUrl = billingApiUrl.replace(/\\/+$/, '');\n }\n\n /** Fetch a raw checkout session by ID. */\n async getCheckoutSession(\n checkoutSessionId: string,\n ): Promise<BillingResponse<RawCheckoutSession>> {\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${checkoutSessionId}`,\n );\n\n if (!response.ok) {\n throw new FloPayError(\n 'Failed to get checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n return response.json() as Promise<BillingResponse<RawCheckoutSession>>;\n }\n\n /**\n * Fetch and normalize a checkout session.\n *\n * Reads the backend's `gateway` field to determine the provider,\n * then wraps the session in a `NormalizedCheckoutSession` for\n * provider-agnostic consumption.\n */\n async getUnifiedCheckoutSession(\n checkoutSessionId: string,\n ): Promise<NormalizedCheckoutSession> {\n const res = await this.getCheckoutSession(checkoutSessionId);\n return this.normalizeRawSession(res.data);\n }\n\n /**\n * Submit a tokenized payment to the billing backend.\n *\n * The backend will either succeed, return `type: '3ds_required'`\n * (with a `threeDSecureToken`), or return `type: 'paypal_redirect_required'`.\n */\n async processPayment(\n userId: string,\n data: ProcessPaymentParams,\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/sessions/process`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-user-id': userId,\n },\n body: JSON.stringify(data),\n },\n );\n }\n\n /**\n * Create a PaymentIntent on the backend.\n *\n * Used by the Stripe flow to create a server-side PaymentIntent\n * with the client's payment method attached.\n */\n async createPaymentIntent(\n sessionId: string,\n email: string,\n paymentMethodType: string,\n options?: { signal?: AbortSignal; isPaypal?: string },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n email,\n paymentMethodType,\n isPaypal: options?.isPaypal ?? false,\n }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Create a SetupIntent for saving payment methods.\n */\n async createSetupIntent(\n sessionId: string,\n email: string,\n paymentMethodType: 'card' | 'google_pay' | 'apple_pay' | 'paypal_express_checkout',\n options?: { signal?: AbortSignal },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/setup-intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, email, paymentMethodType }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Fetch user's prior payments by email.\n * Used to determine if saved card UX should be shown.\n */\n async getPaymentsByEmail(\n email: string,\n options?: { signal?: AbortSignal; page?: number; limit?: number },\n ): Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }> {\n const page = options?.page ?? 1;\n const limit = options?.limit ?? 1;\n const params = new URLSearchParams({\n email,\n page: String(page),\n limit: String(limit),\n sortField: 'occurredAt',\n sortDirection: 'DESC',\n });\n\n const response = await fetch(\n `${this.baseUrl}/v1/payments?${params.toString()}`,\n {\n method: 'GET',\n signal: options?.signal,\n keepalive: true,\n },\n );\n\n if (!response.ok) {\n throw new FloPayError('Failed to fetch payments', 'api_error');\n }\n\n return response.json() as Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }>;\n }\n\n /**\n * Create a checkout session AND return the full session data in one call.\n * Uses `?expand=true` so the backend returns the complete session\n * instead of just a UUID — eliminating the need for a second GET.\n *\n * Falls back to create + GET if the backend doesn't support `expand`.\n */\n async createAndFetchSession(\n params: InlineSessionParams,\n ): Promise<NormalizedCheckoutSession> {\n const payload: Record<string, unknown> = {\n clientId: params.clientId,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n checkoutMode: params.checkoutMode ?? 'full',\n items: (params.items ?? []).map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: (params.subscriptions ?? []).map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: params.account.userId,\n firstName: params.account.firstName ?? null,\n lastName: params.account.lastName ?? null,\n email: params.account.email,\n country: params.account.country ?? null,\n gender: params.account.gender ?? null,\n city: params.account.city ?? null,\n state: params.account.state ?? null,\n zip: params.account.zip ?? null,\n },\n couponCodes: params.couponCodes ?? [],\n };\n\n if (params.tagsData) payload['tagsData'] = params.tagsData;\n if (params.utmMetadata?.length) payload['utmMetadata'] = params.utmMetadata;\n\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions?expand=true`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n );\n\n if (response.status === 204) {\n throw new FloPayError(\n 'Session auto-completed — payment method already on file',\n 'api_error',\n { code: 'session_auto_completed' },\n );\n }\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new FloPayError(\n (body as Record<string, string> | null)?.message ?? 'Failed to create checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n const body = await response.json() as { data: RawCheckoutSession & { uuid?: string } };\n\n // If backend supports expand=true, it returns full session data.\n // If not, it returns { data: { uuid } } and we fall back to a GET.\n if (body.data && 'gateway' in body.data) {\n // Full session returned — normalize directly\n return this.normalizeRawSession(body.data);\n }\n\n // Fallback: backend returned UUID only — fetch full session\n const uuid = body.data?.uuid;\n if (!uuid) {\n throw new FloPayError('No session ID returned', 'api_error');\n }\n return this.getUnifiedCheckoutSession(uuid);\n }\n\n /** Normalize a raw session into a provider-agnostic shape. */\n private normalizeRawSession(session: RawCheckoutSession): NormalizedCheckoutSession {\n const gateway = session.gateway;\n\n if (gateway === 'chargebee') {\n return {\n provider: 'chargebee',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n if (gateway === 'stripe') {\n return {\n provider: 'stripe',\n mode: 'tokenize',\n data: {\n session: this.toCheckoutSession(session),\n stripe: {\n clientSecret: (session as unknown as Record<string, unknown>)['stripeClientSecret'] as string ?? '',\n publishableKey: session.gatewayData?.publishableKey ?? undefined,\n },\n },\n raw: { data: session },\n };\n }\n\n return {\n provider: 'recurly',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n /** Convert raw session to the SDK CheckoutSession shape. */\n private toCheckoutSession(raw: RawCheckoutSession): CheckoutSession {\n const totalAmount = [\n ...raw.subscriptions.map((s) => s.overrideAmount || s.totalAmount),\n ...raw.items.map((i) => i.overrideAmount || i.totalAmount),\n ].reduce((sum, val) => sum + val, 0);\n\n // Billing API returns amounts in major units (e.g. 24.95 USD).\n // Stripe expects amounts in smallest currency unit (cents).\n const amountInCents = Math.round(totalAmount * 100);\n\n return {\n // Core fields (backward compat)\n id: raw.uuid,\n clientSecret: raw.nonce,\n mode: raw.subscriptions.length > 0 ? 'subscription' : 'payment',\n status: raw.status === 'completed' ? 'complete' : 'open',\n amount: amountInCents,\n currency: raw.subscriptions[0]?.currency ?? raw.items[0]?.currency ?? 'USD',\n customer: {\n id: raw.accountData.userId,\n email: raw.accountData.email,\n firstName: raw.accountData.firstName,\n lastName: raw.accountData.lastName,\n country: raw.accountData.country ?? undefined,\n city: raw.accountData.city ?? undefined,\n state: raw.accountData.state ?? undefined,\n zip: raw.accountData.zip ?? undefined,\n gender: raw.accountData.gender ?? undefined,\n },\n metadata: {},\n\n // Full session data from billing API\n checkoutMode: raw.checkoutMode,\n items: raw.items,\n subscriptions: raw.subscriptions,\n successUrl: raw.successUrl,\n cancelUrl: raw.cancelUrl,\n coupons: raw.coupons,\n createdAt: raw.createdAt,\n gateway: raw.gateway,\n gatewayData: raw.gatewayData,\n accountData: raw.accountData,\n tagsData: raw.tagsData,\n };\n }\n}\n","import type {\n CreateSessionParams,\n CheckoutSessionResult,\n} from '@flopay/shared';\n\n/**\n * Creates a checkout session via the billing API and redirects the user\n * to the hosted checkout page.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n *\n * - On 201: Redirects to `{checkoutBaseUrl}/secure?id={uuid}&...redirectParams`\n * - On 204: Redirects directly to `successUrl` (payment method already on file)\n * - On other: Returns `{ status }` without redirecting\n *\n * @example\n * ```ts\n * import { createCheckoutSession } from '@flopay/js';\n *\n * await createCheckoutSession({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{\n * providerItemId: 'prod_abc',\n * providerItemName: 'Pro Plan',\n * totalAmount: 49.99,\n * overrideAmount: 24.99,\n * }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * redirectParams: { email: 'user@example.com', bg: 'courses', mode: 'confirm' },\n * });\n * ```\n */\nexport async function createCheckoutSession(\n options: CreateSessionParams,\n): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n setCookie = true,\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = options;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body — leave undefined\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n if (setCookie && typeof window !== 'undefined' && typeof document !== 'undefined') {\n const checkoutData = JSON.stringify({ origin_url: cancelUrl });\n const domain = window.location.hostname.split('.').slice(-2).join('.');\n document.cookie = `checkout_data=${encodeURIComponent(checkoutData)}; domain=.${domain}; path=/; max-age=3600; SameSite=Lax; Secure;`;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = redirectUrl.toString();\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n if (typeof window !== 'undefined') {\n window.location.href = successUrl;\n }\n return { status: 204 };\n }\n\n return { status };\n}\n\n/**\n * Creates a checkout session with automatic retry on timeout/abort errors.\n *\n * Uses exponential backoff: 100ms, 200ms, 400ms, etc.\n */\nexport async function createCheckoutSessionWithRetries(\n options: CreateSessionParams & { maxRetries?: number },\n): Promise<CheckoutSessionResult> {\n const { maxRetries = 3, ...sessionOptions } = options;\n\n if (!Number.isFinite(maxRetries) || !Number.isInteger(maxRetries) || maxRetries <= 0) {\n throw new Error('Number of retries must be greater than 0');\n }\n\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await createCheckoutSession(sessionOptions);\n } catch (err) {\n lastErr = err;\n\n if (err instanceof Error && err.name === 'AbortError' && attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));\n continue;\n }\n\n throw err;\n }\n }\n\n throw lastErr ?? new Error('Unknown error during checkout session creation');\n}\n"],"mappings":"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","names":["import_shared","import_shared","import_shared","import_shared","body"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/load.ts","../src/stripe-adapter.ts","../src/flopay.ts","../src/elements.ts","../src/payment-api.ts","../src/create-checkout-session.ts"],"sourcesContent":["export { loadFloPay } from './load.js';\nexport { FloPay } from './flopay.js';\nexport { FloPayElements } from './elements.js';\nexport { StripeAdapter } from './stripe-adapter.js';\nexport { PaymentAPI } from './payment-api.js';\nexport { createCheckoutSession, createCheckoutSessionWithRetries } from './create-checkout-session.js';\n","import type { FloPayConfig } from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\nimport { StripeAdapter } from './stripe-adapter.js';\nimport { FloPay } from './flopay.js';\n\n/** Cache to avoid re-initializing for the same key. */\nlet cachedInstance: FloPay | null = null;\nlet cachedKey: string | null = null;\n\n/**\n * Loads and initializes the FloPay SDK.\n *\n * This is the primary entry point for consumer applications.\n * It initializes the underlying payment provider (currently Stripe)\n * and returns a ready-to-use `FloPay` instance.\n *\n * @example\n * ```ts\n * import { loadFloPay } from '@flopay/js';\n *\n * const flopay = await loadFloPay('pk_test_...');\n * const elements = flopay.elements();\n * const cardElement = await elements.create('card');\n * cardElement.mount('#card-container');\n * ```\n */\nexport async function loadFloPay(\n publishableKey: string,\n options?: Omit<FloPayConfig, 'publishableKey'>,\n): Promise<FloPay> {\n if (!publishableKey) {\n throw new FloPayError(\n 'A publishable key is required to initialize FloPay.',\n 'validation_error',\n { param: 'publishableKey' },\n );\n }\n\n // Return cached instance if key matches\n if (cachedInstance && cachedKey === publishableKey) {\n return cachedInstance;\n }\n\n // Clean up previous instance\n if (cachedInstance) {\n cachedInstance.destroy();\n }\n\n const config: FloPayConfig = {\n publishableKey,\n ...options,\n };\n\n // Currently only Stripe is supported. The adapter pattern allows\n // adding Chargebee, Recurly, or other providers in the future.\n const adapter = new StripeAdapter();\n await adapter.initialize(config);\n\n const instance = new FloPay(adapter, config);\n\n cachedKey = publishableKey;\n cachedInstance = instance;\n\n return instance;\n}\n","import type { Stripe, StripeElements, StripeElementType } from '@stripe/stripe-js';\nimport type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementType,\n ElementOptions,\n MountedElement,\n ConfirmPaymentParams,\n PaymentResult,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n BillingDetails,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Maps FloPay element types to Stripe element types.\n * FloPay uses camelCase; Stripe uses lowercase with hyphens or specific names.\n */\nfunction toStripeElementType(type: ElementType): StripeElementType {\n const map: Record<ElementType, string> = {\n payment: 'payment',\n card: 'card',\n cardNumber: 'cardNumber',\n cardExpiry: 'cardExpiry',\n cardCvc: 'cardCvc',\n address: 'address',\n };\n return map[type] as StripeElementType;\n}\n\n/**\n * Wraps a Stripe element instance in the FloPay MountedElement interface.\n *\n * TODO: In a future phase, this wrapper will render the Stripe element inside\n * an iframe hosted on the FloPay domain for PCI DSS SAQ-A compliance.\n * For now, it delegates directly to the Stripe element.\n */\n/** Minimal interface shared by all Stripe element types. */\ninterface StripeElementLike {\n mount(domElement: string | HTMLElement): void;\n unmount(): void;\n destroy(): void;\n update(options?: Record<string, unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void): void;\n off(event: string, handler?: (...args: unknown[]) => void): void;\n}\n\nfunction wrapStripeElement(\n stripeElement: StripeElementLike,\n): MountedElement {\n const el = stripeElement;\n\n return {\n mount(container: HTMLElement) {\n el.mount(container);\n },\n unmount() {\n el.unmount();\n },\n update(options: Partial<ElementOptions>) {\n el.update(options as Record<string, unknown>);\n },\n on(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['on']?.(event, handler);\n },\n off(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['off']?.(event, handler);\n },\n destroy() {\n el.destroy();\n },\n };\n}\n\n/**\n * Payment provider adapter backed by Stripe.\n *\n * Implements the `PaymentProviderAdapter` interface so that FloPay consumers\n * interact with a stable API regardless of the upstream provider.\n */\nexport class StripeAdapter implements PaymentProviderAdapter {\n readonly name = 'stripe';\n private stripe: Stripe | null = null;\n private elements: StripeElements | null = null;\n\n async initialize(config: FloPayConfig): Promise<void> {\n // loadStripe only works in the browser — skip initialization during SSR/SSG\n if (typeof window === 'undefined') {\n return;\n }\n\n const { loadStripe } = await import('@stripe/stripe-js');\n const stripe = await loadStripe(config.publishableKey, {\n locale: (config.locale as 'auto') ?? 'auto',\n });\n\n if (!stripe) {\n throw new FloPayError(\n 'Failed to initialize Stripe. Check your publishable key.',\n 'authentication_error',\n );\n }\n\n this.stripe = stripe;\n }\n\n /** Lazily creates the Stripe Elements group for the given options. */\n private getElements(options?: ElementOptions): StripeElements {\n if (!this.stripe) {\n throw new FloPayError(\n 'StripeAdapter not initialized. Call initialize() first.',\n 'api_error',\n );\n }\n\n if (!this.elements) {\n let elementsOptions: Record<string, unknown>;\n\n if (options?.clientSecret) {\n // Server-side intent already exists — pass its client secret\n elementsOptions = { clientSecret: options.clientSecret };\n } else {\n // No server-side intent yet — use deferred mode with manual payment method creation.\n // This matches checkout/StripeCardForm: mode='payment', paymentMethodCreation='manual'.\n elementsOptions = {\n mode: 'payment' as const,\n amount: options?.amount ?? 0,\n currency: (options?.currency ?? 'usd').toLowerCase(),\n paymentMethodCreation: options?.paymentMethodCreation ?? ('manual' as const),\n };\n }\n\n if (options?.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n this.elements = this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n return this.elements;\n }\n\n async createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement> {\n const elements = this.getElements(options);\n const stripeType = toStripeElementType(type);\n\n const elementOptions: Record<string, unknown> = {};\n if (options.layout) {\n elementOptions['layout'] = options.layout;\n }\n if (options.defaultValues) {\n elementOptions['defaultValues'] = options.defaultValues;\n }\n if (options.readOnly) {\n elementOptions['readOnly'] = options.readOnly;\n }\n if (options.mode) {\n elementOptions['mode'] = options.mode;\n }\n if (options.style) {\n elementOptions['style'] = options.style;\n }\n\n const stripeElement = elements.create(stripeType as 'card', elementOptions) as unknown as StripeElementLike;\n return wrapStripeElement(stripeElement);\n }\n\n getElement(type: ElementType): MountedElement | null {\n if (!this.elements) return null;\n const stripeType = toStripeElementType(type);\n const existing = this.elements.getElement(stripeType as 'card') as unknown as StripeElementLike | null;\n if (!existing) return null;\n return wrapStripeElement(existing);\n }\n\n async submitElements(): Promise<{ error?: FloPayError }> {\n if (!this.stripe || !this.elements) {\n return { error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n const { error } = await this.elements.submit();\n if (error) {\n return {\n error: new FloPayError(error.message ?? 'Validation failed', 'validation_error'),\n };\n }\n return {};\n }\n\n async createPaymentMethod(billingDetails?: BillingDetails): Promise<CreatePaymentMethodResult> {\n if (!this.stripe || !this.elements) {\n return {\n paymentMethodId: null,\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n // Detect split card fields vs unified PaymentElement.\n // With split fields (cardNumber + cardExpiry + cardCvc), Stripe requires\n // passing the specific cardNumber element with type: 'card'.\n // With unified PaymentElement, pass the elements group.\n const cardNumberEl = this.elements.getElement('cardNumber' as 'card');\n\n // Build billing_details for Stripe AVS (Address Verification).\n // When present, Stripe runs postal code and address checks automatically.\n const stripeBilling = billingDetails ? {\n billing_details: {\n ...(billingDetails.name ? { name: billingDetails.name } : {}),\n ...(billingDetails.address ? {\n address: {\n ...(billingDetails.address.country ? { country: billingDetails.address.country } : {}),\n ...(billingDetails.address.postal_code ? { postal_code: billingDetails.address.postal_code } : {}),\n ...(billingDetails.address.city ? { city: billingDetails.address.city } : {}),\n ...(billingDetails.address.line1 ? { line1: billingDetails.address.line1 } : {}),\n ...(billingDetails.address.line2 ? { line2: billingDetails.address.line2 } : {}),\n ...(billingDetails.address.state ? { state: billingDetails.address.state } : {}),\n },\n } : {}),\n },\n } : {};\n\n const { error, paymentMethod } = cardNumberEl\n ? await this.stripe.createPaymentMethod({\n type: 'card',\n card: cardNumberEl,\n ...stripeBilling,\n } as unknown as Parameters<typeof this.stripe.createPaymentMethod>[0])\n : await this.stripe.createPaymentMethod({\n elements: this.elements,\n ...stripeBilling,\n } as unknown as Parameters<typeof this.stripe.createPaymentMethod>[0]);\n\n if (error) {\n return {\n paymentMethodId: null,\n error: new FloPayError(\n error.message ?? 'Failed to create payment method',\n 'api_error',\n { code: error.code },\n ),\n };\n }\n\n return { paymentMethodId: paymentMethod.id };\n }\n\n async confirmCardPayment(\n params: ConfirmCardPaymentParams,\n ): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return {\n status: 'failed',\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n const { error, paymentIntent } = await this.stripe.confirmCardPayment(\n params.clientSecret,\n { payment_method: params.paymentMethodId },\n );\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n { code: error.code, declineCode: error.decline_code },\n ),\n };\n }\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n };\n }\n\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n if (!this.stripe || !this.elements) {\n throw new FloPayError(\n 'StripeAdapter not initialized or no elements created.',\n 'api_error',\n );\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n elements: this.elements,\n clientSecret: params.clientSecret,\n confirmParams: {\n return_url: params.returnUrl ?? window.location.href,\n },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n {\n code: error.code,\n declineCode: error.decline_code,\n },\n ),\n };\n }\n\n if (!paymentIntent) {\n return { status: 'failed', error: new FloPayError('No payment intent returned', 'api_error') };\n }\n\n const statusMap: Record<string, PaymentResult['status']> = {\n succeeded: 'succeeded',\n processing: 'processing',\n requires_action: 'requires_action',\n requires_payment_method: 'failed',\n canceled: 'failed',\n };\n\n return {\n status: statusMap[paymentIntent.status] ?? 'failed',\n paymentIntentId: paymentIntent.id,\n };\n }\n\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return { status: 'failed', error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n\n const baseUrl = params.billingApiUrl.replace(/\\/+$/, '');\n\n // 1. Create a PayPal PaymentMethod upfront — backend needs pm_xxx\n // Mirrors checkout/StripeCardForm: stripe.createPaymentMethod({ type: 'paypal' })\n const createPM = this.stripe.createPaymentMethod as unknown as (\n params: { type: string },\n ) => Promise<{ error?: { message?: string }; paymentMethod?: { id: string } }>;\n\n const { error: pmError, paymentMethod } = await createPM({ type: 'paypal' });\n\n if (pmError) {\n console.warn('[FloPay] Could not create PayPal PM upfront:', pmError.message);\n }\n\n // 2. Create PaymentIntent via billing API with pm_xxx (or 'paypal' fallback)\n // isPaypal MUST be string 'true', not boolean — backend checks === 'true'\n const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId: params.sessionId,\n email: params.email,\n paymentMethodType: paymentMethod?.id ?? 'paypal',\n isPaypal: 'true',\n }),\n });\n\n if (!intentResponse.ok) {\n return { status: 'failed', error: new FloPayError('Failed to create PayPal payment intent', 'api_error') };\n }\n\n const intentJson = await intentResponse.json() as { data?: { id?: string } };\n const intentClientSecret = intentJson.data?.id;\n if (!intentClientSecret) {\n return { status: 'failed', error: new FloPayError('No client_secret in response', 'api_error') };\n }\n\n // 3. Confirm — pass payment_method if we have it (avoids setupFutureUsage mismatch)\n // Matches checkout: stripe.confirmPayment({ clientSecret, confirmParams: { payment_method, return_url } })\n const confirmParams: Record<string, unknown> = {\n return_url: params.returnUrl,\n };\n if (paymentMethod?.id) {\n confirmParams['payment_method'] = paymentMethod.id;\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n clientSecret: intentClientSecret,\n confirmParams: confirmParams as { return_url: string },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'PayPal payment failed', 'api_error', { code: error.code }),\n };\n }\n\n const pmId = typeof paymentIntent?.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent?.payment_method?.id;\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n paymentMethodId: pmId,\n };\n }\n\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n if (!this.stripe || typeof window === 'undefined') return null;\n\n const params = new URLSearchParams(window.location.search);\n const paymentIntentId = params.get('payment_intent');\n const clientSecret = params.get('payment_intent_client_secret');\n const redirectStatus = params.get('redirect_status');\n\n if (!paymentIntentId || !clientSecret) return null;\n\n if (redirectStatus === 'failed') {\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was declined. Please try again.', 'api_error'),\n };\n }\n\n const { paymentIntent, error } = await this.stripe.retrievePaymentIntent(clientSecret);\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'Failed to retrieve PayPal payment', 'api_error'),\n };\n }\n\n if (paymentIntent && (paymentIntent.status === 'requires_capture' || paymentIntent.status === 'succeeded')) {\n const pmId = typeof paymentIntent.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent.payment_method?.id;\n\n // Clean up URL params\n const url = new URL(window.location.href);\n url.searchParams.delete('payment_intent');\n url.searchParams.delete('payment_intent_client_secret');\n url.searchParams.delete('redirect_status');\n window.history.replaceState({}, '', url.toString());\n\n return {\n status: paymentIntent.status as ConfirmCardPaymentResult['status'],\n paymentIntentId: paymentIntent.id,\n paymentMethodId: pmId,\n };\n }\n\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was not completed. Please try again.', 'api_error'),\n };\n }\n\n getRawProvider(): unknown {\n return this.stripe;\n }\n\n createPayPalElements(options: ElementOptions): unknown {\n if (!this.stripe) return null;\n\n const elementsOptions: Record<string, unknown> = {\n mode: 'payment' as const,\n amount: options.amount ?? 0,\n currency: (options.currency ?? 'usd').toLowerCase(),\n captureMethod: 'manual' as const,\n };\n\n if (options.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n return this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n destroy(): void {\n this.elements = null;\n this.stripe = null;\n }\n}\n","import type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementOptions,\n ConfirmPaymentParams,\n PaymentResult,\n CheckoutSession,\n NormalizedCheckoutSession,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError, resolveBillingApiUrl } from '@flopay/shared';\nimport { FloPayElements } from './elements.js';\nimport { PaymentAPI } from './payment-api.js';\n\n/**\n * The main FloPay SDK instance.\n *\n * Created via `loadFloPay(publishableKey)`. Provides element management,\n * payment confirmation, and session retrieval.\n */\nexport class FloPay {\n private readonly provider: PaymentProviderAdapter;\n private readonly config: FloPayConfig;\n private currentElements: FloPayElements | null = null;\n\n constructor(provider: PaymentProviderAdapter, config: FloPayConfig) {\n this.provider = provider;\n this.config = config;\n }\n\n /**\n * Creates a new `FloPayElements` group for mounting payment fields.\n *\n * Only one elements group is active at a time. Creating a new one\n * destroys the previous group.\n */\n elements(options?: ElementOptions): FloPayElements {\n if (this.currentElements) {\n this.currentElements.destroy();\n }\n this.currentElements = new FloPayElements(this.provider, {\n appearance: this.config.appearance,\n ...options,\n });\n return this.currentElements;\n }\n\n /** Submit elements for validation. */\n async submitElements(): Promise<{ error?: import('@flopay/shared').FloPayError }> {\n return this.provider.submitElements();\n }\n\n /** Create a payment method from the current elements (tokenize card). */\n async createPaymentMethod(billingDetails?: import('@flopay/shared').BillingDetails): Promise<CreatePaymentMethodResult> {\n return this.provider.createPaymentMethod(billingDetails);\n }\n\n /** Confirm a card payment with a known client secret and payment method ID. */\n async confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmCardPayment(params);\n }\n\n /** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmPayPalPayment(params);\n }\n\n /** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n return this.provider.resumePayPalPayment();\n }\n\n /** Confirms a payment using the mounted elements. */\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n return this.provider.confirmPayment(params);\n }\n\n /**\n * Retrieves a checkout session by ID via the billing API.\n *\n * Returns the normalized `CheckoutSession` with amount, currency,\n * customer data, and status.\n *\n * Requires `billingApiUrl` to be set — either via `loadFloPay(key, { billingApiUrl })`\n * or passed directly as the second argument.\n */\n async retrieveSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<CheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required to retrieve a session.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n const unified = await api.getUnifiedCheckoutSession(sessionId);\n if (!unified.data.session) {\n throw new FloPayError('Session not found', 'api_error');\n }\n return unified.data.session;\n }\n\n /**\n * Retrieves and normalizes a checkout session, including provider-specific\n * data (Stripe clientSecret/publishableKey, Chargebee site, etc.).\n *\n * The billing API URL is resolved from: explicit param → `loadFloPay()` config\n * → `NEXT_PUBLIC_FLOPAY_ENV` env var → `configureFlopay()` → staging fallback.\n */\n async retrieveUnifiedSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<NormalizedCheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n return api.getUnifiedCheckoutSession(sessionId);\n }\n\n /**\n * Returns the raw underlying provider instance (e.g. Stripe object).\n * Used internally by components that need direct provider access,\n * such as PayPal which requires its own Elements instance.\n */\n getRawProvider(): unknown {\n return this.provider.getRawProvider();\n }\n\n /** Tears down the SDK instance and releases resources. */\n destroy(): void {\n this.currentElements?.destroy();\n this.currentElements = null;\n this.provider.destroy();\n }\n}\n","import type {\n PaymentProviderAdapter,\n ElementType,\n ElementOptions,\n MountedElement,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Manages the creation and lifecycle of payment elements.\n *\n * Each `FloPayElements` instance is bound to a single provider adapter\n * and tracks all created elements for cleanup.\n */\nexport class FloPayElements {\n private readonly provider: PaymentProviderAdapter;\n private readonly elementMap = new Map<ElementType, MountedElement>();\n private readonly baseOptions: ElementOptions;\n\n constructor(provider: PaymentProviderAdapter, options?: ElementOptions) {\n this.provider = provider;\n this.baseOptions = options ?? {};\n }\n\n /**\n * Creates a new element of the given type.\n * If an element of that type already exists, it is destroyed first.\n */\n async create(\n type: ElementType,\n options?: ElementOptions,\n ): Promise<MountedElement> {\n // Check if the provider already has this element (e.g. after React\n // Strict Mode unmount+remount cycle). Reuse it instead of creating\n // a duplicate, which Stripe would reject.\n const providerExisting = this.provider.getElement(type);\n if (providerExisting) {\n this.elementMap.set(type, providerExisting);\n return providerExisting;\n }\n\n const existing = this.elementMap.get(type);\n if (existing) {\n existing.destroy();\n }\n\n const merged: ElementOptions = { ...this.baseOptions, ...options };\n const element = await this.provider.createElement(type, merged);\n this.elementMap.set(type, element);\n return element;\n }\n\n /** Returns a previously created element, or `null`. */\n getElement(type: ElementType): MountedElement | null {\n return this.elementMap.get(type) ?? null;\n }\n\n /**\n * Submits all mounted elements for validation.\n *\n * Returns an object with an optional error if validation fails.\n * This does NOT confirm the payment — call `floPay.confirmPayment()` for that.\n */\n async submit(): Promise<{ error?: FloPayError }> {\n // Walk through all mounted elements and check for incomplete state.\n // The actual validation is handled by the provider's element implementation.\n // For Stripe, the Elements.submit() method is called during confirmPayment.\n // This method exists to match the Stripe Elements API surface.\n return {};\n }\n\n /** Destroys all created elements and clears the internal map. */\n destroy(): void {\n for (const element of this.elementMap.values()) {\n element.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import type {\n CheckoutSession,\n NormalizedCheckoutSession,\n ProcessPaymentParams,\n TokenizedBody,\n BillingProvider,\n InlineSessionParams,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/** Raw billing API response wrapper. */\ninterface BillingResponse<T> {\n data: T;\n}\n\n/** Raw checkout session from the billing API (includes gateway field). */\ninterface RawCheckoutSession {\n uuid: string;\n nonce: string;\n gateway?: BillingProvider;\n status: 'pending' | 'completed';\n successUrl: string;\n cancelUrl: string;\n createdAt?: string;\n checkoutUrl?: string;\n items: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerItemId: string;\n providerItemName: string;\n providerItemDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n metadata?: Record<string, unknown> | null;\n }>;\n subscriptions: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerPlanId: string;\n providerPlanName: string;\n providerPlanDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n isUpdate?: boolean;\n metadata?: Record<string, unknown> | null;\n }>;\n coupons?: string[];\n checkoutMode?: 'full' | 'auto' | 'confirm';\n gatewayData: {\n publishableKey?: string | null;\n };\n accountData: {\n userId: string;\n firstName: string;\n lastName: string;\n email: string;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: string | null;\n };\n tagsData: {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n };\n}\n\n/**\n * Client-side payment API service.\n *\n * Mirrors the `PaymentAPI` class from the checkout project's\n * `src/service/api.ts`. All methods call the billing API endpoints\n * that the checkout backend exposes.\n */\nexport class PaymentAPI {\n private readonly baseUrl: string;\n\n constructor(billingApiUrl: string) {\n this.baseUrl = billingApiUrl.replace(/\\/+$/, '');\n }\n\n /** Fetch a raw checkout session by ID. */\n async getCheckoutSession(\n checkoutSessionId: string,\n ): Promise<BillingResponse<RawCheckoutSession>> {\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${checkoutSessionId}`,\n );\n\n if (!response.ok) {\n throw new FloPayError(\n 'Failed to get checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n return response.json() as Promise<BillingResponse<RawCheckoutSession>>;\n }\n\n /**\n * Fetch and normalize a checkout session.\n *\n * Reads the backend's `gateway` field to determine the provider,\n * then wraps the session in a `NormalizedCheckoutSession` for\n * provider-agnostic consumption.\n */\n async getUnifiedCheckoutSession(\n checkoutSessionId: string,\n ): Promise<NormalizedCheckoutSession> {\n const res = await this.getCheckoutSession(checkoutSessionId);\n return this.normalizeRawSession(res.data);\n }\n\n /**\n * Submit a tokenized payment to the billing backend.\n *\n * The backend will either succeed, return `type: '3ds_required'`\n * (with a `threeDSecureToken`), or return `type: 'paypal_redirect_required'`.\n */\n async processPayment(\n userId: string,\n data: ProcessPaymentParams,\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/sessions/process`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-user-id': userId,\n },\n body: JSON.stringify(data),\n },\n );\n }\n\n /**\n * Create a PaymentIntent on the backend.\n *\n * Used by the Stripe flow to create a server-side PaymentIntent\n * with the client's payment method attached.\n */\n async createPaymentIntent(\n sessionId: string,\n email: string,\n paymentMethodType: string,\n options?: { signal?: AbortSignal; isPaypal?: string },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n email,\n paymentMethodType,\n isPaypal: options?.isPaypal ?? false,\n }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Create a SetupIntent for saving payment methods.\n */\n async createSetupIntent(\n sessionId: string,\n email: string,\n paymentMethodType: 'card' | 'google_pay' | 'apple_pay' | 'paypal_express_checkout',\n options?: { signal?: AbortSignal },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/setup-intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, email, paymentMethodType }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Fetch user's prior payments by email.\n * Used to determine if saved card UX should be shown.\n */\n async getPaymentsByEmail(\n email: string,\n options?: { signal?: AbortSignal; page?: number; limit?: number },\n ): Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }> {\n const page = options?.page ?? 1;\n const limit = options?.limit ?? 1;\n const params = new URLSearchParams({\n email,\n page: String(page),\n limit: String(limit),\n sortField: 'occurredAt',\n sortDirection: 'DESC',\n });\n\n const response = await fetch(\n `${this.baseUrl}/v1/payments?${params.toString()}`,\n {\n method: 'GET',\n signal: options?.signal,\n keepalive: true,\n },\n );\n\n if (!response.ok) {\n throw new FloPayError('Failed to fetch payments', 'api_error');\n }\n\n return response.json() as Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }>;\n }\n\n /**\n * Create a checkout session AND return the full session data in one call.\n * Uses `?expand=true` so the backend returns the complete session\n * instead of just a UUID — eliminating the need for a second GET.\n *\n * Falls back to create + GET if the backend doesn't support `expand`.\n */\n async createAndFetchSession(\n params: InlineSessionParams,\n ): Promise<NormalizedCheckoutSession> {\n const payload: Record<string, unknown> = {\n clientId: params.clientId,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n checkoutMode: params.checkoutMode ?? 'full',\n items: (params.items ?? []).map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: (params.subscriptions ?? []).map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: params.account.userId,\n firstName: params.account.firstName ?? null,\n lastName: params.account.lastName ?? null,\n email: params.account.email,\n country: params.account.country ?? null,\n gender: params.account.gender ?? null,\n city: params.account.city ?? null,\n state: params.account.state ?? null,\n zip: params.account.zip ?? null,\n },\n couponCodes: params.couponCodes ?? [],\n };\n\n if (params.tagsData) payload['tagsData'] = params.tagsData;\n if (params.utmMetadata?.length) payload['utmMetadata'] = params.utmMetadata;\n\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions?expand=true`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n );\n\n if (response.status === 204) {\n throw new FloPayError(\n 'Session auto-completed — payment method already on file',\n 'api_error',\n { code: 'session_auto_completed' },\n );\n }\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new FloPayError(\n (body as Record<string, string> | null)?.message ?? 'Failed to create checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n const body = await response.json() as { data: RawCheckoutSession & { uuid?: string } };\n\n // If backend supports expand=true, it returns full session data.\n // If not, it returns { data: { uuid } } and we fall back to a GET.\n if (body.data && 'gateway' in body.data) {\n // Full session returned — normalize directly\n return this.normalizeRawSession(body.data);\n }\n\n // Fallback: backend returned UUID only — fetch full session\n const uuid = body.data?.uuid;\n if (!uuid) {\n throw new FloPayError('No session ID returned', 'api_error');\n }\n return this.getUnifiedCheckoutSession(uuid);\n }\n\n /** Normalize a raw session into a provider-agnostic shape. */\n private normalizeRawSession(session: RawCheckoutSession): NormalizedCheckoutSession {\n const gateway = session.gateway;\n\n if (gateway === 'chargebee') {\n return {\n provider: 'chargebee',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n if (gateway === 'stripe') {\n return {\n provider: 'stripe',\n mode: 'tokenize',\n data: {\n session: this.toCheckoutSession(session),\n stripe: {\n clientSecret: (session as unknown as Record<string, unknown>)['stripeClientSecret'] as string ?? '',\n publishableKey: session.gatewayData?.publishableKey ?? undefined,\n },\n },\n raw: { data: session },\n };\n }\n\n return {\n provider: 'recurly',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n /** Convert raw session to the SDK CheckoutSession shape. */\n private toCheckoutSession(raw: RawCheckoutSession): CheckoutSession {\n const totalAmount = [\n ...raw.subscriptions.map((s) => s.overrideAmount || s.totalAmount),\n ...raw.items.map((i) => i.overrideAmount || i.totalAmount),\n ].reduce((sum, val) => sum + val, 0);\n\n // Billing API returns amounts in major units (e.g. 24.95 USD).\n // Stripe expects amounts in smallest currency unit (cents).\n const amountInCents = Math.round(totalAmount * 100);\n\n return {\n // Core fields (backward compat)\n id: raw.uuid,\n clientSecret: raw.nonce,\n mode: raw.subscriptions.length > 0 ? 'subscription' : 'payment',\n status: raw.status === 'completed' ? 'complete' : 'open',\n amount: amountInCents,\n currency: raw.subscriptions[0]?.currency ?? raw.items[0]?.currency ?? 'USD',\n customer: {\n id: raw.accountData.userId,\n email: raw.accountData.email,\n firstName: raw.accountData.firstName,\n lastName: raw.accountData.lastName,\n country: raw.accountData.country ?? undefined,\n city: raw.accountData.city ?? undefined,\n state: raw.accountData.state ?? undefined,\n zip: raw.accountData.zip ?? undefined,\n gender: raw.accountData.gender ?? undefined,\n },\n metadata: {},\n\n // Full session data from billing API\n checkoutMode: raw.checkoutMode,\n items: raw.items,\n subscriptions: raw.subscriptions,\n successUrl: raw.successUrl,\n cancelUrl: raw.cancelUrl,\n coupons: raw.coupons,\n createdAt: raw.createdAt,\n gateway: raw.gateway,\n gatewayData: raw.gatewayData,\n accountData: raw.accountData,\n tagsData: raw.tagsData,\n };\n }\n}\n","import type {\n CreateSessionParams,\n CheckoutSessionResult,\n} from '@flopay/shared';\n\n/**\n * Creates a checkout session via the billing API and redirects the user\n * to the hosted checkout page.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n *\n * - On 201: Redirects to `{checkoutBaseUrl}/secure?id={uuid}&...redirectParams`\n * - On 204: Redirects directly to `successUrl` (payment method already on file)\n * - On other: Returns `{ status }` without redirecting\n *\n * @example\n * ```ts\n * import { createCheckoutSession } from '@flopay/js';\n *\n * await createCheckoutSession({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{\n * providerItemId: 'prod_abc',\n * providerItemName: 'Pro Plan',\n * totalAmount: 49.99,\n * overrideAmount: 24.99,\n * }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * redirectParams: { email: 'user@example.com', bg: 'courses', mode: 'confirm' },\n * });\n * ```\n */\nexport async function createCheckoutSession(\n options: CreateSessionParams,\n): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n setCookie = true,\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = options;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body — leave undefined\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n if (setCookie && typeof window !== 'undefined' && typeof document !== 'undefined') {\n const checkoutData = JSON.stringify({ origin_url: cancelUrl });\n const domain = window.location.hostname.split('.').slice(-2).join('.');\n document.cookie = `checkout_data=${encodeURIComponent(checkoutData)}; domain=.${domain}; path=/; max-age=3600; SameSite=Lax; Secure;`;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = redirectUrl.toString();\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n if (typeof window !== 'undefined') {\n window.location.href = successUrl;\n }\n return { status: 204 };\n }\n\n return { status };\n}\n\n/**\n * Creates a checkout session with automatic retry on timeout/abort errors.\n *\n * Uses exponential backoff: 100ms, 200ms, 400ms, etc.\n */\nexport async function createCheckoutSessionWithRetries(\n options: CreateSessionParams & { maxRetries?: number },\n): Promise<CheckoutSessionResult> {\n const { maxRetries = 3, ...sessionOptions } = options;\n\n if (!Number.isFinite(maxRetries) || !Number.isInteger(maxRetries) || maxRetries <= 0) {\n throw new Error('Number of retries must be greater than 0');\n }\n\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await createCheckoutSession(sessionOptions);\n } catch (err) {\n lastErr = err;\n\n if (err instanceof Error && err.name === 'AbortError' && attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));\n continue;\n }\n\n throw err;\n }\n }\n\n throw lastErr ?? new Error('Unknown error during checkout session creation');\n}\n"],"mappings":"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","names":["import_shared","import_shared","import_shared","import_shared","body"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _flopay_shared from '@flopay/shared';
2
- import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CreatePaymentMethodResult, ConfirmCardPaymentParams, ConfirmCardPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, BillingProvider, ProcessPaymentParams, InlineSessionParams, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
2
+ import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CreatePaymentMethodResult, ConfirmCardPaymentParams, ConfirmCardPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, BillingDetails, BillingProvider, ProcessPaymentParams, InlineSessionParams, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
3
3
 
4
4
  /**
5
5
  * Manages the creation and lifecycle of payment elements.
@@ -55,7 +55,7 @@ declare class FloPay {
55
55
  error?: _flopay_shared.FloPayError;
56
56
  }>;
57
57
  /** Create a payment method from the current elements (tokenize card). */
58
- createPaymentMethod(): Promise<CreatePaymentMethodResult>;
58
+ createPaymentMethod(billingDetails?: _flopay_shared.BillingDetails): Promise<CreatePaymentMethodResult>;
59
59
  /** Confirm a card payment with a known client secret and payment method ID. */
60
60
  confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult>;
61
61
  /** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */
@@ -134,7 +134,7 @@ declare class StripeAdapter implements PaymentProviderAdapter {
134
134
  submitElements(): Promise<{
135
135
  error?: FloPayError;
136
136
  }>;
137
- createPaymentMethod(): Promise<CreatePaymentMethodResult>;
137
+ createPaymentMethod(billingDetails?: BillingDetails): Promise<CreatePaymentMethodResult>;
138
138
  confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult>;
139
139
  confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;
140
140
  confirmPayPalPayment(params: {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _flopay_shared from '@flopay/shared';
2
- import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CreatePaymentMethodResult, ConfirmCardPaymentParams, ConfirmCardPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, BillingProvider, ProcessPaymentParams, InlineSessionParams, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
2
+ import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CreatePaymentMethodResult, ConfirmCardPaymentParams, ConfirmCardPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, BillingDetails, BillingProvider, ProcessPaymentParams, InlineSessionParams, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
3
3
 
4
4
  /**
5
5
  * Manages the creation and lifecycle of payment elements.
@@ -55,7 +55,7 @@ declare class FloPay {
55
55
  error?: _flopay_shared.FloPayError;
56
56
  }>;
57
57
  /** Create a payment method from the current elements (tokenize card). */
58
- createPaymentMethod(): Promise<CreatePaymentMethodResult>;
58
+ createPaymentMethod(billingDetails?: _flopay_shared.BillingDetails): Promise<CreatePaymentMethodResult>;
59
59
  /** Confirm a card payment with a known client secret and payment method ID. */
60
60
  confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult>;
61
61
  /** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */
@@ -134,7 +134,7 @@ declare class StripeAdapter implements PaymentProviderAdapter {
134
134
  submitElements(): Promise<{
135
135
  error?: FloPayError;
136
136
  }>;
137
- createPaymentMethod(): Promise<CreatePaymentMethodResult>;
137
+ createPaymentMethod(billingDetails?: BillingDetails): Promise<CreatePaymentMethodResult>;
138
138
  confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult>;
139
139
  confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;
140
140
  confirmPayPalPayment(params: {
package/dist/index.mjs CHANGED
@@ -131,7 +131,7 @@ var StripeAdapter = class {
131
131
  }
132
132
  return {};
133
133
  }
134
- async createPaymentMethod() {
134
+ async createPaymentMethod(billingDetails) {
135
135
  if (!this.stripe || !this.elements) {
136
136
  return {
137
137
  paymentMethodId: null,
@@ -139,11 +139,28 @@ var StripeAdapter = class {
139
139
  };
140
140
  }
141
141
  const cardNumberEl = this.elements.getElement("cardNumber");
142
+ const stripeBilling = billingDetails ? {
143
+ billing_details: {
144
+ ...billingDetails.name ? { name: billingDetails.name } : {},
145
+ ...billingDetails.address ? {
146
+ address: {
147
+ ...billingDetails.address.country ? { country: billingDetails.address.country } : {},
148
+ ...billingDetails.address.postal_code ? { postal_code: billingDetails.address.postal_code } : {},
149
+ ...billingDetails.address.city ? { city: billingDetails.address.city } : {},
150
+ ...billingDetails.address.line1 ? { line1: billingDetails.address.line1 } : {},
151
+ ...billingDetails.address.line2 ? { line2: billingDetails.address.line2 } : {},
152
+ ...billingDetails.address.state ? { state: billingDetails.address.state } : {}
153
+ }
154
+ } : {}
155
+ }
156
+ } : {};
142
157
  const { error, paymentMethod } = cardNumberEl ? await this.stripe.createPaymentMethod({
143
158
  type: "card",
144
- card: cardNumberEl
159
+ card: cardNumberEl,
160
+ ...stripeBilling
145
161
  }) : await this.stripe.createPaymentMethod({
146
- elements: this.elements
162
+ elements: this.elements,
163
+ ...stripeBilling
147
164
  });
148
165
  if (error) {
149
166
  return {
@@ -687,8 +704,8 @@ var FloPay = class {
687
704
  return this.provider.submitElements();
688
705
  }
689
706
  /** Create a payment method from the current elements (tokenize card). */
690
- async createPaymentMethod() {
691
- return this.provider.createPaymentMethod();
707
+ async createPaymentMethod(billingDetails) {
708
+ return this.provider.createPaymentMethod(billingDetails);
692
709
  }
693
710
  /** Confirm a card payment with a known client secret and payment method ID. */
694
711
  async confirmCardPayment(params) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/load.ts","../src/stripe-adapter.ts","../src/flopay.ts","../src/elements.ts","../src/payment-api.ts","../src/create-checkout-session.ts"],"sourcesContent":["import type { FloPayConfig } from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\nimport { StripeAdapter } from './stripe-adapter.js';\nimport { FloPay } from './flopay.js';\n\n/** Cache to avoid re-initializing for the same key. */\nlet cachedInstance: FloPay | null = null;\nlet cachedKey: string | null = null;\n\n/**\n * Loads and initializes the FloPay SDK.\n *\n * This is the primary entry point for consumer applications.\n * It initializes the underlying payment provider (currently Stripe)\n * and returns a ready-to-use `FloPay` instance.\n *\n * @example\n * ```ts\n * import { loadFloPay } from '@flopay/js';\n *\n * const flopay = await loadFloPay('pk_test_...');\n * const elements = flopay.elements();\n * const cardElement = await elements.create('card');\n * cardElement.mount('#card-container');\n * ```\n */\nexport async function loadFloPay(\n publishableKey: string,\n options?: Omit<FloPayConfig, 'publishableKey'>,\n): Promise<FloPay> {\n if (!publishableKey) {\n throw new FloPayError(\n 'A publishable key is required to initialize FloPay.',\n 'validation_error',\n { param: 'publishableKey' },\n );\n }\n\n // Return cached instance if key matches\n if (cachedInstance && cachedKey === publishableKey) {\n return cachedInstance;\n }\n\n // Clean up previous instance\n if (cachedInstance) {\n cachedInstance.destroy();\n }\n\n const config: FloPayConfig = {\n publishableKey,\n ...options,\n };\n\n // Currently only Stripe is supported. The adapter pattern allows\n // adding Chargebee, Recurly, or other providers in the future.\n const adapter = new StripeAdapter();\n await adapter.initialize(config);\n\n const instance = new FloPay(adapter, config);\n\n cachedKey = publishableKey;\n cachedInstance = instance;\n\n return instance;\n}\n","import type { Stripe, StripeElements, StripeElementType } from '@stripe/stripe-js';\nimport type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementType,\n ElementOptions,\n MountedElement,\n ConfirmPaymentParams,\n PaymentResult,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Maps FloPay element types to Stripe element types.\n * FloPay uses camelCase; Stripe uses lowercase with hyphens or specific names.\n */\nfunction toStripeElementType(type: ElementType): StripeElementType {\n const map: Record<ElementType, string> = {\n payment: 'payment',\n card: 'card',\n cardNumber: 'cardNumber',\n cardExpiry: 'cardExpiry',\n cardCvc: 'cardCvc',\n address: 'address',\n };\n return map[type] as StripeElementType;\n}\n\n/**\n * Wraps a Stripe element instance in the FloPay MountedElement interface.\n *\n * TODO: In a future phase, this wrapper will render the Stripe element inside\n * an iframe hosted on the FloPay domain for PCI DSS SAQ-A compliance.\n * For now, it delegates directly to the Stripe element.\n */\n/** Minimal interface shared by all Stripe element types. */\ninterface StripeElementLike {\n mount(domElement: string | HTMLElement): void;\n unmount(): void;\n destroy(): void;\n update(options?: Record<string, unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void): void;\n off(event: string, handler?: (...args: unknown[]) => void): void;\n}\n\nfunction wrapStripeElement(\n stripeElement: StripeElementLike,\n): MountedElement {\n const el = stripeElement;\n\n return {\n mount(container: HTMLElement) {\n el.mount(container);\n },\n unmount() {\n el.unmount();\n },\n update(options: Partial<ElementOptions>) {\n el.update(options as Record<string, unknown>);\n },\n on(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['on']?.(event, handler);\n },\n off(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['off']?.(event, handler);\n },\n destroy() {\n el.destroy();\n },\n };\n}\n\n/**\n * Payment provider adapter backed by Stripe.\n *\n * Implements the `PaymentProviderAdapter` interface so that FloPay consumers\n * interact with a stable API regardless of the upstream provider.\n */\nexport class StripeAdapter implements PaymentProviderAdapter {\n readonly name = 'stripe';\n private stripe: Stripe | null = null;\n private elements: StripeElements | null = null;\n\n async initialize(config: FloPayConfig): Promise<void> {\n // loadStripe only works in the browser — skip initialization during SSR/SSG\n if (typeof window === 'undefined') {\n return;\n }\n\n const { loadStripe } = await import('@stripe/stripe-js');\n const stripe = await loadStripe(config.publishableKey, {\n locale: (config.locale as 'auto') ?? 'auto',\n });\n\n if (!stripe) {\n throw new FloPayError(\n 'Failed to initialize Stripe. Check your publishable key.',\n 'authentication_error',\n );\n }\n\n this.stripe = stripe;\n }\n\n /** Lazily creates the Stripe Elements group for the given options. */\n private getElements(options?: ElementOptions): StripeElements {\n if (!this.stripe) {\n throw new FloPayError(\n 'StripeAdapter not initialized. Call initialize() first.',\n 'api_error',\n );\n }\n\n if (!this.elements) {\n let elementsOptions: Record<string, unknown>;\n\n if (options?.clientSecret) {\n // Server-side intent already exists — pass its client secret\n elementsOptions = { clientSecret: options.clientSecret };\n } else {\n // No server-side intent yet — use deferred mode with manual payment method creation.\n // This matches checkout/StripeCardForm: mode='payment', paymentMethodCreation='manual'.\n elementsOptions = {\n mode: 'payment' as const,\n amount: options?.amount ?? 0,\n currency: (options?.currency ?? 'usd').toLowerCase(),\n paymentMethodCreation: options?.paymentMethodCreation ?? ('manual' as const),\n };\n }\n\n if (options?.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n this.elements = this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n return this.elements;\n }\n\n async createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement> {\n const elements = this.getElements(options);\n const stripeType = toStripeElementType(type);\n\n const elementOptions: Record<string, unknown> = {};\n if (options.layout) {\n elementOptions['layout'] = options.layout;\n }\n if (options.defaultValues) {\n elementOptions['defaultValues'] = options.defaultValues;\n }\n if (options.readOnly) {\n elementOptions['readOnly'] = options.readOnly;\n }\n if (options.mode) {\n elementOptions['mode'] = options.mode;\n }\n if (options.style) {\n elementOptions['style'] = options.style;\n }\n\n const stripeElement = elements.create(stripeType as 'card', elementOptions) as unknown as StripeElementLike;\n return wrapStripeElement(stripeElement);\n }\n\n getElement(type: ElementType): MountedElement | null {\n if (!this.elements) return null;\n const stripeType = toStripeElementType(type);\n const existing = this.elements.getElement(stripeType as 'card') as unknown as StripeElementLike | null;\n if (!existing) return null;\n return wrapStripeElement(existing);\n }\n\n async submitElements(): Promise<{ error?: FloPayError }> {\n if (!this.stripe || !this.elements) {\n return { error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n const { error } = await this.elements.submit();\n if (error) {\n return {\n error: new FloPayError(error.message ?? 'Validation failed', 'validation_error'),\n };\n }\n return {};\n }\n\n async createPaymentMethod(): Promise<CreatePaymentMethodResult> {\n if (!this.stripe || !this.elements) {\n return {\n paymentMethodId: null,\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n // Detect split card fields vs unified PaymentElement.\n // With split fields (cardNumber + cardExpiry + cardCvc), Stripe requires\n // passing the specific cardNumber element with type: 'card'.\n // With unified PaymentElement, pass the elements group.\n const cardNumberEl = this.elements.getElement('cardNumber' as 'card');\n\n const { error, paymentMethod } = cardNumberEl\n ? await this.stripe.createPaymentMethod({\n type: 'card',\n card: cardNumberEl,\n })\n : await this.stripe.createPaymentMethod({\n elements: this.elements,\n });\n\n if (error) {\n return {\n paymentMethodId: null,\n error: new FloPayError(\n error.message ?? 'Failed to create payment method',\n 'api_error',\n { code: error.code },\n ),\n };\n }\n\n return { paymentMethodId: paymentMethod.id };\n }\n\n async confirmCardPayment(\n params: ConfirmCardPaymentParams,\n ): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return {\n status: 'failed',\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n const { error, paymentIntent } = await this.stripe.confirmCardPayment(\n params.clientSecret,\n { payment_method: params.paymentMethodId },\n );\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n { code: error.code, declineCode: error.decline_code },\n ),\n };\n }\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n };\n }\n\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n if (!this.stripe || !this.elements) {\n throw new FloPayError(\n 'StripeAdapter not initialized or no elements created.',\n 'api_error',\n );\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n elements: this.elements,\n clientSecret: params.clientSecret,\n confirmParams: {\n return_url: params.returnUrl ?? window.location.href,\n },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n {\n code: error.code,\n declineCode: error.decline_code,\n },\n ),\n };\n }\n\n if (!paymentIntent) {\n return { status: 'failed', error: new FloPayError('No payment intent returned', 'api_error') };\n }\n\n const statusMap: Record<string, PaymentResult['status']> = {\n succeeded: 'succeeded',\n processing: 'processing',\n requires_action: 'requires_action',\n requires_payment_method: 'failed',\n canceled: 'failed',\n };\n\n return {\n status: statusMap[paymentIntent.status] ?? 'failed',\n paymentIntentId: paymentIntent.id,\n };\n }\n\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return { status: 'failed', error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n\n const baseUrl = params.billingApiUrl.replace(/\\/+$/, '');\n\n // 1. Create a PayPal PaymentMethod upfront — backend needs pm_xxx\n // Mirrors checkout/StripeCardForm: stripe.createPaymentMethod({ type: 'paypal' })\n const createPM = this.stripe.createPaymentMethod as unknown as (\n params: { type: string },\n ) => Promise<{ error?: { message?: string }; paymentMethod?: { id: string } }>;\n\n const { error: pmError, paymentMethod } = await createPM({ type: 'paypal' });\n\n if (pmError) {\n console.warn('[FloPay] Could not create PayPal PM upfront:', pmError.message);\n }\n\n // 2. Create PaymentIntent via billing API with pm_xxx (or 'paypal' fallback)\n // isPaypal MUST be string 'true', not boolean — backend checks === 'true'\n const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId: params.sessionId,\n email: params.email,\n paymentMethodType: paymentMethod?.id ?? 'paypal',\n isPaypal: 'true',\n }),\n });\n\n if (!intentResponse.ok) {\n return { status: 'failed', error: new FloPayError('Failed to create PayPal payment intent', 'api_error') };\n }\n\n const intentJson = await intentResponse.json() as { data?: { id?: string } };\n const intentClientSecret = intentJson.data?.id;\n if (!intentClientSecret) {\n return { status: 'failed', error: new FloPayError('No client_secret in response', 'api_error') };\n }\n\n // 3. Confirm — pass payment_method if we have it (avoids setupFutureUsage mismatch)\n // Matches checkout: stripe.confirmPayment({ clientSecret, confirmParams: { payment_method, return_url } })\n const confirmParams: Record<string, unknown> = {\n return_url: params.returnUrl,\n };\n if (paymentMethod?.id) {\n confirmParams['payment_method'] = paymentMethod.id;\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n clientSecret: intentClientSecret,\n confirmParams: confirmParams as { return_url: string },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'PayPal payment failed', 'api_error', { code: error.code }),\n };\n }\n\n const pmId = typeof paymentIntent?.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent?.payment_method?.id;\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n paymentMethodId: pmId,\n };\n }\n\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n if (!this.stripe || typeof window === 'undefined') return null;\n\n const params = new URLSearchParams(window.location.search);\n const paymentIntentId = params.get('payment_intent');\n const clientSecret = params.get('payment_intent_client_secret');\n const redirectStatus = params.get('redirect_status');\n\n if (!paymentIntentId || !clientSecret) return null;\n\n if (redirectStatus === 'failed') {\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was declined. Please try again.', 'api_error'),\n };\n }\n\n const { paymentIntent, error } = await this.stripe.retrievePaymentIntent(clientSecret);\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'Failed to retrieve PayPal payment', 'api_error'),\n };\n }\n\n if (paymentIntent && (paymentIntent.status === 'requires_capture' || paymentIntent.status === 'succeeded')) {\n const pmId = typeof paymentIntent.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent.payment_method?.id;\n\n // Clean up URL params\n const url = new URL(window.location.href);\n url.searchParams.delete('payment_intent');\n url.searchParams.delete('payment_intent_client_secret');\n url.searchParams.delete('redirect_status');\n window.history.replaceState({}, '', url.toString());\n\n return {\n status: paymentIntent.status as ConfirmCardPaymentResult['status'],\n paymentIntentId: paymentIntent.id,\n paymentMethodId: pmId,\n };\n }\n\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was not completed. Please try again.', 'api_error'),\n };\n }\n\n getRawProvider(): unknown {\n return this.stripe;\n }\n\n createPayPalElements(options: ElementOptions): unknown {\n if (!this.stripe) return null;\n\n const elementsOptions: Record<string, unknown> = {\n mode: 'payment' as const,\n amount: options.amount ?? 0,\n currency: (options.currency ?? 'usd').toLowerCase(),\n captureMethod: 'manual' as const,\n };\n\n if (options.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n return this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n destroy(): void {\n this.elements = null;\n this.stripe = null;\n }\n}\n","import type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementOptions,\n ConfirmPaymentParams,\n PaymentResult,\n CheckoutSession,\n NormalizedCheckoutSession,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError, resolveBillingApiUrl } from '@flopay/shared';\nimport { FloPayElements } from './elements.js';\nimport { PaymentAPI } from './payment-api.js';\n\n/**\n * The main FloPay SDK instance.\n *\n * Created via `loadFloPay(publishableKey)`. Provides element management,\n * payment confirmation, and session retrieval.\n */\nexport class FloPay {\n private readonly provider: PaymentProviderAdapter;\n private readonly config: FloPayConfig;\n private currentElements: FloPayElements | null = null;\n\n constructor(provider: PaymentProviderAdapter, config: FloPayConfig) {\n this.provider = provider;\n this.config = config;\n }\n\n /**\n * Creates a new `FloPayElements` group for mounting payment fields.\n *\n * Only one elements group is active at a time. Creating a new one\n * destroys the previous group.\n */\n elements(options?: ElementOptions): FloPayElements {\n if (this.currentElements) {\n this.currentElements.destroy();\n }\n this.currentElements = new FloPayElements(this.provider, {\n appearance: this.config.appearance,\n ...options,\n });\n return this.currentElements;\n }\n\n /** Submit elements for validation. */\n async submitElements(): Promise<{ error?: import('@flopay/shared').FloPayError }> {\n return this.provider.submitElements();\n }\n\n /** Create a payment method from the current elements (tokenize card). */\n async createPaymentMethod(): Promise<CreatePaymentMethodResult> {\n return this.provider.createPaymentMethod();\n }\n\n /** Confirm a card payment with a known client secret and payment method ID. */\n async confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmCardPayment(params);\n }\n\n /** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmPayPalPayment(params);\n }\n\n /** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n return this.provider.resumePayPalPayment();\n }\n\n /** Confirms a payment using the mounted elements. */\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n return this.provider.confirmPayment(params);\n }\n\n /**\n * Retrieves a checkout session by ID via the billing API.\n *\n * Returns the normalized `CheckoutSession` with amount, currency,\n * customer data, and status.\n *\n * Requires `billingApiUrl` to be set — either via `loadFloPay(key, { billingApiUrl })`\n * or passed directly as the second argument.\n */\n async retrieveSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<CheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required to retrieve a session.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n const unified = await api.getUnifiedCheckoutSession(sessionId);\n if (!unified.data.session) {\n throw new FloPayError('Session not found', 'api_error');\n }\n return unified.data.session;\n }\n\n /**\n * Retrieves and normalizes a checkout session, including provider-specific\n * data (Stripe clientSecret/publishableKey, Chargebee site, etc.).\n *\n * The billing API URL is resolved from: explicit param → `loadFloPay()` config\n * → `NEXT_PUBLIC_FLOPAY_ENV` env var → `configureFlopay()` → staging fallback.\n */\n async retrieveUnifiedSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<NormalizedCheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n return api.getUnifiedCheckoutSession(sessionId);\n }\n\n /**\n * Returns the raw underlying provider instance (e.g. Stripe object).\n * Used internally by components that need direct provider access,\n * such as PayPal which requires its own Elements instance.\n */\n getRawProvider(): unknown {\n return this.provider.getRawProvider();\n }\n\n /** Tears down the SDK instance and releases resources. */\n destroy(): void {\n this.currentElements?.destroy();\n this.currentElements = null;\n this.provider.destroy();\n }\n}\n","import type {\n PaymentProviderAdapter,\n ElementType,\n ElementOptions,\n MountedElement,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Manages the creation and lifecycle of payment elements.\n *\n * Each `FloPayElements` instance is bound to a single provider adapter\n * and tracks all created elements for cleanup.\n */\nexport class FloPayElements {\n private readonly provider: PaymentProviderAdapter;\n private readonly elementMap = new Map<ElementType, MountedElement>();\n private readonly baseOptions: ElementOptions;\n\n constructor(provider: PaymentProviderAdapter, options?: ElementOptions) {\n this.provider = provider;\n this.baseOptions = options ?? {};\n }\n\n /**\n * Creates a new element of the given type.\n * If an element of that type already exists, it is destroyed first.\n */\n async create(\n type: ElementType,\n options?: ElementOptions,\n ): Promise<MountedElement> {\n // Check if the provider already has this element (e.g. after React\n // Strict Mode unmount+remount cycle). Reuse it instead of creating\n // a duplicate, which Stripe would reject.\n const providerExisting = this.provider.getElement(type);\n if (providerExisting) {\n this.elementMap.set(type, providerExisting);\n return providerExisting;\n }\n\n const existing = this.elementMap.get(type);\n if (existing) {\n existing.destroy();\n }\n\n const merged: ElementOptions = { ...this.baseOptions, ...options };\n const element = await this.provider.createElement(type, merged);\n this.elementMap.set(type, element);\n return element;\n }\n\n /** Returns a previously created element, or `null`. */\n getElement(type: ElementType): MountedElement | null {\n return this.elementMap.get(type) ?? null;\n }\n\n /**\n * Submits all mounted elements for validation.\n *\n * Returns an object with an optional error if validation fails.\n * This does NOT confirm the payment — call `floPay.confirmPayment()` for that.\n */\n async submit(): Promise<{ error?: FloPayError }> {\n // Walk through all mounted elements and check for incomplete state.\n // The actual validation is handled by the provider's element implementation.\n // For Stripe, the Elements.submit() method is called during confirmPayment.\n // This method exists to match the Stripe Elements API surface.\n return {};\n }\n\n /** Destroys all created elements and clears the internal map. */\n destroy(): void {\n for (const element of this.elementMap.values()) {\n element.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import type {\n CheckoutSession,\n NormalizedCheckoutSession,\n ProcessPaymentParams,\n TokenizedBody,\n BillingProvider,\n InlineSessionParams,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/** Raw billing API response wrapper. */\ninterface BillingResponse<T> {\n data: T;\n}\n\n/** Raw checkout session from the billing API (includes gateway field). */\ninterface RawCheckoutSession {\n uuid: string;\n nonce: string;\n gateway?: BillingProvider;\n status: 'pending' | 'completed';\n successUrl: string;\n cancelUrl: string;\n createdAt?: string;\n checkoutUrl?: string;\n items: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerItemId: string;\n providerItemName: string;\n providerItemDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n metadata?: Record<string, unknown> | null;\n }>;\n subscriptions: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerPlanId: string;\n providerPlanName: string;\n providerPlanDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n isUpdate?: boolean;\n metadata?: Record<string, unknown> | null;\n }>;\n coupons?: string[];\n checkoutMode?: 'full' | 'auto' | 'confirm';\n gatewayData: {\n publishableKey?: string | null;\n };\n accountData: {\n userId: string;\n firstName: string;\n lastName: string;\n email: string;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: string | null;\n };\n tagsData: {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n };\n}\n\n/**\n * Client-side payment API service.\n *\n * Mirrors the `PaymentAPI` class from the checkout project's\n * `src/service/api.ts`. All methods call the billing API endpoints\n * that the checkout backend exposes.\n */\nexport class PaymentAPI {\n private readonly baseUrl: string;\n\n constructor(billingApiUrl: string) {\n this.baseUrl = billingApiUrl.replace(/\\/+$/, '');\n }\n\n /** Fetch a raw checkout session by ID. */\n async getCheckoutSession(\n checkoutSessionId: string,\n ): Promise<BillingResponse<RawCheckoutSession>> {\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${checkoutSessionId}`,\n );\n\n if (!response.ok) {\n throw new FloPayError(\n 'Failed to get checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n return response.json() as Promise<BillingResponse<RawCheckoutSession>>;\n }\n\n /**\n * Fetch and normalize a checkout session.\n *\n * Reads the backend's `gateway` field to determine the provider,\n * then wraps the session in a `NormalizedCheckoutSession` for\n * provider-agnostic consumption.\n */\n async getUnifiedCheckoutSession(\n checkoutSessionId: string,\n ): Promise<NormalizedCheckoutSession> {\n const res = await this.getCheckoutSession(checkoutSessionId);\n return this.normalizeRawSession(res.data);\n }\n\n /**\n * Submit a tokenized payment to the billing backend.\n *\n * The backend will either succeed, return `type: '3ds_required'`\n * (with a `threeDSecureToken`), or return `type: 'paypal_redirect_required'`.\n */\n async processPayment(\n userId: string,\n data: ProcessPaymentParams,\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/sessions/process`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-user-id': userId,\n },\n body: JSON.stringify(data),\n },\n );\n }\n\n /**\n * Create a PaymentIntent on the backend.\n *\n * Used by the Stripe flow to create a server-side PaymentIntent\n * with the client's payment method attached.\n */\n async createPaymentIntent(\n sessionId: string,\n email: string,\n paymentMethodType: string,\n options?: { signal?: AbortSignal; isPaypal?: string },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n email,\n paymentMethodType,\n isPaypal: options?.isPaypal ?? false,\n }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Create a SetupIntent for saving payment methods.\n */\n async createSetupIntent(\n sessionId: string,\n email: string,\n paymentMethodType: 'card' | 'google_pay' | 'apple_pay' | 'paypal_express_checkout',\n options?: { signal?: AbortSignal },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/setup-intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, email, paymentMethodType }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Fetch user's prior payments by email.\n * Used to determine if saved card UX should be shown.\n */\n async getPaymentsByEmail(\n email: string,\n options?: { signal?: AbortSignal; page?: number; limit?: number },\n ): Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }> {\n const page = options?.page ?? 1;\n const limit = options?.limit ?? 1;\n const params = new URLSearchParams({\n email,\n page: String(page),\n limit: String(limit),\n sortField: 'occurredAt',\n sortDirection: 'DESC',\n });\n\n const response = await fetch(\n `${this.baseUrl}/v1/payments?${params.toString()}`,\n {\n method: 'GET',\n signal: options?.signal,\n keepalive: true,\n },\n );\n\n if (!response.ok) {\n throw new FloPayError('Failed to fetch payments', 'api_error');\n }\n\n return response.json() as Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }>;\n }\n\n /**\n * Create a checkout session AND return the full session data in one call.\n * Uses `?expand=true` so the backend returns the complete session\n * instead of just a UUID — eliminating the need for a second GET.\n *\n * Falls back to create + GET if the backend doesn't support `expand`.\n */\n async createAndFetchSession(\n params: InlineSessionParams,\n ): Promise<NormalizedCheckoutSession> {\n const payload: Record<string, unknown> = {\n clientId: params.clientId,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n checkoutMode: params.checkoutMode ?? 'full',\n items: (params.items ?? []).map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: (params.subscriptions ?? []).map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: params.account.userId,\n firstName: params.account.firstName ?? null,\n lastName: params.account.lastName ?? null,\n email: params.account.email,\n country: params.account.country ?? null,\n gender: params.account.gender ?? null,\n city: params.account.city ?? null,\n state: params.account.state ?? null,\n zip: params.account.zip ?? null,\n },\n couponCodes: params.couponCodes ?? [],\n };\n\n if (params.tagsData) payload['tagsData'] = params.tagsData;\n if (params.utmMetadata?.length) payload['utmMetadata'] = params.utmMetadata;\n\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions?expand=true`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n );\n\n if (response.status === 204) {\n throw new FloPayError(\n 'Session auto-completed — payment method already on file',\n 'api_error',\n { code: 'session_auto_completed' },\n );\n }\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new FloPayError(\n (body as Record<string, string> | null)?.message ?? 'Failed to create checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n const body = await response.json() as { data: RawCheckoutSession & { uuid?: string } };\n\n // If backend supports expand=true, it returns full session data.\n // If not, it returns { data: { uuid } } and we fall back to a GET.\n if (body.data && 'gateway' in body.data) {\n // Full session returned — normalize directly\n return this.normalizeRawSession(body.data);\n }\n\n // Fallback: backend returned UUID only — fetch full session\n const uuid = body.data?.uuid;\n if (!uuid) {\n throw new FloPayError('No session ID returned', 'api_error');\n }\n return this.getUnifiedCheckoutSession(uuid);\n }\n\n /** Normalize a raw session into a provider-agnostic shape. */\n private normalizeRawSession(session: RawCheckoutSession): NormalizedCheckoutSession {\n const gateway = session.gateway;\n\n if (gateway === 'chargebee') {\n return {\n provider: 'chargebee',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n if (gateway === 'stripe') {\n return {\n provider: 'stripe',\n mode: 'tokenize',\n data: {\n session: this.toCheckoutSession(session),\n stripe: {\n clientSecret: (session as unknown as Record<string, unknown>)['stripeClientSecret'] as string ?? '',\n publishableKey: session.gatewayData?.publishableKey ?? undefined,\n },\n },\n raw: { data: session },\n };\n }\n\n return {\n provider: 'recurly',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n /** Convert raw session to the SDK CheckoutSession shape. */\n private toCheckoutSession(raw: RawCheckoutSession): CheckoutSession {\n const totalAmount = [\n ...raw.subscriptions.map((s) => s.overrideAmount || s.totalAmount),\n ...raw.items.map((i) => i.overrideAmount || i.totalAmount),\n ].reduce((sum, val) => sum + val, 0);\n\n // Billing API returns amounts in major units (e.g. 24.95 USD).\n // Stripe expects amounts in smallest currency unit (cents).\n const amountInCents = Math.round(totalAmount * 100);\n\n return {\n // Core fields (backward compat)\n id: raw.uuid,\n clientSecret: raw.nonce,\n mode: raw.subscriptions.length > 0 ? 'subscription' : 'payment',\n status: raw.status === 'completed' ? 'complete' : 'open',\n amount: amountInCents,\n currency: raw.subscriptions[0]?.currency ?? raw.items[0]?.currency ?? 'USD',\n customer: {\n id: raw.accountData.userId,\n email: raw.accountData.email,\n firstName: raw.accountData.firstName,\n lastName: raw.accountData.lastName,\n country: raw.accountData.country ?? undefined,\n city: raw.accountData.city ?? undefined,\n state: raw.accountData.state ?? undefined,\n zip: raw.accountData.zip ?? undefined,\n gender: raw.accountData.gender ?? undefined,\n },\n metadata: {},\n\n // Full session data from billing API\n checkoutMode: raw.checkoutMode,\n items: raw.items,\n subscriptions: raw.subscriptions,\n successUrl: raw.successUrl,\n cancelUrl: raw.cancelUrl,\n coupons: raw.coupons,\n createdAt: raw.createdAt,\n gateway: raw.gateway,\n gatewayData: raw.gatewayData,\n accountData: raw.accountData,\n tagsData: raw.tagsData,\n };\n }\n}\n","import type {\n CreateSessionParams,\n CheckoutSessionResult,\n} from '@flopay/shared';\n\n/**\n * Creates a checkout session via the billing API and redirects the user\n * to the hosted checkout page.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n *\n * - On 201: Redirects to `{checkoutBaseUrl}/secure?id={uuid}&...redirectParams`\n * - On 204: Redirects directly to `successUrl` (payment method already on file)\n * - On other: Returns `{ status }` without redirecting\n *\n * @example\n * ```ts\n * import { createCheckoutSession } from '@flopay/js';\n *\n * await createCheckoutSession({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{\n * providerItemId: 'prod_abc',\n * providerItemName: 'Pro Plan',\n * totalAmount: 49.99,\n * overrideAmount: 24.99,\n * }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * redirectParams: { email: 'user@example.com', bg: 'courses', mode: 'confirm' },\n * });\n * ```\n */\nexport async function createCheckoutSession(\n options: CreateSessionParams,\n): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n setCookie = true,\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = options;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body — leave undefined\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n if (setCookie && typeof window !== 'undefined' && typeof document !== 'undefined') {\n const checkoutData = JSON.stringify({ origin_url: cancelUrl });\n const domain = window.location.hostname.split('.').slice(-2).join('.');\n document.cookie = `checkout_data=${encodeURIComponent(checkoutData)}; domain=.${domain}; path=/; max-age=3600; SameSite=Lax; Secure;`;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = redirectUrl.toString();\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n if (typeof window !== 'undefined') {\n window.location.href = successUrl;\n }\n return { status: 204 };\n }\n\n return { status };\n}\n\n/**\n * Creates a checkout session with automatic retry on timeout/abort errors.\n *\n * Uses exponential backoff: 100ms, 200ms, 400ms, etc.\n */\nexport async function createCheckoutSessionWithRetries(\n options: CreateSessionParams & { maxRetries?: number },\n): Promise<CheckoutSessionResult> {\n const { maxRetries = 3, ...sessionOptions } = options;\n\n if (!Number.isFinite(maxRetries) || !Number.isInteger(maxRetries) || maxRetries <= 0) {\n throw new Error('Number of retries must be greater than 0');\n }\n\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await createCheckoutSession(sessionOptions);\n } catch (err) {\n lastErr = err;\n\n if (err instanceof Error && err.name === 'AbortError' && attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));\n continue;\n }\n\n throw err;\n }\n }\n\n throw lastErr ?? new Error('Unknown error during checkout session creation');\n}\n"],"mappings":";AACA,SAAS,eAAAA,oBAAmB;;;ACY5B,SAAS,mBAAmB;AAM5B,SAAS,oBAAoB,MAAsC;AACjE,QAAM,MAAmC;AAAA,IACvC,SAAS;AAAA,IACT,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACA,SAAO,IAAI,IAAI;AACjB;AAmBA,SAAS,kBACP,eACgB;AAChB,QAAM,KAAK;AAEX,SAAO;AAAA,IACL,MAAM,WAAwB;AAC5B,SAAG,MAAM,SAAS;AAAA,IACpB;AAAA,IACA,UAAU;AACR,SAAG,QAAQ;AAAA,IACb;AAAA,IACA,OAAO,SAAkC;AACvC,SAAG,OAAO,OAAkC;AAAA,IAC9C;AAAA,IACA,GAAG,OAAe,SAAuC;AACvD,MAAC,GAA+D,IAAI,IAAI,OAAO,OAAO;AAAA,IACxF;AAAA,IACA,IAAI,OAAe,SAAuC;AACxD,MAAC,GAA+D,KAAK,IAAI,OAAO,OAAO;AAAA,IACzF;AAAA,IACA,UAAU;AACR,SAAG,QAAQ;AAAA,IACb;AAAA,EACF;AACF;AAQO,IAAM,gBAAN,MAAsD;AAAA,EAAtD;AACL,SAAS,OAAO;AAChB,SAAQ,SAAwB;AAChC,SAAQ,WAAkC;AAAA;AAAA,EAE1C,MAAM,WAAW,QAAqC;AAEpD,QAAI,OAAO,WAAW,aAAa;AACjC;AAAA,IACF;AAEA,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,mBAAmB;AACvD,UAAM,SAAS,MAAM,WAAW,OAAO,gBAAgB;AAAA,MACrD,QAAS,OAAO,UAAqB;AAAA,IACvC,CAAC;AAED,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGQ,YAAY,SAA0C;AAC5D,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,UAAU;AAClB,UAAI;AAEJ,UAAI,SAAS,cAAc;AAEzB,0BAAkB,EAAE,cAAc,QAAQ,aAAa;AAAA,MACzD,OAAO;AAGL,0BAAkB;AAAA,UAChB,MAAM;AAAA,UACN,QAAQ,SAAS,UAAU;AAAA,UAC3B,WAAW,SAAS,YAAY,OAAO,YAAY;AAAA,UACnD,uBAAuB,SAAS,yBAA0B;AAAA,QAC5D;AAAA,MACF;AAEA,UAAI,SAAS,YAAY;AACvB,wBAAgB,YAAY,IAAI;AAAA,UAC9B,OAAQ,QAAQ,WAAW,SAAsB;AAAA,UACjD,WAAW,QAAQ,WAAW;AAAA,UAC9B,OAAO,QAAQ,WAAW;AAAA,QAC5B;AAAA,MACF;AAEA,WAAK,WAAW,KAAK,OAAO,SAAS,eAA+D;AAAA,IACtG;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,cACJ,MACA,SACyB;AACzB,UAAM,WAAW,KAAK,YAAY,OAAO;AACzC,UAAM,aAAa,oBAAoB,IAAI;AAE3C,UAAM,iBAA0C,CAAC;AACjD,QAAI,QAAQ,QAAQ;AAClB,qBAAe,QAAQ,IAAI,QAAQ;AAAA,IACrC;AACA,QAAI,QAAQ,eAAe;AACzB,qBAAe,eAAe,IAAI,QAAQ;AAAA,IAC5C;AACA,QAAI,QAAQ,UAAU;AACpB,qBAAe,UAAU,IAAI,QAAQ;AAAA,IACvC;AACA,QAAI,QAAQ,MAAM;AAChB,qBAAe,MAAM,IAAI,QAAQ;AAAA,IACnC;AACA,QAAI,QAAQ,OAAO;AACjB,qBAAe,OAAO,IAAI,QAAQ;AAAA,IACpC;AAEA,UAAM,gBAAgB,SAAS,OAAO,YAAsB,cAAc;AAC1E,WAAO,kBAAkB,aAAa;AAAA,EACxC;AAAA,EAEA,WAAW,MAA0C;AACnD,QAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,UAAM,aAAa,oBAAoB,IAAI;AAC3C,UAAM,WAAW,KAAK,SAAS,WAAW,UAAoB;AAC9D,QAAI,CAAC,SAAU,QAAO;AACtB,WAAO,kBAAkB,QAAQ;AAAA,EACnC;AAAA,EAEA,MAAM,iBAAmD;AACvD,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU;AAClC,aAAO,EAAE,OAAO,IAAI,YAAY,0BAA0B,WAAW,EAAE;AAAA,IACzE;AACA,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,OAAO;AAC7C,QAAI,OAAO;AACT,aAAO;AAAA,QACL,OAAO,IAAI,YAAY,MAAM,WAAW,qBAAqB,kBAAkB;AAAA,MACjF;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAM,sBAA0D;AAC9D,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU;AAClC,aAAO;AAAA,QACL,iBAAiB;AAAA,QACjB,OAAO,IAAI,YAAY,0BAA0B,WAAW;AAAA,MAC9D;AAAA,IACF;AAMA,UAAM,eAAe,KAAK,SAAS,WAAW,YAAsB;AAEpE,UAAM,EAAE,OAAO,cAAc,IAAI,eAC7B,MAAM,KAAK,OAAO,oBAAoB;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC,IACD,MAAM,KAAK,OAAO,oBAAoB;AAAA,MACpC,UAAU,KAAK;AAAA,IACjB,CAAC;AAEL,QAAI,OAAO;AACT,aAAO;AAAA,QACL,iBAAiB;AAAA,QACjB,OAAO,IAAI;AAAA,UACT,MAAM,WAAW;AAAA,UACjB;AAAA,UACA,EAAE,MAAM,MAAM,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,iBAAiB,cAAc,GAAG;AAAA,EAC7C;AAAA,EAEA,MAAM,mBACJ,QACmC;AACnC,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,YAAY,0BAA0B,WAAW;AAAA,MAC9D;AAAA,IACF;AAEA,UAAM,EAAE,OAAO,cAAc,IAAI,MAAM,KAAK,OAAO;AAAA,MACjD,OAAO;AAAA,MACP,EAAE,gBAAgB,OAAO,gBAAgB;AAAA,IAC3C;AAEA,QAAI,OAAO;AACT,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI;AAAA,UACT,MAAM,WAAW;AAAA,UACjB;AAAA,UACA,EAAE,MAAM,MAAM,MAAM,aAAa,MAAM,aAAa;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAS,eAAe,UAAiD;AAAA,MACzE,iBAAiB,eAAe;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,QAAsD;AACzE,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU;AAClC,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,OAAO,cAAc,IAAI,MAAM,KAAK,OAAO,eAAe;AAAA,MAChE,UAAU,KAAK;AAAA,MACf,cAAc,OAAO;AAAA,MACrB,eAAe;AAAA,QACb,YAAY,OAAO,aAAa,OAAO,SAAS;AAAA,MAClD;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAED,QAAI,OAAO;AACT,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI;AAAA,UACT,MAAM,WAAW;AAAA,UACjB;AAAA,UACA;AAAA,YACE,MAAM,MAAM;AAAA,YACZ,aAAa,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,eAAe;AAClB,aAAO,EAAE,QAAQ,UAAU,OAAO,IAAI,YAAY,8BAA8B,WAAW,EAAE;AAAA,IAC/F;AAEA,UAAM,YAAqD;AAAA,MACzD,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,yBAAyB;AAAA,MACzB,UAAU;AAAA,IACZ;AAEA,WAAO;AAAA,MACL,QAAQ,UAAU,cAAc,MAAM,KAAK;AAAA,MAC3C,iBAAiB,cAAc;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,QAKW;AACpC,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,EAAE,QAAQ,UAAU,OAAO,IAAI,YAAY,0BAA0B,WAAW,EAAE;AAAA,IAC3F;AAEA,UAAM,UAAU,OAAO,cAAc,QAAQ,QAAQ,EAAE;AAIvD,UAAM,WAAW,KAAK,OAAO;AAI7B,UAAM,EAAE,OAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,MAAM,SAAS,CAAC;AAE3E,QAAI,SAAS;AACX,cAAQ,KAAK,gDAAgD,QAAQ,OAAO;AAAA,IAC9E;AAIA,UAAM,iBAAiB,MAAM,MAAM,GAAG,OAAO,kCAAkC;AAAA,MAC7E,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,WAAW,OAAO;AAAA,QAClB,OAAO,OAAO;AAAA,QACd,mBAAmB,eAAe,MAAM;AAAA,QACxC,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,eAAe,IAAI;AACtB,aAAO,EAAE,QAAQ,UAAU,OAAO,IAAI,YAAY,0CAA0C,WAAW,EAAE;AAAA,IAC3G;AAEA,UAAM,aAAa,MAAM,eAAe,KAAK;AAC7C,UAAM,qBAAqB,WAAW,MAAM;AAC5C,QAAI,CAAC,oBAAoB;AACvB,aAAO,EAAE,QAAQ,UAAU,OAAO,IAAI,YAAY,gCAAgC,WAAW,EAAE;AAAA,IACjG;AAIA,UAAM,gBAAyC;AAAA,MAC7C,YAAY,OAAO;AAAA,IACrB;AACA,QAAI,eAAe,IAAI;AACrB,oBAAc,gBAAgB,IAAI,cAAc;AAAA,IAClD;AAEA,UAAM,EAAE,OAAO,cAAc,IAAI,MAAM,KAAK,OAAO,eAAe;AAAA,MAChE,cAAc;AAAA,MACd;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAED,QAAI,OAAO;AACT,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,YAAY,MAAM,WAAW,yBAAyB,aAAa,EAAE,MAAM,MAAM,KAAK,CAAC;AAAA,MACpG;AAAA,IACF;AAEA,UAAM,OAAO,OAAO,eAAe,mBAAmB,WAClD,cAAc,iBACd,eAAe,gBAAgB;AAEnC,WAAO;AAAA,MACL,QAAS,eAAe,UAAiD;AAAA,MACzE,iBAAiB,eAAe;AAAA,MAChC,iBAAiB;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,sBAAgE;AACpE,QAAI,CAAC,KAAK,UAAU,OAAO,WAAW,YAAa,QAAO;AAE1D,UAAM,SAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,UAAM,kBAAkB,OAAO,IAAI,gBAAgB;AACnD,UAAM,eAAe,OAAO,IAAI,8BAA8B;AAC9D,UAAM,iBAAiB,OAAO,IAAI,iBAAiB;AAEnD,QAAI,CAAC,mBAAmB,CAAC,aAAc,QAAO;AAE9C,QAAI,mBAAmB,UAAU;AAC/B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,YAAY,kDAAkD,WAAW;AAAA,MACtF;AAAA,IACF;AAEA,UAAM,EAAE,eAAe,MAAM,IAAI,MAAM,KAAK,OAAO,sBAAsB,YAAY;AAErF,QAAI,OAAO;AACT,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,YAAY,MAAM,WAAW,qCAAqC,WAAW;AAAA,MAC1F;AAAA,IACF;AAEA,QAAI,kBAAkB,cAAc,WAAW,sBAAsB,cAAc,WAAW,cAAc;AAC1G,YAAM,OAAO,OAAO,cAAc,mBAAmB,WACjD,cAAc,iBACd,cAAc,gBAAgB;AAGlC,YAAM,MAAM,IAAI,IAAI,OAAO,SAAS,IAAI;AACxC,UAAI,aAAa,OAAO,gBAAgB;AACxC,UAAI,aAAa,OAAO,8BAA8B;AACtD,UAAI,aAAa,OAAO,iBAAiB;AACzC,aAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC;AAElD,aAAO;AAAA,QACL,QAAQ,cAAc;AAAA,QACtB,iBAAiB,cAAc;AAAA,QAC/B,iBAAiB;AAAA,MACnB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,IAAI,YAAY,uDAAuD,WAAW;AAAA,IAC3F;AAAA,EACF;AAAA,EAEA,iBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAAqB,SAAkC;AACrD,QAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,UAAM,kBAA2C;AAAA,MAC/C,MAAM;AAAA,MACN,QAAQ,QAAQ,UAAU;AAAA,MAC1B,WAAW,QAAQ,YAAY,OAAO,YAAY;AAAA,MAClD,eAAe;AAAA,IACjB;AAEA,QAAI,QAAQ,YAAY;AACtB,sBAAgB,YAAY,IAAI;AAAA,QAC9B,OAAQ,QAAQ,WAAW,SAAsB;AAAA,QACjD,WAAW,QAAQ,WAAW;AAAA,QAC9B,OAAO,QAAQ,WAAW;AAAA,MAC5B;AAAA,IACF;AAEA,WAAO,KAAK,OAAO,SAAS,eAA+D;AAAA,EAC7F;AAAA,EAEA,UAAgB;AACd,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EAChB;AACF;;;AC9cA,SAAS,eAAAC,cAAa,4BAA4B;;;ACNlD,OAA4B;AAQrB,IAAM,iBAAN,MAAqB;AAAA,EAK1B,YAAY,UAAkC,SAA0B;AAHxE,SAAiB,aAAa,oBAAI,IAAiC;AAIjE,SAAK,WAAW;AAChB,SAAK,cAAc,WAAW,CAAC;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OACJ,MACA,SACyB;AAIzB,UAAM,mBAAmB,KAAK,SAAS,WAAW,IAAI;AACtD,QAAI,kBAAkB;AACpB,WAAK,WAAW,IAAI,MAAM,gBAAgB;AAC1C,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,KAAK,WAAW,IAAI,IAAI;AACzC,QAAI,UAAU;AACZ,eAAS,QAAQ;AAAA,IACnB;AAEA,UAAM,SAAyB,EAAE,GAAG,KAAK,aAAa,GAAG,QAAQ;AACjE,UAAM,UAAU,MAAM,KAAK,SAAS,cAAc,MAAM,MAAM;AAC9D,SAAK,WAAW,IAAI,MAAM,OAAO;AACjC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,MAA0C;AACnD,WAAO,KAAK,WAAW,IAAI,IAAI,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAA2C;AAK/C,WAAO,CAAC;AAAA,EACV;AAAA;AAAA,EAGA,UAAgB;AACd,eAAW,WAAW,KAAK,WAAW,OAAO,GAAG;AAC9C,cAAQ,QAAQ;AAAA,IAClB;AACA,SAAK,WAAW,MAAM;AAAA,EACxB;AACF;;;ACtEA,SAAS,eAAAC,oBAAmB;AAwErB,IAAM,aAAN,MAAiB;AAAA,EAGtB,YAAY,eAAuB;AACjC,SAAK,UAAU,cAAc,QAAQ,QAAQ,EAAE;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,mBACJ,mBAC8C;AAC9C,UAAM,WAAW,MAAM;AAAA,MACrB,GAAG,KAAK,OAAO,0BAA0B,iBAAiB;AAAA,IAC5D;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAIA;AAAA,QACR;AAAA,QACA;AAAA,QACA,EAAE,MAAM,QAAQ,SAAS,MAAM,GAAG;AAAA,MACpC;AAAA,IACF;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,0BACJ,mBACoC;AACpC,UAAM,MAAM,MAAM,KAAK,mBAAmB,iBAAiB;AAC3D,WAAO,KAAK,oBAAoB,IAAI,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eACJ,QACA,MACmB;AACnB,WAAO;AAAA,MACL,GAAG,KAAK,OAAO;AAAA,MACf;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACf;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBACJ,WACA,OACA,mBACA,SACmB;AACnB,WAAO;AAAA,MACL,GAAG,KAAK,OAAO;AAAA,MACf;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,SAAS,YAAY;AAAA,QACjC,CAAC;AAAA,QACD,QAAQ,SAAS;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBACJ,WACA,OACA,mBACA,SACmB;AACnB,WAAO;AAAA,MACL,GAAG,KAAK,OAAO;AAAA,MACf;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,WAAW,OAAO,kBAAkB,CAAC;AAAA,QAC5D,QAAQ,SAAS;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mBACJ,OACA,SACsF;AACtF,UAAM,OAAO,SAAS,QAAQ;AAC9B,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC;AAAA,MACA,MAAM,OAAO,IAAI;AAAA,MACjB,OAAO,OAAO,KAAK;AAAA,MACnB,WAAW;AAAA,MACX,eAAe;AAAA,IACjB,CAAC;AAED,UAAM,WAAW,MAAM;AAAA,MACrB,GAAG,KAAK,OAAO,gBAAgB,OAAO,SAAS,CAAC;AAAA,MAChD;AAAA,QACE,QAAQ;AAAA,QACR,QAAQ,SAAS;AAAA,QACjB,WAAW;AAAA,MACb;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAIA,aAAY,4BAA4B,WAAW;AAAA,IAC/D;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,sBACJ,QACoC;AACpC,UAAM,UAAmC;AAAA,MACvC,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO,gBAAgB;AAAA,MACrC,QAAQ,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,QACzC,gBAAgB,KAAK;AAAA,QACrB,kBAAkB,KAAK,oBAAoB;AAAA,QAC3C,UAAU,KAAK,YAAY;AAAA,QAC3B,aAAa,KAAK;AAAA,QAClB,gBAAgB,KAAK,kBAAkB;AAAA,QACvC,UAAU,KAAK,YAAY;AAAA,MAC7B,EAAE;AAAA,MACF,gBAAgB,OAAO,iBAAiB,CAAC,GAAG,IAAI,CAAC,SAAS;AAAA,QACxD,gBAAgB,IAAI;AAAA,QACpB,kBAAkB,IAAI,oBAAoB;AAAA,QAC1C,UAAU,IAAI,YAAY;AAAA,QAC1B,aAAa,IAAI;AAAA,QACjB,gBAAgB,IAAI,kBAAkB;AAAA,QACtC,UAAU,IAAI,YAAY;AAAA,MAC5B,EAAE;AAAA,MACF,aAAa;AAAA,QACX,QAAQ,OAAO,QAAQ;AAAA,QACvB,WAAW,OAAO,QAAQ,aAAa;AAAA,QACvC,UAAU,OAAO,QAAQ,YAAY;AAAA,QACrC,OAAO,OAAO,QAAQ;AAAA,QACtB,SAAS,OAAO,QAAQ,WAAW;AAAA,QACnC,QAAQ,OAAO,QAAQ,UAAU;AAAA,QACjC,MAAM,OAAO,QAAQ,QAAQ;AAAA,QAC7B,OAAO,OAAO,QAAQ,SAAS;AAAA,QAC/B,KAAK,OAAO,QAAQ,OAAO;AAAA,MAC7B;AAAA,MACA,aAAa,OAAO,eAAe,CAAC;AAAA,IACtC;AAEA,QAAI,OAAO,SAAU,SAAQ,UAAU,IAAI,OAAO;AAClD,QAAI,OAAO,aAAa,OAAQ,SAAQ,aAAa,IAAI,OAAO;AAEhE,UAAM,WAAW,MAAM;AAAA,MACrB,GAAG,KAAK,OAAO;AAAA,MACf;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAIA;AAAA,QACR;AAAA,QACA;AAAA,QACA,EAAE,MAAM,yBAAyB;AAAA,MACnC;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAMC,QAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACnD,YAAM,IAAID;AAAA,QACPC,OAAwC,WAAW;AAAA,QACpD;AAAA,QACA,EAAE,MAAM,QAAQ,SAAS,MAAM,GAAG;AAAA,MACpC;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAIjC,QAAI,KAAK,QAAQ,aAAa,KAAK,MAAM;AAEvC,aAAO,KAAK,oBAAoB,KAAK,IAAI;AAAA,IAC3C;AAGA,UAAM,OAAO,KAAK,MAAM;AACxB,QAAI,CAAC,MAAM;AACT,YAAM,IAAID,aAAY,0BAA0B,WAAW;AAAA,IAC7D;AACA,WAAO,KAAK,0BAA0B,IAAI;AAAA,EAC5C;AAAA;AAAA,EAGQ,oBAAoB,SAAwD;AAClF,UAAM,UAAU,QAAQ;AAExB,QAAI,YAAY,aAAa;AAC3B,aAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM;AAAA,QACN,MAAM,EAAE,SAAS,KAAK,kBAAkB,OAAO,EAAE;AAAA,QACjD,KAAK,EAAE,MAAM,QAAQ;AAAA,MACvB;AAAA,IACF;AAEA,QAAI,YAAY,UAAU;AACxB,aAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,SAAS,KAAK,kBAAkB,OAAO;AAAA,UACvC,QAAQ;AAAA,YACN,cAAe,QAA+C,oBAAoB,KAAe;AAAA,YACjG,gBAAgB,QAAQ,aAAa,kBAAkB;AAAA,UACzD;AAAA,QACF;AAAA,QACA,KAAK,EAAE,MAAM,QAAQ;AAAA,MACvB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,MAAM,EAAE,SAAS,KAAK,kBAAkB,OAAO,EAAE;AAAA,MACjD,KAAK,EAAE,MAAM,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA;AAAA,EAGQ,kBAAkB,KAA0C;AAClE,UAAM,cAAc;AAAA,MAClB,GAAG,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,WAAW;AAAA,MACjE,GAAG,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,WAAW;AAAA,IAC3D,EAAE,OAAO,CAAC,KAAK,QAAQ,MAAM,KAAK,CAAC;AAInC,UAAM,gBAAgB,KAAK,MAAM,cAAc,GAAG;AAElD,WAAO;AAAA;AAAA,MAEL,IAAI,IAAI;AAAA,MACR,cAAc,IAAI;AAAA,MAClB,MAAM,IAAI,cAAc,SAAS,IAAI,iBAAiB;AAAA,MACtD,QAAQ,IAAI,WAAW,cAAc,aAAa;AAAA,MAClD,QAAQ;AAAA,MACR,UAAU,IAAI,cAAc,CAAC,GAAG,YAAY,IAAI,MAAM,CAAC,GAAG,YAAY;AAAA,MACtE,UAAU;AAAA,QACR,IAAI,IAAI,YAAY;AAAA,QACpB,OAAO,IAAI,YAAY;AAAA,QACvB,WAAW,IAAI,YAAY;AAAA,QAC3B,UAAU,IAAI,YAAY;AAAA,QAC1B,SAAS,IAAI,YAAY,WAAW;AAAA,QACpC,MAAM,IAAI,YAAY,QAAQ;AAAA,QAC9B,OAAO,IAAI,YAAY,SAAS;AAAA,QAChC,KAAK,IAAI,YAAY,OAAO;AAAA,QAC5B,QAAQ,IAAI,YAAY,UAAU;AAAA,MACpC;AAAA,MACA,UAAU,CAAC;AAAA;AAAA,MAGX,cAAc,IAAI;AAAA,MAClB,OAAO,IAAI;AAAA,MACX,eAAe,IAAI;AAAA,MACnB,YAAY,IAAI;AAAA,MAChB,WAAW,IAAI;AAAA,MACf,SAAS,IAAI;AAAA,MACb,WAAW,IAAI;AAAA,MACf,SAAS,IAAI;AAAA,MACb,aAAa,IAAI;AAAA,MACjB,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,IAChB;AAAA,EACF;AACF;;;AFxXO,IAAM,SAAN,MAAa;AAAA,EAKlB,YAAY,UAAkC,QAAsB;AAFpE,SAAQ,kBAAyC;AAG/C,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,SAA0C;AACjD,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB,QAAQ;AAAA,IAC/B;AACA,SAAK,kBAAkB,IAAI,eAAe,KAAK,UAAU;AAAA,MACvD,YAAY,KAAK,OAAO;AAAA,MACxB,GAAG;AAAA,IACL,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,iBAA4E;AAChF,WAAO,KAAK,SAAS,eAAe;AAAA,EACtC;AAAA;AAAA,EAGA,MAAM,sBAA0D;AAC9D,WAAO,KAAK,SAAS,oBAAoB;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,mBAAmB,QAAqE;AAC5F,WAAO,KAAK,SAAS,mBAAmB,MAAM;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,qBAAqB,QAKW;AACpC,WAAO,KAAK,SAAS,qBAAqB,MAAM;AAAA,EAClD;AAAA;AAAA,EAGA,MAAM,sBAAgE;AACpE,WAAO,KAAK,SAAS,oBAAoB;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,eAAe,QAAsD;AACzE,WAAO,KAAK,SAAS,eAAe,MAAM;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,gBACJ,WACA,eAC0B;AAC1B,QAAI,CAAC,WAAW;AACd,YAAM,IAAIE;AAAA,QACR;AAAA,QACA;AAAA,QACA,EAAE,OAAO,YAAY;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,SAAS,qBAAqB,iBAAiB,KAAK,OAAO,aAAa;AAE9E,UAAM,MAAM,IAAI,WAAW,MAAM;AACjC,UAAM,UAAU,MAAM,IAAI,0BAA0B,SAAS;AAC7D,QAAI,CAAC,QAAQ,KAAK,SAAS;AACzB,YAAM,IAAIA,aAAY,qBAAqB,WAAW;AAAA,IACxD;AACA,WAAO,QAAQ,KAAK;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,uBACJ,WACA,eACoC;AACpC,QAAI,CAAC,WAAW;AACd,YAAM,IAAIA;AAAA,QACR;AAAA,QACA;AAAA,QACA,EAAE,OAAO,YAAY;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,SAAS,qBAAqB,iBAAiB,KAAK,OAAO,aAAa;AAE9E,UAAM,MAAM,IAAI,WAAW,MAAM;AACjC,WAAO,IAAI,0BAA0B,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAA0B;AACxB,WAAO,KAAK,SAAS,eAAe;AAAA,EACtC;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,kBAAkB;AACvB,SAAK,SAAS,QAAQ;AAAA,EACxB;AACF;;;AFrJA,IAAI,iBAAgC;AACpC,IAAI,YAA2B;AAmB/B,eAAsB,WACpB,gBACA,SACiB;AACjB,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAIC;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,OAAO,iBAAiB;AAAA,IAC5B;AAAA,EACF;AAGA,MAAI,kBAAkB,cAAc,gBAAgB;AAClD,WAAO;AAAA,EACT;AAGA,MAAI,gBAAgB;AAClB,mBAAe,QAAQ;AAAA,EACzB;AAEA,QAAM,SAAuB;AAAA,IAC3B;AAAA,IACA,GAAG;AAAA,EACL;AAIA,QAAM,UAAU,IAAI,cAAc;AAClC,QAAM,QAAQ,WAAW,MAAM;AAE/B,QAAM,WAAW,IAAI,OAAO,SAAS,MAAM;AAE3C,cAAY;AACZ,mBAAiB;AAEjB,SAAO;AACT;;;AK5BA,eAAsB,sBACpB,SACgC;AAChC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,gBAAgB,CAAC;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,cAAc,CAAC;AAAA,IACf;AAAA,IACA,iBAAiB,CAAC;AAAA,IAClB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,UAAmC;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,MAAM,IAAI,CAAC,UAAU;AAAA,MAC1B,gBAAgB,KAAK;AAAA,MACrB,kBAAkB,KAAK,oBAAoB;AAAA,MAC3C,UAAU,KAAK,YAAY;AAAA,MAC3B,aAAa,KAAK;AAAA,MAClB,gBAAgB,KAAK,kBAAkB;AAAA,MACvC,UAAU,KAAK,YAAY;AAAA,IAC7B,EAAE;AAAA,IACF,eAAe,cAAc,IAAI,CAAC,SAAS;AAAA,MACzC,gBAAgB,IAAI;AAAA,MACpB,kBAAkB,IAAI,oBAAoB;AAAA,MAC1C,UAAU,IAAI,YAAY;AAAA,MAC1B,aAAa,IAAI;AAAA,MACjB,gBAAgB,IAAI,kBAAkB;AAAA,MACtC,UAAU,IAAI,YAAY;AAAA,IAC5B,EAAE;AAAA,IACF,aAAa;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB,WAAW,QAAQ,aAAa;AAAA,MAChC,UAAU,QAAQ,YAAY;AAAA,MAC9B,OAAO,QAAQ;AAAA,MACf,SAAS,QAAQ,WAAW;AAAA,MAC5B,QAAQ,QAAQ,UAAU;AAAA,MAC1B,MAAM,QAAQ,QAAQ;AAAA,MACtB,OAAO,QAAQ,SAAS;AAAA,MACxB,KAAK,QAAQ,OAAO;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAEA,MAAI,UAAU;AACZ,YAAQ,UAAU,IAAI;AAAA,EACxB;AAEA,MAAI,aAAa,QAAQ;AACvB,YAAQ,aAAa,IAAI;AAAA,EAC3B;AAEA,QAAM,MAAM,GAAG,cAAc,QAAQ,QAAQ,EAAE,CAAC;AAChD,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAE5D,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC5B,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,aAAS,SAAS;AAElB,QAAI;AACF,aAAO,MAAM,SAAS,KAAK;AAAA,IAC7B,QAAQ;AAAA,IAER;AAAA,EACF,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AAEA,MAAI,WAAW,KAAK;AAClB,UAAM,OAAO,MAAM,MAAM;AAEzB,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AAEA,UAAM,cAAc,IAAI,IAAI,GAAG,gBAAgB,QAAQ,QAAQ,EAAE,CAAC,SAAS;AAC3E,gBAAY,aAAa,IAAI,MAAM,IAAI;AAEvC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AACzD,kBAAY,aAAa,IAAI,KAAK,KAAK;AAAA,IACzC;AAEA,QAAI,aAAa,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACjF,YAAM,eAAe,KAAK,UAAU,EAAE,YAAY,UAAU,CAAC;AAC7D,YAAM,SAAS,OAAO,SAAS,SAAS,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG;AACrE,eAAS,SAAS,iBAAiB,mBAAmB,YAAY,CAAC,aAAa,MAAM;AAAA,IACxF;AAEA,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,SAAS,OAAO,YAAY,SAAS;AAAA,IAC9C;AAEA,WAAO,EAAE,QAAQ,KAAK,aAAa,YAAY,SAAS,EAAE;AAAA,EAC5D;AAEA,MAAI,WAAW,KAAK;AAClB,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,SAAS,OAAO;AAAA,IACzB;AACA,WAAO,EAAE,QAAQ,IAAI;AAAA,EACvB;AAEA,SAAO,EAAE,OAAO;AAClB;AAOA,eAAsB,iCACpB,SACgC;AAChC,QAAM,EAAE,aAAa,GAAG,GAAG,eAAe,IAAI;AAE9C,MAAI,CAAC,OAAO,SAAS,UAAU,KAAK,CAAC,OAAO,UAAU,UAAU,KAAK,cAAc,GAAG;AACpF,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAEA,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,QAAI;AACF,aAAO,MAAM,sBAAsB,cAAc;AAAA,IACnD,SAAS,KAAK;AACZ,gBAAU;AAEV,UAAI,eAAe,SAAS,IAAI,SAAS,gBAAgB,UAAU,YAAY;AAC7E,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC;AAClE;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,MAAM,gDAAgD;AAC7E;","names":["FloPayError","FloPayError","FloPayError","body","FloPayError","FloPayError"]}
1
+ {"version":3,"sources":["../src/load.ts","../src/stripe-adapter.ts","../src/flopay.ts","../src/elements.ts","../src/payment-api.ts","../src/create-checkout-session.ts"],"sourcesContent":["import type { FloPayConfig } from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\nimport { StripeAdapter } from './stripe-adapter.js';\nimport { FloPay } from './flopay.js';\n\n/** Cache to avoid re-initializing for the same key. */\nlet cachedInstance: FloPay | null = null;\nlet cachedKey: string | null = null;\n\n/**\n * Loads and initializes the FloPay SDK.\n *\n * This is the primary entry point for consumer applications.\n * It initializes the underlying payment provider (currently Stripe)\n * and returns a ready-to-use `FloPay` instance.\n *\n * @example\n * ```ts\n * import { loadFloPay } from '@flopay/js';\n *\n * const flopay = await loadFloPay('pk_test_...');\n * const elements = flopay.elements();\n * const cardElement = await elements.create('card');\n * cardElement.mount('#card-container');\n * ```\n */\nexport async function loadFloPay(\n publishableKey: string,\n options?: Omit<FloPayConfig, 'publishableKey'>,\n): Promise<FloPay> {\n if (!publishableKey) {\n throw new FloPayError(\n 'A publishable key is required to initialize FloPay.',\n 'validation_error',\n { param: 'publishableKey' },\n );\n }\n\n // Return cached instance if key matches\n if (cachedInstance && cachedKey === publishableKey) {\n return cachedInstance;\n }\n\n // Clean up previous instance\n if (cachedInstance) {\n cachedInstance.destroy();\n }\n\n const config: FloPayConfig = {\n publishableKey,\n ...options,\n };\n\n // Currently only Stripe is supported. The adapter pattern allows\n // adding Chargebee, Recurly, or other providers in the future.\n const adapter = new StripeAdapter();\n await adapter.initialize(config);\n\n const instance = new FloPay(adapter, config);\n\n cachedKey = publishableKey;\n cachedInstance = instance;\n\n return instance;\n}\n","import type { Stripe, StripeElements, StripeElementType } from '@stripe/stripe-js';\nimport type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementType,\n ElementOptions,\n MountedElement,\n ConfirmPaymentParams,\n PaymentResult,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n BillingDetails,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Maps FloPay element types to Stripe element types.\n * FloPay uses camelCase; Stripe uses lowercase with hyphens or specific names.\n */\nfunction toStripeElementType(type: ElementType): StripeElementType {\n const map: Record<ElementType, string> = {\n payment: 'payment',\n card: 'card',\n cardNumber: 'cardNumber',\n cardExpiry: 'cardExpiry',\n cardCvc: 'cardCvc',\n address: 'address',\n };\n return map[type] as StripeElementType;\n}\n\n/**\n * Wraps a Stripe element instance in the FloPay MountedElement interface.\n *\n * TODO: In a future phase, this wrapper will render the Stripe element inside\n * an iframe hosted on the FloPay domain for PCI DSS SAQ-A compliance.\n * For now, it delegates directly to the Stripe element.\n */\n/** Minimal interface shared by all Stripe element types. */\ninterface StripeElementLike {\n mount(domElement: string | HTMLElement): void;\n unmount(): void;\n destroy(): void;\n update(options?: Record<string, unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void): void;\n off(event: string, handler?: (...args: unknown[]) => void): void;\n}\n\nfunction wrapStripeElement(\n stripeElement: StripeElementLike,\n): MountedElement {\n const el = stripeElement;\n\n return {\n mount(container: HTMLElement) {\n el.mount(container);\n },\n unmount() {\n el.unmount();\n },\n update(options: Partial<ElementOptions>) {\n el.update(options as Record<string, unknown>);\n },\n on(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['on']?.(event, handler);\n },\n off(event: string, handler: (...args: unknown[]) => void) {\n (el as unknown as Record<string, (...args: unknown[]) => void>)['off']?.(event, handler);\n },\n destroy() {\n el.destroy();\n },\n };\n}\n\n/**\n * Payment provider adapter backed by Stripe.\n *\n * Implements the `PaymentProviderAdapter` interface so that FloPay consumers\n * interact with a stable API regardless of the upstream provider.\n */\nexport class StripeAdapter implements PaymentProviderAdapter {\n readonly name = 'stripe';\n private stripe: Stripe | null = null;\n private elements: StripeElements | null = null;\n\n async initialize(config: FloPayConfig): Promise<void> {\n // loadStripe only works in the browser — skip initialization during SSR/SSG\n if (typeof window === 'undefined') {\n return;\n }\n\n const { loadStripe } = await import('@stripe/stripe-js');\n const stripe = await loadStripe(config.publishableKey, {\n locale: (config.locale as 'auto') ?? 'auto',\n });\n\n if (!stripe) {\n throw new FloPayError(\n 'Failed to initialize Stripe. Check your publishable key.',\n 'authentication_error',\n );\n }\n\n this.stripe = stripe;\n }\n\n /** Lazily creates the Stripe Elements group for the given options. */\n private getElements(options?: ElementOptions): StripeElements {\n if (!this.stripe) {\n throw new FloPayError(\n 'StripeAdapter not initialized. Call initialize() first.',\n 'api_error',\n );\n }\n\n if (!this.elements) {\n let elementsOptions: Record<string, unknown>;\n\n if (options?.clientSecret) {\n // Server-side intent already exists — pass its client secret\n elementsOptions = { clientSecret: options.clientSecret };\n } else {\n // No server-side intent yet — use deferred mode with manual payment method creation.\n // This matches checkout/StripeCardForm: mode='payment', paymentMethodCreation='manual'.\n elementsOptions = {\n mode: 'payment' as const,\n amount: options?.amount ?? 0,\n currency: (options?.currency ?? 'usd').toLowerCase(),\n paymentMethodCreation: options?.paymentMethodCreation ?? ('manual' as const),\n };\n }\n\n if (options?.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n this.elements = this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n return this.elements;\n }\n\n async createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement> {\n const elements = this.getElements(options);\n const stripeType = toStripeElementType(type);\n\n const elementOptions: Record<string, unknown> = {};\n if (options.layout) {\n elementOptions['layout'] = options.layout;\n }\n if (options.defaultValues) {\n elementOptions['defaultValues'] = options.defaultValues;\n }\n if (options.readOnly) {\n elementOptions['readOnly'] = options.readOnly;\n }\n if (options.mode) {\n elementOptions['mode'] = options.mode;\n }\n if (options.style) {\n elementOptions['style'] = options.style;\n }\n\n const stripeElement = elements.create(stripeType as 'card', elementOptions) as unknown as StripeElementLike;\n return wrapStripeElement(stripeElement);\n }\n\n getElement(type: ElementType): MountedElement | null {\n if (!this.elements) return null;\n const stripeType = toStripeElementType(type);\n const existing = this.elements.getElement(stripeType as 'card') as unknown as StripeElementLike | null;\n if (!existing) return null;\n return wrapStripeElement(existing);\n }\n\n async submitElements(): Promise<{ error?: FloPayError }> {\n if (!this.stripe || !this.elements) {\n return { error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n const { error } = await this.elements.submit();\n if (error) {\n return {\n error: new FloPayError(error.message ?? 'Validation failed', 'validation_error'),\n };\n }\n return {};\n }\n\n async createPaymentMethod(billingDetails?: BillingDetails): Promise<CreatePaymentMethodResult> {\n if (!this.stripe || !this.elements) {\n return {\n paymentMethodId: null,\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n // Detect split card fields vs unified PaymentElement.\n // With split fields (cardNumber + cardExpiry + cardCvc), Stripe requires\n // passing the specific cardNumber element with type: 'card'.\n // With unified PaymentElement, pass the elements group.\n const cardNumberEl = this.elements.getElement('cardNumber' as 'card');\n\n // Build billing_details for Stripe AVS (Address Verification).\n // When present, Stripe runs postal code and address checks automatically.\n const stripeBilling = billingDetails ? {\n billing_details: {\n ...(billingDetails.name ? { name: billingDetails.name } : {}),\n ...(billingDetails.address ? {\n address: {\n ...(billingDetails.address.country ? { country: billingDetails.address.country } : {}),\n ...(billingDetails.address.postal_code ? { postal_code: billingDetails.address.postal_code } : {}),\n ...(billingDetails.address.city ? { city: billingDetails.address.city } : {}),\n ...(billingDetails.address.line1 ? { line1: billingDetails.address.line1 } : {}),\n ...(billingDetails.address.line2 ? { line2: billingDetails.address.line2 } : {}),\n ...(billingDetails.address.state ? { state: billingDetails.address.state } : {}),\n },\n } : {}),\n },\n } : {};\n\n const { error, paymentMethod } = cardNumberEl\n ? await this.stripe.createPaymentMethod({\n type: 'card',\n card: cardNumberEl,\n ...stripeBilling,\n } as unknown as Parameters<typeof this.stripe.createPaymentMethod>[0])\n : await this.stripe.createPaymentMethod({\n elements: this.elements,\n ...stripeBilling,\n } as unknown as Parameters<typeof this.stripe.createPaymentMethod>[0]);\n\n if (error) {\n return {\n paymentMethodId: null,\n error: new FloPayError(\n error.message ?? 'Failed to create payment method',\n 'api_error',\n { code: error.code },\n ),\n };\n }\n\n return { paymentMethodId: paymentMethod.id };\n }\n\n async confirmCardPayment(\n params: ConfirmCardPaymentParams,\n ): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return {\n status: 'failed',\n error: new FloPayError('Stripe not initialized', 'api_error'),\n };\n }\n\n const { error, paymentIntent } = await this.stripe.confirmCardPayment(\n params.clientSecret,\n { payment_method: params.paymentMethodId },\n );\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n { code: error.code, declineCode: error.decline_code },\n ),\n };\n }\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n };\n }\n\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n if (!this.stripe || !this.elements) {\n throw new FloPayError(\n 'StripeAdapter not initialized or no elements created.',\n 'api_error',\n );\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n elements: this.elements,\n clientSecret: params.clientSecret,\n confirmParams: {\n return_url: params.returnUrl ?? window.location.href,\n },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(\n error.message ?? 'Payment failed',\n 'api_error',\n {\n code: error.code,\n declineCode: error.decline_code,\n },\n ),\n };\n }\n\n if (!paymentIntent) {\n return { status: 'failed', error: new FloPayError('No payment intent returned', 'api_error') };\n }\n\n const statusMap: Record<string, PaymentResult['status']> = {\n succeeded: 'succeeded',\n processing: 'processing',\n requires_action: 'requires_action',\n requires_payment_method: 'failed',\n canceled: 'failed',\n };\n\n return {\n status: statusMap[paymentIntent.status] ?? 'failed',\n paymentIntentId: paymentIntent.id,\n };\n }\n\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n if (!this.stripe) {\n return { status: 'failed', error: new FloPayError('Stripe not initialized', 'api_error') };\n }\n\n const baseUrl = params.billingApiUrl.replace(/\\/+$/, '');\n\n // 1. Create a PayPal PaymentMethod upfront — backend needs pm_xxx\n // Mirrors checkout/StripeCardForm: stripe.createPaymentMethod({ type: 'paypal' })\n const createPM = this.stripe.createPaymentMethod as unknown as (\n params: { type: string },\n ) => Promise<{ error?: { message?: string }; paymentMethod?: { id: string } }>;\n\n const { error: pmError, paymentMethod } = await createPM({ type: 'paypal' });\n\n if (pmError) {\n console.warn('[FloPay] Could not create PayPal PM upfront:', pmError.message);\n }\n\n // 2. Create PaymentIntent via billing API with pm_xxx (or 'paypal' fallback)\n // isPaypal MUST be string 'true', not boolean — backend checks === 'true'\n const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId: params.sessionId,\n email: params.email,\n paymentMethodType: paymentMethod?.id ?? 'paypal',\n isPaypal: 'true',\n }),\n });\n\n if (!intentResponse.ok) {\n return { status: 'failed', error: new FloPayError('Failed to create PayPal payment intent', 'api_error') };\n }\n\n const intentJson = await intentResponse.json() as { data?: { id?: string } };\n const intentClientSecret = intentJson.data?.id;\n if (!intentClientSecret) {\n return { status: 'failed', error: new FloPayError('No client_secret in response', 'api_error') };\n }\n\n // 3. Confirm — pass payment_method if we have it (avoids setupFutureUsage mismatch)\n // Matches checkout: stripe.confirmPayment({ clientSecret, confirmParams: { payment_method, return_url } })\n const confirmParams: Record<string, unknown> = {\n return_url: params.returnUrl,\n };\n if (paymentMethod?.id) {\n confirmParams['payment_method'] = paymentMethod.id;\n }\n\n const { error, paymentIntent } = await this.stripe.confirmPayment({\n clientSecret: intentClientSecret,\n confirmParams: confirmParams as { return_url: string },\n redirect: 'if_required',\n });\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'PayPal payment failed', 'api_error', { code: error.code }),\n };\n }\n\n const pmId = typeof paymentIntent?.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent?.payment_method?.id;\n\n return {\n status: (paymentIntent?.status as ConfirmCardPaymentResult['status']) ?? 'failed',\n paymentIntentId: paymentIntent?.id,\n paymentMethodId: pmId,\n };\n }\n\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n if (!this.stripe || typeof window === 'undefined') return null;\n\n const params = new URLSearchParams(window.location.search);\n const paymentIntentId = params.get('payment_intent');\n const clientSecret = params.get('payment_intent_client_secret');\n const redirectStatus = params.get('redirect_status');\n\n if (!paymentIntentId || !clientSecret) return null;\n\n if (redirectStatus === 'failed') {\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was declined. Please try again.', 'api_error'),\n };\n }\n\n const { paymentIntent, error } = await this.stripe.retrievePaymentIntent(clientSecret);\n\n if (error) {\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'Failed to retrieve PayPal payment', 'api_error'),\n };\n }\n\n if (paymentIntent && (paymentIntent.status === 'requires_capture' || paymentIntent.status === 'succeeded')) {\n const pmId = typeof paymentIntent.payment_method === 'string'\n ? paymentIntent.payment_method\n : paymentIntent.payment_method?.id;\n\n // Clean up URL params\n const url = new URL(window.location.href);\n url.searchParams.delete('payment_intent');\n url.searchParams.delete('payment_intent_client_secret');\n url.searchParams.delete('redirect_status');\n window.history.replaceState({}, '', url.toString());\n\n return {\n status: paymentIntent.status as ConfirmCardPaymentResult['status'],\n paymentIntentId: paymentIntent.id,\n paymentMethodId: pmId,\n };\n }\n\n return {\n status: 'failed',\n error: new FloPayError('PayPal payment was not completed. Please try again.', 'api_error'),\n };\n }\n\n getRawProvider(): unknown {\n return this.stripe;\n }\n\n createPayPalElements(options: ElementOptions): unknown {\n if (!this.stripe) return null;\n\n const elementsOptions: Record<string, unknown> = {\n mode: 'payment' as const,\n amount: options.amount ?? 0,\n currency: (options.currency ?? 'usd').toLowerCase(),\n captureMethod: 'manual' as const,\n };\n\n if (options.appearance) {\n elementsOptions['appearance'] = {\n theme: (options.appearance.theme as 'stripe') ?? 'stripe',\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n };\n }\n\n return this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n }\n\n destroy(): void {\n this.elements = null;\n this.stripe = null;\n }\n}\n","import type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementOptions,\n ConfirmPaymentParams,\n PaymentResult,\n CheckoutSession,\n NormalizedCheckoutSession,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n ConfirmCardPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError, resolveBillingApiUrl } from '@flopay/shared';\nimport { FloPayElements } from './elements.js';\nimport { PaymentAPI } from './payment-api.js';\n\n/**\n * The main FloPay SDK instance.\n *\n * Created via `loadFloPay(publishableKey)`. Provides element management,\n * payment confirmation, and session retrieval.\n */\nexport class FloPay {\n private readonly provider: PaymentProviderAdapter;\n private readonly config: FloPayConfig;\n private currentElements: FloPayElements | null = null;\n\n constructor(provider: PaymentProviderAdapter, config: FloPayConfig) {\n this.provider = provider;\n this.config = config;\n }\n\n /**\n * Creates a new `FloPayElements` group for mounting payment fields.\n *\n * Only one elements group is active at a time. Creating a new one\n * destroys the previous group.\n */\n elements(options?: ElementOptions): FloPayElements {\n if (this.currentElements) {\n this.currentElements.destroy();\n }\n this.currentElements = new FloPayElements(this.provider, {\n appearance: this.config.appearance,\n ...options,\n });\n return this.currentElements;\n }\n\n /** Submit elements for validation. */\n async submitElements(): Promise<{ error?: import('@flopay/shared').FloPayError }> {\n return this.provider.submitElements();\n }\n\n /** Create a payment method from the current elements (tokenize card). */\n async createPaymentMethod(billingDetails?: import('@flopay/shared').BillingDetails): Promise<CreatePaymentMethodResult> {\n return this.provider.createPaymentMethod(billingDetails);\n }\n\n /** Confirm a card payment with a known client secret and payment method ID. */\n async confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmCardPayment(params);\n }\n\n /** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n }): Promise<ConfirmCardPaymentResult> {\n return this.provider.confirmPayPalPayment(params);\n }\n\n /** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */\n async resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null> {\n return this.provider.resumePayPalPayment();\n }\n\n /** Confirms a payment using the mounted elements. */\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n return this.provider.confirmPayment(params);\n }\n\n /**\n * Retrieves a checkout session by ID via the billing API.\n *\n * Returns the normalized `CheckoutSession` with amount, currency,\n * customer data, and status.\n *\n * Requires `billingApiUrl` to be set — either via `loadFloPay(key, { billingApiUrl })`\n * or passed directly as the second argument.\n */\n async retrieveSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<CheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required to retrieve a session.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n const unified = await api.getUnifiedCheckoutSession(sessionId);\n if (!unified.data.session) {\n throw new FloPayError('Session not found', 'api_error');\n }\n return unified.data.session;\n }\n\n /**\n * Retrieves and normalizes a checkout session, including provider-specific\n * data (Stripe clientSecret/publishableKey, Chargebee site, etc.).\n *\n * The billing API URL is resolved from: explicit param → `loadFloPay()` config\n * → `NEXT_PUBLIC_FLOPAY_ENV` env var → `configureFlopay()` → staging fallback.\n */\n async retrieveUnifiedSession(\n sessionId: string,\n billingApiUrl?: string,\n ): Promise<NormalizedCheckoutSession> {\n if (!sessionId) {\n throw new FloPayError(\n 'sessionId is required.',\n 'validation_error',\n { param: 'sessionId' },\n );\n }\n\n const apiUrl = resolveBillingApiUrl(billingApiUrl ?? this.config.billingApiUrl);\n\n const api = new PaymentAPI(apiUrl);\n return api.getUnifiedCheckoutSession(sessionId);\n }\n\n /**\n * Returns the raw underlying provider instance (e.g. Stripe object).\n * Used internally by components that need direct provider access,\n * such as PayPal which requires its own Elements instance.\n */\n getRawProvider(): unknown {\n return this.provider.getRawProvider();\n }\n\n /** Tears down the SDK instance and releases resources. */\n destroy(): void {\n this.currentElements?.destroy();\n this.currentElements = null;\n this.provider.destroy();\n }\n}\n","import type {\n PaymentProviderAdapter,\n ElementType,\n ElementOptions,\n MountedElement,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/**\n * Manages the creation and lifecycle of payment elements.\n *\n * Each `FloPayElements` instance is bound to a single provider adapter\n * and tracks all created elements for cleanup.\n */\nexport class FloPayElements {\n private readonly provider: PaymentProviderAdapter;\n private readonly elementMap = new Map<ElementType, MountedElement>();\n private readonly baseOptions: ElementOptions;\n\n constructor(provider: PaymentProviderAdapter, options?: ElementOptions) {\n this.provider = provider;\n this.baseOptions = options ?? {};\n }\n\n /**\n * Creates a new element of the given type.\n * If an element of that type already exists, it is destroyed first.\n */\n async create(\n type: ElementType,\n options?: ElementOptions,\n ): Promise<MountedElement> {\n // Check if the provider already has this element (e.g. after React\n // Strict Mode unmount+remount cycle). Reuse it instead of creating\n // a duplicate, which Stripe would reject.\n const providerExisting = this.provider.getElement(type);\n if (providerExisting) {\n this.elementMap.set(type, providerExisting);\n return providerExisting;\n }\n\n const existing = this.elementMap.get(type);\n if (existing) {\n existing.destroy();\n }\n\n const merged: ElementOptions = { ...this.baseOptions, ...options };\n const element = await this.provider.createElement(type, merged);\n this.elementMap.set(type, element);\n return element;\n }\n\n /** Returns a previously created element, or `null`. */\n getElement(type: ElementType): MountedElement | null {\n return this.elementMap.get(type) ?? null;\n }\n\n /**\n * Submits all mounted elements for validation.\n *\n * Returns an object with an optional error if validation fails.\n * This does NOT confirm the payment — call `floPay.confirmPayment()` for that.\n */\n async submit(): Promise<{ error?: FloPayError }> {\n // Walk through all mounted elements and check for incomplete state.\n // The actual validation is handled by the provider's element implementation.\n // For Stripe, the Elements.submit() method is called during confirmPayment.\n // This method exists to match the Stripe Elements API surface.\n return {};\n }\n\n /** Destroys all created elements and clears the internal map. */\n destroy(): void {\n for (const element of this.elementMap.values()) {\n element.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import type {\n CheckoutSession,\n NormalizedCheckoutSession,\n ProcessPaymentParams,\n TokenizedBody,\n BillingProvider,\n InlineSessionParams,\n} from '@flopay/shared';\nimport { FloPayError } from '@flopay/shared';\n\n/** Raw billing API response wrapper. */\ninterface BillingResponse<T> {\n data: T;\n}\n\n/** Raw checkout session from the billing API (includes gateway field). */\ninterface RawCheckoutSession {\n uuid: string;\n nonce: string;\n gateway?: BillingProvider;\n status: 'pending' | 'completed';\n successUrl: string;\n cancelUrl: string;\n createdAt?: string;\n checkoutUrl?: string;\n items: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerItemId: string;\n providerItemName: string;\n providerItemDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n metadata?: Record<string, unknown> | null;\n }>;\n subscriptions: Array<{\n uuid: string;\n checkoutSessionId: string;\n providerPlanId: string;\n providerPlanName: string;\n providerPlanDescription?: string | null;\n quantity: number;\n totalAmount: number;\n overrideAmount: number | null;\n currency: string;\n isUpdate?: boolean;\n metadata?: Record<string, unknown> | null;\n }>;\n coupons?: string[];\n checkoutMode?: 'full' | 'auto' | 'confirm';\n gatewayData: {\n publishableKey?: string | null;\n };\n accountData: {\n userId: string;\n firstName: string;\n lastName: string;\n email: string;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: string | null;\n };\n tagsData: {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n };\n}\n\n/**\n * Client-side payment API service.\n *\n * Mirrors the `PaymentAPI` class from the checkout project's\n * `src/service/api.ts`. All methods call the billing API endpoints\n * that the checkout backend exposes.\n */\nexport class PaymentAPI {\n private readonly baseUrl: string;\n\n constructor(billingApiUrl: string) {\n this.baseUrl = billingApiUrl.replace(/\\/+$/, '');\n }\n\n /** Fetch a raw checkout session by ID. */\n async getCheckoutSession(\n checkoutSessionId: string,\n ): Promise<BillingResponse<RawCheckoutSession>> {\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${checkoutSessionId}`,\n );\n\n if (!response.ok) {\n throw new FloPayError(\n 'Failed to get checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n return response.json() as Promise<BillingResponse<RawCheckoutSession>>;\n }\n\n /**\n * Fetch and normalize a checkout session.\n *\n * Reads the backend's `gateway` field to determine the provider,\n * then wraps the session in a `NormalizedCheckoutSession` for\n * provider-agnostic consumption.\n */\n async getUnifiedCheckoutSession(\n checkoutSessionId: string,\n ): Promise<NormalizedCheckoutSession> {\n const res = await this.getCheckoutSession(checkoutSessionId);\n return this.normalizeRawSession(res.data);\n }\n\n /**\n * Submit a tokenized payment to the billing backend.\n *\n * The backend will either succeed, return `type: '3ds_required'`\n * (with a `threeDSecureToken`), or return `type: 'paypal_redirect_required'`.\n */\n async processPayment(\n userId: string,\n data: ProcessPaymentParams,\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/sessions/process`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-user-id': userId,\n },\n body: JSON.stringify(data),\n },\n );\n }\n\n /**\n * Create a PaymentIntent on the backend.\n *\n * Used by the Stripe flow to create a server-side PaymentIntent\n * with the client's payment method attached.\n */\n async createPaymentIntent(\n sessionId: string,\n email: string,\n paymentMethodType: string,\n options?: { signal?: AbortSignal; isPaypal?: string },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n email,\n paymentMethodType,\n isPaypal: options?.isPaypal ?? false,\n }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Create a SetupIntent for saving payment methods.\n */\n async createSetupIntent(\n sessionId: string,\n email: string,\n paymentMethodType: 'card' | 'google_pay' | 'apple_pay' | 'paypal_express_checkout',\n options?: { signal?: AbortSignal },\n ): Promise<Response> {\n return fetch(\n `${this.baseUrl}/v1/checkouts/payments/setup-intents`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, email, paymentMethodType }),\n signal: options?.signal,\n },\n );\n }\n\n /**\n * Fetch user's prior payments by email.\n * Used to determine if saved card UX should be shown.\n */\n async getPaymentsByEmail(\n email: string,\n options?: { signal?: AbortSignal; page?: number; limit?: number },\n ): Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }> {\n const page = options?.page ?? 1;\n const limit = options?.limit ?? 1;\n const params = new URLSearchParams({\n email,\n page: String(page),\n limit: String(limit),\n sortField: 'occurredAt',\n sortDirection: 'DESC',\n });\n\n const response = await fetch(\n `${this.baseUrl}/v1/payments?${params.toString()}`,\n {\n method: 'GET',\n signal: options?.signal,\n keepalive: true,\n },\n );\n\n if (!response.ok) {\n throw new FloPayError('Failed to fetch payments', 'api_error');\n }\n\n return response.json() as Promise<{ data: Array<{ id: string }>; total: number; page: number; limit: number }>;\n }\n\n /**\n * Create a checkout session AND return the full session data in one call.\n * Uses `?expand=true` so the backend returns the complete session\n * instead of just a UUID — eliminating the need for a second GET.\n *\n * Falls back to create + GET if the backend doesn't support `expand`.\n */\n async createAndFetchSession(\n params: InlineSessionParams,\n ): Promise<NormalizedCheckoutSession> {\n const payload: Record<string, unknown> = {\n clientId: params.clientId,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n checkoutMode: params.checkoutMode ?? 'full',\n items: (params.items ?? []).map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: (params.subscriptions ?? []).map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: params.account.userId,\n firstName: params.account.firstName ?? null,\n lastName: params.account.lastName ?? null,\n email: params.account.email,\n country: params.account.country ?? null,\n gender: params.account.gender ?? null,\n city: params.account.city ?? null,\n state: params.account.state ?? null,\n zip: params.account.zip ?? null,\n },\n couponCodes: params.couponCodes ?? [],\n };\n\n if (params.tagsData) payload['tagsData'] = params.tagsData;\n if (params.utmMetadata?.length) payload['utmMetadata'] = params.utmMetadata;\n\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions?expand=true`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n );\n\n if (response.status === 204) {\n throw new FloPayError(\n 'Session auto-completed — payment method already on file',\n 'api_error',\n { code: 'session_auto_completed' },\n );\n }\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new FloPayError(\n (body as Record<string, string> | null)?.message ?? 'Failed to create checkout session',\n 'api_error',\n { code: `http_${response.status}` },\n );\n }\n\n const body = await response.json() as { data: RawCheckoutSession & { uuid?: string } };\n\n // If backend supports expand=true, it returns full session data.\n // If not, it returns { data: { uuid } } and we fall back to a GET.\n if (body.data && 'gateway' in body.data) {\n // Full session returned — normalize directly\n return this.normalizeRawSession(body.data);\n }\n\n // Fallback: backend returned UUID only — fetch full session\n const uuid = body.data?.uuid;\n if (!uuid) {\n throw new FloPayError('No session ID returned', 'api_error');\n }\n return this.getUnifiedCheckoutSession(uuid);\n }\n\n /** Normalize a raw session into a provider-agnostic shape. */\n private normalizeRawSession(session: RawCheckoutSession): NormalizedCheckoutSession {\n const gateway = session.gateway;\n\n if (gateway === 'chargebee') {\n return {\n provider: 'chargebee',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n if (gateway === 'stripe') {\n return {\n provider: 'stripe',\n mode: 'tokenize',\n data: {\n session: this.toCheckoutSession(session),\n stripe: {\n clientSecret: (session as unknown as Record<string, unknown>)['stripeClientSecret'] as string ?? '',\n publishableKey: session.gatewayData?.publishableKey ?? undefined,\n },\n },\n raw: { data: session },\n };\n }\n\n return {\n provider: 'recurly',\n mode: 'tokenize',\n data: { session: this.toCheckoutSession(session) },\n raw: { data: session },\n };\n }\n\n /** Convert raw session to the SDK CheckoutSession shape. */\n private toCheckoutSession(raw: RawCheckoutSession): CheckoutSession {\n const totalAmount = [\n ...raw.subscriptions.map((s) => s.overrideAmount || s.totalAmount),\n ...raw.items.map((i) => i.overrideAmount || i.totalAmount),\n ].reduce((sum, val) => sum + val, 0);\n\n // Billing API returns amounts in major units (e.g. 24.95 USD).\n // Stripe expects amounts in smallest currency unit (cents).\n const amountInCents = Math.round(totalAmount * 100);\n\n return {\n // Core fields (backward compat)\n id: raw.uuid,\n clientSecret: raw.nonce,\n mode: raw.subscriptions.length > 0 ? 'subscription' : 'payment',\n status: raw.status === 'completed' ? 'complete' : 'open',\n amount: amountInCents,\n currency: raw.subscriptions[0]?.currency ?? raw.items[0]?.currency ?? 'USD',\n customer: {\n id: raw.accountData.userId,\n email: raw.accountData.email,\n firstName: raw.accountData.firstName,\n lastName: raw.accountData.lastName,\n country: raw.accountData.country ?? undefined,\n city: raw.accountData.city ?? undefined,\n state: raw.accountData.state ?? undefined,\n zip: raw.accountData.zip ?? undefined,\n gender: raw.accountData.gender ?? undefined,\n },\n metadata: {},\n\n // Full session data from billing API\n checkoutMode: raw.checkoutMode,\n items: raw.items,\n subscriptions: raw.subscriptions,\n successUrl: raw.successUrl,\n cancelUrl: raw.cancelUrl,\n coupons: raw.coupons,\n createdAt: raw.createdAt,\n gateway: raw.gateway,\n gatewayData: raw.gatewayData,\n accountData: raw.accountData,\n tagsData: raw.tagsData,\n };\n }\n}\n","import type {\n CreateSessionParams,\n CheckoutSessionResult,\n} from '@flopay/shared';\n\n/**\n * Creates a checkout session via the billing API and redirects the user\n * to the hosted checkout page.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n *\n * - On 201: Redirects to `{checkoutBaseUrl}/secure?id={uuid}&...redirectParams`\n * - On 204: Redirects directly to `successUrl` (payment method already on file)\n * - On other: Returns `{ status }` without redirecting\n *\n * @example\n * ```ts\n * import { createCheckoutSession } from '@flopay/js';\n *\n * await createCheckoutSession({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{\n * providerItemId: 'prod_abc',\n * providerItemName: 'Pro Plan',\n * totalAmount: 49.99,\n * overrideAmount: 24.99,\n * }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * redirectParams: { email: 'user@example.com', bg: 'courses', mode: 'confirm' },\n * });\n * ```\n */\nexport async function createCheckoutSession(\n options: CreateSessionParams,\n): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n setCookie = true,\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = options;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body — leave undefined\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n if (setCookie && typeof window !== 'undefined' && typeof document !== 'undefined') {\n const checkoutData = JSON.stringify({ origin_url: cancelUrl });\n const domain = window.location.hostname.split('.').slice(-2).join('.');\n document.cookie = `checkout_data=${encodeURIComponent(checkoutData)}; domain=.${domain}; path=/; max-age=3600; SameSite=Lax; Secure;`;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = redirectUrl.toString();\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n if (typeof window !== 'undefined') {\n window.location.href = successUrl;\n }\n return { status: 204 };\n }\n\n return { status };\n}\n\n/**\n * Creates a checkout session with automatic retry on timeout/abort errors.\n *\n * Uses exponential backoff: 100ms, 200ms, 400ms, etc.\n */\nexport async function createCheckoutSessionWithRetries(\n options: CreateSessionParams & { maxRetries?: number },\n): Promise<CheckoutSessionResult> {\n const { maxRetries = 3, ...sessionOptions } = options;\n\n if (!Number.isFinite(maxRetries) || !Number.isInteger(maxRetries) || maxRetries <= 0) {\n throw new Error('Number of retries must be greater than 0');\n }\n\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await createCheckoutSession(sessionOptions);\n } catch (err) {\n lastErr = err;\n\n if (err instanceof Error && err.name === 'AbortError' && attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));\n continue;\n }\n\n throw err;\n }\n }\n\n throw lastErr ?? new Error('Unknown error during checkout session creation');\n}\n"],"mappings":"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","names":["FloPayError","FloPayError","FloPayError","body","FloPayError","FloPayError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flopay/js",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -25,7 +25,7 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@flopay/shared": "0.2.1"
28
+ "@flopay/shared": "0.3.1"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@stripe/stripe-js": ">=2.0.0"