@flopay/js 1.4.2 → 1.4.4

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.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/load.ts","../src/stripe-adapter.ts","../src/payment-api.ts","../src/api-error.ts","../src/session-display-cache.ts","../src/telemetry-reporter.ts","../src/flopay.ts","../src/elements.ts","../src/pci-vault-card-capture.ts","../src/telemetry-bridge.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 { PciVaultCardCapture } from './pci-vault-card-capture.js';\nexport type { PciVaultCardCaptureConfig } from './pci-vault-card-capture.js';\nexport { createCheckoutSession, createCheckoutSessionWithRetries } from './create-checkout-session.js';\nexport {\n cacheSessionDisplayData,\n getSessionDisplayData,\n clearSessionDisplayData,\n} from './session-display-cache.js';\nexport type {\n SessionDisplayProduct,\n SessionDisplayCacheData,\n} from './session-display-cache.js';\n","import type { FloPayConfig } from '@flopay/shared';\nimport { FloPayError, resolveBillingApiUrl, SDK_VERSION } from '@flopay/shared';\nimport { StripeAdapter } from './stripe-adapter.js';\nimport { FloPay, createInstrumentedFloPay } from './flopay.js';\nimport { TelemetryReporter } from './telemetry-reporter.js';\nimport { getFloPayTelemetryBridge } from './telemetry-bridge.js';\n\n/**\n * Cache of FloPay instances keyed by every behavior-affecting configuration\n * option. Opted-out and default-enabled consumers must never share a reporter\n * because opt-out is permanent for an instance.\n */\nconst instanceCache = new Map<string, FloPay>();\n\nfunction stableCacheValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(stableCacheValue);\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, stableCacheValue(entry)]),\n );\n }\n return value;\n}\n\nfunction instanceCacheKey(\n publishableKey: string,\n options: Omit<FloPayConfig, 'publishableKey'> | undefined,\n): string {\n return JSON.stringify([\n publishableKey,\n resolveBillingApiUrl(options?.billingApiUrl),\n options?.telemetry !== false,\n options?.locale ?? 'auto',\n options?.apiVersion ?? null,\n stableCacheValue(options?.appearance ?? null),\n ]);\n}\n\n/**\n * Provider initialization promises keyed by publishable key. This closes the\n * window before `instanceCache` is populated so concurrent callers share the\n * same provider work and resolve to the same SDK instance.\n */\nconst initializationCache = new Map<string, Promise<FloPay>>();\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 * Instances are cached per complete behavior-affecting configuration.\n * Matching calls return the same instance; calls with different billing API,\n * telemetry, locale, API version, or appearance options receive independent\n * instances.\n *\n * @example\n * ```ts\n * import { loadFloPay } from '@flopay/js';\n *\n * const flopay = await loadFloPay('pk_test_...');\n * const elements = flopay.elements({ paymentMethodTypes: ['cashapp', 'ideal'] });\n * const paymentElement = await elements.create('payment');\n * paymentElement.mount('#payment-container');\n * ```\n */\nexport async function loadFloPay(\n publishableKey: string,\n options?: Omit<FloPayConfig, 'publishableKey'>,\n): Promise<FloPay> {\n if (!publishableKey) {\n const reporter = new TelemetryReporter({\n billingApiUrl: resolveBillingApiUrl(options?.billingApiUrl),\n sdkVersion: SDK_VERSION,\n enabled: options?.telemetry !== false,\n });\n reporter.error({\n errorCode: 'CONFIGURATION_INVALID',\n stage: 'sdk_initialize',\n paymentMethodCategory: 'unknown',\n });\n void reporter.flush()\n .catch(() => {})\n .finally(() => reporter.destroy());\n throw new FloPayError(\n 'A publishable key is required to initialize FloPay.',\n 'validation_error',\n { param: 'publishableKey' },\n );\n }\n\n const cacheKey = instanceCacheKey(publishableKey, options);\n const cached = instanceCache.get(cacheKey);\n if (cached) {\n if (options?.telemetry !== false) {\n getFloPayTelemetryBridge(cached)?.log({\n name: 'sdk.cache.hit',\n stage: 'sdk_initialize',\n });\n }\n return cached;\n }\n\n const initializing = initializationCache.get(cacheKey);\n if (initializing) return initializing;\n\n const config: FloPayConfig = {\n ...options,\n publishableKey,\n };\n\n const initialization = (async () => {\n const reporter = new TelemetryReporter({\n billingApiUrl: resolveBillingApiUrl(config.billingApiUrl),\n sdkVersion: SDK_VERSION,\n enabled: config.telemetry !== false,\n });\n const initializationStarted = reporter.now();\n reporter.log({ name: 'sdk.initialize.started', stage: 'sdk_initialize' });\n reporter.log({ name: 'sdk.cache.miss', stage: 'sdk_initialize' });\n reporter.log({\n name: 'provider.load.started',\n stage: 'provider_load',\n provider: 'stripe',\n });\n\n // Stripe is the only adapter today. Direct PayPal does not flow through\n // this loader — it renders via the official PayPal JS SDK from\n // `DirectPayPalButton`.\n const adapter = new StripeAdapter();\n try {\n await adapter.initialize(config);\n } catch (error) {\n reporter.error({\n errorCode: 'SDK_INITIALIZATION_FAILED',\n stage: 'sdk_initialize',\n provider: 'stripe',\n paymentMethodCategory: 'unknown',\n });\n reporter.destroy();\n throw error;\n }\n reporter.log({ name: 'provider.ready', stage: 'provider_ready', provider: 'stripe' });\n reporter.log({\n name: 'provider.availability.checked',\n stage: 'provider_ready',\n provider: 'stripe',\n });\n reporter.log({ name: 'sdk.initialize.ready', stage: 'sdk_initialize' });\n const initializationDuration = reporter.now() - initializationStarted;\n reporter.performance({\n stage: 'sdk_initialize',\n durationMs: initializationDuration,\n durationMode: 'machine',\n provider: 'stripe',\n });\n reporter.performance({\n stage: 'provider_ready',\n durationMs: initializationDuration,\n durationMode: 'machine',\n provider: 'stripe',\n });\n\n const instance = createInstrumentedFloPay(adapter, config, reporter);\n instanceCache.set(cacheKey, instance);\n return instance;\n })();\n initializationCache.set(cacheKey, initialization);\n\n try {\n return await initialization;\n } finally {\n // Successful instances live in `instanceCache`; failed work is deliberately\n // forgotten so a later call can retry provider initialization.\n if (initializationCache.get(cacheKey) === initialization) {\n initializationCache.delete(cacheKey);\n }\n }\n}\n","import {loadStripe} from '@stripe/stripe-js';\nimport type {Stripe, StripeElements, StripeElementType} from '@stripe/stripe-js';\nimport type {\n BillingDetails,\n ConfirmPaymentParams,\n ElementOptions,\n ElementType,\n FloPayConfig,\n MountedElement,\n PayPalPaymentResult,\n PaymentProviderAdapter,\n PaymentResult,\n} from '@flopay/shared';\nimport {FloPayError, isSetupIntentClientSecret} from '@flopay/shared';\nimport {PaymentAPI} from './payment-api.js';\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 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\n/**\n * Maps a `FloPayAppearance.theme` ('default' | 'flat' | 'night' | 'none') to a\n * Stripe Elements Appearance `theme` ('stripe' | 'flat' | 'night'). Stripe's\n * Appearance API only accepts those three; anything else triggers a console\n * warning and silently falls back. We normalize here so the bundles can keep\n * `'default'` as their public token.\n */\nfunction toStripeAppearanceTheme(\n theme: 'default' | 'flat' | 'night' | 'none' | undefined,\n): 'stripe' | 'night' | 'flat' {\n switch (theme) {\n case 'night': return 'night';\n case 'flat': return 'flat';\n // 'default', 'none', undefined, or any unexpected value → Stripe's baseline.\n default: return 'stripe';\n }\n}\n\nfunction paymentMethodTypesKey(paymentMethodTypes: readonly string[] | undefined): string | null {\n return paymentMethodTypes\n ? JSON.stringify(paymentMethodTypes.map((paymentMethodType) => paymentMethodType.trim().toLowerCase()))\n : null;\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 * Map FloPay `BillingDetails` onto Stripe's `billing_details` shape for AVS.\n * Every field is spread conditionally so Stripe only ever receives the values\n * the buyer actually supplied to `confirmPayment` as `payment_method_data`.\n */\nfunction toStripeBillingDetails(billing: BillingDetails) {\n return {\n billing_details: {\n ...(billing.email ? { email: billing.email } : {}),\n ...(billing.name ? { name: billing.name } : {}),\n ...(billing.address ? {\n address: {\n ...(billing.address.country ? { country: billing.address.country } : {}),\n ...(billing.address.postal_code ? { postal_code: billing.address.postal_code } : {}),\n ...(billing.address.city ? { city: billing.address.city } : {}),\n ...(billing.address.line1 ? { line1: billing.address.line1 } : {}),\n ...(billing.address.line2 ? { line2: billing.address.line2 } : {}),\n ...(billing.address.state ? { state: billing.address.state } : {}),\n },\n } : {}),\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 // Serialized appearance currently applied to `this.elements`. Used to detect\n // when consumers swap themes mid-session so we can live-update the Stripe\n // Elements group instead of returning a stale-styled cache. `null` while no\n // elements group exists.\n private appliedAppearanceKey: string | null = null;\n private appliedPaymentMethodTypesKey: string | null = null;\n private appliedClientSecret: string | null = null;\n private verifiedClientSecret: string | null = null;\n private verifiedPaymentMethodTypesKey: string | 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 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 const stripeAppearance = options?.appearance\n ? {\n theme: toStripeAppearanceTheme(options.appearance.theme),\n variables: options.appearance.variables as Record<string, string>,\n rules: options.appearance.rules,\n }\n : undefined;\n const nextAppearanceKey = stripeAppearance ? JSON.stringify(stripeAppearance) : null;\n const nextPaymentMethodTypesKey = paymentMethodTypesKey(options?.paymentMethodTypes);\n const nextClientSecret = options?.clientSecret ?? null;\n\n if (\n this.elements\n && nextPaymentMethodTypesKey\n && (\n nextPaymentMethodTypesKey !== this.appliedPaymentMethodTypesKey\n || nextClientSecret !== this.appliedClientSecret\n )\n ) {\n this.elements = null;\n this.appliedAppearanceKey = null;\n this.appliedPaymentMethodTypesKey = null;\n this.appliedClientSecret = null;\n this.verifiedClientSecret = null;\n this.verifiedPaymentMethodTypesKey = null;\n }\n\n if (!this.elements) {\n let elementsOptions: Record<string, unknown>;\n\n const deferredAmount = options?.amount ?? 0;\n const deferredCurrency = (options?.currency ?? 'usd').toLowerCase();\n const paymentMethodCreation = options?.paymentMethodCreation ?? ('manual' as const);\n\n if (options?.clientSecret) {\n // Server-side intent already exists — pass its client secret. Stripe\n // infers payment vs setup mode from the secret prefix (`pi_` / `seti_`).\n // createElement() has already verified the provider intent against the\n // sanitized non-card allowlist; Stripe does not accept\n // paymentMethodTypes alongside clientSecret.\n elementsOptions = { clientSecret: options.clientSecret };\n } else if (deferredAmount > 0) {\n // No server-side intent yet — use deferred payment mode with manual\n // payment method creation for the declared wallet/APM allowlist.\n elementsOptions = {\n mode: 'payment' as const,\n amount: deferredAmount,\n currency: deferredCurrency,\n paymentMethodCreation,\n };\n\n if (options?.setupFutureUsage) {\n elementsOptions['setupFutureUsage'] = options.setupFutureUsage;\n }\n } else {\n // Trial-only / $0 checkout: there is nothing to charge up front, so a\n // deferred PaymentIntent is invalid — Stripe rejects `elements()` with\n // \"Invalid value for elements(): `amount` must be greater than 0\" and\n // the buyer never reaches the payment surface. Use deferred *setup*\n // mode instead (no amount) so a reusable wallet/APM method can be\n // attached to the SetupIntent and charged when the trial ends.\n elementsOptions = {\n mode: 'setup' as const,\n currency: deferredCurrency,\n paymentMethodCreation,\n };\n }\n\n if (!options?.clientSecret && options?.paymentMethodTypes) {\n elementsOptions['paymentMethodTypes'] = options.paymentMethodTypes;\n }\n\n if (stripeAppearance) {\n elementsOptions['appearance'] = stripeAppearance;\n }\n\n this.elements = this.stripe.elements(elementsOptions as unknown as Parameters<Stripe['elements']>[0]);\n this.appliedAppearanceKey = nextAppearanceKey;\n this.appliedPaymentMethodTypesKey = nextPaymentMethodTypesKey;\n this.appliedClientSecret = nextClientSecret;\n this.verifiedClientSecret = null;\n this.verifiedPaymentMethodTypesKey = null;\n } else if (nextAppearanceKey !== this.appliedAppearanceKey) {\n // Elements group already exists but the consumer changed (or removed)\n // the appearance. Stripe Elements supports a live `update({ appearance })`\n // call which re-styles mounted elements in place — no re-create, no\n // input-state loss. When the consumer drops `appearance`, fall through\n // with an empty payload so any prior variables/rules are cleared.\n (this.elements as unknown as { update: (opts: Record<string, unknown>) => void }).update({\n appearance: stripeAppearance ?? {},\n });\n this.appliedAppearanceKey = nextAppearanceKey;\n }\n\n return this.elements;\n }\n\n private async assertClientSecretPaymentMethods(\n clientSecret: string,\n allowedPaymentMethodTypes: readonly string[],\n ): Promise<void> {\n if (!this.stripe) {\n throw new FloPayError(\n 'StripeAdapter not initialized. Call initialize() first.',\n 'api_error',\n );\n }\n\n let intent: { payment_method_types?: unknown } | undefined;\n let retrievalFailed = false;\n if (isSetupIntentClientSecret(clientSecret)) {\n const { setupIntent, error } = await this.stripe.retrieveSetupIntent(clientSecret);\n intent = setupIntent;\n retrievalFailed = Boolean(error);\n } else {\n const { paymentIntent, error } = await this.stripe.retrievePaymentIntent(clientSecret);\n intent = paymentIntent;\n retrievalFailed = Boolean(error);\n }\n const providerPaymentMethodTypes = intent?.payment_method_types;\n\n if (retrievalFailed || !Array.isArray(providerPaymentMethodTypes)) {\n throw new FloPayError(\n 'Unable to verify the payment methods configured for this client secret.',\n 'api_error',\n { param: 'clientSecret' },\n );\n }\n\n const allowlist = new Set(\n allowedPaymentMethodTypes.map((paymentMethodType) => paymentMethodType.toLowerCase()),\n );\n const hasDisallowedProviderMethod = providerPaymentMethodTypes.some(\n (paymentMethodType) =>\n typeof paymentMethodType !== 'string'\n || !allowlist.has(paymentMethodType.trim().toLowerCase()),\n );\n if (hasDisallowedProviderMethod || providerPaymentMethodTypes.length === 0) {\n throw new FloPayError(\n 'The client-secret intent must enable only declared non-card payment methods.',\n 'validation_error',\n { param: 'clientSecret' },\n );\n }\n }\n\n async createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement> {\n let resolvedOptions = options;\n if (type === 'payment') {\n const paymentMethodTypes = options.paymentMethodTypes\n ?.map((paymentMethodType) => paymentMethodType.trim())\n .filter((paymentMethodType) => paymentMethodType && paymentMethodType.toLowerCase() !== 'card');\n if (!paymentMethodTypes?.length) {\n throw new FloPayError(\n 'At least one supported non-card payment method is required.',\n 'validation_error',\n { param: 'paymentMethodTypes' },\n );\n }\n resolvedOptions = { ...options, paymentMethodTypes };\n if (resolvedOptions.clientSecret) {\n const resolvedPaymentMethodTypesKey = paymentMethodTypesKey(paymentMethodTypes);\n const verificationIsCached = Boolean(\n this.elements\n && this.appliedClientSecret === resolvedOptions.clientSecret\n && this.appliedPaymentMethodTypesKey === resolvedPaymentMethodTypesKey\n && this.verifiedClientSecret === resolvedOptions.clientSecret\n && this.verifiedPaymentMethodTypesKey === resolvedPaymentMethodTypesKey,\n );\n if (!verificationIsCached) {\n await this.assertClientSecretPaymentMethods(\n resolvedOptions.clientSecret,\n paymentMethodTypes,\n );\n }\n }\n }\n\n const elements = this.getElements(resolvedOptions);\n if (type === 'payment' && resolvedOptions.clientSecret) {\n this.verifiedClientSecret = resolvedOptions.clientSecret;\n this.verifiedPaymentMethodTypesKey = paymentMethodTypesKey(\n resolvedOptions.paymentMethodTypes,\n );\n }\n const stripeType = toStripeElementType(type);\n\n const elementOptions: Record<string, unknown> = {};\n if (resolvedOptions.layout) {\n elementOptions['layout'] = resolvedOptions.layout;\n }\n if (resolvedOptions.defaultValues) {\n elementOptions['defaultValues'] = resolvedOptions.defaultValues;\n }\n if (resolvedOptions.readOnly) {\n elementOptions['readOnly'] = resolvedOptions.readOnly;\n }\n if (resolvedOptions.mode) {\n elementOptions['mode'] = resolvedOptions.mode;\n }\n const stripeElement = elements.create(stripeType as 'payment', 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 'payment') 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 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 billing = params.billingDetails;\n const paymentMethodData = billing ? toStripeBillingDetails(billing) : undefined;\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 ...(paymentMethodData ? { payment_method_data: paymentMethodData } : {}),\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 paymentMethodId: this.extractPaymentMethodId(paymentIntent.payment_method),\n };\n }\n\n private extractPaymentMethodId(\n paymentMethod: string | { id?: string | null } | null | undefined,\n ): string | undefined {\n if (typeof paymentMethod === 'string' && paymentMethod.startsWith('pm_')) {\n return paymentMethod;\n }\n if (paymentMethod && typeof paymentMethod === 'object' && typeof paymentMethod.id === 'string') {\n return paymentMethod.id;\n }\n return undefined;\n }\n\n async confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n nonce?: string;\n }): Promise<PayPalPaymentResult> {\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 if (this.elements) {\n const { error: submitError } = await this.elements.submit();\n if (submitError) {\n return {\n status: 'failed',\n error: new FloPayError(\n submitError.message ?? 'PayPal payment failed',\n 'validation_error',\n { code: submitError.code },\n ),\n };\n }\n }\n\n let intentClientSecret: string;\n try {\n const intent = await new PaymentAPI(baseUrl).createSessionIntent(\n params.sessionId,\n params.nonce ?? '',\n {\n provider: 'stripe',\n paymentMethodCategory: 'wallet',\n paymentMethodType: 'paypal',\n paymentMethodId: null,\n intentKind: 'payment',\n },\n );\n if (intent.provider !== 'stripe') {\n throw new FloPayError('Invalid provider returned for PayPal intent', 'api_error');\n }\n intentClientSecret = intent.clientSecret;\n } catch (error) {\n return {\n status: 'failed',\n error: error instanceof FloPayError\n ? error\n : new FloPayError('Failed to create PayPal payment intent', 'api_error'),\n };\n }\n\n const { error } = await this.stripe.confirmPayment({\n clientSecret: intentClientSecret,\n elements: this.elements ?? undefined,\n confirmParams: { return_url: params.returnUrl },\n });\n\n if (error) {\n if (params.nonce) {\n try {\n await new PaymentAPI(baseUrl).reportSessionIntentDecline(\n params.sessionId,\n params.nonce,\n {\n provider: 'stripe',\n paymentMethodCategory: 'wallet',\n paymentMethodType: 'paypal',\n providerDeclineReason: error.code ?? 'provider_declined',\n },\n );\n } catch {\n // Best-effort decline classification must not replace the provider error.\n }\n }\n return {\n status: 'failed',\n error: new FloPayError(error.message ?? 'PayPal payment failed', 'api_error', { code: error.code }),\n };\n }\n\n return {\n status: 'processing',\n };\n }\n\n async resumePayPalPayment(): Promise<PayPalPaymentResult | 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 PayPalPaymentResult['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.setupFutureUsage) {\n elementsOptions['setupFutureUsage'] = options.setupFutureUsage;\n }\n\n if (options.appearance) {\n elementsOptions['appearance'] = {\n theme: toStripeAppearanceTheme(options.appearance.theme),\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.appliedAppearanceKey = null;\n this.appliedPaymentMethodTypesKey = null;\n this.appliedClientSecret = null;\n this.verifiedClientSecret = null;\n this.verifiedPaymentMethodTypesKey = null;\n this.stripe = null;\n }\n}\n","import type {\n CheckoutGateways,\n CheckoutSession,\n CheckoutProcessError,\n CheckoutProcessingPending,\n CheckoutSessionProduct,\n NormalizedCheckoutSession,\n ProcessPaymentParams,\n TokenizedBody,\n BillingProvider,\n InlineSessionDraft,\n VaultCaptureBlock,\n TelemetryErrorCode,\n TelemetryRequestCategory,\n TelemetryStage,\n TelemetryStatusClass,\n CreateSessionIntentRequest,\n SessionIntent,\n SessionIntentDeclineRequest,\n} from '@flopay/shared';\nimport {\n FloPayError,\n SDK_VERSION,\n FLO_SDK_VERSION_HEADER,\n IDEMPOTENCY_KEY_HEADER,\n IDEMPOTENCY_IN_PROGRESS_CODE,\n buildProductPayload,\n foldIntoProducts,\n isUuidV4,\n randomUuidV4,\n resolveIdempotencyKey,\n resolveSessionCurrency,\n} from '@flopay/shared';\nimport { readErrorMessage, readErrorString } from './api-error.js';\nimport {\n cacheSessionDisplayData,\n clearSessionDisplayData,\n getSessionDisplayData,\n} from './session-display-cache.js';\nimport { telemetryNow } from './telemetry-reporter.js';\nimport { TelemetryReporter } from './telemetry-reporter.js';\nimport type {\n SessionDisplayCacheData,\n SessionDisplayProduct,\n} from './session-display-cache.js';\n\n/** Raw billing API response wrapper. */\ninterface BillingResponse<T> {\n data: T;\n}\n\n/** Raw checkout session from the billing API. */\ninterface RawCheckoutSession {\n uuid: string;\n nonce: string;\n status: 'pending' | 'completed' | 'expired';\n successUrl: string;\n cancelUrl: string;\n /** Session-level currency. */\n currency?: string;\n createdAt?: string;\n checkoutUrl?: string;\n /** Unified products list returned by the billing API (post-#760). */\n products?: Array<{\n uuid: string;\n checkoutSessionId: string;\n /** 'item' or 'subscription'. */\n type: 'item' | 'subscription';\n code?: string;\n name?: string | null;\n description?: string | null;\n quantity: number;\n totalAmount?: number;\n overrideAmount?: number | null;\n currency?: string;\n metadata?: Record<string, unknown> | null;\n }>;\n coupons?: string[];\n /**\n * Pre-discount total in cart-currency major units. Populated by billing\n * API ≥ v1.1.2; absent on older backends.\n */\n subtotalAmount?: number;\n /** Total reduction from applied coupons (cart-currency major units). */\n discountAmount?: number;\n /** Final charge amount after coupon discount (cart-currency major units). */\n totalAmount?: number;\n checkoutMode?: 'full' | 'auto' | 'confirm';\n gateways?: CheckoutGateways;\n /**\n * Generic downstream card-method id for a card already on file\n * (TeamFloPay/backend#823) — present for returning customers so the SDK can\n * skip the vault widget. Absent for first-time buyers.\n */\n providerPaymentMethodId?: string | null;\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 addressLine1?: string | null;\n addressLine2?: string | null;\n };\n tagsData: {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n };\n}\n\ntype ApiErrorPayload = Record<string, unknown> | null;\n\nconst DEFAULT_PROCESSING_RETRY_AFTER_MS = 1_000;\nconst MIN_PROCESSING_RETRY_AFTER_MS = 500;\nconst DEFAULT_PROCESSING_TIMEOUT_MS = 15_000;\nconst MAX_PROCESSING_RETRY_AFTER_MS = 3_000;\n// Bounds the pre-pay account-snapshot PATCH so a stalled request can't leave the\n// vault submit gate blocked forever (sdk#124). The whole retry sequence must\n// finish inside this window; on expiry the AbortController fires and the caller\n// falls back to its transient-failure path (release the gate best-effort).\nconst DEFAULT_ACCOUNT_SNAPSHOT_TIMEOUT_MS = 10_000;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction telemetryStatusClass(status: number | undefined): TelemetryStatusClass {\n if (status === undefined) return 'network_error';\n const statusClass = `${Math.floor(status / 100)}xx`;\n return statusClass === '2xx'\n || statusClass === '3xx'\n || statusClass === '4xx'\n || statusClass === '5xx'\n ? statusClass\n : 'unknown';\n}\n\nfunction telemetryFailure(\n error: unknown,\n fallbackCode: TelemetryErrorCode,\n): { errorCode: TelemetryErrorCode; statusClass: TelemetryStatusClass } {\n if (\n error instanceof Error\n && (error.name === 'AbortError'\n || (error instanceof FloPayError && error.code === 'checkout_processing_timeout'))\n ) {\n return { errorCode: 'REQUEST_TIMEOUT', statusClass: 'timeout' };\n }\n if (error instanceof TypeError) {\n return { errorCode: 'NETWORK_REQUEST_FAILED', statusClass: 'network_error' };\n }\n return {\n errorCode: fallbackCode,\n statusClass: telemetryStatusClass(\n error instanceof FloPayError ? error.statusCode : undefined,\n ),\n };\n}\n\nfunction readString(payload: ApiErrorPayload, key: string): string | undefined {\n return readErrorString(payload?.[key]);\n}\n\nfunction readMessage(payload: ApiErrorPayload, key: string): string | undefined {\n return readErrorMessage(payload?.[key]);\n}\n\nfunction readNumber(payload: ApiErrorPayload, key: string): number | undefined {\n const value = payload?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction createCheckoutProcessingTimeoutError(): FloPayError {\n return new FloPayError(\n 'Checkout is still processing. Please try again shortly.',\n 'api_error',\n { code: 'checkout_processing_timeout' },\n );\n}\n\nasync function buildApiErrorFromResponse(\n response: Response,\n fallbackMessage: string,\n): Promise<FloPayError> {\n const payload = await response.json().catch(() => null) as ApiErrorPayload;\n const nestedError = isRecord(payload?.error) ? payload.error : null;\n const message =\n readMessage(payload, 'message') ??\n readMessage(nestedError, 'message') ??\n fallbackMessage;\n const code =\n readString(payload, 'code') ??\n readString(payload, 'gatewayErrorCode') ??\n readString(nestedError, 'code') ??\n `http_${response.status}`;\n\n return new FloPayError(message, 'api_error', {\n code,\n statusCode: response.status,\n });\n}\n\n/**\n * Extra attempts (beyond the first) for transient network failures.\n * Three total tries: immediate, +150ms, +300ms.\n */\nconst NETWORK_RETRY_ATTEMPTS = 2;\n\n/**\n * Extra attempts (beyond the first) for the backend's documented in-progress\n * replay ({@link IDEMPOTENCY_IN_PROGRESS_CODE}) on checkout-session create.\n * The same stable key is replayed after a short backoff (+150ms, +300ms); a\n * payload-conflict (`409`) and every other error fail fast\n * (TeamFloPay/backend#972).\n */\nconst IDEMPOTENCY_IN_PROGRESS_RETRY_ATTEMPTS = 2;\n\n/**\n * Run `fetch` with a bounded retry on transient network failures.\n *\n * `fetch` rejects — rather than resolving with a non-ok `Response` — only when\n * the request never produced an HTTP response at all: a dropped connection, a\n * DNS hiccup, or a failed CORS preflight, which all surface as\n * `TypeError: Failed to fetch`. Those blips are worth retrying. An `AbortError`\n * (caller-initiated cancellation) is not, and any HTTP-level failure resolves\n * normally and is left for the caller to handle via `response.ok`.\n *\n * Backoff is exponential (150ms, 300ms). Only use this for requests whose\n * replay is harmless — idempotent reads, or session bootstrap where a re-sent\n * create can at worst leave an unused draft session behind.\n */\nasync function fetchWithNetworkRetry(\n input: RequestInfo | URL,\n init?: RequestInit,\n attempts = NETWORK_RETRY_ATTEMPTS,\n onRetry?: (attempt: number) => void,\n): Promise<Response> {\n let lastErr: unknown;\n for (let attempt = 0; ; attempt++) {\n try {\n return await fetch(input, init);\n } catch (err) {\n // Caller-initiated cancellation must propagate immediately, never retry.\n if (err instanceof Error && err.name === 'AbortError') throw err;\n lastErr = err;\n if (attempt >= attempts) throw lastErr;\n try {\n onRetry?.(attempt + 1);\n } catch {\n // Telemetry observation must never alter retry behavior.\n }\n await delay(150 * 2 ** attempt);\n }\n }\n}\n\nexport interface PaymentAPIOptions {\n /** Flo-owned privacy-safe telemetry is enabled by default; set false to opt out. */\n telemetry?: boolean;\n}\n\ninterface PaymentApiTelemetryHooks {\n now?: () => number;\n onFirstByte?: (durationMs: number) => void;\n onSessionCreateFailure?: (error: unknown) => void;\n onRetry?: (requestCategory: TelemetryRequestCategory, attempt: number) => void;\n}\n\nfunction isPaymentApiTelemetryHooks(\n value: PaymentAPIOptions | PaymentApiTelemetryHooks,\n): value is PaymentApiTelemetryHooks {\n return 'now' in value\n || 'onFirstByte' in value\n || 'onSessionCreateFailure' in value\n || 'onRetry' in value;\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 private readonly directTelemetry?: TelemetryReporter;\n private readonly telemetryHooks?: PaymentApiTelemetryHooks;\n private directTelemetryCheckoutId?: string;\n\n constructor(billingApiUrl: string, options?: PaymentAPIOptions);\n constructor(\n billingApiUrl: string,\n telemetryOptionsOrHooks: PaymentAPIOptions | PaymentApiTelemetryHooks = {},\n ) {\n this.baseUrl = billingApiUrl.replace(/\\/+$/, '');\n const hasInternalHooks = isPaymentApiTelemetryHooks(telemetryOptionsOrHooks);\n this.telemetryHooks = hasInternalHooks ? telemetryOptionsOrHooks : undefined;\n this.directTelemetry = hasInternalHooks || telemetryOptionsOrHooks.telemetry === false\n ? undefined\n : new TelemetryReporter({\n billingApiUrl: this.baseUrl,\n sdkVersion: SDK_VERSION,\n });\n }\n\n /** Dispose the reporter owned by direct public usage. Internal hooks are never disposed here. */\n destroy(): void {\n this.directTelemetry?.destroy();\n }\n\n private reportDirectFailure(\n error: unknown,\n fallbackCode: TelemetryErrorCode,\n stage: TelemetryStage,\n requestCategory: TelemetryRequestCategory,\n paymentMethodCategory: 'card' | 'saved' | 'unknown' = 'unknown',\n ): void {\n const failure = telemetryFailure(error, fallbackCode);\n this.directTelemetry?.error({\n ...failure,\n stage,\n requestCategory,\n paymentMethodCategory,\n });\n }\n\n private telemetryTimestamp(): number {\n try {\n return this.telemetryHooks?.now?.() ?? this.directTelemetry?.now() ?? telemetryNow();\n } catch {\n return telemetryNow();\n }\n }\n\n private beginDirectTelemetryCheckout(checkoutSessionId: string): void {\n if (!this.directTelemetry || this.directTelemetryCheckoutId === checkoutSessionId) return;\n this.directTelemetryCheckoutId = checkoutSessionId;\n this.directTelemetry.beginCheckout();\n }\n\n private beginDirectTelemetryOperation(): void {\n if (!this.directTelemetry) return;\n this.directTelemetryCheckoutId = undefined;\n this.directTelemetry.beginCheckout();\n }\n\n private adoptDirectTelemetryCheckout(checkoutSessionId: string | undefined): void {\n if (checkoutSessionId) this.directTelemetryCheckoutId = checkoutSessionId;\n }\n\n /**\n * Fetch a raw checkout session by ID.\n *\n * `nonce` is the session-bound checkout token returned when the session\n * was created. When supplied it is sent as the `x-checkout-session-token`\n * header that post-#640 backends match against `checkout_session.nonce`\n * before returning the row — the UUID alone is no longer sufficient.\n * Backends that don't yet enforce it ignore the extra header.\n */\n async getCheckoutSession(\n checkoutSessionId: string,\n nonce?: string,\n ): Promise<BillingResponse<RawCheckoutSession>> {\n this.beginDirectTelemetryCheckout(checkoutSessionId);\n const requestStarted = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'session.read.started',\n stage: 'session_read',\n requestCategory: 'session_read',\n });\n // Keep the SDK version header for compatibility visibility and telemetry.\n // Vault-capable backends return `session.vault` independently of this value.\n const headers: Record<string, string> = { [FLO_SDK_VERSION_HEADER]: SDK_VERSION };\n if (nonce) headers['x-checkout-session-token'] = nonce;\n try {\n const response = await fetchWithNetworkRetry(\n `${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(checkoutSessionId)}`,\n { headers },\n NETWORK_RETRY_ATTEMPTS,\n (attempt) => {\n this.telemetryHooks?.onRetry?.('session_read', attempt);\n this.directTelemetry?.log({\n name: 'operation.retry',\n stage: 'session_read',\n requestCategory: 'session_read',\n attempt,\n });\n },\n );\n const firstByteDuration = Math.max(0, this.telemetryTimestamp() - requestStarted);\n try {\n this.telemetryHooks?.onFirstByte?.(firstByteDuration);\n } catch {\n // Telemetry hooks must never alter the checkout-session response.\n }\n const statusClass = `${Math.floor(response.status / 100)}xx` as '2xx' | '3xx' | '4xx' | '5xx';\n this.directTelemetry?.log({\n name: 'session.request.first_byte',\n stage: 'session_first_byte',\n requestCategory: 'session_read',\n statusClass,\n });\n this.directTelemetry?.performance({\n stage: 'session_first_byte',\n durationMs: firstByteDuration,\n durationMode: 'machine',\n requestCategory: 'session_read',\n statusClass,\n });\n\n if (!response.ok) {\n throw await buildApiErrorFromResponse(response, 'Failed to get checkout session');\n }\n\n const body = await response.json() as BillingResponse<RawCheckoutSession>;\n this.directTelemetry?.log({\n name: 'session.request.completed',\n stage: 'session_complete',\n requestCategory: 'session_read',\n statusClass,\n });\n this.directTelemetry?.performance({\n stage: 'session_complete',\n durationMs: Math.max(0, this.telemetryTimestamp() - requestStarted),\n durationMode: 'machine',\n requestCategory: 'session_read',\n statusClass,\n });\n return { ...body, data: this.mergeCachedDisplayData(body.data) };\n } catch (error) {\n const statusCode = error instanceof FloPayError ? error.statusCode : undefined;\n this.directTelemetry?.error({\n errorCode: error instanceof FloPayError && error.code === 'checkout_processing_timeout'\n ? 'REQUEST_TIMEOUT'\n : 'NETWORK_REQUEST_FAILED',\n stage: 'session_read',\n requestCategory: 'session_read',\n statusClass: statusCode\n ? `${Math.floor(statusCode / 100)}xx` as '4xx' | '5xx'\n : 'network_error',\n });\n throw error;\n }\n }\n\n /**\n * Stash display-only data for a session so subsequent fetches can fill in\n * fields the backend no longer persists (`overrideAmount`, `totalAmount`,\n * `providerItemName`, `providerPlanName`).\n *\n * Backed by `sessionStorage` in the browser, with an in-memory fallback in\n * Node/SSR contexts. Default TTL: 1 hour.\n *\n * Server-returned values always win — cached values fill in only where the\n * server returned `null` / `undefined`.\n *\n * @example\n * ```ts\n * paymentAPI.cacheSessionDisplayData(sessionId, {\n * currency: 'USD',\n * items: [{ code: 'pro_plan', overrideAmount: 24.99, providerItemName: 'Pro' }],\n * });\n * ```\n */\n cacheSessionDisplayData(\n sessionId: string,\n data: SessionDisplayCacheData,\n options?: { ttlMs?: number },\n ): void {\n cacheSessionDisplayData(sessionId, data, options);\n }\n\n /**\n * Drop any cached display data for a session. Call after the payment\n * completes; otherwise the TTL handles cleanup.\n */\n clearSessionDisplayData(sessionId: string): void {\n clearSessionDisplayData(sessionId);\n }\n\n /**\n * Fetch (re-mint) the hosted vault capture widget for a session\n * (TeamFloPay/backend#823).\n *\n * `POST /v1/checkouts/sessions/{id}/vault/capture` returns the SDK-ready\n * {@link VaultCaptureBlock} (`html` + `url`, plus `messageToken` /\n * `expectedOrigin` once the backend mints them). The SDK injects `html` as\n * the card-capture widget. This is the fallback path for sessions that did\n * not receive the embedded `vault` block on create (e.g. a session loaded by\n * id via `GET`, or a pre-1.3.0 create); the endpoint is idempotent and reuses\n * session-cached creds when available.\n *\n * Because the endpoint is idempotent, the request is wrapped in\n * `fetchWithNetworkRetry`: a transient network blip (dropped connection, DNS\n * hiccup, failed CORS preflight) would otherwise leave the secure card form\n * unable to load and hard-block checkout.\n *\n * The PCIVault submit *secret* the backend may include in the response is\n * intentionally **not** read or surfaced — it is server-only and never enters\n * the SDK runtime.\n *\n * `nonce` is forwarded as `x-checkout-session-token` (required by post-#640\n * backends, matched against the session's stored nonce).\n */\n async getVaultCapture(\n checkoutSessionId: string,\n nonce?: string,\n ): Promise<VaultCaptureBlock> {\n this.beginDirectTelemetryCheckout(checkoutSessionId);\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'vault.capture.requested',\n stage: 'vault_request',\n requestCategory: 'vault_capture',\n paymentMethodCategory: 'card',\n });\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (nonce) headers['x-checkout-session-token'] = nonce;\n try {\n const response = await fetchWithNetworkRetry(\n `${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(checkoutSessionId)}/vault/capture`,\n { method: 'POST', headers },\n NETWORK_RETRY_ATTEMPTS,\n (attempt) => {\n this.telemetryHooks?.onRetry?.('vault_capture', attempt);\n this.directTelemetry?.log({\n name: 'operation.retry',\n stage: 'vault_request',\n requestCategory: 'vault_capture',\n paymentMethodCategory: 'card',\n attempt,\n });\n },\n );\n if (!response.ok) {\n throw await buildApiErrorFromResponse(response, 'Failed to load the secure card form');\n }\n const block = await response.json() as VaultCaptureBlock;\n this.directTelemetry?.performance({\n stage: 'vault_request',\n durationMs: Math.max(0, this.telemetryTimestamp() - startedAt),\n durationMode: 'machine',\n requestCategory: 'vault_capture',\n paymentMethodCategory: 'card',\n statusClass: '2xx',\n });\n return this.toVaultBlock(block);\n } catch (error) {\n this.reportDirectFailure(\n error,\n 'VAULT_LOAD_FAILED',\n 'vault_request',\n 'vault_capture',\n 'card',\n );\n throw error;\n }\n }\n\n /**\n * Fetch and normalize a checkout session.\n *\n * Reads the backend's `gateways` map to enumerate provider-specific data,\n * then wraps the session in a `NormalizedCheckoutSession` for provider-\n * agnostic consumption.\n */\n async getUnifiedCheckoutSession(\n checkoutSessionId: string,\n nonce?: string,\n ): Promise<NormalizedCheckoutSession> {\n const res = await this.getCheckoutSession(checkoutSessionId, nonce);\n const normalized = this.normalizeRawSession(res.data);\n // The embedded vault block is a top-level sibling of `data` on the read\n // response (mirrors the create response). Thread it onto the session so a\n // reused/resumed session keeps the hosted card form instead of falling back\n // to Stripe (TeamFloPay/backend#823).\n const vault = (res as { vault?: VaultCaptureBlock }).vault;\n if (vault && normalized.data.session) {\n normalized.data.session.vault = this.toVaultBlock(vault);\n }\n return normalized;\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 * Hits the session-scoped route `POST /v1/checkouts/sessions/:id/process`\n * and forwards `data.nonce` as `x-checkout-session-token`. Backend\n * `TeamFloPay/backend#640` rejects callers without a matching nonce with a\n * 401 — this method throws synchronously when `data.nonce` is missing so the\n * problem surfaces before the network round trip.\n *\n * @param userId Vestigial — backend's GatewayInterceptor routes via session,\n * not headers, so this value is no longer sent on the wire. Kept in the\n * signature for back-compat with existing callers; will be removed in a\n * future major version.\n */\n async processPayment(\n _userId: string,\n data: ProcessPaymentParams,\n options?: {\n pollTimeoutMs?: number;\n },\n ): Promise<Response> {\n this.beginDirectTelemetryCheckout(data.sessionId);\n if (!data.nonce) {\n this.directTelemetry?.terminal({\n outcome: 'validation_rejected',\n stage: 'processing',\n requestCategory: 'process_payment',\n });\n throw new FloPayError(\n 'processPayment requires `nonce` — pass the value returned from session creation.',\n 'validation_error',\n { code: 'MissingCheckoutSessionToken', param: 'nonce' },\n );\n }\n\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'payment.processing.started',\n stage: 'processing',\n requestCategory: 'process_payment',\n });\n const { nonce, ...processBody } = data;\n let response: Response;\n try {\n response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(data.sessionId)}/process`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-checkout-session-token': nonce,\n },\n body: JSON.stringify(processBody),\n },\n );\n } catch (error) {\n this.reportDirectFailure(\n error,\n 'PAYMENT_PROCESSING_FAILED',\n 'processing',\n 'process_payment',\n );\n throw error;\n }\n\n if (!response.ok && response.status !== 202) {\n this.directTelemetry?.error({\n errorCode: 'PAYMENT_PROCESSING_FAILED',\n stage: 'processing',\n requestCategory: 'process_payment',\n statusClass: telemetryStatusClass(response.status),\n });\n return response;\n }\n\n try {\n const result = await this.resolveProcessResponse(\n response,\n data.sessionId,\n { ...options, nonce },\n );\n this.directTelemetry?.log({\n name: 'payment.processing.completed',\n stage: 'processing',\n requestCategory: 'process_payment',\n statusClass: telemetryStatusClass(result.status),\n });\n this.directTelemetry?.performance({\n stage: 'processing',\n durationMs: Math.max(0, this.telemetryTimestamp() - startedAt),\n durationMode: 'machine',\n requestCategory: 'process_payment',\n statusClass: telemetryStatusClass(result.status),\n });\n return result;\n } catch (error) {\n if (!(error instanceof FloPayError && error.code === 'checkout_processing_timeout')) {\n this.reportDirectFailure(\n error,\n 'PAYMENT_PROCESSING_FAILED',\n 'processing',\n 'process_payment',\n );\n }\n throw error;\n }\n }\n\n /**\n * Patch the buyer's account snapshot (email, name, billing address, AVS\n * intent) onto a checkout session via\n * `PATCH /v1/checkouts/sessions/{id}/account` (TeamFloPay/backend#823).\n *\n * The vault path's hosted form owns the charge end-to-end so the SDK\n * never calls `/process` on this path; the buyer-typed AVS / billing\n * address would otherwise be lost. The SDK calls this just before\n * submitting the vault widget so the downstream listener mints the\n * Stripe PaymentMethod with the right `billing_details.address` and the\n * per-attempt + per-PM address snapshots are populated.\n *\n * Body shape mirrors the relevant subset of `/process`'s\n * `ProcessCheckoutBodyDto` — same keys, same validators. The endpoint\n * is idempotent: empty/undefined fields are not written, addresses are\n * last-writer-wins, AVS analytics are first-writer-wins.\n *\n * Wrapped in `fetchWithNetworkRetry` because a transient blip on this\n * pre-pay PATCH would silently leave AVS unsent and cause an\n * AVS-protected charge to decline downstream.\n */\n async patchAccountSnapshot(\n sessionId: string,\n nonce: string,\n body: {\n accountData: {\n userId: string;\n email: string;\n firstName?: string | null;\n lastName?: string | null;\n addressLine1?: string | null;\n addressLine2?: string | null;\n city?: string | null;\n state?: string | null;\n zip?: string | null;\n country?: string | null;\n gender?: string | null;\n };\n avsCheck?: boolean;\n avsConfig?: Record<string, unknown>;\n },\n options?: { signal?: AbortSignal; timeoutMs?: number },\n ): Promise<void> {\n this.beginDirectTelemetryCheckout(sessionId);\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'operation.state_transition',\n stage: 'processing',\n requestCategory: 'account_snapshot',\n });\n // Bound the whole retry sequence so a stalled network request can't hang the\n // submit gate indefinitely. Compose the caller's signal (if any) with an\n // internal timeout so either can abort the fetch.\n const timeoutMs = options?.timeoutMs ?? DEFAULT_ACCOUNT_SNAPSHOT_TIMEOUT_MS;\n const controller = new AbortController();\n const onCallerAbort = () => controller.abort();\n if (options?.signal) {\n if (options.signal.aborted) controller.abort();\n else options.signal.addEventListener('abort', onCallerAbort, { once: true });\n }\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n let response: Response;\n try {\n response = await fetchWithNetworkRetry(\n `${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(sessionId)}/account`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n 'x-checkout-session-token': nonce,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n },\n NETWORK_RETRY_ATTEMPTS,\n (attempt) => {\n this.telemetryHooks?.onRetry?.('account_snapshot', attempt);\n this.directTelemetry?.log({\n name: 'operation.retry',\n stage: 'processing',\n requestCategory: 'account_snapshot',\n attempt,\n });\n },\n );\n } finally {\n clearTimeout(timer);\n options?.signal?.removeEventListener('abort', onCallerAbort);\n }\n if (!response.ok) {\n throw await buildApiErrorFromResponse(response, 'Failed to persist account snapshot');\n }\n this.directTelemetry?.performance({\n stage: 'processing',\n durationMs: Math.max(0, this.telemetryTimestamp() - startedAt),\n durationMode: 'machine',\n requestCategory: 'account_snapshot',\n statusClass: '2xx',\n });\n } catch (error) {\n this.reportDirectFailure(\n error,\n 'NETWORK_REQUEST_FAILED',\n 'processing',\n 'account_snapshot',\n );\n throw error;\n }\n }\n\n /** Create a wallet/APM/PayPal intent through the session-scoped contract. */\n async createSessionIntent(\n sessionId: string,\n nonce: string,\n request: CreateSessionIntentRequest,\n options?: { signal?: AbortSignal; idempotencyKey?: string },\n ): Promise<SessionIntent> {\n if (!nonce) {\n throw new FloPayError(\n 'createSessionIntent requires the checkout session nonce.',\n 'validation_error',\n { code: 'MissingCheckoutSessionToken', param: 'nonce' },\n );\n }\n\n const rawRequest = request as unknown as Record<string, unknown>;\n const paymentMethodType = rawRequest['paymentMethodType'];\n const directCardType = typeof paymentMethodType === 'string'\n && paymentMethodType.trim().toLowerCase() === 'card';\n const commonRequestFieldsValid =\n typeof paymentMethodType === 'string'\n && paymentMethodType.length > 0\n && !directCardType\n && (typeof rawRequest['paymentMethodId'] === 'string' || rawRequest['paymentMethodId'] === null);\n const stripeRequestValid = rawRequest['provider'] === 'stripe'\n && (rawRequest['paymentMethodCategory'] === 'wallet' || rawRequest['paymentMethodCategory'] === 'apm')\n && (rawRequest['intentKind'] === 'payment' || rawRequest['intentKind'] === 'setup');\n const paypalRequestValid = rawRequest['provider'] === 'paypal'\n && rawRequest['paymentMethodCategory'] === 'wallet'\n && rawRequest['paymentMethodType'] === 'paypal'\n && rawRequest['paymentMethodId'] === null\n && (rawRequest['intentKind'] === 'order' || rawRequest['intentKind'] === 'subscription');\n\n if (!commonRequestFieldsValid || (!stripeRequestValid && !paypalRequestValid)) {\n throw new FloPayError(\n 'Only wallet, APM, and PayPal session intents are supported.',\n 'validation_error',\n { code: 'InvalidSessionIntentRequest' },\n );\n }\n\n // The session-scoped intents route requires a v4 UUID authorizationAttemptId\n // (backend folds it into the provider idempotency key). Reject a malformed\n // caller-supplied value up front rather than surfacing an opaque backend 400.\n const suppliedAttemptId = rawRequest['authorizationAttemptId'];\n if (suppliedAttemptId !== undefined && !isUuidV4(suppliedAttemptId)) {\n throw new FloPayError(\n 'authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.',\n 'validation_error',\n { code: 'InvalidAuthorizationAttemptId', param: 'authorizationAttemptId' },\n );\n }\n // Omitted → a fresh UUID (a new authorization attempt). A caller that drives\n // its own transport retries can pass a stable value so the retry reuses the\n // same provider intent instead of minting a duplicate.\n const authorizationAttemptId = isUuidV4(suppliedAttemptId)\n ? suppliedAttemptId\n : randomUuidV4();\n\n this.beginDirectTelemetryCheckout(sessionId);\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'payment.intent.started',\n stage: 'processing',\n requestCategory: 'intent_create',\n });\n\n // The session-scoped intents route requires an Idempotency-Key header. Default\n // it to the authorization-attempt id so a transport retry of the same attempt\n // (same body) dedupes to one provider intent; an explicit option still wins for\n // callers that key their own retries.\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-checkout-session-token': nonce,\n [IDEMPOTENCY_KEY_HEADER]: options?.idempotencyKey || authorizationAttemptId,\n };\n\n let failureReported = false;\n try {\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(sessionId)}/intents`,\n {\n method: 'POST',\n headers,\n body: JSON.stringify({ ...request, authorizationAttemptId }),\n signal: options?.signal,\n },\n );\n\n if (!response.ok) {\n failureReported = true;\n this.directTelemetry?.error({\n errorCode: 'PAYMENT_PROCESSING_FAILED',\n stage: 'processing',\n requestCategory: 'intent_create',\n statusClass: telemetryStatusClass(response.status),\n });\n throw await buildApiErrorFromResponse(response, 'Failed to create checkout intent');\n }\n\n const body = await response.json() as { data?: unknown };\n const data = body.data;\n if (!data || typeof data !== 'object') {\n throw new FloPayError('Invalid checkout intent response.', 'api_error', {\n code: 'InvalidSessionIntentResponse',\n });\n }\n\n const intent = data as Record<string, unknown>;\n const responsePaymentMethodType = intent['paymentMethodType'];\n const commonFieldsValid =\n (intent['paymentMethodCategory'] === 'wallet' || intent['paymentMethodCategory'] === 'apm')\n && typeof responsePaymentMethodType === 'string'\n && responsePaymentMethodType.trim().toLowerCase() !== 'card'\n && (typeof intent['paymentMethodId'] === 'string' || intent['paymentMethodId'] === null)\n && typeof intent['providerObjectId'] === 'string';\n const stripeValid = intent['provider'] === 'stripe'\n && (intent['intentKind'] === 'payment' || intent['intentKind'] === 'setup')\n && typeof intent['clientSecret'] === 'string';\n const paypalValid = intent['provider'] === 'paypal'\n && intent['paymentMethodCategory'] === 'wallet'\n && intent['paymentMethodType'] === 'paypal'\n && intent['paymentMethodId'] === null\n && (intent['intentKind'] === 'order' || intent['intentKind'] === 'subscription')\n && intent['clientSecret'] === null;\n const discriminantsMatchRequest =\n intent['provider'] === request.provider\n && intent['paymentMethodCategory'] === request.paymentMethodCategory\n && intent['paymentMethodType'] === request.paymentMethodType\n && intent['paymentMethodId'] === request.paymentMethodId\n && intent['intentKind'] === request.intentKind;\n\n if (!commonFieldsValid || (!stripeValid && !paypalValid) || !discriminantsMatchRequest) {\n throw new FloPayError('Invalid checkout intent response.', 'api_error', {\n code: 'InvalidSessionIntentResponse',\n });\n }\n\n this.directTelemetry?.log({\n name: 'payment.intent.completed',\n stage: 'processing',\n requestCategory: 'intent_create',\n statusClass: telemetryStatusClass(response.status),\n });\n this.directTelemetry?.performance({\n stage: 'processing',\n durationMs: Math.max(0, this.telemetryTimestamp() - startedAt),\n durationMode: 'machine',\n requestCategory: 'intent_create',\n statusClass: telemetryStatusClass(response.status),\n });\n return intent as unknown as SessionIntent;\n } catch (error) {\n if (!failureReported) {\n this.reportDirectFailure(\n error,\n 'PAYMENT_PROCESSING_FAILED',\n 'processing',\n 'intent_create',\n );\n }\n throw error;\n }\n }\n\n /** Record a provider-neutral non-card decline without sensitive identifiers. */\n async reportSessionIntentDecline(\n sessionId: string,\n nonce: string,\n request: SessionIntentDeclineRequest,\n options?: { signal?: AbortSignal },\n ): Promise<void> {\n if (!nonce) {\n throw new FloPayError(\n 'reportSessionIntentDecline requires the checkout session nonce.',\n 'validation_error',\n { code: 'MissingCheckoutSessionToken', param: 'nonce' },\n );\n }\n\n const rawRequest = request as unknown as Record<string, unknown>;\n const reason = rawRequest['providerDeclineReason'];\n const paymentMethodType = rawRequest['paymentMethodType'];\n const safeReason = typeof reason === 'string'\n && /^[a-z0-9][a-z0-9_.:-]{0,63}$/i.test(reason)\n && !/^(?:pm|pi|seti|tok|src|cus|sess|sk|pk)_/i.test(reason);\n const commonFieldsValid = typeof paymentMethodType === 'string'\n && paymentMethodType.length > 0\n && paymentMethodType.trim().toLowerCase() !== 'card'\n && safeReason;\n const stripeFieldsValid = rawRequest['provider'] === 'stripe'\n && (rawRequest['paymentMethodCategory'] === 'wallet' || rawRequest['paymentMethodCategory'] === 'apm');\n const paypalFieldsValid = rawRequest['provider'] === 'paypal'\n && rawRequest['paymentMethodCategory'] === 'wallet'\n && rawRequest['paymentMethodType'] === 'paypal';\n if (!commonFieldsValid || (!stripeFieldsValid && !paypalFieldsValid)) {\n throw new FloPayError(\n 'Invalid non-card decline classification.',\n 'validation_error',\n { code: 'InvalidSessionIntentDeclineRequest' },\n );\n }\n\n const safeRequest: SessionIntentDeclineRequest = paypalFieldsValid\n ? {\n provider: 'paypal',\n paymentMethodCategory: 'wallet',\n paymentMethodType: 'paypal',\n providerDeclineReason: reason,\n }\n : {\n provider: 'stripe',\n paymentMethodCategory: rawRequest['paymentMethodCategory'] as 'wallet' | 'apm',\n paymentMethodType: rawRequest['paymentMethodType'] as string,\n providerDeclineReason: reason,\n };\n\n const response = await fetch(\n `${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(sessionId)}/intents/decline`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-checkout-session-token': nonce,\n },\n body: JSON.stringify(safeRequest),\n signal: options?.signal,\n },\n );\n\n if (!response.ok) {\n throw await buildApiErrorFromResponse(response, 'Failed to report checkout decline');\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 this.beginDirectTelemetryOperation();\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'operation.recovery.started',\n stage: 'recovery',\n requestCategory: 'other',\n paymentMethodCategory: 'saved',\n });\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: 'createdAt',\n sortDirection: 'DESC',\n });\n\n try {\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(\n 'Failed to fetch payments',\n 'api_error',\n { statusCode: response.status },\n );\n }\n const result = await response.json() as {\n data: Array<{ id: string }>;\n total: number;\n page: number;\n limit: number;\n };\n this.directTelemetry?.log({\n name: 'operation.recovery.completed',\n stage: 'recovery',\n requestCategory: 'other',\n paymentMethodCategory: 'saved',\n statusClass: '2xx',\n });\n this.directTelemetry?.performance({\n stage: 'recovery',\n durationMs: Math.max(0, this.telemetryTimestamp() - startedAt),\n durationMode: 'machine',\n requestCategory: 'other',\n paymentMethodCategory: 'saved',\n statusClass: '2xx',\n });\n return result;\n } catch (error) {\n this.reportDirectFailure(error, 'RECOVERY_FAILED', 'recovery', 'other', 'saved');\n throw error;\n }\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: InlineSessionDraft,\n ): Promise<NormalizedCheckoutSession> {\n this.beginDirectTelemetryOperation();\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'session.create.started',\n stage: 'session_create',\n requestCategory: 'session_create',\n });\n try {\n const result = await this.createAndFetchSessionRequest(params, startedAt);\n this.adoptDirectTelemetryCheckout(result.data.session?.id);\n this.directTelemetry?.log({\n name: 'session.request.completed',\n stage: 'session_complete',\n requestCategory: 'session_create',\n statusClass: '2xx',\n });\n this.directTelemetry?.performance({\n stage: 'session_create',\n durationMs: this.telemetryTimestamp() - startedAt,\n durationMode: 'machine',\n requestCategory: 'session_create',\n statusClass: '2xx',\n });\n return result;\n } catch (error) {\n if (!(error instanceof FloPayError && error.code === 'session_auto_completed')) {\n try {\n this.telemetryHooks?.onSessionCreateFailure?.(error);\n } catch {\n // Preserve the original API failure when telemetry observation fails.\n }\n }\n if (error instanceof FloPayError && error.type === 'validation_error') {\n this.directTelemetry?.terminal({\n outcome: 'validation_rejected',\n stage: 'session_create',\n requestCategory: 'session_create',\n });\n } else if (!(error instanceof FloPayError && error.code === 'session_auto_completed')) {\n const statusCode = error instanceof FloPayError ? error.statusCode : undefined;\n this.directTelemetry?.error({\n errorCode: error instanceof Error && error.name === 'AbortError'\n ? 'REQUEST_TIMEOUT'\n : error instanceof TypeError\n ? 'NETWORK_REQUEST_FAILED'\n : 'CHECKOUT_SESSION_CREATE_FAILED',\n stage: 'session_create',\n requestCategory: 'session_create',\n statusClass: error instanceof Error && error.name === 'AbortError'\n ? 'timeout'\n : statusCode\n ? `${Math.floor(statusCode / 100)}xx` as '4xx' | '5xx'\n : 'network_error',\n });\n }\n throw error;\n }\n }\n\n private async createAndFetchSessionRequest(\n params: InlineSessionDraft,\n telemetryStartedAt: number,\n ): Promise<NormalizedCheckoutSession> {\n const wireProducts = params.products ?? foldIntoProducts(params.items, params.subscriptions);\n const sessionCurrency = resolveSessionCurrency(\n params.currency,\n params.items,\n params.subscriptions,\n wireProducts,\n );\n if (!sessionCurrency) {\n throw new FloPayError(\n 'currency is required: pass `currency` on the session, or include a `currency` on the first item/subscription/product.',\n 'validation_error',\n { code: 'CurrencyRequired', param: 'currency' },\n );\n }\n\n const payload: Record<string, unknown> = {\n clientId: params.clientId,\n checkoutVersion: SDK_VERSION,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n currency: sessionCurrency,\n checkoutMode: params.checkoutMode ?? 'full',\n products: wireProducts.map((product) => buildProductPayload(product, sessionCurrency)),\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 addressLine1: params.account.addressLine1 ?? null,\n addressLine2: params.account.addressLine2 ?? null,\n },\n couponCodes: params.couponCodes ?? [],\n };\n\n if (params.tokenizedData) payload['tokenizedData'] = params.tokenizedData;\n if (params.tagsData) payload['tagsData'] = params.tagsData;\n if (params.utmMetadata?.length) payload['utmMetadata'] = params.utmMetadata;\n\n // Checkout analytics metadata\n if (params.avsCheck !== undefined) payload['avsCheck'] = params.avsCheck;\n if (params.checkoutType) payload['checkoutType'] = params.checkoutType;\n if (params.checkoutLayout) payload['checkoutLayout'] = params.checkoutLayout;\n if (params.avsConfig) payload['avsConfig'] = params.avsConfig;\n\n // Resolve the stable idempotency key once (an invalid merchant-supplied key\n // throws here, before any request). Because `fetchWithNetworkRetry` reuses\n // this same `headers` object across its transport retries — and the\n // in-progress replay loop below reuses it too — every attempt of this\n // logical create replays the same key and cannot mint a second session\n // (TeamFloPay/backend#972).\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n // Retain the SDK version header for compatibility visibility. Backends\n // must not gate the hosted vault block on this value.\n [FLO_SDK_VERSION_HEADER]: SDK_VERSION,\n };\n const idempotencyKey = resolveIdempotencyKey(params.idempotencyKey);\n if (idempotencyKey) {\n headers[IDEMPOTENCY_KEY_HEADER] = idempotencyKey;\n }\n\n // On top of `fetchWithNetworkRetry`'s transport retries, retry the backend's\n // documented in-progress replay (a non-OK response carrying\n // `IDEMPOTENCY_IN_PROGRESS_CODE`) with the *same* key after a short backoff.\n // A payload-conflict (`409`) and every other non-OK response fail fast — only\n // the exact same request may safely replay a key (TeamFloPay/backend#972).\n let response: Response;\n let firstByteReported = false;\n for (let attempt = 0; ; attempt++) {\n response = await fetchWithNetworkRetry(\n `${this.baseUrl}/v1/checkouts/sessions?expand=true`,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n },\n NETWORK_RETRY_ATTEMPTS,\n (networkAttempt) => {\n this.telemetryHooks?.onRetry?.('session_create', networkAttempt);\n this.directTelemetry?.log({\n name: 'operation.retry',\n stage: 'session_create',\n requestCategory: 'session_create',\n attempt: networkAttempt,\n });\n },\n );\n\n if (!firstByteReported) {\n firstByteReported = true;\n const statusClass = `${Math.floor(response.status / 100)}xx` as\n '2xx' | '3xx' | '4xx' | '5xx';\n this.directTelemetry?.log({\n name: 'session.request.first_byte',\n stage: 'session_first_byte',\n requestCategory: 'session_create',\n statusClass,\n });\n this.directTelemetry?.performance({\n stage: 'session_first_byte',\n durationMs: this.telemetryTimestamp() - telemetryStartedAt,\n durationMode: 'machine',\n requestCategory: 'session_create',\n statusClass,\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) break;\n\n const error = await buildApiErrorFromResponse(response, 'Failed to create checkout session');\n if (\n error.code === IDEMPOTENCY_IN_PROGRESS_CODE &&\n attempt < IDEMPOTENCY_IN_PROGRESS_RETRY_ATTEMPTS\n ) {\n try {\n this.telemetryHooks?.onRetry?.('session_create', attempt + 1);\n this.directTelemetry?.log({\n name: 'operation.retry',\n stage: 'session_create',\n requestCategory: 'session_create',\n attempt: attempt + 1,\n });\n } catch {\n // Telemetry observation must never alter idempotent replay behavior.\n }\n await delay(150 * 2 ** attempt);\n continue;\n }\n throw error;\n }\n\n const body = await response.json() as {\n data: RawCheckoutSession & { uuid?: string };\n autoProcessingError?: CheckoutProcessError;\n autoProcessingAttempted?: boolean;\n autoProcessingPending?: CheckoutProcessingPending;\n vault?: VaultCaptureBlock;\n };\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 && 'gateways' in body.data) {\n // Auto-stash display-only fields the consumer just sent so wallet\n // sheets and the post-redirect fetch see the same totals. Must run\n // BEFORE the merge so the merge picks them up.\n this.autoCacheDisplayData(body.data.uuid, params);\n const merged = this.mergeCachedDisplayData(body.data);\n const normalized = this.normalizeRawSession(merged);\n // Thread the embedded vault capture block (TeamFloPay/backend#823) onto\n // the session so the React card form can inject the hosted widget without\n // a second `/vault/capture` round-trip.\n if (body.vault && normalized.data.session) {\n normalized.data.session.vault = this.toVaultBlock(body.vault);\n }\n return {\n ...normalized,\n autoProcessingError: body.autoProcessingError,\n autoProcessingAttempted: body.autoProcessingAttempted,\n autoProcessingPending: body.autoProcessingPending,\n };\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 this.autoCacheDisplayData(uuid, params);\n this.adoptDirectTelemetryCheckout(uuid);\n const unifiedSession = await this.getUnifiedCheckoutSession(uuid);\n return {\n ...unifiedSession,\n autoProcessingError: body.autoProcessingError,\n autoProcessingAttempted: body.autoProcessingAttempted,\n autoProcessingPending: body.autoProcessingPending,\n };\n }\n\n async waitForCheckoutSessionCompletion(\n checkoutSessionId: string,\n options?: {\n initialDelayMs?: number;\n timeoutMs?: number;\n /**\n * Session-bound checkout token; forwarded on the poll's\n * `GET /v1/checkouts/sessions/:id`. Required by post-#640 backends.\n */\n nonce?: string;\n },\n ): Promise<NormalizedCheckoutSession> {\n this.beginDirectTelemetryCheckout(checkoutSessionId);\n const startedAt = this.telemetryTimestamp();\n this.directTelemetry?.log({\n name: 'operation.recovery.started',\n stage: 'recovery',\n requestCategory: 'session_read',\n paymentMethodCategory: 'saved',\n });\n const timeoutMs = options?.timeoutMs ?? DEFAULT_PROCESSING_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n let nextDelayMs = this.clampRetryAfterMs(options?.initialDelayMs ?? DEFAULT_PROCESSING_RETRY_AFTER_MS);\n let pollAttempt = 0;\n\n try {\n while (true) {\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n throw createCheckoutProcessingTimeoutError();\n }\n\n if (nextDelayMs > 0) {\n try {\n pollAttempt += 1;\n this.telemetryHooks?.onRetry?.('session_read', pollAttempt);\n this.directTelemetry?.log({\n name: 'operation.retry',\n stage: 'recovery',\n requestCategory: 'session_read',\n paymentMethodCategory: 'saved',\n attempt: pollAttempt,\n });\n } catch {\n // Telemetry observation must never alter polling behavior.\n }\n await delay(Math.min(nextDelayMs, remainingMs));\n\n if (Date.now() >= deadline) {\n throw createCheckoutProcessingTimeoutError();\n }\n }\n\n const session = await this.getUnifiedCheckoutSession(checkoutSessionId, options?.nonce);\n const status = session.data.session?.status;\n\n if (status === 'complete' || status === 'expired') {\n this.directTelemetry?.log({\n name: 'operation.recovery.completed',\n stage: 'recovery',\n requestCategory: 'session_read',\n paymentMethodCategory: 'saved',\n });\n this.directTelemetry?.performance({\n stage: 'recovery',\n durationMs: Math.max(0, this.telemetryTimestamp() - startedAt),\n durationMode: 'machine',\n requestCategory: 'session_read',\n paymentMethodCategory: 'saved',\n });\n return session;\n }\n\n if (Date.now() >= deadline) {\n throw createCheckoutProcessingTimeoutError();\n }\n\n nextDelayMs = this.clampRetryAfterMs(\n Math.max(nextDelayMs * 2, MIN_PROCESSING_RETRY_AFTER_MS),\n );\n }\n } catch (error) {\n if (error instanceof FloPayError && error.code === 'checkout_processing_timeout') {\n this.reportDirectFailure(\n error,\n 'RECOVERY_FAILED',\n 'recovery',\n 'session_read',\n 'saved',\n );\n }\n throw error;\n }\n }\n\n /** Normalize a raw session into a provider-agnostic shape. */\n private normalizeRawSession(session: RawCheckoutSession): NormalizedCheckoutSession {\n const gateways: CheckoutGateways = session.gateways ?? {};\n const providers: BillingProvider[] = [];\n const data: NormalizedCheckoutSession['data'] = {\n session: this.toCheckoutSession(session),\n };\n\n const stripeGateway = gateways.stripe;\n if (stripeGateway?.publishableKey) {\n providers.push('stripe');\n const rawSession = session as unknown as Record<string, unknown>;\n const stripeClientSecret = [\n rawSession['stripeClientSecret'],\n stripeGateway.stripeClientSecret,\n ].find((value) => typeof value === 'string' && value.length > 0) as string | undefined;\n\n data.stripe = {\n clientSecret: stripeClientSecret ?? '',\n publishableKey: stripeGateway.publishableKey ?? undefined,\n paypalPublishableKey: stripeGateway.paypalPublishableKey ?? undefined,\n environment: stripeGateway.environment,\n enabledPaymentMethods: Array.isArray(stripeGateway.enabledPaymentMethods)\n ? stripeGateway.enabledPaymentMethods.filter((m): m is string => typeof m === 'string')\n : undefined,\n };\n }\n\n const paypalGateway = gateways.paypal;\n if (paypalGateway?.publishableKey) {\n providers.push('paypal');\n data.paypal = {\n publishableKey: paypalGateway.publishableKey,\n environment: paypalGateway.environment,\n };\n }\n\n return {\n providers,\n mode: 'tokenize',\n data,\n raw: { data: session },\n };\n }\n\n /** Convert raw session to the SDK CheckoutSession shape. */\n private toCheckoutSession(raw: RawCheckoutSession): CheckoutSession {\n const rawProducts = raw.products ?? [];\n\n // Billing API ≥ v1.1.2 returns the coupon-adjusted `totalAmount` on the\n // session. Prefer it as the source of truth so wallet sheets render the\n // post-coupon amount; fall back to summing per-line `overrideAmount`.\n const hasBackendTotal =\n typeof raw.totalAmount === 'number' && Number.isFinite(raw.totalAmount);\n const computedTotal = rawProducts.reduce(\n (sum, p) => sum + (p.overrideAmount ?? p.totalAmount ?? 0),\n 0,\n );\n const totalAmount = hasBackendTotal ? (raw.totalAmount as number) : computedTotal;\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 const currency = raw.currency ?? rawProducts[0]?.currency ?? 'USD';\n\n const mode: CheckoutSession['mode'] =\n rawProducts.some((p) => p.type === 'subscription') ? 'subscription' : 'payment';\n\n return {\n id: raw.uuid,\n clientSecret: raw.nonce,\n mode,\n status: this.toCheckoutSessionStatus(raw.status),\n amount: amountInCents,\n currency,\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 line1: raw.accountData.addressLine1 ?? undefined,\n line2: raw.accountData.addressLine2 ?? undefined,\n },\n metadata: {},\n checkoutMode: raw.checkoutMode,\n providerPaymentMethodId:\n typeof raw.providerPaymentMethodId === 'string' ? raw.providerPaymentMethodId : null,\n products: rawProducts.map((p): CheckoutSessionProduct => ({\n ...p,\n totalAmount: typeof p.totalAmount === 'number' ? p.totalAmount : undefined,\n overrideAmount: typeof p.overrideAmount === 'number' ? p.overrideAmount : null,\n currency: typeof p.currency === 'string' ? p.currency : undefined,\n metadata: p.metadata ?? null,\n })),\n successUrl: raw.successUrl,\n cancelUrl: raw.cancelUrl,\n coupons: raw.coupons,\n subtotalAmount: raw.subtotalAmount,\n discountAmount: raw.discountAmount,\n totalAmount: raw.totalAmount,\n createdAt: raw.createdAt,\n gateways: raw.gateways,\n accountData: raw.accountData,\n tagsData: raw.tagsData,\n };\n }\n\n /**\n * Coerce a raw vault block into a typed {@link VaultCaptureBlock}. The\n * server-only PCIVault submit `secret` is deliberately dropped so it never\n * lands on the public session surface (logs / telemetry / client inspection).\n */\n private toVaultBlock(raw: VaultCaptureBlock): VaultCaptureBlock {\n return {\n html: typeof raw.html === 'string' ? raw.html : undefined,\n url: typeof raw.url === 'string' ? raw.url : undefined,\n messageToken: typeof raw.messageToken === 'string' ? raw.messageToken : undefined,\n expectedOrigin: typeof raw.expectedOrigin === 'string' ? raw.expectedOrigin : undefined,\n };\n }\n\n private toCheckoutSessionStatus(status: RawCheckoutSession['status']): CheckoutSession['status'] {\n if (status === 'completed') {\n return 'complete';\n }\n\n if (status === 'expired') {\n return 'expired';\n }\n\n return 'open';\n }\n\n private async resolveProcessResponse(\n response: Response,\n checkoutSessionId: string,\n options?: {\n pollTimeoutMs?: number;\n nonce?: string;\n },\n ): Promise<Response> {\n if (response.status !== 202) {\n return response;\n }\n\n const payload = await response.json().catch(() => null) as ApiErrorPayload;\n const pending = this.toCheckoutProcessingPending(payload, response, checkoutSessionId);\n const session = await this.waitForCheckoutSessionCompletion(pending.sessionId, {\n initialDelayMs: pending.retryAfterMs,\n timeoutMs: options?.pollTimeoutMs,\n nonce: options?.nonce,\n });\n\n if (session.data.session?.status === 'complete') {\n return new Response(null, { status: 204, statusText: 'No Content' });\n }\n\n if (session.data.session?.status === 'expired') {\n throw new FloPayError(\n 'Checkout session has expired.',\n 'api_error',\n { code: 'checkout_session_expired' },\n );\n }\n\n throw createCheckoutProcessingTimeoutError();\n }\n\n private toCheckoutProcessingPending(\n payload: ApiErrorPayload,\n response: Response,\n checkoutSessionId: string,\n ): CheckoutProcessingPending {\n const retryAfterHeader = response.headers.get('Retry-After');\n const headerRetryAfterSeconds = retryAfterHeader === null\n || retryAfterHeader.trim() === ''\n ? undefined\n : Number(retryAfterHeader);\n const headerRetryAfterMs = headerRetryAfterSeconds !== undefined\n && Number.isFinite(headerRetryAfterSeconds)\n ? headerRetryAfterSeconds * 1_000\n : undefined;\n\n return {\n type: 'checkout_processing',\n sessionId: readString(payload, 'sessionId') ?? checkoutSessionId,\n retryAfterMs: this.clampRetryAfterMs(\n readNumber(payload, 'retryAfterMs')\n ?? headerRetryAfterMs\n ?? DEFAULT_PROCESSING_RETRY_AFTER_MS,\n ),\n statusUrl: readString(payload, 'statusUrl'),\n sessionUrl: readString(payload, 'sessionUrl'),\n };\n }\n\n private clampRetryAfterMs(retryAfterMs: number): number {\n return Math.max(0, Math.min(retryAfterMs, MAX_PROCESSING_RETRY_AFTER_MS));\n }\n\n /**\n * Stash the display-only fields the consumer passed into a create-session\n * call. Runs after the backend assigns a UUID so a later GET on the same\n * session (typically after a redirect) can fill in fields the backend no\n * longer persists — `overrideAmount`, `totalAmount`, `name`, etc.\n *\n * No-op when no UUID is available.\n */\n private autoCacheDisplayData(\n sessionId: string | undefined,\n params: InlineSessionDraft,\n ): void {\n if (!sessionId) return;\n const products = params.products ?? foldIntoProducts(params.items, params.subscriptions);\n if (products.length === 0 && !params.currency) {\n return;\n }\n const usingUnifiedProducts = params.products !== undefined;\n const sessionCurrency = resolveSessionCurrency(\n params.currency,\n usingUnifiedProducts ? undefined : params.items,\n usingUnifiedProducts ? undefined : params.subscriptions,\n products,\n );\n cacheSessionDisplayData(sessionId, {\n currency: sessionCurrency ?? undefined,\n products: products.map((p) => ({\n code: p.code ?? p.providerItemId ?? p.providerPlanId,\n type: p.type,\n name: p.name ?? p.itemName ?? p.providerItemName ?? p.subscriptionName ?? p.providerPlanName ?? null,\n totalAmount: p.totalAmount,\n overrideAmount: p.overrideAmount,\n currency: p.currency ?? sessionCurrency ?? undefined,\n })),\n });\n }\n\n /**\n * Merge cached display-only fields (set by {@link cacheSessionDisplayData})\n * into a raw session response. Server values always win — cache fills in\n * only where the server returned `null` / `undefined`.\n */\n private mergeCachedDisplayData(raw: RawCheckoutSession): RawCheckoutSession {\n const cached = getSessionDisplayData(raw.uuid);\n\n const cachedProducts = new Map<string, SessionDisplayProduct>();\n // Key on `code` alone: the catalog code is the product's identity (the\n // backend resolves item-vs-subscription from it), so cached display data\n // merges back correctly even when the create-side payload omitted the\n // deprecated `type`.\n const productKey = (code: string | undefined): string | undefined =>\n code ? `code:${code}` : undefined;\n for (const p of cached?.products ?? []) {\n const key = productKey(p.code);\n if (key) cachedProducts.set(key, p);\n }\n\n const mergedProducts = (raw.products ?? []).map((p) => {\n const key = productKey(p.code);\n const fallback = key ? cachedProducts.get(key) : undefined;\n return {\n ...p,\n name: p.name ?? fallback?.name ?? null,\n totalAmount: p.totalAmount ?? fallback?.totalAmount,\n overrideAmount: p.overrideAmount ?? fallback?.overrideAmount,\n currency: p.currency ?? fallback?.currency,\n };\n });\n\n return {\n ...raw,\n currency: raw.currency ?? cached?.currency,\n products: mergedProducts,\n };\n }\n}\n\n/** Create an internally observed API client without publishing hook options. */\nexport function createInstrumentedPaymentAPI(\n billingApiUrl: string,\n hooks: PaymentApiTelemetryHooks,\n): PaymentAPI {\n const InstrumentedPaymentAPI = PaymentAPI as unknown as new (\n baseUrl: string,\n telemetryHooks: PaymentApiTelemetryHooks,\n ) => PaymentAPI;\n return new InstrumentedPaymentAPI(billingApiUrl, hooks);\n}\n","/**\n * Shared primitives for reading billing-API error bodies. The two error\n * builders that consume these — `buildApiErrorFromResponse` (payment-api) and\n * `buildCheckoutSessionError` (create-checkout-session) — diverge in their\n * fallback semantics (array-message joining + status code vs. coupon-specific\n * messages), but the field-level guards are identical, so they live here.\n */\n\n/** A non-empty string value, or `undefined` for anything else. */\nexport function readErrorString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value : undefined;\n}\n\n/**\n * Read an error `message` that may be a `string` or a `string[]`.\n *\n * NestJS class-validator returns `message` as a `string[]` (one entry per\n * failed constraint), e.g. `[\"postcode must be a valid GB postcode\"]`. Read as\n * a plain string that collapses to the generic fallback; here we join the\n * non-empty entries so a country-aware account-snapshot validation error\n * surfaces its real reason instead of \"Failed to persist account snapshot\".\n */\nexport function readErrorMessage(value: unknown): string | undefined {\n if (typeof value === 'string') return value.trim() ? value : undefined;\n if (Array.isArray(value)) {\n const joined = value\n .filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0)\n .join('; ');\n return joined || undefined;\n }\n return undefined;\n}\n","/**\n * Client-side cache for display-only checkout fields the backend no longer\n * persists (`overrideAmount`, `totalAmount`, `providerItemName`,\n * `providerPlanName`, per-line `currency`).\n *\n * The cache lives in `sessionStorage` so it survives the navigation from the\n * page that creates the session to the checkout page that fetches it, but\n * dies on tab close. An in-memory fallback keeps the SDK working in Node /\n * SSR contexts where `sessionStorage` is unavailable.\n *\n * Values from the server response always win — cached values fill in only\n * where the server returned `null` or `undefined`.\n */\n\nconst STORAGE_KEY_PREFIX = 'flopay_session_display:';\nconst DEFAULT_TTL_MS = 60 * 60 * 1000;\n\n/** Display-only fields per product that can be cached and merged back later. */\nexport interface SessionDisplayProduct {\n /** Catalog code (match key). */\n code?: string;\n /** Whether this product is a one-time item or a recurring subscription. */\n type?: 'item' | 'subscription';\n /** Display-only name for the product. */\n name?: string | null;\n totalAmount?: number;\n overrideAmount?: number | null;\n currency?: string;\n}\n\n/** Display-only payload that can be stashed for later merge into a session response. */\nexport interface SessionDisplayCacheData {\n /** Session-level currency (falls into the response only when the server omits it). */\n currency?: string;\n products?: SessionDisplayProduct[];\n}\n\ninterface CachedEntry {\n data: SessionDisplayCacheData;\n expiresAt: number;\n}\n\nconst memoryStore = new Map<string, CachedEntry>();\n\nfunction storageKey(sessionId: string): string {\n return `${STORAGE_KEY_PREFIX}${sessionId}`;\n}\n\nfunction getSessionStorage(): Storage | null {\n if (typeof window === 'undefined') return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n}\n\n/**\n * Stash display-only data for a session. Called client-side right after the\n * server returns a session ID, so the values survive the redirect to the\n * checkout page.\n */\nexport function cacheSessionDisplayData(\n sessionId: string,\n data: SessionDisplayCacheData,\n options?: { ttlMs?: number },\n): void {\n if (!sessionId) return;\n\n const ttl = options?.ttlMs ?? DEFAULT_TTL_MS;\n const entry: CachedEntry = { data, expiresAt: Date.now() + ttl };\n\n const storage = getSessionStorage();\n if (storage) {\n try {\n storage.setItem(storageKey(sessionId), JSON.stringify(entry));\n return;\n } catch {\n // Quota / serialization error — fall through to in-memory store\n }\n }\n\n memoryStore.set(sessionId, entry);\n}\n\n/**\n * Read previously-cached display data for a session, or `null` if nothing\n * is cached (or the TTL has elapsed).\n */\nexport function getSessionDisplayData(\n sessionId: string,\n): SessionDisplayCacheData | null {\n if (!sessionId) return null;\n\n const storage = getSessionStorage();\n if (storage) {\n try {\n const raw = storage.getItem(storageKey(sessionId));\n if (raw) {\n const entry = JSON.parse(raw) as CachedEntry;\n if (entry && typeof entry.expiresAt === 'number' && entry.expiresAt > Date.now()) {\n return entry.data;\n }\n storage.removeItem(storageKey(sessionId));\n }\n } catch {\n // Malformed entry — fall through to memory store\n }\n }\n\n const memEntry = memoryStore.get(sessionId);\n if (memEntry) {\n if (memEntry.expiresAt > Date.now()) {\n return memEntry.data;\n }\n memoryStore.delete(sessionId);\n }\n\n return null;\n}\n\n/**\n * Drop any cached display data for a session. Call from the success page\n * after the payment completes; otherwise the TTL handles cleanup.\n */\nexport function clearSessionDisplayData(sessionId: string): void {\n if (!sessionId) return;\n\n memoryStore.delete(sessionId);\n\n const storage = getSessionStorage();\n if (storage) {\n try {\n storage.removeItem(storageKey(sessionId));\n } catch {\n // ignore\n }\n }\n}\n","import {\n buildTelemetryErrorEvent,\n buildTelemetryLogEvent,\n buildTelemetryPerformanceEvent,\n buildTelemetryTerminalEvent,\n serializeTelemetryBatch,\n TELEMETRY_MAX_BATCH_BYTES,\n} from '@flopay/shared';\nimport type {\n BuildTelemetryErrorEventInput,\n BuildTelemetryLogEventInput,\n BuildTelemetryPerformanceEventInput,\n BuildTelemetryTerminalEventInput,\n TelemetryCheckoutMode,\n TelemetryEvent,\n TelemetryEventClass,\n TelemetryLayout,\n TelemetrySdkPackage,\n} from '@flopay/shared';\n\nconst TELEMETRY_PATH = '/v1/sdk-telemetry/events';\nconst MAX_BATCH_SIZE = 16;\nconst MAX_QUEUE_SIZE = 64;\nconst UPLOAD_TIMEOUT_MS = 1_500;\nconst ERROR_DEDUPLICATION_WINDOW_MS = 1_000;\nconst MAX_REPORTED_FAILURES = 64;\nconst DEDUPLICATION_EVENT_ID = '00000000-0000-4000-8000-000000000000';\nconst EVENT_BUDGETS: Record<TelemetryEventClass, number> = {\n technical_error: 8,\n lifecycle: 32,\n expected_outcome: 32,\n performance: 24,\n};\n\nexport interface TelemetryReporterOptions {\n billingApiUrl: string;\n /** Package that owns every event in this package-homogeneous reporter. */\n sdkPackage?: TelemetrySdkPackage;\n sdkVersion: string;\n enabled?: boolean;\n /** @internal Monotonic clock injection for deterministic SDK tests. */\n clock?: () => number;\n}\n\nexport type TelemetryReporterLogInput = Omit<\n BuildTelemetryLogEventInput,\n 'eventId' | 'sequence'\n>;\n\nexport type TelemetryReporterErrorInput = Omit<\n BuildTelemetryErrorEventInput,\n 'eventId' | 'sequence'\n>;\n\nexport type TelemetryReporterPerformanceInput = Omit<\n BuildTelemetryPerformanceEventInput,\n 'eventId' | 'sequence'\n>;\n\nexport type TelemetryReporterTerminalInput = Omit<\n BuildTelemetryTerminalEventInput,\n 'eventId' | 'sequence'\n>;\n\nexport interface TelemetryCheckoutContext {\n checkoutMode?: TelemetryCheckoutMode;\n layout?: TelemetryLayout;\n}\n\nfunction createUuidV4(): string {\n try {\n return globalThis.crypto.randomUUID();\n } catch {\n const bytes = new Uint8Array(16);\n try {\n globalThis.crypto.getRandomValues(bytes);\n } catch {\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n}\n\nfunction bodyByteLength(body: string): number {\n try {\n return new TextEncoder().encode(body).byteLength;\n } catch {\n return body.length;\n }\n}\n\nfunction failureDeduplicationKey(\n event: ReturnType<typeof buildTelemetryErrorEvent>,\n): string {\n return JSON.stringify([\n event.code,\n event.stage,\n event.provider,\n event.attempt,\n event.statusClass,\n event.requestCategory,\n event.paymentMethodCategory,\n event.checkoutMode,\n event.layout,\n ]);\n}\n\n/** Monotonic SDK clock. Telemetry never reads Resource Timing or page URLs. */\nexport function telemetryNow(): number {\n return globalThis.performance?.now() ?? 0;\n}\n\n/**\n * Bounded, best-effort browser telemetry reporter. It accepts only the closed\n * shared contract and never exposes custom event fields or endpoint settings.\n */\nexport class TelemetryReporter {\n private readonly endpoint: string;\n private readonly sdkPackage: TelemetrySdkPackage;\n private readonly sdkVersion: string;\n private readonly correlationId: string;\n private merchantEnabled: boolean;\n private readonly clock: () => number;\n private readonly browserTransportAvailable: boolean;\n private ingestionDisabled = false;\n private readonly queue: TelemetryEvent[] = [];\n private sequence = 0;\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private flushInFlight: Promise<void> | null = null;\n private readonly reportedFailures = new Map<string, number>();\n private checkoutContext: TelemetryCheckoutContext = {};\n private checkoutStartedAt: number | null = null;\n private destroyed = false;\n private readonly pageExitHandler = (): void => {\n this.drainQueue();\n };\n private readonly visibilityHandler = (): void => {\n if (document.visibilityState === 'hidden') void this.flush();\n };\n private eventCounts: Record<TelemetryEventClass, number> = {\n technical_error: 0,\n lifecycle: 0,\n expected_outcome: 0,\n performance: 0,\n };\n\n constructor(options: TelemetryReporterOptions) {\n this.endpoint = `${options.billingApiUrl.replace(/\\/+$/, '')}${TELEMETRY_PATH}`;\n this.sdkPackage = options.sdkPackage ?? '@flopay/js';\n this.sdkVersion = options.sdkVersion;\n this.correlationId = createUuidV4();\n this.merchantEnabled = options.enabled !== false;\n this.clock = options.clock ?? telemetryNow;\n this.browserTransportAvailable =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n if (this.browserTransportAvailable) {\n window.addEventListener('pagehide', this.pageExitHandler);\n document.addEventListener('visibilitychange', this.visibilityHandler);\n }\n }\n\n log(input: TelemetryReporterLogInput): void {\n if (!this.canCollect()) return;\n this.enqueue(buildTelemetryLogEvent({\n ...this.checkoutContext,\n ...input,\n eventId: createUuidV4(),\n sequence: this.sequence++,\n }));\n }\n\n error(input: TelemetryReporterErrorInput): void {\n if (!this.canCollect()) return;\n const normalizedFailure = buildTelemetryErrorEvent({\n ...this.checkoutContext,\n ...input,\n eventId: DEDUPLICATION_EVENT_ID,\n sequence: 0,\n });\n const deduplicationKey = failureDeduplicationKey(normalizedFailure);\n const now = this.now();\n this.pruneReportedFailures(now);\n const previouslyReportedAt = this.reportedFailures.get(deduplicationKey);\n if (\n previouslyReportedAt !== undefined\n && now >= previouslyReportedAt\n && now - previouslyReportedAt < ERROR_DEDUPLICATION_WINDOW_MS\n ) {\n this.log({\n name: 'operation.deduplicated',\n stage: input.stage,\n provider: input.provider,\n paymentMethodCategory: input.paymentMethodCategory,\n attempt: input.attempt,\n });\n return;\n }\n this.rememberReportedFailure(deduplicationKey, now);\n this.enqueue(buildTelemetryErrorEvent({\n ...this.checkoutContext,\n ...input,\n eventId: createUuidV4(),\n sequence: this.sequence++,\n }));\n }\n\n performance(input: TelemetryReporterPerformanceInput): void {\n if (!this.canCollect()) return;\n this.enqueue(buildTelemetryPerformanceEvent({\n ...this.checkoutContext,\n ...input,\n eventId: createUuidV4(),\n sequence: this.sequence++,\n }));\n }\n\n terminal(input: TelemetryReporterTerminalInput): void {\n if (!this.canCollect()) return;\n this.enqueue(buildTelemetryTerminalEvent({\n ...this.checkoutContext,\n ...input,\n eventId: createUuidV4(),\n sequence: this.sequence++,\n }));\n if (input.outcome !== 'action_required' && this.checkoutStartedAt !== null) {\n const checkoutStartedAt = this.checkoutStartedAt;\n this.checkoutStartedAt = null;\n this.performance({\n stage: 'total_journey',\n durationMs: Math.max(0, this.now() - checkoutStartedAt),\n durationMode: 'total',\n provider: input.provider,\n paymentMethodCategory: input.paymentMethodCategory,\n });\n }\n }\n\n /** @internal Read the reporter's monotonic clock without Resource Timing. */\n now(): number {\n try {\n return this.clock();\n } catch {\n return telemetryNow();\n }\n }\n\n private pruneReportedFailures(now: number): void {\n for (const [key, reportedAt] of this.reportedFailures) {\n if (\n now < reportedAt\n || now - reportedAt >= ERROR_DEDUPLICATION_WINDOW_MS\n ) {\n this.reportedFailures.delete(key);\n }\n }\n }\n\n private rememberReportedFailure(key: string, reportedAt: number): void {\n while (this.reportedFailures.size >= MAX_REPORTED_FAILURES) {\n const oldest = this.reportedFailures.keys().next();\n if (oldest.done) break;\n this.reportedFailures.delete(oldest.value);\n }\n this.reportedFailures.set(key, reportedAt);\n }\n\n /** @internal Add closed checkout dimensions to subsequent SDK events. */\n setCheckoutContext(context: TelemetryCheckoutContext): void {\n this.checkoutContext = {\n checkoutMode: context.checkoutMode,\n layout: context.layout,\n };\n }\n\n /** @internal Start a fresh checkout budget, dedupe window, and total span. */\n beginCheckout(context: TelemetryCheckoutContext = {}): number {\n if (!this.canCollect()) return 0;\n this.drainQueue();\n this.setCheckoutContext(context);\n this.sequence = 0;\n this.reportedFailures.clear();\n this.eventCounts = {\n technical_error: 0,\n lifecycle: 0,\n expected_outcome: 0,\n performance: 0,\n };\n this.checkoutStartedAt = this.now();\n return this.checkoutStartedAt;\n }\n\n private enqueue(event: TelemetryEvent): void {\n if (!this.canCollect()) return;\n if (\n this.queue.length >= MAX_QUEUE_SIZE ||\n this.eventCounts[event.class] >= EVENT_BUDGETS[event.class]\n ) return;\n this.eventCounts[event.class] += 1;\n this.queue.push(event);\n if (this.queue.length >= MAX_BATCH_SIZE) {\n void this.flush();\n return;\n }\n this.scheduleFlush();\n }\n\n private canCollect(): boolean {\n return this.browserTransportAvailable\n && this.merchantEnabled\n && !this.ingestionDisabled\n && !this.destroyed;\n }\n\n /** Flush one bounded batch. Failures are intentionally dropped. */\n async flush(): Promise<void> {\n if (this.flushInFlight) return this.flushInFlight;\n if (\n !this.browserTransportAvailable ||\n this.destroyed ||\n this.ingestionDisabled ||\n this.queue.length === 0\n ) return;\n this.clearFlushTimer();\n const events = this.queue.splice(0, MAX_BATCH_SIZE);\n this.flushInFlight = this.sendBatch(events).finally(() => {\n this.flushInFlight = null;\n if (this.queue.length > 0) this.scheduleFlush();\n });\n return this.flushInFlight;\n }\n\n /** Flush pending work and detach browser lifecycle listeners. */\n destroy(): void {\n if (this.destroyed) return;\n this.drainQueue();\n this.destroyed = true;\n this.clearFlushTimer();\n if (this.browserTransportAvailable) {\n window.removeEventListener('pagehide', this.pageExitHandler);\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n }\n this.queue.splice(0);\n this.reportedFailures.clear();\n }\n\n /** Permanently honor a merchant opt-out and discard queued events. */\n disable(): void {\n this.merchantEnabled = false;\n this.queue.splice(0);\n this.reportedFailures.clear();\n this.clearFlushTimer();\n }\n\n /** Start every bounded keepalive request synchronously before page teardown. */\n private drainQueue(): void {\n if (\n !this.browserTransportAvailable ||\n this.destroyed ||\n this.ingestionDisabled ||\n this.queue.length === 0\n ) return;\n this.clearFlushTimer();\n while (this.queue.length > 0) {\n const events = this.queue.splice(0, MAX_BATCH_SIZE);\n void this.sendBatch(events);\n }\n }\n\n private async sendBatch(events: readonly TelemetryEvent[]): Promise<void> {\n if (!this.browserTransportAvailable || this.ingestionDisabled) return;\n const body = serializeTelemetryBatch(events, {\n correlationId: this.correlationId,\n sdkPackage: this.sdkPackage,\n sdkVersion: this.sdkVersion,\n batchId: createUuidV4(),\n });\n if (bodyByteLength(body) > TELEMETRY_MAX_BATCH_BYTES) return;\n\n const controller = typeof AbortController === 'undefined' ? null : new AbortController();\n let timeout: ReturnType<typeof setTimeout> | null = null;\n try {\n const request = fetch(this.endpoint, {\n method: 'POST',\n headers: { 'content-type': 'text/plain;charset=UTF-8' },\n body,\n credentials: 'omit',\n keepalive: true,\n referrerPolicy: 'no-referrer',\n signal: controller?.signal,\n }).then(async (response): Promise<'disabled' | null> => {\n if (response.status !== 202) return null;\n const payload = await response.json().catch(() => null) as { status?: unknown } | null;\n return payload?.status === 'disabled' ? 'disabled' : null;\n }).catch(() => null);\n const expired = new Promise<null>((resolve) => {\n timeout = setTimeout(() => {\n controller?.abort();\n resolve(null);\n }, UPLOAD_TIMEOUT_MS);\n });\n const status = await Promise.race([request, expired]);\n if (status === 'disabled') this.disableFromIngestion();\n } catch {\n // Best effort by contract: never retry or surface transport failures.\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n }\n\n private disableFromIngestion(): void {\n this.ingestionDisabled = true;\n this.queue.splice(0);\n this.reportedFailures.clear();\n this.clearFlushTimer();\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer || this.destroyed || this.ingestionDisabled) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n void this.flush();\n }, 0);\n }\n\n private clearFlushTimer(): void {\n if (!this.flushTimer) return;\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n}\n\nconst TELEMETRY_REPORTER_FACTORY = Symbol.for('@flopay/js.telemetry.reporter-factory.v1');\nconst telemetryGlobal = globalThis as Record<PropertyKey, unknown>;\nif (telemetryGlobal[TELEMETRY_REPORTER_FACTORY] === undefined) {\n Object.defineProperty(telemetryGlobal, TELEMETRY_REPORTER_FACTORY, {\n configurable: true,\n enumerable: false,\n writable: false,\n value: (options: TelemetryReporterOptions) => new TelemetryReporter(options),\n });\n}\n","import type {\n PaymentProviderAdapter,\n FloPayConfig,\n ElementOptions,\n ConfirmPaymentParams,\n PaymentResult,\n CardCaptureAdapter,\n CheckoutSession,\n NormalizedCheckoutSession,\n PayPalPaymentResult,\n} from '@flopay/shared';\nimport { FloPayError, resolveBillingApiUrl, SDK_VERSION } from '@flopay/shared';\nimport { FloPayElements } from './elements.js';\nimport { createInstrumentedPaymentAPI } from './payment-api.js';\nimport {\n PciVaultCardCapture,\n createInstrumentedPciVaultCardCapture,\n} from './pci-vault-card-capture.js';\nimport { TelemetryReporter, telemetryNow } from './telemetry-reporter.js';\nimport { attachFloPayTelemetryBridge } from './telemetry-bridge.js';\n\nfunction isExpectedDecline(error: FloPayError | undefined): boolean {\n if (!error) return false;\n const code = error.code?.toLowerCase() ?? '';\n return Boolean(error.declineCode) || code.includes('declin');\n}\n\nfunction telemetryProvider(name: string): 'stripe' | 'paypal' | 'pcivault' | 'other' {\n if (name === 'stripe' || name === 'paypal' || name === 'pcivault') return name;\n return 'other';\n}\n\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 readonly telemetryReporter?: TelemetryReporter;\n private currentElements: FloPayElements | null = null;\n\n private now(): number {\n return this.telemetryReporter?.now?.() ?? telemetryNow();\n }\n\n constructor(provider: PaymentProviderAdapter, config: FloPayConfig);\n constructor(\n provider: PaymentProviderAdapter,\n config: FloPayConfig,\n telemetryReporter?: TelemetryReporter,\n ) {\n this.provider = provider;\n this.config = config;\n this.telemetryReporter = telemetryReporter ?? new TelemetryReporter({\n billingApiUrl: resolveBillingApiUrl(config.billingApiUrl),\n sdkVersion: SDK_VERSION,\n enabled: config.telemetry !== false,\n });\n attachFloPayTelemetryBridge(this, this.telemetryReporter, telemetryNow);\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 /**\n * Create a {@link CardCaptureAdapter} for collecting card details through the\n * backend-rendered hosted vault PCI widget (TeamFloPay/backend#823).\n *\n * The returned adapter injects the server-supplied widget HTML (the session's\n * {@link CheckoutSession.vault} block, or one fetched via\n * `PaymentAPI.getVaultCapture`) and relays the widget's terminal outcome. The\n * backend owns tokenization, the PaymentIntent, 3DS, and fulfilment — no\n * Stripe.js is involved on the card path and PCI-sensitive fields never enter\n * the SDK runtime.\n */\n cardCapture(options?: {\n /** Checkout session id to bind the capture to (outcome correlation). */\n sessionId?: string;\n }): CardCaptureAdapter {\n const requestedAt = this.now();\n this.telemetryReporter?.log({\n name: 'vault.capture.requested',\n stage: 'vault_request',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n if (this.telemetryReporter) {\n return createInstrumentedPciVaultCardCapture(\n { sessionId: options?.sessionId },\n this.telemetryReporter,\n requestedAt,\n );\n }\n return new PciVaultCardCapture({\n sessionId: options?.sessionId,\n telemetry: false,\n });\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 /**\n * Session-bound checkout token forwarded to the session-scoped non-card\n * intent contract as `x-checkout-session-token`.\n */\n nonce?: string;\n }): Promise<PayPalPaymentResult> {\n const startedAt = this.now();\n this.telemetryReporter?.log({\n name: 'payment.method.selected',\n stage: 'processing',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n this.telemetryReporter?.log({\n name: 'payment.intent.started',\n stage: 'processing',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n requestCategory: 'intent_create',\n });\n try {\n const result = await this.provider.confirmPayPalPayment(params);\n this.telemetryReporter?.performance({\n stage: 'processing',\n durationMs: this.now() - startedAt,\n durationMode: 'machine',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n if (!result.error) {\n this.telemetryReporter?.log({\n name: 'payment.intent.completed',\n stage: 'processing',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n requestCategory: 'intent_create',\n statusClass: '2xx',\n });\n }\n if (result.status === 'requires_action') {\n this.telemetryReporter?.log({\n name: 'provider.redirect.started',\n stage: 'redirect',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n this.telemetryReporter?.terminal({\n outcome: 'action_required',\n stage: 'redirect',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (result.status === 'succeeded') {\n this.telemetryReporter?.terminal({\n outcome: 'payment_succeeded',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (result.status !== 'processing') {\n if (isExpectedDecline(result.error)) {\n this.telemetryReporter?.terminal({\n outcome: 'payment_declined',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (result.error?.type === 'validation_error') {\n this.telemetryReporter?.terminal({\n outcome: 'validation_rejected',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (result.error) {\n this.telemetryReporter?.error({\n errorCode: 'PAYMENT_PROCESSING_FAILED',\n stage: 'processing',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n requestCategory: 'intent_create',\n });\n }\n }\n return result;\n } catch (error) {\n this.telemetryReporter?.performance({\n stage: 'processing',\n durationMs: this.now() - startedAt,\n durationMode: 'machine',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n this.telemetryReporter?.error({\n errorCode: 'NETWORK_REQUEST_FAILED',\n stage: 'processing',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n requestCategory: 'intent_create',\n statusClass: 'network_error',\n });\n throw error;\n }\n }\n\n /** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */\n async resumePayPalPayment(): Promise<PayPalPaymentResult | null> {\n const startedAt = this.now();\n try {\n const result = await this.provider.resumePayPalPayment();\n if (result === null) return null;\n this.telemetryReporter?.log({\n name: 'provider.redirect.resumed',\n stage: 'redirect_resume',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n this.telemetryReporter?.performance({\n stage: 'redirect_resume',\n durationMs: this.now() - startedAt,\n durationMode: 'machine',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n if (result.status === 'succeeded') {\n this.telemetryReporter?.terminal({\n outcome: 'payment_succeeded',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (isExpectedDecline(result.error)) {\n this.telemetryReporter?.terminal({\n outcome: 'payment_declined',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (result.error?.type === 'validation_error') {\n this.telemetryReporter?.terminal({\n outcome: 'validation_rejected',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n } else if (result.error) {\n this.telemetryReporter?.error({\n errorCode: 'REDIRECT_RESUME_FAILED',\n stage: 'redirect_resume',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n }\n return result;\n } catch (error) {\n this.telemetryReporter?.performance({\n stage: 'redirect_resume',\n durationMs: this.now() - startedAt,\n durationMode: 'machine',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n this.telemetryReporter?.error({\n errorCode: 'REDIRECT_RESUME_FAILED',\n stage: 'redirect_resume',\n provider: 'paypal',\n paymentMethodCategory: 'paypal',\n });\n throw error;\n }\n }\n\n /** Confirms a non-card wallet/APM payment using the mounted PaymentElement. */\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult> {\n if (\n (params.paymentMethodCategory !== 'wallet' && params.paymentMethodCategory !== 'apm')\n || !params.paymentMethodType?.trim()\n || params.paymentMethodType.trim().toLowerCase() === 'card'\n ) {\n throw new FloPayError(\n 'A supported non-card payment method is required.',\n 'validation_error',\n { param: 'paymentMethodType' },\n );\n }\n const started = this.now();\n const provider = telemetryProvider(this.provider.name);\n this.telemetryReporter?.log({\n name: 'payment.processing.started',\n stage: 'processing',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n try {\n const result = await this.provider.confirmPayment(params);\n const durationMs = this.now() - started;\n this.telemetryReporter?.performance({\n stage: 'processing',\n durationMs,\n durationMode: 'machine',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n if (result.status === 'succeeded') {\n this.telemetryReporter?.terminal({\n outcome: 'payment_succeeded',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n } else if (isExpectedDecline(result.error)) {\n this.telemetryReporter?.terminal({\n outcome: 'payment_declined',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n } else if (result.error?.type === 'validation_error') {\n this.telemetryReporter?.terminal({\n outcome: 'validation_rejected',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n } else if (result.status === 'requires_action') {\n this.telemetryReporter?.terminal({\n outcome: 'action_required',\n stage: 'three_ds_handoff',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n } else if (result.status === 'failed' && result.error) {\n this.telemetryReporter?.error({\n errorCode: 'PAYMENT_PROCESSING_FAILED',\n stage: 'processing',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n }\n if (result.status === 'succeeded' || result.status === 'failed') {\n this.telemetryReporter?.log({\n name: 'payment.processing.completed',\n stage: 'processing',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n } else {\n this.telemetryReporter?.log({\n name: 'operation.state_transition',\n stage: result.status === 'requires_action' ? 'three_ds_handoff' : 'processing',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n }\n return result;\n } catch (error) {\n this.telemetryReporter?.performance({\n stage: 'processing',\n durationMs: this.now() - started,\n durationMode: 'machine',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n this.telemetryReporter?.error({\n errorCode: 'PAYMENT_PROCESSING_FAILED',\n stage: 'processing',\n provider,\n paymentMethodCategory: params.paymentMethodCategory,\n });\n throw error;\n }\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 unified = await this.retrieveUnifiedSession(sessionId, billingApiUrl);\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 started = this.now();\n this.telemetryReporter?.log({\n name: 'session.read.started',\n stage: 'session_read',\n requestCategory: 'session_read',\n });\n let firstByteDuration: number | undefined;\n const api = createInstrumentedPaymentAPI(apiUrl, {\n now: () => this.telemetryReporter?.now() ?? telemetryNow(),\n onFirstByte: (durationMs) => {\n firstByteDuration = durationMs;\n },\n onRetry: (requestCategory, attempt) => {\n this.telemetryReporter?.log({\n name: 'operation.retry',\n stage: requestCategory === 'session_read' ? 'session_read' : 'processing',\n requestCategory,\n attempt,\n });\n },\n });\n try {\n const result = await api.getUnifiedCheckoutSession(sessionId);\n if (firstByteDuration !== undefined) {\n this.telemetryReporter?.log({\n name: 'session.request.first_byte',\n stage: 'session_first_byte',\n requestCategory: 'session_read',\n statusClass: '2xx',\n });\n this.telemetryReporter?.performance({\n stage: 'session_first_byte',\n durationMs: firstByteDuration,\n durationMode: 'machine',\n requestCategory: 'session_read',\n statusClass: '2xx',\n });\n }\n this.telemetryReporter?.log({\n name: 'session.request.completed',\n stage: 'session_complete',\n requestCategory: 'session_read',\n statusClass: '2xx',\n });\n this.telemetryReporter?.log({\n name: 'checkout.data.ready',\n stage: 'checkout_data_ready',\n });\n this.telemetryReporter?.performance({\n stage: 'session_complete',\n durationMs: this.now() - started,\n durationMode: 'machine',\n requestCategory: 'session_read',\n statusClass: '2xx',\n });\n return result;\n } catch (error) {\n const statusCode = error instanceof FloPayError ? error.statusCode : undefined;\n this.telemetryReporter?.error({\n errorCode: error instanceof FloPayError && error.code === 'checkout_processing_timeout'\n ? 'REQUEST_TIMEOUT'\n : 'NETWORK_REQUEST_FAILED',\n stage: 'session_read',\n provider: 'flo',\n paymentMethodCategory: 'unknown',\n });\n this.telemetryReporter?.performance({\n stage: 'session_complete',\n durationMs: this.now() - started,\n durationMode: 'machine',\n requestCategory: 'session_read',\n statusClass: statusCode ? `${Math.floor(statusCode / 100)}xx` as '4xx' | '5xx' : 'network_error',\n });\n throw error;\n }\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.telemetryReporter?.log({ name: 'checkout.unmount', stage: 'unmount' });\n this.telemetryReporter?.destroy();\n this.currentElements?.destroy();\n this.currentElements = null;\n this.provider.destroy();\n }\n}\n\n/** Create the loadFloPay-owned instance without publishing reporter injection. */\nexport function createInstrumentedFloPay(\n provider: PaymentProviderAdapter,\n config: FloPayConfig,\n reporter: TelemetryReporter,\n): FloPay {\n const InstrumentedFloPay = FloPay as unknown as new (\n adapter: PaymentProviderAdapter,\n sdkConfig: FloPayConfig,\n telemetry: TelemetryReporter,\n ) => FloPay;\n return new InstrumentedFloPay(provider, config, reporter);\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 const merged: ElementOptions = { ...this.baseOptions, ...options };\n if (type === 'payment') {\n const paymentMethodTypes = merged.paymentMethodTypes\n ?.map((paymentMethodType) => paymentMethodType.trim())\n .filter((paymentMethodType) => paymentMethodType && paymentMethodType.toLowerCase() !== 'card');\n if (!paymentMethodTypes?.length) {\n throw new FloPayError(\n 'At least one supported non-card payment method is required.',\n 'validation_error',\n { param: 'paymentMethodTypes' },\n );\n }\n merged.paymentMethodTypes = paymentMethodTypes;\n }\n\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 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 CardCaptureAdapter,\n CardCaptureEventType,\n CardCaptureMountOptions,\n CardCaptureOutcomeEvent,\n CardCaptureProviderId,\n VaultCaptureResultMessage,\n VaultCardFieldKey,\n VaultCardThemeColors,\n} from '@flopay/shared';\nimport {\n buildTelemetryErrorEvent,\n buildTelemetryLogEvent,\n buildTelemetryTerminalEvent,\n FloPayError,\n resolveBillingApiUrl,\n SDK_VERSION,\n} from '@flopay/shared';\nimport type { TelemetryEvent } from '@flopay/shared';\nimport { TelemetryReporter, telemetryNow } from './telemetry-reporter.js';\n\n// ---------------------------------------------------------------------------\n// PCIVault hosted-widget capture (Model A — backend-orchestrated)\n//\n// Under TeamFloPay/backend#823 the vault card form is a self-contained,\n// server-rendered widget: the backend returns a `VaultCaptureBlock.html`\n// bundle that owns the PCIVault card fields, its own submit button, card\n// tokenization, PaymentIntent creation + confirmation, 3DS, and decline\n// display. The SDK's only job is to inject that HTML and relay the widget's\n// terminal `postMessage` outcome to the host checkout. No Stripe.js, no\n// PCIVault SDK loading, and no client-side readiness polling happen here —\n// PAN / CVC never enter the SDK runtime.\n//\n// Outcome authenticity: the widget HTML is injected *same-window*, so a genuine\n// outcome's `event.origin` is the merchant page's own origin and the\n// `source: 'flopay-vault'` marker alone is forgeable by any other script on the\n// page (XSS, a rogue dependency, a foreign frame). Before honouring a terminal\n// `complete` / `decline` the listener therefore enforces, when available:\n// • `messageToken` — an unguessable per-session token the backend bakes into\n// the widget bootstrap and echoes back (the only defence against a\n// same-window forger); enforced when the SDK was mounted with one.\n// • `sessionId` — money-affecting outcomes must be bound to the mounted\n// session; an anonymous or mismatched `complete` / `decline` is dropped.\n// • `expectedOrigin` — an optional strict origin gate for widgets that post\n// from a cross-origin frame.\n// Full same-window XSS protection requires the backend to mint+echo\n// `messageToken` (TeamFloPay/backend#823); the enforcement path is in place and\n// activates automatically once the vault block carries the token.\n// ---------------------------------------------------------------------------\n\n/** Configuration for a {@link PciVaultCardCapture} instance. */\nexport interface PciVaultCardCaptureConfig {\n /** Checkout session id bound to the capture (for outcome correlation + trust). */\n sessionId?: string;\n /**\n * Default strict origin for vault `postMessage` outcomes. Overridden by\n * {@link CardCaptureMountOptions.expectedOrigin} when that is supplied at\n * mount. When neither is set the origin gate is skipped (the widget posts\n * same-window in the Model-A flow).\n */\n expectedOrigin?: string;\n /** Flo-owned privacy-safe telemetry is enabled by default; set false to opt out. */\n telemetry?: boolean;\n}\n\ninterface InternalPciVaultTelemetry {\n reporter: TelemetryReporter;\n requestedAt?: number;\n}\n\n/** Marker the hosted vault widget stamps on its `postMessage` payloads. */\nconst VAULT_MESSAGE_SOURCE = 'flopay-vault';\n\nconst VAULT_NON_TERMINAL_OUTCOME_LOGS = {\n ready: ['vault.widget.ready', 'vault_ready'],\n submitting: ['vault.submission.started', 'vault_submit'],\n blocked: ['operation.state_transition', 'vault_submit'],\n action_required: ['vault.action.required', 'three_ds_handoff'],\n} as const;\n\n/** Best-effort merchant Sentry breadcrumb using the same closed Flo taxonomy. */\nfunction addBreadcrumb(event: TelemetryEvent): void {\n const data: Record<string, unknown> = {\n class: event.class,\n stage: event.stage,\n };\n if ('code' in event) data['code'] = event.code;\n if ('provider' in event && event.provider) data['provider'] = event.provider;\n if ('paymentMethodCategory' in event && event.paymentMethodCategory) {\n data['paymentMethodCategory'] = event.paymentMethodCategory;\n }\n if ('outcome' in event) data['outcome'] = event.outcome;\n if ('durationMs' in event && event.durationMs !== undefined) data['durationMs'] = event.durationMs;\n if ('durationMode' in event && event.durationMode) data['durationMode'] = event.durationMode;\n try {\n const sentry = (globalThis as unknown as {\n Sentry?: { addBreadcrumb?: (b: Record<string, unknown>) => void };\n }).Sentry;\n sentry?.addBreadcrumb?.({\n category: 'flopay.telemetry',\n level: event.class === 'technical_error' ? 'error' : 'info',\n message: event.class === 'lifecycle'\n ? event.name\n : event.class === 'technical_error'\n ? event.code\n : event.class === 'expected_outcome'\n ? event.outcome\n : 'sdk.performance',\n data,\n });\n } catch {\n // Merchant monitoring must never alter checkout behavior.\n }\n}\n\nfunction vaultLog(\n name: Parameters<typeof buildTelemetryLogEvent>[0]['name'],\n stage: Parameters<typeof buildTelemetryLogEvent>[0]['stage'],\n): TelemetryEvent {\n return buildTelemetryLogEvent({\n eventId: '11111111-1111-4111-8111-111111111111',\n name,\n stage,\n sequence: 0,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n}\n\nfunction vaultErrorClassification(submissionStarted: boolean): {\n errorCode: 'VAULT_LOAD_FAILED' | 'VAULT_SUBMIT_FAILED';\n stage: 'vault_mount' | 'vault_submit';\n} {\n return submissionStarted\n ? { errorCode: 'VAULT_SUBMIT_FAILED', stage: 'vault_submit' }\n : { errorCode: 'VAULT_LOAD_FAILED', stage: 'vault_mount' };\n}\n\nfunction vaultOutcomeBreadcrumb(\n type: VaultCaptureResultMessage['type'],\n submissionStarted: boolean,\n): TelemetryEvent {\n if (type === 'complete' || type === 'decline') {\n return buildTelemetryTerminalEvent({\n eventId: '22222222-2222-4222-8222-222222222222',\n outcome: type === 'complete' ? 'payment_succeeded' : 'payment_declined',\n sequence: 0,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n }\n if (type === 'error') {\n const classification = vaultErrorClassification(submissionStarted);\n return buildTelemetryErrorEvent({\n eventId: '33333333-3333-4333-8333-333333333333',\n ...classification,\n sequence: 0,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n }\n const [name, stage] = VAULT_NON_TERMINAL_OUTCOME_LOGS[type];\n return vaultLog(name, stage);\n}\n\nfunction isVaultResultMessage(value: unknown): value is VaultCaptureResultMessage {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record['source'] === VAULT_MESSAGE_SOURCE &&\n (record['type'] === 'ready' ||\n record['type'] === 'submitting' ||\n record['type'] === 'blocked' ||\n record['type'] === 'complete' ||\n record['type'] === 'decline' ||\n record['type'] === 'error' ||\n record['type'] === 'action_required')\n );\n}\n\ninterface VaultResizeMessage {\n source: typeof VAULT_MESSAGE_SOURCE;\n type: 'resize';\n height: number;\n messageToken?: string;\n}\n\ninterface VaultValidationMessage {\n source: typeof VAULT_MESSAGE_SOURCE;\n type: 'validation';\n messages: string[];\n messageToken?: string;\n}\n\nfunction isVaultValidationMessage(value: unknown): value is VaultValidationMessage {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record['source'] === VAULT_MESSAGE_SOURCE &&\n record['type'] === 'validation' &&\n Array.isArray(record['messages'])\n );\n}\n\nfunction isVaultResizeMessage(value: unknown): value is VaultResizeMessage {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record['source'] === VAULT_MESSAGE_SOURCE &&\n record['type'] === 'resize' &&\n typeof record['height'] === 'number' &&\n Number.isFinite(record['height'])\n );\n}\n\n/**\n * {@link CardCaptureAdapter} backed by the backend-rendered PCIVault hosted\n * widget.\n *\n * `mount()` injects the server-supplied widget HTML (re-executing its bundled\n * `<script>` so the form bootstraps) and subscribes to the widget's\n * `postMessage` outcome. The backend owns everything else; this adapter never\n * touches the card data, a payment intent, or 3DS.\n */\nexport class PciVaultCardCapture implements CardCaptureAdapter {\n readonly provider: CardCaptureProviderId = 'pcivault';\n\n private readonly config: PciVaultCardCaptureConfig;\n private telemetryReporter?: TelemetryReporter;\n private readonly ownsTelemetryReporter: boolean;\n private readonly requestedAt?: number;\n private container: HTMLElement | null = null;\n private messageHandler: ((event: MessageEvent) => void) | null = null;\n /**\n * Parent-page-level overlay rendering the provider's verification challenge\n * (3DS-2 iframe) on `action_required`. Owned by the adapter — not the\n * widget — so it can sit above the host SDK's processing backdrop, which\n * would otherwise visually cover an in-widget challenge iframe.\n */\n private actionOverlay: HTMLElement | null = null;\n /**\n * Listener that catches the `flopay-vault-3ds-return` postMessage from the\n * provider's challenge return page. When the SDK owns the challenge iframe\n * the return page lives inside *that* iframe (not the widget's), so\n * `window.parent` is the host page — the widget's existing message\n * listener can't see it. The SDK forwards completion into the widget via\n * `action_completed` so the widget kicks `/3ds/complete` immediately\n * instead of waiting on the eventual provider webhook.\n */\n private threeDsReturnHandler: ((event: MessageEvent) => void) | null = null;\n /** Per-session integrity token to require on outcomes (from mount options). */\n private messageToken: string | null = null;\n /** Strict origin to require on outcomes, when configured. */\n private expectedOrigin: string | null = null;\n /** Latest merchant theme to push into the (cross-origin) widget. */\n private theme: VaultCardThemeColors | null = null;\n /** Latest host submit-gate state to push into the widget (block its submit). */\n private submitGateBlocked = false;\n /** Latest card-field order + autofocus directive to push into the widget. */\n private cardFieldOrder: VaultCardFieldKey[] | null = null;\n private cardAutoFocus = true;\n private captureRequestedAt = 0;\n private vaultReadyReported = false;\n private submissionStarted = false;\n private submissionStartedAt: number | null = null;\n private readonly listeners = new Map<\n CardCaptureEventType,\n Set<(event: CardCaptureOutcomeEvent) => void>\n >();\n\n constructor(config?: PciVaultCardCaptureConfig);\n constructor(\n config: PciVaultCardCaptureConfig = {},\n internalTelemetry?: InternalPciVaultTelemetry,\n ) {\n this.config = config;\n this.ownsTelemetryReporter = !internalTelemetry && config.telemetry !== false;\n this.telemetryReporter = internalTelemetry?.reporter\n ?? (this.ownsTelemetryReporter ? new TelemetryReporter({\n billingApiUrl: resolveBillingApiUrl(),\n sdkVersion: SDK_VERSION,\n }) : undefined);\n this.requestedAt = internalTelemetry?.requestedAt;\n }\n\n async mount(container: HTMLElement, options: CardCaptureMountOptions): Promise<void> {\n if (this.ownsTelemetryReporter && !this.telemetryReporter) {\n this.telemetryReporter = new TelemetryReporter({\n billingApiUrl: resolveBillingApiUrl(),\n sdkVersion: SDK_VERSION,\n });\n }\n const mountedAt = this.telemetryReporter?.now?.() ?? telemetryNow();\n this.captureRequestedAt = this.requestedAt ?? mountedAt;\n this.vaultReadyReported = false;\n this.submissionStarted = false;\n this.submissionStartedAt = null;\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n this.reportVaultLoadFailure();\n throw new FloPayError(\n 'The vault card form is only available in the browser.',\n 'api_error',\n { code: 'card_capture_no_window' },\n );\n }\n if (!options?.html || !options.html.trim()) {\n this.reportVaultLoadFailure();\n throw new FloPayError(\n 'No vault capture widget HTML was provided to mount the secure card form.',\n 'api_error',\n { code: 'card_capture_no_widget_html' },\n );\n }\n\n this.container = container;\n this.messageToken = options.messageToken ?? null;\n this.expectedOrigin = options.expectedOrigin ?? this.config.expectedOrigin ?? null;\n this.theme = options.theme ?? null;\n try {\n this.attachMessageListener();\n this.injectWidget(container, options.html);\n } catch (error) {\n this.reportVaultLoadFailure();\n throw error;\n }\n // Push the initial theme + submit-gate + field order once the widget signals\n // ready (its message listener is attached by then); all run on every `ready`.\n this.postTheme();\n this.postSubmitGate();\n this.postCardFieldOrder();\n addBreadcrumb(vaultLog('vault.widget.mounted', 'vault_mount'));\n this.telemetryReporter?.log({\n name: 'vault.widget.mounted',\n stage: 'vault_mount',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n // The hosted widget renders its own fields/submit asynchronously after its\n // script boots; surface `ready` once injection succeeds so the surrounding\n // form can drop any loading affordance.\n this.emit('ready', { sessionId: this.config.sessionId });\n }\n\n private reportVaultLoadFailure(): void {\n this.telemetryReporter?.error({\n errorCode: 'VAULT_LOAD_FAILED',\n stage: 'vault_mount',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n }\n\n on(\n event: CardCaptureEventType,\n handler: (event: CardCaptureOutcomeEvent) => void,\n ): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(handler);\n return () => {\n this.listeners.get(event)?.delete(handler);\n };\n }\n\n unmount(): void {\n this.hideActionRequiredOverlay();\n if (this.messageHandler) {\n window.removeEventListener('message', this.messageHandler);\n this.messageHandler = null;\n }\n if (this.container) {\n this.container.replaceChildren();\n this.container = null;\n }\n this.messageToken = null;\n this.expectedOrigin = null;\n if (this.ownsTelemetryReporter) {\n this.telemetryReporter?.destroy();\n this.telemetryReporter = undefined;\n }\n // NB: do *not* clear `this.listeners` here. Subscribers own their handlers\n // and remove them via the `off()` returned by `on()`. The card form keeps\n // two independent subscription effects on this adapter — VaultCardFields\n // (ready/error/validation) and the parent card form (submitting/complete/\n // decline/error). A widget remount (e.g. the buttons-layout card expand)\n // unmounts/remounts VaultCardFields, but the parent effect's deps are stable\n // so it does not re-subscribe. Clearing here used to silently drop the\n // parent's listeners → no `submitting` (no AVS red-ring, no account PATCH)\n // on the buttons path. The message listener + container are still torn down.\n }\n\n // ── internals ──\n\n /**\n * Inject the server-rendered widget HTML. `innerHTML` does not execute\n * embedded `<script>` tags, so each script node is replaced with a freshly\n * created element that the browser will load and run (this is what boots the\n * PCIVault form bundle against the `data-flopay-config` container).\n */\n private injectWidget(container: HTMLElement, html: string): void {\n container.innerHTML = html;\n const scripts = Array.from(container.querySelectorAll('script'));\n for (const oldScript of scripts) {\n const script = document.createElement('script');\n for (const attr of Array.from(oldScript.attributes)) {\n script.setAttribute(attr.name, attr.value);\n }\n script.text = oldScript.text;\n oldScript.replaceWith(script);\n }\n }\n\n private attachMessageListener(): void {\n if (this.messageHandler) return;\n const handler = (event: MessageEvent): void => {\n // 1. Optional strict origin gate (for cross-origin-posting widgets).\n if (this.expectedOrigin && event.origin !== this.expectedOrigin) return;\n const data = event.data;\n // Auto-resize: the hosted form reports its content height so the\n // cross-origin iframe (which cannot self-size) grows/shrinks to fit.\n // Validate the widget source + integrity token, then size the iframe.\n if (isVaultResizeMessage(data)) {\n if (this.messageToken && data.messageToken !== this.messageToken) return;\n this.applyHeight(data.height);\n return;\n }\n // Inline field-validation surfaced from the hosted form (live). Forwarded\n // so the host can show it in the error box + onError. Empty `messages`\n // clears it.\n if (isVaultValidationMessage(data)) {\n if (this.messageToken && data.messageToken !== this.messageToken) return;\n const text = data.messages.filter((m) => typeof m === 'string' && m.trim()).join(' ');\n this.emit('validation', { sessionId: this.config.sessionId, message: text || undefined });\n return;\n }\n if (!isVaultResultMessage(data)) return;\n // 2. Integrity token: when the SDK was mounted with one, every outcome\n // must echo it. This is the only defence that survives same-window\n // forgery (the token is not present in the DOM/URL).\n if (this.messageToken && data.messageToken !== this.messageToken) return;\n const boundSession = this.config.sessionId;\n const incomingSession =\n typeof data.sessionId === 'string' ? data.sessionId : undefined;\n // 3. Reject any session-tagged outcome that targets a different session.\n if (boundSession && incomingSession && incomingSession !== boundSession) {\n return;\n }\n // 4. Money-affecting outcomes must be bound to the mounted session — a\n // forged `complete` / `decline` that omits the (server-issued) session\n // id cannot falsely drive merchant-side completion logic.\n if (\n (data.type === 'complete' || data.type === 'decline') &&\n boundSession &&\n incomingSession !== boundSession\n ) {\n return;\n }\n const outcome: CardCaptureOutcomeEvent = {\n sessionId: data.sessionId ?? this.config.sessionId,\n intentId: data.intentId,\n declineReason: data.declineReason,\n message: data.message,\n nextActionRedirectUrl: data.nextActionRedirectUrl,\n };\n if (data.type === 'submitting') {\n this.submissionStarted = true;\n this.submissionStartedAt = this.telemetryReporter?.now?.() ?? telemetryNow();\n }\n addBreadcrumb(vaultOutcomeBreadcrumb(data.type, this.submissionStarted));\n this.reportOutcome(data.type);\n // The widget's `ready` confirms its message listener is attached — (re)push\n // the theme + submit-gate so a form that mounted before the host posted\n // still gets them.\n if (data.type === 'ready') {\n this.postTheme();\n this.postSubmitGate();\n this.postCardFieldOrder();\n }\n // Provider needs the buyer to complete a verification challenge (3DS-2).\n // Render the challenge iframe at the PARENT page level — the widget can\n // only mount the challenge inside its own iframe, which gets visually\n // covered by the host's processing backdrop, so the adapter does the\n // rendering up here where it can sit above everything.\n if (data.type === 'action_required' && data.nextActionRedirectUrl) {\n this.showActionRequiredOverlay(data.nextActionRedirectUrl);\n }\n // Terminal outcomes always tear down the challenge overlay (success,\n // decline, or error). A `submitting` follow-up (e.g. the buyer retried\n // after a soft decline) also clears it.\n if (\n data.type === 'complete' ||\n data.type === 'decline' ||\n data.type === 'error' ||\n data.type === 'submitting'\n ) {\n this.hideActionRequiredOverlay();\n }\n this.emit(data.type, outcome);\n };\n this.messageHandler = handler;\n window.addEventListener('message', handler);\n }\n\n private reportOutcome(type: VaultCaptureResultMessage['type']): void {\n const reporter = this.telemetryReporter;\n if (!reporter) return;\n if (type === 'ready' && !this.vaultReadyReported) {\n this.vaultReadyReported = true;\n reporter.performance({\n stage: 'vault_ready',\n durationMs: Math.max(0, reporter.now() - this.captureRequestedAt),\n durationMode: 'machine',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n }\n if (type === 'complete' || type === 'decline') {\n reporter.log({\n name: 'vault.terminal',\n stage: 'completion',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n reporter.terminal({\n outcome: type === 'complete' ? 'payment_succeeded' : 'payment_declined',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n return;\n }\n if (type === 'error') {\n const classification = vaultErrorClassification(this.submissionStarted);\n reporter.log({\n name: 'vault.terminal',\n stage: classification.stage,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n reporter.error({\n ...classification,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n return;\n }\n if (type === 'action_required') {\n reporter.log({\n name: 'vault.action.required',\n stage: 'three_ds_handoff',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n reporter.log({\n name: 'vault.three_ds.handoff',\n stage: 'three_ds_handoff',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n const submissionStartedAt = this.submissionStartedAt;\n this.submissionStartedAt = null;\n if (submissionStartedAt !== null) {\n reporter.performance({\n stage: 'three_ds_handoff',\n durationMs: Math.max(0, reporter.now() - submissionStartedAt),\n durationMode: 'machine',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n }\n reporter.terminal({\n outcome: 'action_required',\n stage: 'three_ds_handoff',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n return;\n }\n const [name, stage] = VAULT_NON_TERMINAL_OUTCOME_LOGS[type];\n reporter.log({\n name,\n stage,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n }\n\n /**\n * Push merchant theme colors into the hosted widget (live). The host calls\n * this on a runtime theme switch; the widget applies them to its CSS variables\n * without a remount. Stores the latest theme so `ready` can re-push it.\n */\n applyTheme(theme: VaultCardThemeColors): void {\n this.theme = theme;\n this.postTheme();\n }\n\n /** postMessage the current theme to the widget's (cross-origin) document. */\n private postTheme(): void {\n if (!this.theme || !this.container) return;\n const iframe = this.container.querySelector('iframe');\n const target = iframe?.contentWindow;\n if (!target) return;\n try {\n target.postMessage({ source: 'flopay-vault-host', type: 'theme', theme: this.theme }, '*');\n } catch {\n // Best-effort — theming is cosmetic and must never break the form.\n }\n }\n\n /**\n * Gate the widget's submit from the host. When `blocked`, the widget cancels\n * its next submit and emits `'blocked'` instead of `'submitting'` so the host\n * can validate merchant-DOM fields (AVS) first. Stored so `ready` re-pushes it.\n */\n setSubmitGate(blocked: boolean): void {\n this.submitGateBlocked = blocked;\n this.postSubmitGate();\n }\n\n /** postMessage the current submit-gate state to the widget's document. */\n private postSubmitGate(): void {\n if (!this.container) return;\n const iframe = this.container.querySelector('iframe');\n const target = iframe?.contentWindow;\n if (!target) return;\n try {\n target.postMessage(\n { source: 'flopay-vault-host', type: 'gate', blocked: this.submitGateBlocked },\n '*',\n );\n } catch {\n // Best-effort — the host still validates and surfaces errors on its side.\n }\n }\n\n /**\n * Push the card-field order + autofocus directive into the widget (live). The\n * widget re-sequences its rows (DOM order, so tab order follows) and focuses\n * its first field unless `autoFocus` is false. Stored so `ready` re-pushes it.\n */\n setCardFieldOrder(order: VaultCardFieldKey[] | null, autoFocus: boolean): void {\n this.cardFieldOrder = order;\n this.cardAutoFocus = autoFocus;\n this.postCardFieldOrder();\n }\n\n /** postMessage the current field order + autofocus to the widget's document. */\n private postCardFieldOrder(): void {\n if (!this.container) return;\n const iframe = this.container.querySelector('iframe');\n const target = iframe?.contentWindow;\n if (!target) return;\n try {\n target.postMessage(\n {\n source: 'flopay-vault-host',\n type: 'fieldOrder',\n order: this.cardFieldOrder,\n autoFocus: this.cardAutoFocus,\n },\n '*',\n );\n } catch {\n // Best-effort — field order is cosmetic and must never break the form.\n }\n }\n\n private emit(event: CardCaptureEventType, payload: CardCaptureOutcomeEvent): void {\n for (const handler of this.listeners.get(event) ?? []) {\n handler(payload);\n }\n }\n\n /**\n * Render the provider-hosted verification challenge (e.g. Stripe 3DS-2) in a\n * full-page overlay at the PARENT page level. The widget's inline-iframe\n * approach is unusable because the SDK's processing backdrop sits above the\n * vault iframe, hiding any challenge mounted inside it — by lifting the\n * iframe to the host page the adapter can give it a z-index that wins.\n *\n * The overlay tears down on the next terminal outcome\n * (`complete`/`decline`/`error`) or when the buyer closes it via the backdrop\n * close button. Closing manually is a soft abandon — the next `/status` poll\n * either reveals a real outcome (the challenge completed via the issuer's\n * own redirect to `/vault/3ds/return`, which posts back into the widget) or\n * surfaces `requires_action` again so the host can decide what to do.\n */\n private showActionRequiredOverlay(challengeUrl: string): void {\n if (typeof document === 'undefined') return;\n // Idempotent: re-targeting an existing overlay just navigates the iframe.\n if (this.actionOverlay) {\n const existingIframe = this.actionOverlay.querySelector('iframe');\n if (existingIframe instanceof HTMLIFrameElement) {\n existingIframe.src = challengeUrl;\n }\n return;\n }\n\n const backdrop = document.createElement('div');\n backdrop.setAttribute('data-flopay-action-required', '1');\n backdrop.style.cssText = [\n 'position:fixed',\n 'inset:0',\n // Maximum signed 32-bit z-index; the SDK's own processing backdrop sits\n // well below this so the challenge is visible and interactive.\n 'z-index:2147483647',\n 'background:rgba(15,23,42,0.6)',\n 'display:flex',\n 'align-items:center',\n 'justify-content:center',\n 'padding:16px',\n ].join(';');\n\n const frame = document.createElement('iframe');\n frame.setAttribute('title', 'Card authentication');\n frame.setAttribute('allow', 'payment');\n frame.style.cssText = [\n 'width:min(100%,460px)',\n 'height:min(100%,640px)',\n 'border:0',\n 'border-radius:12px',\n 'background:#fff',\n 'box-shadow:0 12px 30px rgba(0,0,0,0.35)',\n ].join(';');\n frame.src = challengeUrl;\n backdrop.appendChild(frame);\n\n const closeButton = document.createElement('button');\n closeButton.type = 'button';\n closeButton.setAttribute('aria-label', 'Close card authentication');\n closeButton.textContent = '×';\n closeButton.style.cssText = [\n 'position:fixed',\n 'top:20px',\n 'right:20px',\n 'width:40px',\n 'height:40px',\n 'border:0',\n 'border-radius:9999px',\n 'background:#fff',\n 'color:#0f172a',\n 'font-size:28px',\n 'line-height:40px',\n 'cursor:pointer',\n 'box-shadow:0 4px 14px rgba(0,0,0,0.25)',\n ].join(';');\n closeButton.addEventListener('click', () => this.abandonActionRequiredOverlay());\n backdrop.appendChild(closeButton);\n backdrop.addEventListener('click', (event) => {\n if (event.target === backdrop) this.abandonActionRequiredOverlay();\n });\n\n // Listen for the `/vault/3ds/return` postMessage. The return page is\n // loaded inside THIS overlay iframe (not the widget's), so its\n // `window.parent` is the host page, not the widget — the widget's own\n // listener won't catch it. Forward completion into the widget so the\n // widget kicks `/3ds/complete` immediately.\n const returnHandler = (event: MessageEvent): void => {\n // Only the challenge iframe we just mounted may dismiss this overlay. The\n // `/vault/3ds/return` page loads inside `frame`, so its postMessage\n // arrives with `event.source === frame.contentWindow`. Gating on the\n // frame's window stops an unrelated frame on the host page from forging\n // the marker string to trigger a premature dismissal. (Origin can't be\n // matched against `challengeUrl` here — the return page is served by the\n // billing API, a different origin from the provider's challenge.)\n if (event.source !== frame.contentWindow) return;\n const data = event.data;\n if (!data || typeof data !== 'object') return;\n const record = data as Record<string, unknown>;\n if (record['source'] !== 'flopay-vault-3ds-return') return;\n addBreadcrumb(vaultLog('vault.three_ds.returned', 'three_ds_return'));\n this.telemetryReporter?.log({\n name: 'vault.three_ds.returned',\n stage: 'three_ds_return',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n this.hideActionRequiredOverlay();\n this.postActionCompleted(record['status']);\n };\n window.addEventListener('message', returnHandler);\n this.threeDsReturnHandler = returnHandler;\n\n document.body.appendChild(backdrop);\n this.actionOverlay = backdrop;\n addBreadcrumb(vaultLog('vault.three_ds.handoff', 'three_ds_handoff'));\n }\n\n /**\n * Tell the vault widget that the buyer has completed (or abandoned) the\n * challenge. The widget responds by POSTing `/3ds/complete` — its\n * sub-300ms sync resolver writes the follow-up attempt row immediately,\n * so the next `/status` poll resolves to a terminal outcome instead of\n * waiting for the eventual provider webhook.\n */\n private postActionCompleted(status: unknown): void {\n if (!this.container) return;\n const iframe = this.container.querySelector('iframe');\n const target = iframe?.contentWindow;\n if (!target) return;\n try {\n target.postMessage(\n {\n source: 'flopay-vault-host',\n type: 'action_completed',\n status: typeof status === 'string' ? status : 'unknown',\n },\n '*',\n );\n } catch {\n // Best-effort — even if the postMessage fails the widget's poll loop\n // will eventually catch the terminal state from the provider webhook.\n }\n }\n\n private abandonActionRequiredOverlay(): void {\n if (!this.actionOverlay) return;\n const breadcrumb = buildTelemetryTerminalEvent({\n eventId: '77777777-7777-4777-8777-777777777777',\n outcome: 'customer_abandoned',\n stage: 'three_ds_handoff',\n sequence: 0,\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n addBreadcrumb(breadcrumb);\n this.telemetryReporter?.terminal({\n outcome: 'customer_abandoned',\n stage: 'three_ds_handoff',\n provider: 'pcivault',\n paymentMethodCategory: 'card',\n });\n this.hideActionRequiredOverlay();\n this.postActionCompleted('abandoned');\n }\n\n private hideActionRequiredOverlay(): void {\n if (this.threeDsReturnHandler) {\n window.removeEventListener('message', this.threeDsReturnHandler);\n this.threeDsReturnHandler = null;\n }\n if (!this.actionOverlay) return;\n this.actionOverlay.parentNode?.removeChild(this.actionOverlay);\n this.actionOverlay = null;\n }\n\n /**\n * Size the hosted-widget iframe to the height reported by the form inside it.\n * Cross-origin iframes don't auto-size to their content, so the widget posts\n * its measured height and we apply it here (clamped to a sane range). This is\n * what lets the card form shrink/grow to fit instead of sitting at a fixed\n * height.\n */\n private applyHeight(height: number): void {\n const iframe = this.container?.querySelector('iframe');\n if (!iframe) return;\n const clamped = Math.max(0, Math.min(Math.ceil(height), 2000));\n iframe.style.height = `${clamped}px`;\n }\n}\n\n/** Build the adapter with the existing SDK reporter without publishing injection. */\nexport function createInstrumentedPciVaultCardCapture(\n config: PciVaultCardCaptureConfig,\n reporter: TelemetryReporter,\n requestedAt?: number,\n): PciVaultCardCapture {\n const InstrumentedCapture = PciVaultCardCapture as unknown as new (\n options: PciVaultCardCaptureConfig,\n telemetry: InternalPciVaultTelemetry,\n ) => PciVaultCardCapture;\n return new InstrumentedCapture(config, { reporter, requestedAt });\n}\n","import type {\n TelemetryCheckoutContext,\n TelemetryReporter,\n TelemetryReporterErrorInput,\n TelemetryReporterLogInput,\n TelemetryReporterPerformanceInput,\n TelemetryReporterTerminalInput,\n} from './telemetry-reporter.js';\n\nconst FLOPAY_TELEMETRY_BRIDGE = Symbol.for('@flopay/js.telemetry.bridge.v1');\n\nexport interface FloPayTelemetryBridge {\n error(input: TelemetryReporterErrorInput): void;\n log(input: TelemetryReporterLogInput): void;\n performance(input: TelemetryReporterPerformanceInput): void;\n terminal(input: TelemetryReporterTerminalInput): void;\n now(): number;\n elapsed(startedAt: number): number;\n setCheckoutContext(context: TelemetryCheckoutContext): void;\n beginCheckout(context?: TelemetryCheckoutContext): number;\n disable(): void;\n}\n\n/** Attach the non-enumerable bridge consumed by @flopay/react. */\nexport function attachFloPayTelemetryBridge(\n target: object,\n reporter: TelemetryReporter | undefined,\n fallbackNow: () => number,\n): void {\n const now = (): number => reporter?.now() ?? fallbackNow();\n const bridge: FloPayTelemetryBridge = {\n error: (input) => reporter?.error(input),\n log: (input) => reporter?.log(input),\n performance: (input) => reporter?.performance(input),\n terminal: (input) => reporter?.terminal(input),\n now,\n elapsed: (startedAt) => Math.max(0, now() - startedAt),\n setCheckoutContext: (context) => reporter?.setCheckoutContext(context),\n beginCheckout: (context = {}) => reporter?.beginCheckout(context) ?? now(),\n disable: () => reporter?.disable(),\n };\n Object.defineProperty(target, FLOPAY_TELEMETRY_BRIDGE, {\n configurable: false,\n enumerable: false,\n writable: false,\n value: bridge,\n });\n}\n\n/** Read the bridge inside @flopay/js without making it a package export. */\nexport function getFloPayTelemetryBridge(target: object): FloPayTelemetryBridge | undefined {\n return (\n (target as Record<PropertyKey, unknown>)[FLOPAY_TELEMETRY_BRIDGE]\n ) as FloPayTelemetryBridge | undefined;\n}\n","import type {\n CreateSessionParams,\n CheckoutSessionResult,\n} from '@flopay/shared';\nimport {\n FloPayError,\n IDEMPOTENCY_IN_PROGRESS_CODE,\n IDEMPOTENCY_KEY_HEADER,\n SDK_VERSION,\n buildProductPayload,\n foldIntoProducts,\n resolveIdempotencyKey,\n resolveSessionCurrency,\n} from '@flopay/shared';\nimport { readErrorString } from './api-error.js';\nimport { cacheSessionDisplayData } from './session-display-cache.js';\nimport { TelemetryReporter } from './telemetry-reporter.js';\n\n/**\n * Max number of coupon codes the billing API accepts per session create.\n * Mirrors the backend guard introduced in billing v1.1.2 — exceeding this\n * returns the `CouponLimitExceeded` error.\n */\nconst MAX_COUPON_CODES = 5;\n\ninterface ApiErrorBody {\n code?: unknown;\n message?: unknown;\n error?: { code?: unknown; message?: unknown };\n}\n\n/**\n * Map a billing API error body to a `FloPayError`. Surfaces the coupon\n * validation codes introduced in billing v1.1.2 (`CouponLimitExceeded`,\n * `CouponCurrencyUnsupported`) as structured errors so callers can branch\n * on `error.code` instead of parsing the HTTP status.\n */\nfunction buildCheckoutSessionError(status: number, payload: ApiErrorBody | undefined): FloPayError {\n const nested = payload?.error;\n const code =\n readErrorString(payload?.code)\n ?? readErrorString(nested?.code)\n ?? `http_${status}`;\n const message =\n readErrorString(payload?.message)\n ?? readErrorString(nested?.message)\n ?? defaultMessageForCode(code, status);\n\n return new FloPayError(message, 'api_error', { code, statusCode: status });\n}\n\nfunction defaultMessageForCode(code: string, status: number): string {\n switch (code) {\n case 'CouponLimitExceeded':\n return `Too many coupon codes — a checkout session accepts at most ${MAX_COUPON_CODES}.`;\n case 'CouponCurrencyUnsupported':\n return 'One of the applied coupons has no price configured for the cart currency.';\n default:\n return `Failed to create checkout session (HTTP ${status}).`;\n }\n}\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 * currency: 'USD',\n * items: [{\n * code: 'initial_charge',\n * quantity: 1,\n * metadata: { source: 'web' },\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 */\nasync function createCheckoutSessionCore(\n options: CreateSessionParams,\n onFirstByte?: (status: number) => void,\n): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n products,\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n setCookie = true,\n timeoutMs = 12000,\n clientId,\n currency,\n utmMetadata,\n idempotencyKey,\n } = options;\n\n // Resolve the stable idempotency key up front — before any HTTP work — so an\n // invalid merchant-supplied key surfaces without issuing a request. A\n // generated key is high-entropy and per-call, so two independent creates with\n // identical bodies remain distinct logical operations (TeamFloPay/backend#972).\n const resolvedIdempotencyKey = resolveIdempotencyKey(idempotencyKey);\n\n if (couponCodes.length > MAX_COUPON_CODES) {\n throw new FloPayError(\n `Too many coupon codes — a checkout session accepts at most ${MAX_COUPON_CODES}.`,\n 'validation_error',\n { code: 'CouponLimitExceeded', param: 'couponCodes' },\n );\n }\n\n const wireProducts = products ?? foldIntoProducts(items, subscriptions);\n const sessionCurrency = resolveSessionCurrency(currency, items, subscriptions, wireProducts);\n if (!sessionCurrency) {\n throw new FloPayError(\n 'currency is required: pass `currency` on the session, or include a `currency` on the first item/subscription/product.',\n 'validation_error',\n { code: 'CurrencyRequired', param: 'currency' },\n );\n }\n\n const payload: Record<string, unknown> = {\n clientId,\n checkoutVersion: SDK_VERSION,\n successUrl,\n cancelUrl,\n currency: sessionCurrency,\n checkoutMode,\n products: wireProducts.map((product) => buildProductPayload(product, sessionCurrency)),\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 addressLine1: account.addressLine1 ?? null,\n addressLine2: account.addressLine2 ?? 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 const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (resolvedIdempotencyKey) {\n headers[IDEMPOTENCY_KEY_HEADER] = resolvedIdempotencyKey;\n }\n\n let status: number;\n let body: ({ data?: { uuid?: string; nonce?: string } } & ApiErrorBody) | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n try {\n onFirstByte?.(response.status);\n } catch {\n // Telemetry observation must never alter session creation.\n }\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string; nonce?: string } } & ApiErrorBody;\n } catch {\n // 204 or empty body — leave undefined\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status >= 400) {\n throw buildCheckoutSessionError(status, body);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n const nonce = body?.data?.nonce;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n if (!nonce) {\n throw new FloPayError(\n 'Checkout session created but no `nonce` was returned by the billing API. Upgrade the billing service to TeamFloPay/backend#640 or later.',\n 'api_error',\n { code: 'MissingCheckoutSessionToken' },\n );\n }\n\n // Auto-stash display-only fields the consumer passed in so the checkout\n // page (post-redirect) renders the right totals/names even though the\n // backend no longer persists them. Runs before the redirect — values\n // survive the navigation via sessionStorage.\n if (wireProducts.length || sessionCurrency) {\n cacheSessionDisplayData(uuid, {\n currency: sessionCurrency,\n products: wireProducts.map((p) => ({\n code: p.code ?? p.providerItemId ?? p.providerPlanId,\n type: p.type,\n name: p.name ?? p.itemName ?? p.providerItemName ?? p.subscriptionName ?? p.providerPlanName ?? null,\n totalAmount: p.totalAmount,\n overrideAmount: p.overrideAmount,\n currency: p.currency ?? sessionCurrency,\n })),\n });\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 // Carry the session-bound checkout token to the hosted checkout page so\n // it can echo `x-checkout-session-token` on every continuation call\n // (post-#640 backends require this header to match the session nonce).\n // The URL is deliberately not modified — keeping the nonce out of the\n // location bar avoids history / Referer leakage.\n document.cookie = `flopay_checkout_token=${encodeURIComponent(nonce)}; 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(), nonce };\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\nexport async function createCheckoutSession(\n options: CreateSessionParams,\n): Promise<CheckoutSessionResult> {\n const telemetry = beginCreateSessionTelemetry(options);\n const recordFirstByte = createFirstByteRecorder(telemetry);\n try {\n const result = await createCheckoutSessionCore(options, recordFirstByte);\n completeCreateSessionTelemetry(telemetry, result);\n return result;\n } catch (error) {\n failCreateSessionTelemetry(telemetry.reporter, error);\n throw error;\n } finally {\n finishCreateSessionTelemetry(telemetry.reporter);\n }\n}\n\nfunction createFirstByteRecorder(\n telemetry: { reporter: TelemetryReporter; startedAt: number },\n): (status: number) => void {\n let recorded = false;\n return (status: number): void => {\n if (recorded) return;\n recorded = true;\n const statusClass = `${Math.floor(status / 100)}xx` as '2xx' | '3xx' | '4xx' | '5xx';\n telemetry.reporter.log({\n name: 'session.request.first_byte',\n stage: 'session_first_byte',\n requestCategory: 'session_create',\n statusClass,\n });\n telemetry.reporter.performance({\n stage: 'session_first_byte',\n durationMs: telemetry.reporter.now() - telemetry.startedAt,\n durationMode: 'machine',\n requestCategory: 'session_create',\n statusClass,\n });\n };\n}\n\nfunction beginCreateSessionTelemetry(options: CreateSessionParams): {\n reporter: TelemetryReporter;\n startedAt: number;\n} {\n const reporter = new TelemetryReporter({\n billingApiUrl: options.billingApiUrl,\n sdkVersion: SDK_VERSION,\n enabled: options.telemetry !== false,\n });\n const startedAt = reporter.now();\n reporter.log({\n name: 'session.create.started',\n stage: 'session_create',\n requestCategory: 'session_create',\n });\n return { reporter, startedAt };\n}\n\nfunction completeCreateSessionTelemetry(\n telemetry: { reporter: TelemetryReporter; startedAt: number },\n result: CheckoutSessionResult,\n): void {\n const statusClass = `${Math.floor(result.status / 100)}xx` as '2xx' | '3xx';\n telemetry.reporter.log({\n name: 'session.request.completed',\n stage: 'session_complete',\n requestCategory: 'session_create',\n statusClass,\n });\n telemetry.reporter.performance({\n stage: 'session_complete',\n durationMs: telemetry.reporter.now() - telemetry.startedAt,\n durationMode: 'machine',\n requestCategory: 'session_create',\n statusClass,\n });\n}\n\nfunction failCreateSessionTelemetry(reporter: TelemetryReporter, error: unknown): void {\n if (error instanceof FloPayError && error.type === 'validation_error') {\n reporter.terminal({\n outcome: 'validation_rejected',\n stage: 'session_create',\n requestCategory: 'session_create',\n });\n return;\n }\n const statusCode = error instanceof FloPayError ? error.statusCode : undefined;\n reporter.error({\n errorCode: error instanceof Error && error.name === 'AbortError'\n ? 'REQUEST_TIMEOUT'\n : error instanceof TypeError\n ? 'NETWORK_REQUEST_FAILED'\n : 'CHECKOUT_SESSION_CREATE_FAILED',\n stage: 'session_create',\n requestCategory: 'session_create',\n statusClass: error instanceof Error && error.name === 'AbortError'\n ? 'timeout'\n : statusCode\n ? `${Math.floor(statusCode / 100)}xx` as '4xx' | '5xx'\n : 'network_error',\n });\n}\n\nfunction finishCreateSessionTelemetry(reporter: TelemetryReporter): void {\n void reporter.flush()\n .catch(() => {})\n .finally(() => reporter.destroy());\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 *\n * The idempotency key (supplied or generated) is resolved **once**, before the\n * retry loop, and reused for every attempt — so a timeout, a lost response, or\n * a documented in-progress reply all replay the *same* key and cannot mint a\n * second checkout session (TeamFloPay/backend#972). A later independent call\n * resolves its own fresh key. A payload-conflict (`409`) is surfaced without\n * retrying, since only the exact same request may safely replay a key.\n */\nexport async function createCheckoutSessionWithRetries(\n options: CreateSessionParams & { maxRetries?: number },\n): Promise<CheckoutSessionResult> {\n const { maxRetries = 3, ...sessionOptions } = options;\n const telemetry = beginCreateSessionTelemetry(options);\n const recordFirstByte = createFirstByteRecorder(telemetry);\n\n if (!Number.isFinite(maxRetries) || !Number.isInteger(maxRetries) || maxRetries <= 0) {\n telemetry.reporter.terminal({\n outcome: 'validation_rejected',\n stage: 'session_create',\n requestCategory: 'session_create',\n });\n finishCreateSessionTelemetry(telemetry.reporter);\n throw new Error('Number of retries must be greater than 0');\n }\n\n // Resolve the key up front so every attempt below reuses this exact value\n // instead of `createCheckoutSession` generating a new one per attempt.\n const attemptOptions: CreateSessionParams = {\n ...sessionOptions,\n idempotencyKey: resolveIdempotencyKey(sessionOptions.idempotencyKey),\n };\n\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const result = await createCheckoutSessionCore(attemptOptions, recordFirstByte);\n completeCreateSessionTelemetry(telemetry, result);\n finishCreateSessionTelemetry(telemetry.reporter);\n return result;\n } catch (err) {\n lastErr = err;\n\n const isTransportAbort = err instanceof Error && err.name === 'AbortError';\n const isInProgressReplay =\n err instanceof FloPayError && err.code === IDEMPOTENCY_IN_PROGRESS_CODE;\n\n if ((isTransportAbort || isInProgressReplay) && attempt < maxRetries) {\n telemetry.reporter.log({\n name: 'operation.retry',\n stage: 'session_create',\n requestCategory: 'session_create',\n attempt: attempt + 1,\n });\n await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));\n continue;\n }\n\n failCreateSessionTelemetry(telemetry.reporter, err);\n finishCreateSessionTelemetry(telemetry.reporter);\n throw err;\n }\n }\n\n failCreateSessionTelemetry(telemetry.reporter, lastErr);\n finishCreateSessionTelemetry(telemetry.reporter);\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","error","import_shared","import_shared","import_shared","import_shared"]}