@flopay/js 1.11.5 → 1.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,6 +1,7 @@
1
- import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance } from '@flopay/shared';
2
- export { SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
3
- export { C as CardCaptureOperation, P as PaymentAPI, a as PciVaultCardCapture, b as PciVaultCardCaptureConfig, S as SESSION_CREATE_TELEMETRY, c as SessionDisplayCacheData, d as SessionDisplayProduct, e as cacheSessionDisplayData, f as clearSessionDisplayData, g as getSessionDisplayData } from './card-setup-Cn9t5eLo.cjs';
1
+ import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession, FloPayError } from '@flopay/shared';
2
+ export { SentryEventLike, SentryStackFrameLike, StripeSafeAppearance, dropThirdPartyOnlyError, toStripeAppearance, toStripeAppearanceTheme } from '@flopay/shared';
3
+ import { P as PaymentAPI } from './pci-vault-card-capture-Dt3F9i7Q.cjs';
4
+ export { C as CardCaptureOperation, a as PciVaultCardCapture, b as PciVaultCardCaptureConfig, S as SESSION_CREATE_TELEMETRY, c as SessionDisplayCacheData, d as SessionDisplayProduct, e as cacheSessionDisplayData, f as clearSessionDisplayData, g as getSessionDisplayData } from './pci-vault-card-capture-Dt3F9i7Q.cjs';
4
5
 
5
6
  declare function createCheckoutSession(options: CreateSessionParams): Promise<CheckoutSessionResult>;
6
7
  /**
@@ -101,20 +102,124 @@ declare class FloPay {
101
102
  declare function loadFloPay(publishableKey: string, options?: Omit<FloPayConfig, 'publishableKey'>): Promise<FloPay>;
102
103
 
103
104
  /**
104
- * A `FloPayAppearance` whose `theme` has been normalized to the set Stripe's
105
- * Appearance API accepts, so it can be handed straight to
106
- * `@stripe/react-stripe-js`'s `<Elements options={{ appearance }}>` without
107
- * tripping Stripe.js's `Invalid value … provided to "theme"` warning.
105
+ * Outcome the backend's `/3ds/complete` sync resolver returns to the SDK.
106
+ * Mirrors `ThreeDsResolveOutcome` on the backend without importing it. The
107
+ * caller branches on `status`:
108
+ * - `succeeded` → show success
109
+ * - `authorized` → a captured-later authorization (manual capture); as
110
+ * terminal as `succeeded`
111
+ * - `declined` → a decline (the session stays `pending`, so polling
112
+ * session-status would just time out)
113
+ * - `timeout` → the documented 3DS timeout
114
+ * - `pending` / `requires_action` / `no_attempt` → fall back to the
115
+ * session-status poll
108
116
  */
109
- interface StripeSafeAppearance {
110
- theme: 'stripe' | 'night' | 'flat';
111
- variables?: FloPayThemeVariables;
112
- rules?: Record<string, Record<string, string>>;
117
+ type SavedCardChallengeOutcome = {
118
+ status: 'succeeded';
119
+ providerIntentId?: string | null;
120
+ } | {
121
+ status: 'authorized';
122
+ providerIntentId?: string | null;
123
+ } | {
124
+ status: 'declined';
125
+ providerIntentId?: string | null;
126
+ declineReason?: string | null;
127
+ gatewayDeclineReason?: string | null;
128
+ } | {
129
+ status: 'requires_action';
130
+ providerIntentId?: string | null;
131
+ nextActionRedirectUrl?: string | null;
132
+ } | {
133
+ status: 'pending';
134
+ providerIntentId?: string | null;
135
+ } | {
136
+ status: 'timeout';
137
+ providerIntentId?: string | null;
138
+ } | {
139
+ status: 'no_attempt';
140
+ } | {
141
+ status: 'unknown';
142
+ };
143
+ /** A `declined` outcome from `/3ds/complete`. */
144
+ type SavedCardChallengeDecline = Extract<SavedCardChallengeOutcome, {
145
+ status: 'declined';
146
+ }>;
147
+ /** Input for {@link runSavedCardChallenge}. */
148
+ interface SavedCardChallengeInput {
149
+ billingApiUrl: string;
150
+ sessionId: string;
151
+ /** Session-bound checkout token, sent as `x-checkout-session-token`. */
152
+ nonce: string;
153
+ /** The provider-hosted challenge the backend advertised for the attempt. */
154
+ nextActionRedirectUrl: string;
155
+ /**
156
+ * Legacy flows poll `/3ds/complete` while the challenge is open; provider-neutral
157
+ * saved cards complete once, only after the authenticated return. Defaults to polling.
158
+ */
159
+ pollCompletionEndpoint?: boolean;
160
+ /**
161
+ * Optional cancellation hook. SPA callers pass a signal tied to component
162
+ * unmount / route change so an abandoned challenge tears down its overlay
163
+ * (and rejects the promise) immediately.
164
+ */
165
+ signal?: AbortSignal;
113
166
  }
114
- /** Maps FloPay's public appearance token to Stripe's accepted theme set. */
115
- declare function toStripeAppearanceTheme(theme: 'default' | 'flat' | 'night' | 'none' | undefined): 'stripe' | 'night' | 'flat';
116
- /** Normalizes a FloPay appearance before React passes it to Stripe Elements. */
117
- declare function toStripeAppearance(appearance: FloPayAppearance): StripeSafeAppearance;
167
+ /** Input for {@link completeSavedCardNextAction}. */
168
+ interface SavedCardNextActionInput {
169
+ billingApiUrl: string;
170
+ sessionId: string;
171
+ /** Session-bound checkout token, sent as `x-checkout-session-token`. */
172
+ nonce: string;
173
+ /** The provider-hosted challenge the backend advertised for the attempt. */
174
+ nextActionRedirectUrl: string;
175
+ /** Cancels the challenge (component unmount, route change). */
176
+ signal?: AbortSignal;
177
+ /**
178
+ * Builds the error thrown for a `/3ds/complete` decline, so each framework
179
+ * keeps its own decline mapping. Defaults to a `FloPayError` whose `code` is
180
+ * the decline reason.
181
+ */
182
+ createDeclineError?: (decline: SavedCardChallengeDecline) => Error;
183
+ }
184
+ /** The buyer cancelled (or the owning UI unmounted) during a saved-card challenge. */
185
+ declare function createSavedCardActionAbortedError(cause?: unknown): FloPayError;
186
+ /**
187
+ * Render a provider-hosted 3DS challenge in a full-page overlay iframe and
188
+ * resolve once the buyer completes (or abandons) it. This is the one saved-card
189
+ * challenge runner: `@flopay/react` and `@flopay/vue` both use it.
190
+ *
191
+ * The provider's challenge eventually redirects to `/v1/vault/3ds/return`,
192
+ * which postMessages `flopay-vault-3ds-return` back to the parent (this
193
+ * window). The promise resolves on receipt of that message — but only when it
194
+ * arrives from the challenge iframe (`event.source`) and the billing API
195
+ * origin, so a sibling frame on the merchant page can't dismiss the challenge
196
+ * early by forging the marker string. We then call `/3ds/complete` to drive the
197
+ * backend's sync resolver to write the terminal attempt row.
198
+ *
199
+ * The overlay carries `role="dialog"`/`aria-modal` and moves focus into the
200
+ * iframe on mount, restoring the prior focus target on teardown, so keyboard /
201
+ * screen-reader buyers aren't stranded on the obscured page.
202
+ *
203
+ * Times out after the 3DS challenge window with `three_ds_timeout`; an aborted
204
+ * `signal` rejects with `three_ds_aborted`.
205
+ */
206
+ declare function runSavedCardChallenge(input: SavedCardChallengeInput): Promise<SavedCardChallengeOutcome>;
207
+ /**
208
+ * Complete a backend-owned saved-card challenge (`ACTION_REQUIRED` with a
209
+ * `nextActionRedirectUrl`) with no browser payment provider: show the
210
+ * challenge, post `/3ds/complete` once after the authenticated return, then
211
+ * reconcile the session through the authenticated `/status` endpoint.
212
+ *
213
+ * The status poll also races the challenge, because a provider sandbox can
214
+ * swallow the return-page message while the signed return endpoint still
215
+ * resolves the attempt server-side.
216
+ *
217
+ * Resolves with the reconciled session. Rejects with a decline (built by
218
+ * `createDeclineError`), `three_ds_timeout`, the status poll's own timeout, or
219
+ * `three_ds_aborted`.
220
+ */
221
+ declare function completeSavedCardNextAction(input: SavedCardNextActionInput, api: Pick<PaymentAPI, 'waitForCheckoutSessionCompletion'>): Promise<NormalizedCheckoutSession>;
222
+
118
223
  /** Payment provider adapter backed by Stripe. */
119
224
  declare class StripeAdapter implements PaymentProviderAdapter {
120
225
  readonly name = "stripe";
@@ -124,4 +229,4 @@ declare class StripeAdapter implements PaymentProviderAdapter {
124
229
  destroy(): void;
125
230
  }
126
231
 
127
- export { FloPay, StripeAdapter, type StripeSafeAppearance, createCheckoutSession, createCheckoutSessionWithRetries, loadFloPay, toStripeAppearance, toStripeAppearanceTheme };
232
+ export { FloPay, PaymentAPI, type SavedCardChallengeDecline, type SavedCardChallengeInput, type SavedCardChallengeOutcome, type SavedCardNextActionInput, StripeAdapter, completeSavedCardNextAction, createCheckoutSession, createCheckoutSessionWithRetries, createSavedCardActionAbortedError, loadFloPay, runSavedCardChallenge };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance } from '@flopay/shared';
2
- export { SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
3
- export { C as CardCaptureOperation, P as PaymentAPI, a as PciVaultCardCapture, b as PciVaultCardCaptureConfig, S as SESSION_CREATE_TELEMETRY, c as SessionDisplayCacheData, d as SessionDisplayProduct, e as cacheSessionDisplayData, f as clearSessionDisplayData, g as getSessionDisplayData } from './card-setup-Cn9t5eLo.js';
1
+ import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession, FloPayError } from '@flopay/shared';
2
+ export { SentryEventLike, SentryStackFrameLike, StripeSafeAppearance, dropThirdPartyOnlyError, toStripeAppearance, toStripeAppearanceTheme } from '@flopay/shared';
3
+ import { P as PaymentAPI } from './pci-vault-card-capture-Dt3F9i7Q.js';
4
+ export { C as CardCaptureOperation, a as PciVaultCardCapture, b as PciVaultCardCaptureConfig, S as SESSION_CREATE_TELEMETRY, c as SessionDisplayCacheData, d as SessionDisplayProduct, e as cacheSessionDisplayData, f as clearSessionDisplayData, g as getSessionDisplayData } from './pci-vault-card-capture-Dt3F9i7Q.js';
4
5
 
5
6
  declare function createCheckoutSession(options: CreateSessionParams): Promise<CheckoutSessionResult>;
6
7
  /**
@@ -101,20 +102,124 @@ declare class FloPay {
101
102
  declare function loadFloPay(publishableKey: string, options?: Omit<FloPayConfig, 'publishableKey'>): Promise<FloPay>;
102
103
 
103
104
  /**
104
- * A `FloPayAppearance` whose `theme` has been normalized to the set Stripe's
105
- * Appearance API accepts, so it can be handed straight to
106
- * `@stripe/react-stripe-js`'s `<Elements options={{ appearance }}>` without
107
- * tripping Stripe.js's `Invalid value … provided to "theme"` warning.
105
+ * Outcome the backend's `/3ds/complete` sync resolver returns to the SDK.
106
+ * Mirrors `ThreeDsResolveOutcome` on the backend without importing it. The
107
+ * caller branches on `status`:
108
+ * - `succeeded` → show success
109
+ * - `authorized` → a captured-later authorization (manual capture); as
110
+ * terminal as `succeeded`
111
+ * - `declined` → a decline (the session stays `pending`, so polling
112
+ * session-status would just time out)
113
+ * - `timeout` → the documented 3DS timeout
114
+ * - `pending` / `requires_action` / `no_attempt` → fall back to the
115
+ * session-status poll
108
116
  */
109
- interface StripeSafeAppearance {
110
- theme: 'stripe' | 'night' | 'flat';
111
- variables?: FloPayThemeVariables;
112
- rules?: Record<string, Record<string, string>>;
117
+ type SavedCardChallengeOutcome = {
118
+ status: 'succeeded';
119
+ providerIntentId?: string | null;
120
+ } | {
121
+ status: 'authorized';
122
+ providerIntentId?: string | null;
123
+ } | {
124
+ status: 'declined';
125
+ providerIntentId?: string | null;
126
+ declineReason?: string | null;
127
+ gatewayDeclineReason?: string | null;
128
+ } | {
129
+ status: 'requires_action';
130
+ providerIntentId?: string | null;
131
+ nextActionRedirectUrl?: string | null;
132
+ } | {
133
+ status: 'pending';
134
+ providerIntentId?: string | null;
135
+ } | {
136
+ status: 'timeout';
137
+ providerIntentId?: string | null;
138
+ } | {
139
+ status: 'no_attempt';
140
+ } | {
141
+ status: 'unknown';
142
+ };
143
+ /** A `declined` outcome from `/3ds/complete`. */
144
+ type SavedCardChallengeDecline = Extract<SavedCardChallengeOutcome, {
145
+ status: 'declined';
146
+ }>;
147
+ /** Input for {@link runSavedCardChallenge}. */
148
+ interface SavedCardChallengeInput {
149
+ billingApiUrl: string;
150
+ sessionId: string;
151
+ /** Session-bound checkout token, sent as `x-checkout-session-token`. */
152
+ nonce: string;
153
+ /** The provider-hosted challenge the backend advertised for the attempt. */
154
+ nextActionRedirectUrl: string;
155
+ /**
156
+ * Legacy flows poll `/3ds/complete` while the challenge is open; provider-neutral
157
+ * saved cards complete once, only after the authenticated return. Defaults to polling.
158
+ */
159
+ pollCompletionEndpoint?: boolean;
160
+ /**
161
+ * Optional cancellation hook. SPA callers pass a signal tied to component
162
+ * unmount / route change so an abandoned challenge tears down its overlay
163
+ * (and rejects the promise) immediately.
164
+ */
165
+ signal?: AbortSignal;
113
166
  }
114
- /** Maps FloPay's public appearance token to Stripe's accepted theme set. */
115
- declare function toStripeAppearanceTheme(theme: 'default' | 'flat' | 'night' | 'none' | undefined): 'stripe' | 'night' | 'flat';
116
- /** Normalizes a FloPay appearance before React passes it to Stripe Elements. */
117
- declare function toStripeAppearance(appearance: FloPayAppearance): StripeSafeAppearance;
167
+ /** Input for {@link completeSavedCardNextAction}. */
168
+ interface SavedCardNextActionInput {
169
+ billingApiUrl: string;
170
+ sessionId: string;
171
+ /** Session-bound checkout token, sent as `x-checkout-session-token`. */
172
+ nonce: string;
173
+ /** The provider-hosted challenge the backend advertised for the attempt. */
174
+ nextActionRedirectUrl: string;
175
+ /** Cancels the challenge (component unmount, route change). */
176
+ signal?: AbortSignal;
177
+ /**
178
+ * Builds the error thrown for a `/3ds/complete` decline, so each framework
179
+ * keeps its own decline mapping. Defaults to a `FloPayError` whose `code` is
180
+ * the decline reason.
181
+ */
182
+ createDeclineError?: (decline: SavedCardChallengeDecline) => Error;
183
+ }
184
+ /** The buyer cancelled (or the owning UI unmounted) during a saved-card challenge. */
185
+ declare function createSavedCardActionAbortedError(cause?: unknown): FloPayError;
186
+ /**
187
+ * Render a provider-hosted 3DS challenge in a full-page overlay iframe and
188
+ * resolve once the buyer completes (or abandons) it. This is the one saved-card
189
+ * challenge runner: `@flopay/react` and `@flopay/vue` both use it.
190
+ *
191
+ * The provider's challenge eventually redirects to `/v1/vault/3ds/return`,
192
+ * which postMessages `flopay-vault-3ds-return` back to the parent (this
193
+ * window). The promise resolves on receipt of that message — but only when it
194
+ * arrives from the challenge iframe (`event.source`) and the billing API
195
+ * origin, so a sibling frame on the merchant page can't dismiss the challenge
196
+ * early by forging the marker string. We then call `/3ds/complete` to drive the
197
+ * backend's sync resolver to write the terminal attempt row.
198
+ *
199
+ * The overlay carries `role="dialog"`/`aria-modal` and moves focus into the
200
+ * iframe on mount, restoring the prior focus target on teardown, so keyboard /
201
+ * screen-reader buyers aren't stranded on the obscured page.
202
+ *
203
+ * Times out after the 3DS challenge window with `three_ds_timeout`; an aborted
204
+ * `signal` rejects with `three_ds_aborted`.
205
+ */
206
+ declare function runSavedCardChallenge(input: SavedCardChallengeInput): Promise<SavedCardChallengeOutcome>;
207
+ /**
208
+ * Complete a backend-owned saved-card challenge (`ACTION_REQUIRED` with a
209
+ * `nextActionRedirectUrl`) with no browser payment provider: show the
210
+ * challenge, post `/3ds/complete` once after the authenticated return, then
211
+ * reconcile the session through the authenticated `/status` endpoint.
212
+ *
213
+ * The status poll also races the challenge, because a provider sandbox can
214
+ * swallow the return-page message while the signed return endpoint still
215
+ * resolves the attempt server-side.
216
+ *
217
+ * Resolves with the reconciled session. Rejects with a decline (built by
218
+ * `createDeclineError`), `three_ds_timeout`, the status poll's own timeout, or
219
+ * `three_ds_aborted`.
220
+ */
221
+ declare function completeSavedCardNextAction(input: SavedCardNextActionInput, api: Pick<PaymentAPI, 'waitForCheckoutSessionCompletion'>): Promise<NormalizedCheckoutSession>;
222
+
118
223
  /** Payment provider adapter backed by Stripe. */
119
224
  declare class StripeAdapter implements PaymentProviderAdapter {
120
225
  readonly name = "stripe";
@@ -124,4 +229,4 @@ declare class StripeAdapter implements PaymentProviderAdapter {
124
229
  destroy(): void;
125
230
  }
126
231
 
127
- export { FloPay, StripeAdapter, type StripeSafeAppearance, createCheckoutSession, createCheckoutSessionWithRetries, loadFloPay, toStripeAppearance, toStripeAppearanceTheme };
232
+ export { FloPay, PaymentAPI, type SavedCardChallengeDecline, type SavedCardChallengeInput, type SavedCardChallengeOutcome, type SavedCardNextActionInput, StripeAdapter, completeSavedCardNextAction, createCheckoutSession, createCheckoutSessionWithRetries, createSavedCardActionAbortedError, loadFloPay, runSavedCardChallenge };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as U,b as D,c as N,d as G,e as q,f as ve,g as _e,h as A,i as g,j as ke,k as Re,l as H,m as B,n as J}from"./chunk-6HODBABS.mjs";import{dropThirdPartyOnlyError as ht}from"@flopay/shared";import{assertCaptureMethodEligible as Te,buildProductPayload as Ae,classifyTelemetryFailure as Ee,FloPayError as b,foldIntoProducts as Fe,IDEMPOTENCY_IN_PROGRESS_CODE as Ie,IDEMPOTENCY_KEY_HEADER as Me,resolveIdempotencyKey as Q,resolveSessionCurrency as xe,SDK_VERSION as X,telemetryStatusClass as Z}from"@flopay/shared";var L=5,ee=new WeakSet;function Oe(t){(typeof t=="object"&&t!==null||typeof t=="function")&&ee.add(t)}function Ue(t){return(typeof t=="object"&&t!==null||typeof t=="function")&&ee.has(t)}function De(t,e){let r=e?.error,o=U(e?.code)??U(r?.code)??`http_${t}`,i=D(e?.message)??D(r?.message)??Ne(o,t);return new b(i,"api_error",{code:o,statusCode:t})}function Ne(t,e){switch(t){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${L}.`;case"CouponCurrencyUnsupported":return"One of the applied coupons has no price configured for the cart currency.";default:return`Failed to create checkout session (HTTP ${e}).`}}async function te(t,e,r){let{billingApiUrl:o,checkoutBaseUrl:i,items:n=[],subscriptions:l=[],products:a,account:c,successUrl:s,cancelUrl:d,checkoutMode:p="confirm",captureMethod:m,couponCodes:y=[],checkoutMetadata:K,tagsData:$,redirectParams:ge={},setCookie:he=!0,clientId:Ce,currency:we,utmMetadata:x,idempotencyKey:be}=t,Y=Q(be);if(y.length>L)throw new b(`Too many coupon codes \u2014 a checkout session accepts at most ${L}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let S=a??Fe(n,l);Te({captureMethod:m,products:S});let h=xe(we,n,l,S);if(!h)throw new b("currency is required: pass `currency` on the session, or include a `currency` on the first item/subscription/product.","validation_error",{code:"CurrencyRequired",param:"currency"});let P={clientId:Ce,checkoutVersion:X,successUrl:s,cancelUrl:d,currency:h,checkoutMode:p,products:S.map(f=>Ae(f,h)),accountData:{userId:c.userId,firstName:c.firstName??null,lastName:c.lastName??null,email:c.email,country:c.country??null,gender:c.gender??null,city:c.city??null,state:c.state??null,zip:c.zip??null,addressLine1:c.addressLine1??null,addressLine2:c.addressLine2??null},couponCodes:y};m==="manual"&&(P.captureMethod=m),K!==void 0&&(P.checkoutMetadata=K),$&&(P.tagsData=$),x&&x.length>0&&(P.utmMetadata=x);let Se=`${o.replace(/\/+$/,"")}/v1/checkouts/sessions`,W={"Content-Type":"application/json"};Y&&(W[Me]=Y);let C,_,Pe={method:"POST",headers:W,body:JSON.stringify(P),signal:e},k;try{r?.startAttempt(),k=await fetch(Se,Pe)}catch(f){throw Oe(f),f}try{r?.record(k.status)}catch{}C=k.status;try{_=await k.json()}catch{}if(C>=400)throw De(C,_);if(C===201){let f=_?.data?.uuid,O=_?.data?.nonce;if(!f)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!O)throw new b("Checkout session created but no `nonce` was returned by the billing API. Upgrade the billing service to TeamFloPay/backend#640 or later.","api_error",{code:"MissingCheckoutSessionToken"});(S.length>0||h)&&q(f,{currency:h,products:S.map(u=>({code:u.code??u.providerItemId??u.providerPlanId,type:u.type,name:u.name??u.itemName??u.providerItemName??u.subscriptionName??u.providerPlanName??null,totalAmount:u.totalAmount,overrideAmount:u.overrideAmount,currency:u.currency??h}))});let R=new URL(`${i.replace(/\/+$/,"")}/secure`);R.searchParams.set("id",f);for(let[u,T]of Object.entries(ge))R.searchParams.set(u,T);if(he&&typeof window<"u"&&typeof document<"u"){let u=JSON.stringify({origin_url:d}),T=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(u)}; domain=.${T}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(O)}; domain=.${T}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=R.toString()),{status:201,redirectUrl:R.toString(),nonce:O}}return C===204?(typeof window<"u"&&(window.location.href=s),{status:204}):{status:C}}async function qe(t){let e=oe(t),r=re(e),o=N(t.timeoutMs);try{let i=await te(t,o.signal,r);return r.commit(),se(e,i),i}catch(i){throw r.commit(),E(e,i),i}finally{o.clear(),w(e.reporter)}}function re(t){let e=!1,r=t.startedAt,o;return{startAttempt(){r=t.reporter.now()},record(i){o={status:i,durationMs:Math.max(0,t.reporter.now()-r),attempt:t.attempt}},commit(){if(e||!o)return;e=!0;let i=Z(o.status);t.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:i,attempt:o.attempt}),t.reporter.performance({stage:"session_first_byte",durationMs:o.durationMs,durationMode:"machine",requestCategory:"session_create",statusClass:i,attempt:o.attempt})}}}function oe(t){let e=new g({billingApiUrl:t.billingApiUrl,sdkVersion:X,enabled:t.telemetry!==!1}),r=e.now();return e.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:e,startedAt:r,attempt:0}}function se(t,e){let r=Z(e.status);t.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:r}),t.reporter.performance({stage:"session_create",durationMs:t.reporter.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:r,attempt:t.attempt})}function E(t,e){let{reporter:r}=t,o=Ee(e,"CHECKOUT_SESSION_CREATE_FAILED");if(r.performance({stage:"session_create",durationMs:r.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:t.attempt}),e instanceof b&&e.type==="validation_error"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(o.statusClass==="4xx"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}r.error({...o,stage:"session_create",requestCategory:"session_create"})}function w(t){t.flush().catch(()=>{}).finally(()=>t.destroy())}async function Be(t){let{maxRetries:e=2,...r}=t,o=oe(t),i=re(o);if(!Number.isFinite(e)||!Number.isInteger(e)||e<0||e>=3)throw o.reporter.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),w(o.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let n={...r,idempotencyKey:Q(r.idempotencyKey)},l=N(r.timeoutMs),a;for(let c=0;c<=e;c++){o.attempt=c;try{let s=await te(n,l.signal,i);return i.commit(),se(o,s),l.clear(),w(o.reporter),s}catch(s){a=s;let d=s instanceof Error&&s.name==="AbortError",p=Ue(s),m=s instanceof b&&s.code===Ie;if((d||p||m)&&!l.signal.aborted&&c<e){o.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:c+1});try{await G(c,l.signal)}catch(y){throw i.commit(),E(o,y),l.clear(),w(o.reporter),y}continue}throw i.commit(),E(o,s),l.clear(),w(o.reporter),s}}throw i.commit(),E(o,a),l.clear(),w(o.reporter),a??new Error("Unknown error during checkout session creation")}import{classifyTelemetryFailure as je,FloPayError as F,resolveBillingApiUrl as ce,SDK_VERSION as Le}from"@flopay/shared";var ne=Symbol.for("@flopay/js.telemetry.bridge.v1");function ie(t,e,r){let o=()=>e?.now()??r();Object.defineProperty(t,ne,{configurable:!1,enumerable:!1,writable:!1,value:{error:n=>e?.error(n),log:n=>e?.log(n),performance:n=>e?.performance(n),terminal:n=>e?.terminal(n),now:o,elapsed:n=>Math.max(0,o()-n),setCheckoutContext:n=>e?.setCheckoutContext(n),beginCheckout:(n={})=>e?.beginCheckout(n)??o(),disable:()=>e?.disable(),subscribe:n=>e?.subscribe(n)??(()=>{}),flush:()=>e?.flush()??Promise.resolve()}})}function ae(t){return t[ne]}var I=class{now(){return this.telemetryReporter?.now?.()??A()}constructor(e,r,o){this.provider=e,this.config=r,this.telemetryReporter=o??new g({billingApiUrl:ce(r.billingApiUrl),sdkVersion:Le,enabled:r.telemetry!==!1}),ie(this,this.telemetryReporter,A)}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?J({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new B({sessionId:e?.sessionId,captureMethod:e?.captureMethod,telemetry:!1})}async retrieveSession(e,r){if(!e)throw new F("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let o=await this.retrieveUnifiedSession(e,r);if(!o.data.session)throw new F("Session not found","api_error");return o.data.session}async retrieveUnifiedSession(e,r){if(!e)throw new F("sessionId is required.","validation_error",{param:"sessionId"});let o=ce(r??this.config.billingApiUrl),i=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let n,l,a=s=>{if(n===void 0)return;let d=n,p=l;n=void 0,l=void 0,this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:s,attempt:p}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:d,durationMode:"machine",requestCategory:"session_read",statusClass:s,attempt:p})},c=H(o,{now:()=>this.telemetryReporter?.now()??A(),onFirstByte:(s,d)=>{n=s,l=d},onRetry:(s,d)=>{this.telemetryReporter?.log({name:"operation.retry",stage:s==="session_read"?"session_read":"processing",requestCategory:s,attempt:d})}});try{let s=await c.getUnifiedCheckoutSession(e);return a("2xx"),this.telemetryReporter?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.log({name:"checkout.data.ready",stage:"checkout_data_ready"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-i,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),s}catch(s){let d=je(s,s instanceof F&&s.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw a(d.statusClass),this.telemetryReporter?.error({...d,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-i,durationMode:"machine",requestCategory:"session_read",statusClass:d.statusClass}),s}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.provider.destroy()}};function le(t,e,r){let o=I;return new o(t,e,r)}import{FloPayError as Ke,resolveBillingApiUrl as z,SDK_VERSION as ye}from"@flopay/shared";import{FloPayError as de}from"@flopay/shared";import{loadStripe as ze}from"@stripe/stripe-js";var ue=new WeakSet;function pe(t){return t instanceof de&&ue.has(t)}function me(t){switch(t){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function Ve(t){return{...t,theme:me(t.theme)}}var v=class{constructor(){this.name="stripe";this.stripe=null}async initialize(e){if(typeof window>"u")return;let r=await ze(e.publishableKey,{locale:e.locale??"auto"});if(!r){let o=new de("Failed to initialize Stripe. Check your publishable key.","authentication_error");throw ue.add(o),o}this.stripe=r}getRawProvider(){return this.stripe}destroy(){this.stripe=null}};var fe=new Map;function V(t){return Array.isArray(t)?t.map(V):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[r])=>e.localeCompare(r)).map(([e,r])=>[e,V(r)])):t}function $e(t,e){return JSON.stringify([t,z(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,V(e?.appearance??null)])}var M=new Map;async function Ye(t,e){if(!t){let a=new g({billingApiUrl:z(e?.billingApiUrl),sdkVersion:ye,enabled:e?.telemetry!==!1});throw a.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),a.flush().catch(()=>{}).finally(()=>a.destroy()),new Ke("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let r=$e(t,e),o=fe.get(r);if(o)return e?.telemetry!==!1&&ae(o)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),o;let i=M.get(r);if(i)return i;let n={...e,publishableKey:t},l=(async()=>{let a=new g({billingApiUrl:z(n.billingApiUrl),sdkVersion:ye,enabled:n.telemetry!==!1}),c=a.now();a.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),a.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),a.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let s=new v,d=a.now();try{await s.initialize(n)}catch(y){throw a.error({errorCode:"PROVIDER_LOAD_FAILED",failureCategory:pe(y)?"invalid_response":"provider_runtime",stage:"provider_load",provider:"stripe",requestCategory:"provider_sdk",paymentMethodCategory:"unknown"}),a.destroy(),y}let p=a.now();a.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),a.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),a.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),a.performance({stage:"sdk_initialize",durationMs:p-c,durationMode:"machine",provider:"stripe"}),a.performance({stage:"provider_ready",durationMs:p-d,durationMode:"machine",provider:"stripe"});let m=le(s,n,a);return fe.set(r,m),m})();M.set(r,l);try{return await l}finally{M.get(r)===l&&M.delete(r)}}export{I as FloPay,Re as PaymentAPI,B as PciVaultCardCapture,ke as SESSION_CREATE_TELEMETRY,v as StripeAdapter,q as cacheSessionDisplayData,_e as clearSessionDisplayData,qe as createCheckoutSession,Be as createCheckoutSessionWithRetries,ht as dropThirdPartyOnlyError,ve as getSessionDisplayData,Ye as loadFloPay,Ve as toStripeAppearance,me as toStripeAppearanceTheme};
1
+ import{a as V,b as W,c as H,d as te,e as Y,f as Ee,g as Te,h as L,i as v,j as Ie,k as xe,l as re,m as G,n as oe}from"./chunk-IK3EID7W.mjs";import{dropThirdPartyOnlyError as Mt}from"@flopay/shared";import{assertCaptureMethodEligible as Fe,buildProductPayload as Me,classifyTelemetryFailure as Ue,FloPayError as A,foldIntoProducts as Oe,IDEMPOTENCY_IN_PROGRESS_CODE as De,IDEMPOTENCY_KEY_HEADER as Le,resolveIdempotencyKey as ne,resolveSessionCurrency as Ne,SDK_VERSION as ae,telemetryStatusClass as ie}from"@flopay/shared";var Q=5,se=new WeakSet;function qe(e){(typeof e=="object"&&e!==null||typeof e=="function")&&se.add(e)}function Be(e){return(typeof e=="object"&&e!==null||typeof e=="function")&&se.has(e)}function ze(e,t){let r=t?.error,o=V(t?.code)??V(r?.code)??`http_${e}`,l=W(t?.message)??W(r?.message)??je(o,e);return new A(l,"api_error",{code:o,statusCode:e})}function je(e,t){switch(e){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${Q}.`;case"CouponCurrencyUnsupported":return"One of the applied coupons has no price configured for the cart currency.";default:return`Failed to create checkout session (HTTP ${t}).`}}async function le(e,t,r){let{billingApiUrl:o,checkoutBaseUrl:l,items:s=[],subscriptions:c=[],products:n,account:i,successUrl:a,cancelUrl:d,checkoutMode:p="confirm",captureMethod:u,couponCodes:y=[],checkoutMetadata:k,tagsData:b,redirectParams:R={},setCookie:S=!0,clientId:I,currency:x,utmMetadata:C,idempotencyKey:F}=e,f=ne(F);if(y.length>Q)throw new A(`Too many coupon codes \u2014 a checkout session accepts at most ${Q}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let g=n??Oe(s,c);Fe({captureMethod:u,products:g});let w=Ne(x,s,c,g);if(!w)throw new A("currency is required: pass `currency` on the session, or include a `currency` on the first item/subscription/product.","validation_error",{code:"CurrencyRequired",param:"currency"});let E={clientId:I,checkoutVersion:ae,successUrl:a,cancelUrl:d,currency:w,checkoutMode:p,products:g.map(h=>Me(h,w)),accountData:{userId:i.userId,firstName:i.firstName??null,lastName:i.lastName??null,email:i.email,country:i.country??null,gender:i.gender??null,city:i.city??null,state:i.state??null,zip:i.zip??null,addressLine1:i.addressLine1??null,addressLine2:i.addressLine2??null},couponCodes:y};u==="manual"&&(E.captureMethod=u),k!==void 0&&(E.checkoutMetadata=k),b&&(E.tagsData=b),C&&C.length>0&&(E.utmMetadata=C);let ke=`${o.replace(/\/+$/,"")}/v1/checkouts/sessions`,ee={"Content-Type":"application/json"};f&&(ee[Le]=f);let _,M,Re={method:"POST",headers:ee,body:JSON.stringify(E),signal:t},U;try{r?.startAttempt(),U=await fetch(ke,Re)}catch(h){throw qe(h),h}try{r?.record(U.status)}catch{}_=U.status;try{M=await U.json()}catch{}if(_>=400)throw ze(_,M);if(_===201){let h=M?.data?.uuid,K=M?.data?.nonce;if(!h)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!K)throw new A("Checkout session created but no `nonce` was returned by the billing API. Upgrade the billing service to TeamFloPay/backend#640 or later.","api_error",{code:"MissingCheckoutSessionToken"});(g.length>0||w)&&Y(h,{currency:w,products:g.map(m=>({code:m.code??m.providerItemId??m.providerPlanId,type:m.type,name:m.name??m.itemName??m.providerItemName??m.subscriptionName??m.providerPlanName??null,totalAmount:m.totalAmount,overrideAmount:m.overrideAmount,currency:m.currency??w}))});let O=new URL(`${l.replace(/\/+$/,"")}/secure`);O.searchParams.set("id",h);for(let[m,D]of Object.entries(R))O.searchParams.set(m,D);if(S&&typeof window<"u"&&typeof document<"u"){let m=JSON.stringify({origin_url:d}),D=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(m)}; domain=.${D}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(K)}; domain=.${D}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=O.toString()),{status:201,redirectUrl:O.toString(),nonce:K}}return _===204?(typeof window<"u"&&(window.location.href=a),{status:204}):{status:_}}async function $e(e){let t=de(e),r=ce(t),o=H(e.timeoutMs);try{let l=await le(e,o.signal,r);return r.commit(),ue(t,l),l}catch(l){throw r.commit(),N(t,l),l}finally{o.clear(),P(t.reporter)}}function ce(e){let t=!1,r=e.startedAt,o;return{startAttempt(){r=e.reporter.now()},record(l){o={status:l,durationMs:Math.max(0,e.reporter.now()-r),attempt:e.attempt}},commit(){if(t||!o)return;t=!0;let l=ie(o.status);e.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:l,attempt:o.attempt}),e.reporter.performance({stage:"session_first_byte",durationMs:o.durationMs,durationMode:"machine",requestCategory:"session_create",statusClass:l,attempt:o.attempt})}}}function de(e){let t=new v({billingApiUrl:e.billingApiUrl,sdkVersion:ae,enabled:e.telemetry!==!1}),r=t.now();return t.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:t,startedAt:r,attempt:0}}function ue(e,t){let r=ie(t.status);e.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:r}),e.reporter.performance({stage:"session_create",durationMs:e.reporter.now()-e.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:r,attempt:e.attempt})}function N(e,t){let{reporter:r}=e,o=Ue(t,"CHECKOUT_SESSION_CREATE_FAILED");if(r.performance({stage:"session_create",durationMs:r.now()-e.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:e.attempt}),t instanceof A&&t.type==="validation_error"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(o.statusClass==="4xx"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}r.error({...o,stage:"session_create",requestCategory:"session_create"})}function P(e){e.flush().catch(()=>{}).finally(()=>e.destroy())}async function Ke(e){let{maxRetries:t=2,...r}=e,o=de(e),l=ce(o);if(!Number.isFinite(t)||!Number.isInteger(t)||t<0||t>=3)throw o.reporter.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),P(o.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let s={...r,idempotencyKey:ne(r.idempotencyKey)},c=H(r.timeoutMs),n;for(let i=0;i<=t;i++){o.attempt=i;try{let a=await le(s,c.signal,l);return l.commit(),ue(o,a),c.clear(),P(o.reporter),a}catch(a){n=a;let d=a instanceof Error&&a.name==="AbortError",p=Be(a),u=a instanceof A&&a.code===De;if((d||p||u)&&!c.signal.aborted&&i<t){o.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:i+1});try{await te(i,c.signal)}catch(y){throw l.commit(),N(o,y),c.clear(),P(o.reporter),y}continue}throw l.commit(),N(o,a),c.clear(),P(o.reporter),a}}throw l.commit(),N(o,n),c.clear(),P(o.reporter),n??new Error("Unknown error during checkout session creation")}import{classifyTelemetryFailure as Ve,FloPayError as q,resolveBillingApiUrl as fe,SDK_VERSION as We}from"@flopay/shared";var me=Symbol.for("@flopay/js.telemetry.bridge.v1");function pe(e,t,r){let o=()=>t?.now()??r();Object.defineProperty(e,me,{configurable:!1,enumerable:!1,writable:!1,value:{error:s=>t?.error(s),log:s=>t?.log(s),performance:s=>t?.performance(s),terminal:s=>t?.terminal(s),now:o,elapsed:s=>Math.max(0,o()-s),setCheckoutContext:s=>t?.setCheckoutContext(s),beginCheckout:(s={})=>t?.beginCheckout(s)??o(),disable:()=>t?.disable(),subscribe:s=>t?.subscribe(s)??(()=>{}),flush:()=>t?.flush()??Promise.resolve()}})}function ye(e){return e[me]}var B=class{now(){return this.telemetryReporter?.now?.()??L()}constructor(t,r,o){this.provider=t,this.config=r,this.telemetryReporter=o??new v({billingApiUrl:fe(r.billingApiUrl),sdkVersion:We,enabled:r.telemetry!==!1}),pe(this,this.telemetryReporter,L)}cardCapture(t){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?oe({sessionId:t?.sessionId,captureMethod:t?.captureMethod},this.telemetryReporter):new G({sessionId:t?.sessionId,captureMethod:t?.captureMethod,telemetry:!1})}async retrieveSession(t,r){if(!t)throw new q("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let o=await this.retrieveUnifiedSession(t,r);if(!o.data.session)throw new q("Session not found","api_error");return o.data.session}async retrieveUnifiedSession(t,r){if(!t)throw new q("sessionId is required.","validation_error",{param:"sessionId"});let o=fe(r??this.config.billingApiUrl),l=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let s,c,n=a=>{if(s===void 0)return;let d=s,p=c;s=void 0,c=void 0,this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:a,attempt:p}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:d,durationMode:"machine",requestCategory:"session_read",statusClass:a,attempt:p})},i=re(o,{now:()=>this.telemetryReporter?.now()??L(),onFirstByte:(a,d)=>{s=a,c=d},onRetry:(a,d)=>{this.telemetryReporter?.log({name:"operation.retry",stage:a==="session_read"?"session_read":"processing",requestCategory:a,attempt:d})}});try{let a=await i.getUnifiedCheckoutSession(t);return n("2xx"),this.telemetryReporter?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.log({name:"checkout.data.ready",stage:"checkout_data_ready"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-l,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),a}catch(a){let d=Ve(a,a instanceof q&&a.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw n(d.statusClass),this.telemetryReporter?.error({...d,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-l,durationMode:"machine",requestCategory:"session_read",statusClass:d.statusClass}),a}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.provider.destroy()}};function ge(e,t,r){let o=B;return new o(e,t,r)}import{FloPayError as Je,resolveBillingApiUrl as X,SDK_VERSION as ve}from"@flopay/shared";import{FloPayError as he}from"@flopay/shared";import{loadStripe as He}from"@stripe/stripe-js";import{toStripeAppearance as Ye,toStripeAppearanceTheme as Ge}from"@flopay/shared";var Ce=new WeakSet;function we(e){return e instanceof he&&Ce.has(e)}var T=class{constructor(){this.name="stripe";this.stripe=null}async initialize(t){if(typeof window>"u")return;let r=await He(t.publishableKey,{locale:t.locale??"auto"});if(!r){let o=new he("Failed to initialize Stripe. Check your publishable key.","authentication_error");throw Ce.add(o),o}this.stripe=r}getRawProvider(){return this.stripe}destroy(){this.stripe=null}};var be=new Map;function Z(e){return Array.isArray(e)?e.map(Z):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>[t,Z(r)])):e}function Qe(e,t){return JSON.stringify([e,X(t?.billingApiUrl),t?.telemetry!==!1,t?.locale??"auto",t?.apiVersion??null,Z(t?.appearance??null)])}var z=new Map;async function Xe(e,t){if(!e){let n=new v({billingApiUrl:X(t?.billingApiUrl),sdkVersion:ve,enabled:t?.telemetry!==!1});throw n.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),n.flush().catch(()=>{}).finally(()=>n.destroy()),new Je("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let r=Qe(e,t),o=be.get(r);if(o)return t?.telemetry!==!1&&ye(o)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),o;let l=z.get(r);if(l)return l;let s={...t,publishableKey:e},c=(async()=>{let n=new v({billingApiUrl:X(s.billingApiUrl),sdkVersion:ve,enabled:s.telemetry!==!1}),i=n.now();n.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),n.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),n.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let a=new T,d=n.now();try{await a.initialize(s)}catch(y){throw n.error({errorCode:"PROVIDER_LOAD_FAILED",failureCategory:we(y)?"invalid_response":"provider_runtime",stage:"provider_load",provider:"stripe",requestCategory:"provider_sdk",paymentMethodCategory:"unknown"}),n.destroy(),y}let p=n.now();n.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),n.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),n.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),n.performance({stage:"sdk_initialize",durationMs:p-i,durationMode:"machine",provider:"stripe"}),n.performance({stage:"provider_ready",durationMs:p-d,durationMode:"machine",provider:"stripe"});let u=ge(a,s,n);return be.set(r,u),u})();z.set(r,c);try{return await c}finally{z.get(r)===c&&z.delete(r)}}import{FloPayError as $,THREE_DS_CHALLENGE_WINDOW_MS as Se}from"@flopay/shared";var Ze=1e3,et=1e3,tt=15e3;function j(e){return new $("Card authentication was cancelled.","api_error",{code:"three_ds_aborted",cause:e})}function _e(){return new $("Card authentication timed out.","api_error",{code:"three_ds_timeout"})}function Pe(e){return e.replace(/\/+$/,"")}function rt(e){return e.status==="succeeded"||e.status==="authorized"||e.status==="declined"}function ot(e){if(!e||typeof e!="object")return{status:"unknown"};let t=typeof e.status=="string"?e.status:"unknown",r=typeof e.providerIntentId=="string"?e.providerIntentId:null;switch(t){case"succeeded":case"authorized":case"pending":case"timeout":return{status:t,providerIntentId:r};case"declined":return{status:"declined",providerIntentId:r,declineReason:typeof e.declineReason=="string"?e.declineReason:null,gatewayDeclineReason:typeof e.gatewayDeclineReason=="string"?e.gatewayDeclineReason:null};case"requires_action":return{status:"requires_action",providerIntentId:r,nextActionRedirectUrl:typeof e.nextActionRedirectUrl=="string"?e.nextActionRedirectUrl:null};case"no_attempt":return{status:"no_attempt"};default:return{status:"unknown"}}}async function Ae(e){if(typeof document>"u"||typeof window>"u")throw new $("3DS challenge requires a browser environment.","api_error",{code:"three_ds_no_window"});if(e.signal?.aborted)throw j();let t=`${Pe(e.billingApiUrl)}/v1/checkouts/sessions/${encodeURIComponent(e.sessionId)}/3ds/complete`,r=async()=>{let a=new AbortController,d=()=>a.abort();e.signal?.aborted?a.abort():e.signal?.addEventListener("abort",d);let p=window.setTimeout(()=>a.abort(),tt);try{let u=await fetch(t,{method:"POST",headers:{"x-checkout-session-token":e.nonce,"content-type":"application/json"},body:"{}",signal:a.signal});if(!u.ok)return{status:"unknown"};let y=await u.json().catch(()=>null);return ot(y)}catch{return{status:"unknown"}}finally{window.clearTimeout(p),e.signal?.removeEventListener("abort",d)}},o,l=()=>e.pollCompletionEndpoint!==!1?r():(o??(o=r()),o),s=document.activeElement instanceof HTMLElement?document.activeElement:null,c=document.createElement("div");c.setAttribute("data-flopay-auto-3ds-overlay","1"),c.setAttribute("role","dialog"),c.setAttribute("aria-modal","true"),c.setAttribute("aria-label","Card authentication"),c.style.cssText=["position:fixed","inset:0","z-index:2147483647","background:rgba(15,23,42,0.6)","display:flex","align-items:center","justify-content:center","padding:16px"].join(";");let n=document.createElement("iframe");n.setAttribute("title","Card authentication"),n.setAttribute("allow","payment"),n.tabIndex=0,n.style.cssText=["width:min(100%,460px)","height:min(100%,640px)","border:0","border-radius:12px","background:#fff","box-shadow:0 12px 30px rgba(0,0,0,0.35)"].join(";");let i=null;try{i=new URL(e.billingApiUrl,window.location.href).origin}catch{i=null}try{let a=await new Promise((d,p)=>{let u=!1,y=0,k=0,b=0,R=!1,S=()=>{window.clearTimeout(y),window.clearInterval(k),window.clearTimeout(b),window.removeEventListener("message",F),n.removeEventListener("load",x),e.signal?.removeEventListener("abort",C)},I=async()=>{if(!(u||R)){R=!0;try{let f=await l();if(u||!rt(f))return;u=!0,S(),d(f)}finally{R=!1}}},x=()=>{e.pollCompletionEndpoint!==!1&&(window.clearTimeout(b),b=window.setTimeout(()=>{I()},250))},C=()=>{u||(u=!0,S(),p(j()))},F=f=>{if(f.source!==n.contentWindow||i&&f.origin!==i)return;let g=f.data;!g||typeof g!="object"||g.source!=="flopay-vault-3ds-return"||u||(u=!0,S(),d(null))};y=window.setTimeout(()=>{u||(u=!0,S(),p(_e()))},Se),e.pollCompletionEndpoint!==!1&&(k=window.setInterval(()=>{I()},et)),n.addEventListener("load",x),window.addEventListener("message",F),e.signal?.addEventListener("abort",C),n.src=e.nextActionRedirectUrl,c.appendChild(n),document.body.appendChild(c),n.focus(),e.signal?.aborted&&C()});return a||await l()}finally{c.parentNode?.removeChild(c),s?.isConnected&&s.focus()}}function nt(e){return new $("Card was declined.","api_error",{code:e.declineReason??"authorization_declined",...e.gatewayDeclineReason?{declineCode:e.gatewayDeclineReason}:{}})}async function at(e,t){let r=`${Pe(e.billingApiUrl)}/v1/checkouts/sessions/${encodeURIComponent(e.sessionId)}/status`,o=new AbortController,l=new AbortController,s=()=>{o.abort(e.signal?.reason),l.abort(e.signal?.reason)};e.signal?.aborted?s():e.signal?.addEventListener("abort",s,{once:!0});let c=Ae({billingApiUrl:e.billingApiUrl,sessionId:e.sessionId,nonce:e.nonce,nextActionRedirectUrl:e.nextActionRedirectUrl,signal:o.signal,pollCompletionEndpoint:!1}),n=t.waitForCheckoutSessionCompletion(e.sessionId,{initialDelayMs:Ze,nonce:e.nonce,statusUrl:r,continueAfterActionRequired:!0,timeoutMs:Se+15e3,signal:l.signal});n.catch(()=>{}),c.catch(()=>{});try{let i=await Promise.race([c,n]);if("data"in i)return i;if(i.status==="declined")throw(e.createDeclineError??nt)(i);if(i.status==="timeout")throw _e();return await n}catch(i){throw e.signal?.aborted||i instanceof Error&&i.name==="AbortError"?j(i):i}finally{e.signal?.removeEventListener("abort",s),o.abort(),l.abort()}}export{B as FloPay,xe as PaymentAPI,G as PciVaultCardCapture,Ie as SESSION_CREATE_TELEMETRY,T as StripeAdapter,Y as cacheSessionDisplayData,Te as clearSessionDisplayData,at as completeSavedCardNextAction,$e as createCheckoutSession,Ke as createCheckoutSessionWithRetries,j as createSavedCardActionAbortedError,Mt as dropThirdPartyOnlyError,Ee as getSessionDisplayData,Xe as loadFloPay,Ae as runSavedCardChallenge,Ye as toStripeAppearance,Ge as toStripeAppearanceTheme};
@@ -612,7 +612,11 @@ declare class PciVaultCardCapture implements CardCaptureAdapter {
612
612
  */
613
613
  private injectWidget;
614
614
  private attachMessageListener;
615
- /** A pre-submit `error` from a form mounted behind the production human check. */
615
+ /**
616
+ * A pre-submit `error` from a form mounted behind the production human check
617
+ * whose cause is the check's own buyer-facing state (see
618
+ * {@link isVerificationStateCause}).
619
+ */
616
620
  private isVerificationStateError;
617
621
  private reportOutcome;
618
622
  /**
@@ -612,7 +612,11 @@ declare class PciVaultCardCapture implements CardCaptureAdapter {
612
612
  */
613
613
  private injectWidget;
614
614
  private attachMessageListener;
615
- /** A pre-submit `error` from a form mounted behind the production human check. */
615
+ /**
616
+ * A pre-submit `error` from a form mounted behind the production human check
617
+ * whose cause is the check's own buyer-facing state (see
618
+ * {@link isVerificationStateCause}).
619
+ */
616
620
  private isVerificationStateError;
617
621
  private reportOutcome;
618
622
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flopay/js",
3
- "version": "1.11.5",
3
+ "version": "1.11.6",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "publishConfig": {
@@ -32,7 +32,7 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@stripe/stripe-js": "^9.17.0",
35
- "@flopay/shared": "1.11.5"
35
+ "@flopay/shared": "1.11.6"
36
36
  },
37
37
  "devDependencies": {
38
38
  "jsdom": "^29.1.1",