@flopay/js 1.11.5 → 1.12.0
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/card-setup.cjs +1 -1
- package/dist/card-setup.d.cts +23 -1
- package/dist/card-setup.d.ts +23 -1
- package/dist/card-setup.mjs +1 -1
- package/dist/{chunk-6HODBABS.mjs → chunk-IK3EID7W.mjs} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +121 -16
- package/dist/index.d.ts +121 -16
- package/dist/index.mjs +1 -1
- package/dist/{card-setup-Cn9t5eLo.d.cts → pci-vault-card-capture-Dt3F9i7Q.d.cts} +5 -1
- package/dist/{card-setup-Cn9t5eLo.d.ts → pci-vault-card-capture-Dt3F9i7Q.d.ts} +5 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession,
|
|
2
|
-
export { SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
|
|
3
|
-
|
|
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
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
/**
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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,
|
|
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,
|
|
2
|
-
export { SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
|
|
3
|
-
|
|
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
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
/**
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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,
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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.
|
|
3
|
+
"version": "1.12.0",
|
|
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.
|
|
35
|
+
"@flopay/shared": "1.12.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"jsdom": "^29.1.1",
|