@flopay/js 1.7.0 → 1.8.2
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/README.md +8 -66
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +12 -119
- package/dist/index.d.ts +12 -119
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @flopay/js
|
|
2
2
|
|
|
3
|
-
Browser-side FloPay SDK. Provides `loadFloPay()` to initialize the SDK, a `FloPay` class for
|
|
3
|
+
Browser-side FloPay SDK. Provides `loadFloPay()` to initialize the SDK, a `FloPay` class for hosted card capture and session access, `PaymentAPI` for billing API calls, and `createCheckoutSession` for server-initiated checkout flows.
|
|
4
4
|
|
|
5
5
|
Currently backed by Stripe via the `StripeAdapter`. The adapter pattern (`PaymentProviderAdapter` interface) allows swapping providers without changing consumer code.
|
|
6
6
|
|
|
@@ -32,57 +32,6 @@ a later call can retry. The optional second argument accepts
|
|
|
32
32
|
`appearance`, and `telemetry`; set `telemetry: false` to opt out of privacy-safe
|
|
33
33
|
operational telemetry.
|
|
34
34
|
|
|
35
|
-
### Create and Mount Non-card Elements
|
|
36
|
-
|
|
37
|
-
```ts
|
|
38
|
-
const elements = flopay.elements({
|
|
39
|
-
amount: 2999, // in cents
|
|
40
|
-
currency: 'usd',
|
|
41
|
-
paymentMethodTypes: ['cashapp', 'ideal'],
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const paymentElement = await elements.create('payment');
|
|
45
|
-
paymentElement.mount(document.getElementById('payment-container')!);
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
`paymentMethodTypes` is required for `payment` elements and must contain at
|
|
49
|
-
least one wallet/APM method. Any `card` entry is removed; a missing or empty
|
|
50
|
-
non-card allowlist throws `FloPayError('validation_error')`. When Elements are
|
|
51
|
-
initialized with a `clientSecret`, the provider intent is verified against the
|
|
52
|
-
explicit non-card allowlist before mounting; the allowlist remains required and
|
|
53
|
-
any extra provider method is rejected. Use
|
|
54
|
-
`@flopay/react`'s `FloPayCheckout` or `SplitCardForm` for card checkout; both
|
|
55
|
-
mount the backend-hosted vault widget supplied in the session's `vault` block.
|
|
56
|
-
|
|
57
|
-
### PayPal Payment
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
const result = await flopay.confirmPayPalPayment({
|
|
61
|
-
billingApiUrl: 'https://billing.example.com',
|
|
62
|
-
sessionId: 'session_uuid',
|
|
63
|
-
nonce: sessionNonce,
|
|
64
|
-
email: 'user@example.com',
|
|
65
|
-
returnUrl: window.location.href,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// After redirect return, resume the payment:
|
|
69
|
-
const resumed = await flopay.resumePayPalPayment();
|
|
70
|
-
if (resumed) {
|
|
71
|
-
console.log('PayPal payment status:', resumed.status);
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Direct-PayPal checkout surfaces use `PaymentAPI.createSessionIntent()` instead
|
|
76
|
-
of `confirmPayPalPayment()`. The payment-method type is the channel selector:
|
|
77
|
-
legacy `paymentMethodType: 'paypal'` (always `intentKind: 'payment'`) returns
|
|
78
|
-
an Order or provider-managed Subscription exactly as released, while
|
|
79
|
-
`paymentMethodType: 'paypal_vaulted'` opts the request into the Flo-owned
|
|
80
|
-
channel — `intentKind: 'payment'` returns a Flo-owned Order and
|
|
81
|
-
`intentKind: 'setup'` returns a PayPal vault setup token. There is no
|
|
82
|
-
capability header; sessions advertise availability via
|
|
83
|
-
`gateways.paypal.providerObjectType`. See
|
|
84
|
-
[Flo-owned PayPal subscription continuations](../../docs/PAYPAL_FLO_SUBSCRIPTION_CONTINUATIONS.md).
|
|
85
|
-
|
|
86
35
|
### Retrieve a Session
|
|
87
36
|
|
|
88
37
|
```ts
|
|
@@ -98,6 +47,10 @@ const unified = await flopay.retrieveUnifiedSession('session_uuid');
|
|
|
98
47
|
console.log(unified.data.stripe?.clientSecret);
|
|
99
48
|
```
|
|
100
49
|
|
|
50
|
+
`retrieveUnifiedSession()` exposes provider-specific session data without
|
|
51
|
+
mounting provider UI. Use `FloPayCheckout` or `SplitCardForm` from
|
|
52
|
+
`@flopay/react` for hosted-vault card, wallet, and APM rendering.
|
|
53
|
+
|
|
101
54
|
Failed session loads reject with `FloPayError`. When the billing API returns a structured error body, the SDK preserves the safe `message`, backend `code`, and HTTP `statusCode`; body-less responses fall back to `code: "http_<status>"`.
|
|
102
55
|
|
|
103
56
|
### PaymentAPI (Billing API Client)
|
|
@@ -380,36 +333,25 @@ which can be rewritten to `true` for third-party frames by host tooling.
|
|
|
380
333
|
| Export | Description |
|
|
381
334
|
|--------|-------------|
|
|
382
335
|
| `loadFloPay(publishableKey, options?)` | Initializes the SDK. Returns a `Promise<FloPay>`. Shares successful and in-flight work by key; failed work remains retryable. |
|
|
383
|
-
| `FloPay` | Main SDK class. Methods: `
|
|
384
|
-
| `FloPayElements` | Element group manager. Methods: `create(type, options?)`, `getElement(type)`, `submit()`, `destroy()` |
|
|
336
|
+
| `FloPay` | Main SDK class. Methods: `cardCapture()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
|
|
385
337
|
| `StripeAdapter` | `PaymentProviderAdapter` implementation for Stripe |
|
|
386
338
|
| `PciVaultCardCapture` | `CardCaptureAdapter` implementation that injects the backend-served hosted vault card widget. See [Vault card capture](#vault-card-capture). |
|
|
387
339
|
| `PaymentAPI` | Billing API client. Includes session retrieval/creation, vault recovery, `/process`, `createSessionIntent()` (including PayPal payment/setup continuations), `reportSessionIntentDecline()`, completion polling, and saved-payment lookup. |
|
|
388
340
|
| `createCheckoutSession(options)` | Creates a checkout session and redirects. Returns `CheckoutSessionResult`. |
|
|
389
341
|
| `createCheckoutSessionWithRetries(options)` | Same as above with two retries by default (three total attempts) under one total deadline with jittered exponential backoff. |
|
|
390
342
|
| `dropThirdPartyOnlyError(event)` | Host-owned Sentry `beforeSend` predicate. Drops recognized third-party-only exception stacks and otherwise returns the original event. |
|
|
391
|
-
| `toStripeAppearance(appearance)` | Normalizes a `FloPayAppearance` into a `StripeSafeAppearance` by mapping FloPay's public `theme` token (`'default' \| 'flat' \| 'night' \| 'none'`) onto Stripe's accepted set (`'stripe' \| 'flat' \| 'night'`). Use at any site that hands an appearance to `@stripe/react-stripe-js`'s `<Elements>` so `theme: 'default'` never reaches Stripe.js
|
|
343
|
+
| `toStripeAppearance(appearance)` | Normalizes a `FloPayAppearance` into a `StripeSafeAppearance` by mapping FloPay's public `theme` token (`'default' \| 'flat' \| 'night' \| 'none'`) onto Stripe's accepted set (`'stripe' \| 'flat' \| 'night'`). Use at any site that hands an appearance to `@stripe/react-stripe-js`'s `<Elements>` so `theme: 'default'` never reaches Stripe.js. `variables`/`rules` pass through untouched. |
|
|
392
344
|
| `toStripeAppearanceTheme(theme)` | Lower-level helper backing `toStripeAppearance`: maps a single FloPay `theme` token to Stripe's. |
|
|
393
345
|
|
|
394
346
|
### FloPay Class Methods
|
|
395
347
|
|
|
396
348
|
| Method | Returns | Description |
|
|
397
349
|
|--------|---------|-------------|
|
|
398
|
-
| `elements(options?)` | `FloPayElements` | Creates a new elements group. Destroys previous group. |
|
|
399
|
-
| `submitElements()` | `Promise<{ error? }>` | Validates all mounted elements |
|
|
400
350
|
| `cardCapture(options?)` | `CardCaptureAdapter` | Creates a hosted vault card-widget adapter (`PciVaultCardCapture`). See [Vault card capture](#vault-card-capture). |
|
|
401
|
-
| `confirmPayment(params)` | `Promise<PaymentResult>` | Confirms a mounted wallet/APM using `clientSecret`, `paymentMethodCategory`, and `paymentMethodType`; rejects `card`. |
|
|
402
|
-
| `confirmPayPalPayment(params)` | `Promise<PayPalPaymentResult>` | Stripe-hosted PayPal flow through the nonce-protected session intent contract, followed by confirmation/redirect. |
|
|
403
|
-
| `resumePayPalPayment()` | `Promise<PayPalPaymentResult \| null>` | Resumes after PayPal redirect. Returns `null` if no PayPal params in URL. |
|
|
404
351
|
| `retrieveSession(sessionId, billingApiUrl?)` | `Promise<CheckoutSession>` | Retrieves a checkout session by ID via `GET /v1/checkouts/sessions/{id}`. Uses `billingApiUrl` from config or the optional second argument. |
|
|
405
352
|
| `retrieveUnifiedSession(sessionId, billingApiUrl?)` | `Promise<NormalizedCheckoutSession>` | Retrieves and normalizes a checkout session, including provider-specific data (Stripe `clientSecret`/`publishableKey`, etc.). |
|
|
406
353
|
| `getRawProvider()` | `unknown` | Returns the raw underlying provider instance (e.g. Stripe object) |
|
|
407
|
-
| `destroy()` | `void` | Tears down
|
|
408
|
-
|
|
409
|
-
### Supported Element Types
|
|
410
|
-
|
|
411
|
-
- `payment` -- Provider PaymentElement for supported non-card methods
|
|
412
|
-
- `address` -- Address input element
|
|
354
|
+
| `destroy()` | `void` | Tears down telemetry and the provider |
|
|
413
355
|
|
|
414
356
|
### Vault card capture
|
|
415
357
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var ge=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var dt=Object.prototype.hasOwnProperty;var ut=(n,e)=>{for(var t in e)ge(n,t,{get:e[t],enumerable:!0})},pt=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of ct(e))!dt.call(n,o)&&o!==t&&ge(n,o,{get:()=>e[o],enumerable:!(r=lt(e,o))||r.enumerable});return n};var mt=n=>pt(ge({},"__esModule",{value:!0}),n);var Gt={};ut(Gt,{FloPay:()=>Q,FloPayElements:()=>K,PaymentAPI:()=>I,PciVaultCardCapture:()=>L,SESSION_CREATE_TELEMETRY:()=>be,StripeAdapter:()=>Y,cacheSessionDisplayData:()=>F,clearSessionDisplayData:()=>ce,createCheckoutSession:()=>De,createCheckoutSessionWithRetries:()=>Ue,dropThirdPartyOnlyError:()=>it.dropThirdPartyOnlyError,getSessionDisplayData:()=>le,loadFloPay:()=>st,toStripeAppearance:()=>nt,toStripeAppearanceTheme:()=>X});module.exports=mt(Gt);var it=require("@flopay/shared");var g=require("@flopay/shared");function D(n){return typeof n=="string"&&n.trim()?n:void 0}function Pe(n){if(typeof n=="string")return n.trim()?n:void 0;if(Array.isArray(n))return n.filter(t=>typeof t=="string"&&t.trim().length>0).join("; ")||void 0}function O(n=12e3){let e=Number.isFinite(n)&&n>=0?n:12e3,t=new AbortController,r=setTimeout(()=>t.abort(),e);return{signal:t.signal,clear:()=>clearTimeout(r)}}function yt(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function z(n,e){let t=150*2**n,r=Math.round(t*(.75+Math.random()*.5));return new Promise((o,s)=>{let i,a=()=>e.removeEventListener("abort",l),l=()=>{i!==void 0&&clearTimeout(i),a(),s(yt())};if(e.aborted){l();return}i=setTimeout(()=>{a(),o()},r),e.addEventListener("abort",l,{once:!0})})}var ht="flopay_session_display:";var ie=new Map;function ae(n){return`${ht}${n}`}function fe(){if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}}function F(n,e,t){if(!n)return;let r=t?.ttlMs??36e5,o={data:e,expiresAt:Date.now()+r},s=fe();if(s)try{s.setItem(ae(n),JSON.stringify(o));return}catch{}ie.set(n,o)}function le(n){if(!n)return null;let e=fe();if(e)try{let r=e.getItem(ae(n));if(r){let o=JSON.parse(r);if(o&&typeof o.expiresAt=="number"&&o.expiresAt>Date.now())return o.data;e.removeItem(ae(n))}}catch{}let t=ie.get(n);if(t){if(t.expiresAt>Date.now())return t.data;ie.delete(n)}return null}function ce(n){if(!n)return;ie.delete(n);let e=fe();if(e)try{e.removeItem(ae(n))}catch{}}var w=require("@flopay/shared"),gt="/v1/sdk-telemetry/events",Ce=16,ft=64,Ct=1500,Ee=1e3,vt=64,Tt="00000000-0000-4000-8000-000000000000",_t={technical_error:8,lifecycle:32,expected_outcome:32,performance:24};function j(){try{return globalThis.crypto.randomUUID()}catch{let n=new Uint8Array(16);try{globalThis.crypto.getRandomValues(n)}catch{for(let t=0;t<n.length;t+=1)n[t]=Math.floor(Math.random()*256)}n[6]=n[6]&15|64,n[8]=n[8]&63|128;let e=[...n].map(t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}}function bt(n){try{return new TextEncoder().encode(n).byteLength}catch{return n.length}}function wt(n){return JSON.stringify([n.code,n.failureCategory,n.stage,n.provider,n.attempt,n.statusClass,n.requestCategory,n.paymentMethodCategory,n.checkoutMode,n.layout])}function M(){return globalThis.performance?.now()??0}var _=class{constructor(e){this.ingestionDisabled=!1;this.queue=[];this.sequence=0;this.flushTimer=null;this.flushInFlight=null;this.reportedFailures=new Map;this.checkoutContext={};this.checkoutStartedAt=null;this.destroyed=!1;this.observers=new Set;this.pageExitHandler=()=>{this.drainQueue()};this.visibilityHandler=()=>{document.visibilityState==="hidden"&&this.flush()};this.eventCounts={technical_error:0,lifecycle:0,expected_outcome:0,performance:0};this.endpoint=`${e.billingApiUrl.replace(/\/+$/,"")}${gt}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=j(),this.merchantEnabled=e.enabled!==!1,this.clock=e.clock??M,this.browserTransportAvailable=typeof window<"u"&&typeof document<"u",this.browserTransportAvailable&&(window.addEventListener("pagehide",this.pageExitHandler),document.addEventListener("visibilitychange",this.visibilityHandler))}log(e){this.notify({...e,class:"lifecycle"}),this.canCollect()&&this.enqueue((0,w.buildTelemetryLogEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}error(e){if(this.notify({...e,class:"technical_error"}),!this.canCollect())return;let t=(0,w.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:Tt,sequence:0}),r=wt(t),o=this.now();this.pruneReportedFailures(o);let s=this.reportedFailures.get(r);if(s!==void 0&&o>=s&&o-s<Ee){this.log({name:"operation.deduplicated",stage:e.stage,provider:e.provider,paymentMethodCategory:e.paymentMethodCategory,attempt:e.attempt});return}this.rememberReportedFailure(r,o),this.enqueue((0,w.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue((0,w.buildTelemetryPerformanceEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue((0,w.buildTelemetryTerminalEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++})),e.outcome!=="action_required"&&this.checkoutStartedAt!==null)){let t=this.checkoutStartedAt;this.checkoutStartedAt=null,this.performance({stage:"total_journey",durationMs:Math.max(0,this.now()-t),durationMode:"total",provider:e.provider,paymentMethodCategory:e.paymentMethodCategory})}}now(){try{return this.clock()}catch{return M()}}subscribe(e){return this.destroyed?()=>{}:(this.observers.add(e),()=>this.observers.delete(e))}notify(e){if(!this.destroyed)for(let t of this.observers)try{t(e)}catch{}}pruneReportedFailures(e){for(let[t,r]of this.reportedFailures)(e<r||e-r>=Ee)&&this.reportedFailures.delete(t)}rememberReportedFailure(e,t){for(;this.reportedFailures.size>=vt;){let r=this.reportedFailures.keys().next();if(r.done)break;this.reportedFailures.delete(r.value)}this.reportedFailures.set(e,t)}setCheckoutContext(e){this.checkoutContext={checkoutMode:e.checkoutMode,layout:e.layout}}beginCheckout(e={}){return this.canCollect()?(this.drainQueue(),this.setCheckoutContext(e),this.sequence=0,this.reportedFailures.clear(),this.eventCounts={technical_error:0,lifecycle:0,expected_outcome:0,performance:0},this.checkoutStartedAt=this.now(),this.checkoutStartedAt):0}enqueue(e){if(this.canCollect()&&!(this.queue.length>=ft||this.eventCounts[e.class]>=_t[e.class])){if(this.eventCounts[e.class]+=1,this.queue.push(e),this.queue.length>=Ce){this.flush();return}this.scheduleFlush()}}canCollect(){return this.browserTransportAvailable&&this.merchantEnabled&&!this.ingestionDisabled&&!this.destroyed}async flush(){if(this.flushInFlight)return this.flushInFlight;if(!this.browserTransportAvailable||this.destroyed||this.ingestionDisabled||this.queue.length===0)return;this.clearFlushTimer();let e=this.queue.splice(0,Ce);return this.flushInFlight=this.sendBatch(e).finally(()=>{this.flushInFlight=null,this.queue.length>0&&this.scheduleFlush()}),this.flushInFlight}destroy(){this.destroyed||(this.drainQueue(),this.destroyed=!0,this.clearFlushTimer(),this.browserTransportAvailable&&(window.removeEventListener("pagehide",this.pageExitHandler),document.removeEventListener("visibilitychange",this.visibilityHandler)),this.queue.splice(0),this.reportedFailures.clear(),this.observers.clear())}disable(){this.merchantEnabled=!1,this.queue.splice(0),this.reportedFailures.clear(),this.clearFlushTimer()}drainQueue(){if(!(!this.browserTransportAvailable||this.destroyed||this.ingestionDisabled||this.queue.length===0))for(this.clearFlushTimer();this.queue.length>0;){let e=this.queue.splice(0,Ce);this.sendBatch(e)}}async sendBatch(e){if(!this.browserTransportAvailable||this.ingestionDisabled)return;let t=(0,w.serializeTelemetryBatch)(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:j()});if(bt(t)>w.TELEMETRY_MAX_BATCH_BYTES)return;let r=typeof AbortController>"u"?null:new AbortController,o=null;try{let s=fetch(this.endpoint,{method:"POST",headers:{"content-type":"text/plain;charset=UTF-8"},body:t,credentials:"omit",keepalive:!0,referrerPolicy:"no-referrer",signal:r?.signal}).then(async l=>l.status!==202?null:(await l.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(l=>{o=setTimeout(()=>{r?.abort(),l(null)},Ct)});await Promise.race([s,i])==="disabled"&&this.disableFromIngestion()}catch{}finally{o&&clearTimeout(o)}}disableFromIngestion(){this.ingestionDisabled=!0,this.queue.splice(0),this.reportedFailures.clear(),this.clearFlushTimer()}scheduleFlush(){this.flushTimer||this.destroyed||this.ingestionDisabled||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flush()},0))}clearFlushTimer(){this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null)}},Re=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),Ae=globalThis;Ae[Re]===void 0&&Object.defineProperty(Ae,Re,{configurable:!0,enumerable:!1,writable:!1,value:n=>new _(n)});var ve=5,Ie=new WeakSet;function St(n){(typeof n=="object"&&n!==null||typeof n=="function")&&Ie.add(n)}function Mt(n){return(typeof n=="object"&&n!==null||typeof n=="function")&&Ie.has(n)}function kt(n,e){let t=e?.error,r=D(e?.code)??D(t?.code)??`http_${n}`,o=D(e?.message)??D(t?.message)??Pt(r,n);return new g.FloPayError(o,"api_error",{code:r,statusCode:n})}function Pt(n,e){switch(n){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${ve}.`;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 xe(n,e,t){let{billingApiUrl:r,checkoutBaseUrl:o,items:s=[],subscriptions:i=[],products:a,account:l,successUrl:c,cancelUrl:u,checkoutMode:y="confirm",captureMethod:p,couponCodes:m=[],tagsData:k,redirectParams:b={},setCookie:S=!0,clientId:ke,currency:G,utmMetadata:h,idempotencyKey:Z}=n,ee=(0,g.resolveIdempotencyKey)(Z);if(m.length>ve)throw new g.FloPayError(`Too many coupon codes \u2014 a checkout session accepts at most ${ve}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let x=a??(0,g.foldIntoProducts)(s,i);(0,g.assertCaptureMethodEligible)({captureMethod:p,products:x});let R=(0,g.resolveSessionCurrency)(G,s,i,x);if(!R)throw new g.FloPayError("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 N={clientId:ke,checkoutVersion:g.SDK_VERSION,successUrl:c,cancelUrl:u,currency:R,checkoutMode:y,products:x.map(A=>(0,g.buildProductPayload)(A,R)),accountData:{userId:l.userId,firstName:l.firstName??null,lastName:l.lastName??null,email:l.email,country:l.country??null,gender:l.gender??null,city:l.city??null,state:l.state??null,zip:l.zip??null,addressLine1:l.addressLine1??null,addressLine2:l.addressLine2??null},couponCodes:m};p==="manual"&&(N.captureMethod=p),k&&(N.tagsData=k),h?.length&&(N.utmMetadata=h);let W=`${r.replace(/\/+$/,"")}/v1/checkouts/sessions`,te={"Content-Type":"application/json"};ee&&(te[g.IDEMPOTENCY_KEY_HEADER]=ee);let V,re,at={method:"POST",headers:te,body:JSON.stringify(N),signal:e},ne;try{ne=await fetch(W,at)}catch(A){throw St(A),A}try{t?.(ne.status)}catch{}V=ne.status;try{re=await ne.json()}catch{}if(V>=400)throw kt(V,re);if(V===201){let A=re?.data?.uuid,he=re?.data?.nonce;if(!A)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!he)throw new g.FloPayError("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"});(x.length||R)&&F(A,{currency:R,products:x.map(v=>({code:v.code??v.providerItemId??v.providerPlanId,type:v.type,name:v.name??v.itemName??v.providerItemName??v.subscriptionName??v.providerPlanName??null,totalAmount:v.totalAmount,overrideAmount:v.overrideAmount,currency:v.currency??R}))});let oe=new URL(`${o.replace(/\/+$/,"")}/secure`);oe.searchParams.set("id",A);for(let[v,se]of Object.entries(b))oe.searchParams.set(v,se);if(S&&typeof window<"u"&&typeof document<"u"){let v=JSON.stringify({origin_url:u}),se=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(v)}; domain=.${se}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(he)}; domain=.${se}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=oe.toString()),{status:201,redirectUrl:oe.toString(),nonce:he}}return V===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:V}}async function De(n){let e=Fe(n),t=Oe(e),r=O(n.timeoutMs);try{let o=await xe(n,r.signal,t);return qe(e,o),o}catch(o){throw de(e,o),o}finally{r.clear(),B(e.reporter)}}function Oe(n){let e=!1;return t=>{if(e)return;e=!0;let r=(0,g.telemetryStatusClass)(t);n.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:r,attempt:n.attempt}),n.reporter.performance({stage:"session_first_byte",durationMs:n.reporter.now()-n.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:r,attempt:n.attempt})}}function Fe(n){let e=new _({billingApiUrl:n.billingApiUrl,sdkVersion:g.SDK_VERSION,enabled:n.telemetry!==!1}),t=e.now();return e.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:e,startedAt:t,attempt:0}}function qe(n,e){let t=(0,g.telemetryStatusClass)(e.status);n.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:t}),n.reporter.performance({stage:"session_create",durationMs:n.reporter.now()-n.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:t,attempt:n.attempt})}function de(n,e){let{reporter:t}=n,r=(0,g.classifyTelemetryFailure)(e,"CHECKOUT_SESSION_CREATE_FAILED");if(t.performance({stage:"session_create",durationMs:t.now()-n.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:r.statusClass,attempt:n.attempt}),e instanceof g.FloPayError&&e.type==="validation_error"){t.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(r.statusClass==="4xx"){t.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}t.error({...r,stage:"session_create",requestCategory:"session_create"})}function B(n){n.flush().catch(()=>{}).finally(()=>n.destroy())}async function Ue(n){let{maxRetries:e=2,...t}=n,r=Fe(n),o=Oe(r);if(!Number.isFinite(e)||!Number.isInteger(e)||e<0||e>=3)throw r.reporter.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),B(r.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let s={...t,idempotencyKey:(0,g.resolveIdempotencyKey)(t.idempotencyKey)},i=O(t.timeoutMs),a;for(let l=0;l<=e;l++){r.attempt=l;try{let c=await xe(s,i.signal,o);return qe(r,c),i.clear(),B(r.reporter),c}catch(c){a=c;let u=c instanceof Error&&c.name==="AbortError",y=Mt(c),p=c instanceof g.FloPayError&&c.code===g.IDEMPOTENCY_IN_PROGRESS_CODE;if((u||y||p)&&!i.signal.aborted&&l<e){r.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:l+1});try{await z(l,i.signal)}catch(m){throw de(r,m),i.clear(),B(r.reporter),m}continue}throw de(r,c),i.clear(),B(r.reporter),c}}throw de(r,a),i.clear(),B(r.reporter),a??new Error("Unknown error during checkout session creation")}var Le=require("@flopay/shared"),K=class{constructor(e,t){this.elementMap=new Map;this.provider=e,this.baseOptions=t??{}}async create(e,t){let r={...this.baseOptions,...t};if(e==="payment"){let a=r.paymentMethodTypes?.map(l=>l.trim()).filter(l=>l&&l.toLowerCase()!=="card");if(!a?.length)throw new Le.FloPayError("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});r.paymentMethodTypes=a}let o=this.provider.getElement(e);if(o)return this.elementMap.set(e,o),o;let s=this.elementMap.get(e);s&&s.destroy();let i=await this.provider.createElement(e,r);return this.elementMap.set(e,i),i}getElement(e){return this.elementMap.get(e)??null}async submit(){return{}}destroy(){for(let e of this.elementMap.values())e.destroy();this.elementMap.clear()}};var C=require("@flopay/shared");var d=require("@flopay/shared");var Ne=1e3,Et=500,Rt=15e3,At=3e3,It=1e4,xt=1e4;function Dt(n){return typeof n=="object"&&n!==null}function H(n,e){return D(n?.[e])}function Ve(n,e){return Pe(n?.[e])}function Ot(n,e){let t=n?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function je(n){return new Promise(e=>setTimeout(e,n))}function ue(){return new d.FloPayError("Checkout is still processing. Please try again shortly.","api_error",{code:"checkout_processing_timeout"})}async function q(n,e){let t=await n.json().catch(()=>null),r=Dt(t?.error)?t.error:null,o=Ve(t,"message")??Ve(r,"message")??e,s=H(t,"code")??H(t,"gatewayErrorCode")??H(r,"code")??`http_${n.status}`;return new d.FloPayError(o,"api_error",{code:s,statusCode:n.status})}async function Ft(n){let e=n.status===400?await n.clone().json().catch(()=>null):null;return(0,d.classifyPaymentRejection)(n.status,e)}function ze(n){return n===400||n===422}var pe=2;async function _e(n,e,t=pe,r){let o;for(let s=0;;s++)try{return await fetch(n,e)}catch(i){if(e?.signal?.aborted||i instanceof Error&&i.name==="AbortError")throw i;if(o=i,s>=t)throw o;try{r?.(s+1)}catch{}await je(150*2**s)}}var be=Symbol.for("@flopay/js.session-create.telemetry.v1");function qt(n){return n[be]}function Ut(n){return"now"in n||"onFirstByte"in n||"onSessionCreateFailure"in n||"onRetry"in n}function Be(n){return{userId:n.userId,firstName:n.firstName??null,lastName:n.lastName??null,email:n.email,country:n.country??null,gender:n.gender??null,city:n.city??null,state:n.state??null,zip:n.zip??null,addressLine1:n.addressLine1??null,addressLine2:n.addressLine2??null}}function Ke(n,e){e.tagsData&&(n.tagsData=e.tagsData),e.utmMetadata?.length&&(n.utmMetadata=e.utmMetadata),e.avsCheck!==void 0&&(n.avsCheck=e.avsCheck),e.checkoutType&&(n.checkoutType=e.checkoutType),e.checkoutLayout&&(n.checkoutLayout=e.checkoutLayout),e.avsConfig&&(n.avsConfig=e.avsConfig)}function Lt(n,e){let t={clientId:n.clientId,checkoutVersion:d.SDK_VERSION,successUrl:n.successUrl,cancelUrl:n.cancelUrl,currency:e,checkoutMode:"full",deferDataAttachment:!0};return n.captureMethod==="manual"&&(t.captureMethod=n.captureMethod),n.account.country&&(t.accountData={country:n.account.country}),Ke(t,n),t}function Nt(n,e,t){return{currency:e,products:t.map(r=>(0,d.buildProductPayload)(r,e)),couponCodes:n.couponCodes??[],accountData:Be(n.account)}}var U=class U{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let r=Ut(t);this.telemetryHooks=r?t:void 0,this.directTelemetry=r||t.telemetry===!1?void 0:new _({billingApiUrl:this.baseUrl,sdkVersion:d.SDK_VERSION})}destroy(){this.directTelemetry?.destroy()}reportDirectFailure(e,t,r,o,s="unknown"){let i=(0,d.classifyTelemetryFailure)(e,t);this.directTelemetry?.error({...i,stage:r,requestCategory:o,paymentMethodCategory:s})}reportAccountSnapshotFailure(e,t){let r=(0,d.classifyTelemetryFailure)(e,"NETWORK_REQUEST_FAILED");if(t==="best_effort"&&r.errorCode==="REQUEST_TIMEOUT"){this.directTelemetry?.log({name:"operation.fallback",stage:"processing",requestCategory:"account_snapshot",statusClass:"timeout"});return}this.directTelemetry?.error({...r,stage:"processing",requestCategory:"account_snapshot",paymentMethodCategory:"unknown"})}telemetryTimestamp(){try{return this.telemetryHooks?.now?.()??this.directTelemetry?.now()??M()}catch{return M()}}beginDirectTelemetryCheckout(e){!this.directTelemetry||this.directTelemetryCheckoutId===e||(this.directTelemetryCheckoutId=e,this.directTelemetry.beginCheckout())}beginDirectTelemetryOperation(){this.directTelemetry&&(this.directTelemetryCheckoutId=void 0,this.directTelemetry.beginCheckout())}adoptDirectTelemetryCheckout(e){e&&(this.directTelemetryCheckoutId=e)}async getCheckoutSession(e,t){this.beginDirectTelemetryCheckout(e);let r=this.telemetryTimestamp();this.directTelemetry?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let o={[d.FLO_SDK_VERSION_HEADER]:d.SDK_VERSION};t&&(o["x-checkout-session-token"]=t);try{let s=await _e(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:o},pe,c=>{this.telemetryHooks?.onRetry?.("session_read",c),this.directTelemetry?.log({name:"operation.retry",stage:"session_read",requestCategory:"session_read",attempt:c})}),i=Math.max(0,this.telemetryTimestamp()-r);try{this.telemetryHooks?.onFirstByte?.(i)}catch{}let a=`${Math.floor(s.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:a}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:a}),!s.ok)throw await q(s,"Failed to get checkout session");let l=await s.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:a}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",statusClass:a}),{...l,data:this.mergeCachedDisplayData(l.data)}}catch(s){throw this.directTelemetry?.error({...(0,d.classifyTelemetryFailure)(s,"NETWORK_REQUEST_FAILED"),stage:"session_read",requestCategory:"session_read"}),s}}cacheSessionDisplayData(e,t,r){F(e,t,r)}clearSessionDisplayData(e){ce(e)}async getVaultCapture(e,t){let r=`${this.baseUrl}\0${e}\0${t??""}`,o=U.activeVaultCaptureRequests.get(r);if(o)return o;let s=this.requestVaultCapture(e,t);U.activeVaultCaptureRequests.set(r,s);try{return await s}finally{U.activeVaultCaptureRequests.get(r)===s&&U.activeVaultCaptureRequests.delete(r)}}async requestVaultCapture(e,t){let r=new AbortController,o=setTimeout(()=>r.abort(),xt);this.beginDirectTelemetryCheckout(e);let s=this.telemetryTimestamp();this.directTelemetry?.log({name:"vault.capture.requested",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card"});let i={"Content-Type":"application/json"};t&&(i["x-checkout-session-token"]=t);try{let a=await _e(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:r.signal},pe,c=>{this.telemetryHooks?.onRetry?.("vault_capture",c),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:c})});if(!a.ok)throw await q(a,"Failed to load the secure card form");let l=await a.json();return this.directTelemetry?.performance({stage:"vault_request",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"vault_capture",paymentMethodCategory:"card",statusClass:"2xx"}),this.toVaultBlock(l)}catch(a){let l=r.signal.aborted?new d.FloPayError("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):a;throw this.reportDirectFailure(l,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),l}finally{clearTimeout(o)}}async getUnifiedCheckoutSession(e,t){let r=await this.getCheckoutSession(e,t),o=this.normalizeRawSession(r.data),s=r.vault;return s&&o.data.session&&(o.data.session.vault=this.toVaultBlock(s)),o}async processPayment(e,t,r){if(this.beginDirectTelemetryCheckout(t.sessionId),!t.nonce)throw this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"process_payment"}),new d.FloPayError("processPayment requires `nonce` \u2014 pass the value returned from session creation.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let o=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.processing.started",stage:"processing",requestCategory:"process_payment"});let{nonce:s,...i}=t,a;try{a=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(t.sessionId)}/process`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":s},body:JSON.stringify(i)})}catch(l){throw this.reportDirectFailure(l,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),l}if(!a.ok&&a.status!==202){let l=await Ft(a);return l?this.directTelemetry?.terminal({outcome:l,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(a.status),failureCategory:a.status>=500?"server_error":void 0}),a}try{let l=await this.resolveProcessResponse(a,t.sessionId,{...r,nonce:s});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(l.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(l.status)}),l}catch(l){throw l instanceof d.FloPayError&&l.code==="checkout_processing_timeout"||this.reportDirectFailure(l,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),l}}async patchAccountSnapshot(e,t,r,o){this.beginDirectTelemetryCheckout(e);let s=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.state_transition",stage:"processing",requestCategory:"account_snapshot"});let i=o?.timeoutMs??It,a=new AbortController,l=()=>a.abort();o?.signal&&(o.signal.aborted?a.abort():o.signal.addEventListener("abort",l,{once:!0}));let c=setTimeout(()=>a.abort(),i);try{let u;try{u=await _e(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/account`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t},body:JSON.stringify(r),signal:a.signal},pe,y=>{this.telemetryHooks?.onRetry?.("account_snapshot",y),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:y})})}finally{clearTimeout(c),o?.signal?.removeEventListener("abort",l)}if(!u.ok)throw await q(u,"Failed to persist account snapshot");this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"account_snapshot",statusClass:"2xx"})}catch(u){throw this.reportAccountSnapshotFailure(u,o?.telemetryMode??"blocking"),u}}async createSessionIntent(e,t,r,o){if(!t)throw new d.FloPayError("createSessionIntent requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=r,i=s.paymentMethodType,a=typeof i=="string"&&i.trim().toLowerCase()==="card",l=typeof i=="string"&&i.length>0&&!a&&(typeof s.paymentMethodId=="string"||s.paymentMethodId===null),c=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm")&&(s.intentKind==="payment"||s.intentKind==="setup"),u=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodId===null&&(s.paymentMethodType==="paypal"&&s.intentKind==="payment"||s.paymentMethodType===d.PAYPAL_VAULTED_PAYMENT_METHOD_TYPE&&(s.intentKind==="payment"||s.intentKind==="setup"));if(!l||!c&&!u)throw new d.FloPayError("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let y=s.authorizationAttemptId;if(y!==void 0&&!(0,d.isUuidV4)(y))throw new d.FloPayError("authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.","validation_error",{code:"InvalidAuthorizationAttemptId",param:"authorizationAttemptId"});let p=(0,d.isUuidV4)(y)?y:(0,d.randomUuidV4)();this.beginDirectTelemetryCheckout(e);let m=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.intent.started",stage:"processing",requestCategory:"intent_create"});let k={"Content-Type":"application/json","x-checkout-session-token":t,[d.IDEMPOTENCY_KEY_HEADER]:o?.idempotencyKey||p},b=!1;try{let S=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:k,body:JSON.stringify({...r,authorizationAttemptId:p}),signal:o?.signal});if(!S.ok){b=!0;let W=await q(S,"Failed to create checkout intent"),te=(0,d.classifyTelemetryFailure)(W,"PAYMENT_PROCESSING_FAILED");throw ze(W.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...te,stage:"processing",requestCategory:"intent_create"}),W}let G=(await S.json()).data;if(!G||typeof G!="object")throw new d.FloPayError("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let h=G,Z=h.paymentMethodType,ee=(h.paymentMethodCategory==="wallet"||h.paymentMethodCategory==="apm")&&typeof Z=="string"&&Z.trim().toLowerCase()!=="card"&&(typeof h.paymentMethodId=="string"||h.paymentMethodId===null)&&typeof h.providerObjectId=="string",x=h.provider==="stripe"&&(h.intentKind==="payment"||h.intentKind==="setup")&&typeof h.clientSecret=="string",R=h.provider==="paypal"&&h.paymentMethodCategory==="wallet"&&h.paymentMethodId===null&&(h.paymentMethodType==="paypal"&&h.intentKind==="payment"&&(h.providerObjectType==="order"||h.providerObjectType==="subscription")||h.paymentMethodType===d.PAYPAL_VAULTED_PAYMENT_METHOD_TYPE&&h.intentKind==="payment"&&h.providerObjectType==="order"||h.paymentMethodType===d.PAYPAL_VAULTED_PAYMENT_METHOD_TYPE&&h.intentKind==="setup"&&h.providerObjectType==="setup_token")&&h.clientSecret===null,N=h.provider===r.provider&&h.paymentMethodCategory===r.paymentMethodCategory&&h.paymentMethodType===r.paymentMethodType&&h.paymentMethodId===r.paymentMethodId&&h.intentKind===r.intentKind;if(!ee||!x&&!R||!N)throw new d.FloPayError("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});return this.directTelemetry?.log({name:"payment.intent.completed",stage:"processing",requestCategory:"intent_create",statusClass:(0,d.telemetryStatusClass)(S.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-m),durationMode:"machine",requestCategory:"intent_create",statusClass:(0,d.telemetryStatusClass)(S.status)}),h}catch(S){throw b||this.reportDirectFailure(S,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),S}}async reportSessionIntentDecline(e,t,r,o){if(!t)throw new d.FloPayError("reportSessionIntentDecline requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=r,i=s.providerDeclineReason,a=s.paymentMethodType,l=typeof i=="string"&&/^[a-z0-9][a-z0-9_.:-]{0,63}$/i.test(i)&&!/^(?:pm|pi|seti|tok|src|cus|sess|sk|pk)_/i.test(i),c=typeof a=="string"&&a.length>0&&a.trim().toLowerCase()!=="card"&&l,u=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm"),y=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodType==="paypal";if(!c||!u&&!y)throw new d.FloPayError("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let p=y?{provider:"paypal",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:i}:{provider:"stripe",paymentMethodCategory:s.paymentMethodCategory,paymentMethodType:s.paymentMethodType,providerDeclineReason:i},m=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents/decline`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":t},body:JSON.stringify(p),signal:o?.signal});if(!m.ok)throw await q(m,"Failed to report checkout decline")}async getPaymentsByEmail(e,t){this.beginDirectTelemetryOperation();let r=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.recovery.started",stage:"recovery",requestCategory:"other",paymentMethodCategory:"saved"});let o=t?.page??1,s=t?.limit??1,i=new URLSearchParams({email:e,page:String(o),limit:String(s),sortField:"createdAt",sortDirection:"DESC"});try{let a=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!a.ok)throw new d.FloPayError("Failed to fetch payments","api_error",{statusCode:a.status});let l=await a.json();return this.directTelemetry?.log({name:"operation.recovery.completed",stage:"recovery",requestCategory:"other",paymentMethodCategory:"saved",statusClass:"2xx"}),this.directTelemetry?.performance({stage:"recovery",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"other",paymentMethodCategory:"saved",statusClass:"2xx"}),l}catch(a){throw this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","other","saved"),a}}async createAndFetchSession(e){if((0,d.isDetachedSessionEligible)(e))return(await this.createDetachedSession(e)).claimed;this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),r=O(e.timeoutMs??12e3),o={attempt:0,statusClass:"unknown"};this.directTelemetry?.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"});try{let s=await this.createAndFetchSessionRequest(e,t,r.signal,o);return this.adoptDirectTelemetryCheckout(s.data.session?.id),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:o.statusClass}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:o.attempt}),s}catch(s){throw this.reportSessionCreateFailure(s,t,o),s}finally{r.clear()}}async createAndFetchSessionRequest(e,t,r,o){let s=e.products??(0,d.foldIntoProducts)(e.items,e.subscriptions);(0,d.assertCaptureMethodEligible)({captureMethod:e.captureMethod,products:s});let i=(0,d.resolveSessionCurrency)(e.currency,e.items,e.subscriptions,s);if(!i)throw new d.FloPayError("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 a={clientId:e.clientId,checkoutVersion:d.SDK_VERSION,successUrl:e.successUrl,cancelUrl:e.cancelUrl,currency:i,checkoutMode:e.checkoutMode??"full",products:s.map(p=>(0,d.buildProductPayload)(p,i)),accountData:Be(e.account),couponCodes:e.couponCodes??[]};e.captureMethod==="manual"&&(a.captureMethod=e.captureMethod),e.tokenizedData&&(a.tokenizedData=e.tokenizedData),Ke(a,e);let c=await(await this.postCheckoutSessionCreate(a,e,t,r,o)).json();if(c.data&&"gateways"in c.data){this.autoCacheDisplayData(c.data.uuid,e);let p=this.mergeCachedDisplayData(c.data),m=this.normalizeRawSession(p);return c.vault&&m.data.session&&(m.data.session.vault=this.toVaultBlock(c.vault)),{...m,autoProcessingError:c.autoProcessingError,autoProcessingAttempted:c.autoProcessingAttempted,autoProcessingPending:c.autoProcessingPending}}let u=c.data?.uuid;if(!u)throw new d.FloPayError("No session ID returned","api_error",{code:"InvalidCheckoutSessionResponse"});return this.autoCacheDisplayData(u,e),this.adoptDirectTelemetryCheckout(u),{...await this.getUnifiedCheckoutSession(u),autoProcessingError:c.autoProcessingError,autoProcessingAttempted:c.autoProcessingAttempted,autoProcessingPending:c.autoProcessingPending}}async postCheckoutSessionCreate(e,t,r,o,s){let i={"Content-Type":"application/json",[d.FLO_SDK_VERSION_HEADER]:d.SDK_VERSION},a=(0,d.resolveIdempotencyKey)(t.idempotencyKey);a&&(i[d.IDEMPOTENCY_KEY_HEADER]=a);let l,c=!1,u=qt(t),y=p=>{try{this.telemetryHooks?.onRetry?.("session_create",p),this.directTelemetry?.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:p})}catch{}};for(let p=0;p<3;p++){s.attempt=p;try{u?.onAttempt?.(p)}catch{}try{l=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:i,body:JSON.stringify(e),signal:o})}catch(b){if(s.statusClass=o.aborted||b instanceof Error&&b.name==="AbortError"?"timeout":"network_error",o.aborted||b instanceof Error&&b.name==="AbortError"||p>=2)throw b;let S=p+1;y(S),await z(p,o);continue}let m=(0,d.telemetryStatusClass)(l.status);if(s.statusClass=m,c||(c=!0,this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:m,attempt:p}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_create",statusClass:m,attempt:p})),l.status===204)throw new d.FloPayError("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(l.ok)break;let k=await q(l,"Failed to create checkout session");if(k.code===d.IDEMPOTENCY_IN_PROGRESS_CODE&&p<2){y(p+1),await z(p,o);continue}throw k}if(!l)throw new TypeError("Checkout-session creation exhausted its retry budget.");return l}async createDetachedSession(e){this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),r=O(e.timeoutMs??12e3),o={attempt:0,statusClass:"unknown"};this.directTelemetry?.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"});let s=e.products??(0,d.foldIntoProducts)(e.items,e.subscriptions);try{(0,d.assertCaptureMethodEligible)({captureMethod:e.captureMethod,products:s})}catch(m){throw r.clear(),this.reportSessionCreateFailure(m,t,o),m}let i=(0,d.resolveSessionCurrency)(e.currency,e.items,e.subscriptions,s);if(!i)throw r.clear(),this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),new d.FloPayError("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 a;try{a=Nt(e,i,s)}catch(m){throw r.clear(),this.reportSessionCreateFailure(m,t,o),m}let l,c;try{if(c=await(await this.postCheckoutSessionCreate(Lt(e,i),e,t,r.signal,o)).json(),!c.data||!("gateways"in c.data))throw new d.FloPayError("The billing API returned no session shell for a detached create. It must support `deferDataAttachment` (TeamFloPay/backend#1099).","api_error",{code:"InvalidCheckoutSessionResponse"});l=this.normalizeRawSession(this.mergeCachedDisplayData(c.data)),c.vault&&l.data.session&&(l.data.session.vault=this.toVaultBlock(c.vault))}catch(m){throw r.clear(),this.reportSessionCreateFailure(m,t,o),m}let u=l.data.session?.id??c.data.uuid??"",y=l.data.session?.clientSecret??c.data.nonce??"";if(!u||!y){r.clear();let m=new d.FloPayError("Checkout session shell was created without a session id or nonce.","api_error",{code:"InvalidCheckoutSessionResponse"});throw this.reportSessionCreateFailure(m,t,o),m}this.adoptDirectTelemetryCheckout(u),this.directTelemetry?.log({name:"session.shell.ready",stage:"session_shell",requestCategory:"session_create",statusClass:o.statusClass,paymentMethodCategory:"card"}),this.directTelemetry?.performance({stage:"session_shell",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:o.attempt,paymentMethodCategory:"card"});let p=this.claimCheckoutSession(u,y,a,{params:e,startedAt:t,deadline:r,createAttempt:o.attempt});return p.catch(()=>{}),{shell:l,sessionId:u,nonce:y,claimed:p}}async claimCheckoutSession(e,t,r,o){let s=o?.startedAt??this.telemetryTimestamp(),i=this.telemetryTimestamp(),a=o?.deadline??O(12e3),l=JSON.stringify(r),c="unknown",u=0;this.directTelemetry?.log({name:"session.claim.started",stage:"session_claim",requestCategory:"session_claim"});try{let y;for(u=0;u<3;u++){try{y=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/claim`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t,[d.FLO_SDK_VERSION_HEADER]:d.SDK_VERSION},body:l,signal:a.signal})}catch(k){let b=a.signal.aborted||k instanceof Error&&k.name==="AbortError";if(c=b?"timeout":"network_error",b||u>=2)throw k;try{this.telemetryHooks?.onRetry?.("session_claim",u+1),this.directTelemetry?.log({name:"operation.retry",stage:"session_claim",requestCategory:"session_claim",attempt:u+1})}catch{}await z(u,a.signal);continue}if(c=(0,d.telemetryStatusClass)(y.status),y.ok)break;throw await q(y,"Failed to attach checkout session data")}if(!y)throw new TypeError("Checkout-session claim exhausted its retry budget.");let p=await y.json();if(!p.data?.gateways)throw new d.FloPayError("The billing API returned no checkout session with gateways after claiming it.","api_error",{code:"InvalidCheckoutSessionResponse"});o?.params&&this.autoCacheDisplayData(p.data.uuid??e,o.params);let m=this.normalizeRawSession(this.mergeCachedDisplayData(p.data));return p.vault&&m.data.session&&(m.data.session.vault=this.toVaultBlock(p.vault)),this.directTelemetry?.log({name:"session.claim.completed",stage:"session_claim",requestCategory:"session_claim",statusClass:c}),this.directTelemetry?.performance({stage:"session_claim",durationMs:Math.max(0,this.telemetryTimestamp()-i),durationMode:"machine",requestCategory:"session_claim",statusClass:c,attempt:u}),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:c}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"session_create",statusClass:c,attempt:o?.createAttempt??u}),m}catch(y){throw this.reportSessionCreateFailure(y,s,{attempt:u,statusClass:c},"session_claim"),y}finally{a.clear()}}reportSessionCreateFailure(e,t,r,o="session_create"){if(!(e instanceof d.FloPayError&&e.code==="session_auto_completed"))try{this.telemetryHooks?.onSessionCreateFailure?.(e)}catch{}let s=(0,d.classifyTelemetryFailure)(e,"CHECKOUT_SESSION_CREATE_FAILED");if(this.directTelemetry?.performance({stage:o,durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:o==="session_claim"?"session_claim":"session_create",statusClass:s.statusClass,attempt:r.attempt}),e instanceof d.FloPayError&&e.type==="validation_error"||e instanceof d.FloPayError&&ze(e.statusCode)){this.directTelemetry?.terminal({outcome:"validation_rejected",stage:o,requestCategory:o==="session_claim"?"session_claim":"session_create",...e.type==="validation_error"?{}:{statusClass:"4xx"}});return}e instanceof d.FloPayError&&e.code==="session_auto_completed"||this.directTelemetry?.error({...s,stage:o,requestCategory:o==="session_claim"?"session_claim":"session_create"})}async waitForCheckoutSessionCompletion(e,t){this.beginDirectTelemetryCheckout(e);let r=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.recovery.started",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved"});let o=t?.timeoutMs??Rt,s=Date.now()+o,i=this.clampRetryAfterMs(t?.initialDelayMs??Ne),a=0;try{for(;;){let l=s-Date.now();if(l<=0)throw ue();if(i>0){try{a+=1,this.telemetryHooks?.onRetry?.("session_read",a),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:a})}catch{}if(await je(Math.min(i,l)),Date.now()>=s)throw ue()}let c=await this.getUnifiedCheckoutSession(e,t?.nonce),u=c.data.session?.status;if(u==="authorized"||u==="complete"||u==="expired")return this.directTelemetry?.log({name:"operation.recovery.completed",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved"}),this.directTelemetry?.performance({stage:"recovery",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",paymentMethodCategory:"saved"}),c;if(Date.now()>=s)throw ue();i=this.clampRetryAfterMs(Math.max(i*2,Et))}}catch(l){throw l instanceof d.FloPayError&&l.code==="checkout_processing_timeout"&&this.reportDirectFailure(l,"RECOVERY_FAILED","recovery","session_read","saved"),l}}normalizeRawSession(e){let t=e.gateways??{},r=[],o={session:this.toCheckoutSession(e)},s=t.stripe;if(s?.publishableKey){r.push("stripe");let l=[e.stripeClientSecret,s.stripeClientSecret].find(c=>typeof c=="string"&&c.length>0);o.stripe={clientSecret:l??"",publishableKey:s.publishableKey??void 0,paypalPublishableKey:s.paypalPublishableKey??void 0,environment:s.environment,enabledPaymentMethods:Array.isArray(s.enabledPaymentMethods)?s.enabledPaymentMethods.filter(c=>typeof c=="string"):void 0}}let i=t.paypal;return i?.publishableKey&&(r.push("paypal"),o.paypal={publishableKey:i.publishableKey,environment:i.environment,providerObjectType:i.providerObjectType}),{providers:r,mode:"tokenize",data:o,raw:{data:e}}}toCheckoutSession(e){let t=e.products??[],r=typeof e.totalAmount=="number"&&Number.isFinite(e.totalAmount),o=t.reduce((c,u)=>c+(u.overrideAmount??u.totalAmount??0),0),s=r?e.totalAmount:o,i=Math.round(s*100),a=e.currency??t[0]?.currency??"USD",l=e.checkoutMode==="setup"?"setup":t.some(c=>c.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:l,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:a,captureMethod:e.captureMethod,paymentId:e.paymentId,authorizationExpiresAt:e.authorizationExpiresAt,failureOutcome:(0,d.normalizeCheckoutFailureOutcome)(e.outcome)??(0,d.normalizeCheckoutFailureOutcome)(e.failureReason)??(e.status==="expired"&&e.captureMethod==="manual"?"authorization_expired":void 0),customer:{id:e.accountData.userId,email:e.accountData.email,firstName:e.accountData.firstName,lastName:e.accountData.lastName,country:e.accountData.country??void 0,city:e.accountData.city??void 0,state:e.accountData.state??void 0,zip:e.accountData.zip??void 0,gender:e.accountData.gender??void 0,line1:e.accountData.addressLine1??void 0,line2:e.accountData.addressLine2??void 0},metadata:{},checkoutMode:e.checkoutMode,providerPaymentMethodId:typeof e.providerPaymentMethodId=="string"?e.providerPaymentMethodId:null,products:t.map(c=>({...c,totalAmount:typeof c.totalAmount=="number"?c.totalAmount:void 0,overrideAmount:typeof c.overrideAmount=="number"?c.overrideAmount:null,currency:typeof c.currency=="string"?c.currency:void 0,metadata:c.metadata??null})),successUrl:e.successUrl,cancelUrl:e.cancelUrl,coupons:e.coupons,subtotalAmount:e.subtotalAmount,discountAmount:e.discountAmount,totalAmount:e.totalAmount,createdAt:e.createdAt,gateways:e.gateways,accountData:e.accountData,tagsData:e.tagsData}}toVaultBlock(e){return{html:typeof e.html=="string"?e.html:void 0,url:typeof e.url=="string"?e.url:void 0,messageToken:typeof e.messageToken=="string"?e.messageToken:void 0,expectedOrigin:typeof e.expectedOrigin=="string"?e.expectedOrigin:void 0}}toCheckoutSessionStatus(e){return e==="completed"?"complete":e==="authorized"?"authorized":e==="expired"?"expired":"open"}async resolveProcessResponse(e,t,r){if(e.status!==202)return e;let o=await e.json().catch(()=>null),s=this.toCheckoutProcessingPending(o,e,t),i=await this.waitForCheckoutSessionCompletion(s.sessionId,{initialDelayMs:s.retryAfterMs,timeoutMs:r?.pollTimeoutMs,nonce:r?.nonce});if(i.data.session?.status==="complete")return new Response(null,{status:204,statusText:"No Content"});if(i.data.session?.status==="authorized"){let a=i.data.session;return new Response(JSON.stringify({status:"authorized",paymentId:a.paymentId,sessionId:a.id||t,authorizationExpiresAt:a.authorizationExpiresAt}),{status:200,headers:{"Content-Type":"application/json"}})}if(i.data.session?.status==="expired"){let a=i.data.session.failureOutcome==="authorization_expired"||i.data.session.captureMethod==="manual";throw new d.FloPayError(a?"Authorization has expired.":"Checkout session has expired.","api_error",{code:a?"authorization_expired":"checkout_session_expired"})}throw ue()}toCheckoutProcessingPending(e,t,r){let o=t.headers.get("Retry-After"),s=o===null||o.trim()===""?void 0:Number(o),i=s!==void 0&&Number.isFinite(s)?s*1e3:void 0;return{type:"checkout_processing",sessionId:H(e,"sessionId")??r,retryAfterMs:this.clampRetryAfterMs(Ot(e,"retryAfterMs")??i??Ne),statusUrl:H(e,"statusUrl"),sessionUrl:H(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,At))}autoCacheDisplayData(e,t){if(!e)return;let r=t.products??(0,d.foldIntoProducts)(t.items,t.subscriptions);if(r.length===0&&!t.currency)return;let o=t.products!==void 0,s=(0,d.resolveSessionCurrency)(t.currency,o?void 0:t.items,o?void 0:t.subscriptions,r);F(e,{currency:s??void 0,products:r.map(i=>({code:i.code??i.providerItemId??i.providerPlanId,type:i.type,name:i.name??i.itemName??i.providerItemName??i.subscriptionName??i.providerPlanName??null,totalAmount:i.totalAmount,overrideAmount:i.overrideAmount,currency:i.currency??s??void 0}))})}mergeCachedDisplayData(e){let t=le(e.uuid),r=new Map,o=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let a=o(i.code);a&&r.set(a,i)}let s=(e.products??[]).map(i=>{let a=o(i.code),l=a?r.get(a):void 0;return{...i,name:i.name??l?.name??null,totalAmount:i.totalAmount??l?.totalAmount,overrideAmount:i.overrideAmount??l?.overrideAmount,currency:i.currency??l?.currency}});return{...e,currency:e.currency??t?.currency,products:s}}};U.activeVaultCaptureRequests=new Map;var I=U;function He(n,e){let t=I;return new t(n,e)}var T=require("@flopay/shared");var we="flopay-vault",$e={ready:["vault.widget.ready","vault_ready"],submitting:["vault.submission.started","vault_submit"],blocked:["operation.state_transition","vault_submit"],action_required:["vault.action.required","three_ds_handoff"]};function J(n){let e={class:n.class,stage:n.stage};"code"in n&&(e.code=n.code),"provider"in n&&n.provider&&(e.provider=n.provider),"paymentMethodCategory"in n&&n.paymentMethodCategory&&(e.paymentMethodCategory=n.paymentMethodCategory),"outcome"in n&&(e.outcome=n.outcome),"durationMs"in n&&n.durationMs!==void 0&&(e.durationMs=n.durationMs),"durationMode"in n&&n.durationMode&&(e.durationMode=n.durationMode);try{globalThis.Sentry?.addBreadcrumb?.({category:"flopay.telemetry",level:n.class==="technical_error"?"error":"info",message:n.class==="lifecycle"?n.name:n.class==="technical_error"?n.code:n.class==="expected_outcome"?n.outcome:"sdk.performance",data:e})}catch{}}function me(n,e){return(0,T.buildTelemetryLogEvent)({eventId:"11111111-1111-4111-8111-111111111111",name:n,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function Ye(n){return n?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function Ge(n,e,t="checkout"){return t==="card_setup"?n.type==="decline"?"card_setup_declined":"card_setup_succeeded":n.type==="decline"?"payment_declined":n.outcome==="authorized"||e==="manual"?"payment_authorized":"payment_succeeded"}function Vt(n,e,t,r="checkout"){let{type:o}=n;if(o==="complete"||o==="decline")return(0,T.buildTelemetryTerminalEvent)({eventId:"22222222-2222-4222-8222-222222222222",outcome:Ge(n,t,r),sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(o==="error"){let a=Ye(e);return(0,T.buildTelemetryErrorEvent)({eventId:"33333333-3333-4333-8333-333333333333",...a,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[s,i]=$e[o];return me(s,i)}function zt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===we&&(e.type==="ready"||e.type==="submitting"||e.type==="blocked"||e.type==="complete"||e.type==="decline"||e.type==="error"||e.type==="action_required")}function jt(n){if(typeof n!="object"||n===null)return;let e=n,t=e.status;if(!(typeof e.id!="string"||e.id.trim()===""||typeof e.brand!="string"||e.brand.trim()===""||typeof e.lastFour!="string"||!/^\d{4}$/.test(e.lastFour)||typeof e.expiryMonth!="number"||!Number.isInteger(e.expiryMonth)||e.expiryMonth<1||e.expiryMonth>12||typeof e.expiryYear!="number"||!Number.isInteger(e.expiryYear)||e.expiryYear<1970||e.expiryYear>9999||t!=="pending"&&t!=="active"&&t!=="deleted"))return{id:e.id,brand:e.brand,lastFour:e.lastFour,expiryMonth:e.expiryMonth,expiryYear:e.expiryYear,status:t}}function Bt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===we&&e.type==="validation"&&Array.isArray(e.messages)}function Kt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===we&&e.type==="resize"&&typeof e.height=="number"&&Number.isFinite(e.height)}var L=class{constructor(e={},t){this.provider="pcivault";this.container=null;this.messageHandler=null;this.actionOverlay=null;this.threeDsReturnHandler=null;this.messageToken=null;this.expectedOrigin=null;this.theme=null;this.submitGateBlocked=!1;this.cardFieldOrder=null;this.cardAutoFocus=!0;this.mountStartedAt=0;this.vaultReadyReported=!1;this.submissionStarted=!1;this.submissionStartedAt=null;this.listeners=new Map;this.config=e,this.ownsTelemetryReporter=!t&&e.telemetry!==!1,this.telemetryReporter=t?.reporter??(this.ownsTelemetryReporter?new _({billingApiUrl:(0,T.resolveBillingApiUrl)(),sdkVersion:T.SDK_VERSION}):void 0)}async mount(e,t){this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new _({billingApiUrl:(0,T.resolveBillingApiUrl)(),sdkVersion:T.SDK_VERSION}));let r=this.telemetryReporter;if(this.config.operation==="card_setup"&&r&&this.setupTelemetryReporter!==r){this.setupTelemetryReporter=r;try{r.beginCheckout({checkoutMode:"setup"})}catch{}}if(this.mountStartedAt=this.telemetryReporter?.now?.()??M(),this.vaultReadyReported=!1,this.submissionStarted=!1,this.submissionStartedAt=null,typeof window>"u"||typeof document>"u")throw this.reportVaultLoadFailure(),new T.FloPayError("The vault card form is only available in the browser.","api_error",{code:"card_capture_no_window"});if(!t?.html?.trim())throw this.reportVaultLoadFailure(),new T.FloPayError("No vault capture widget HTML was provided to mount the secure card form.","api_error",{code:"card_capture_no_widget_html"});this.container=e,this.messageToken=t.messageToken??null,this.expectedOrigin=t.expectedOrigin??this.config.expectedOrigin??null,this.theme=t.theme??null;try{this.attachMessageListener(),this.injectWidget(e,t.html)}catch(o){throw this.reportVaultLoadFailure(),o}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),J(me("vault.widget.mounted","vault_mount")),this.telemetryReporter?.log({name:"vault.widget.mounted",stage:"vault_mount",provider:"pcivault",paymentMethodCategory:"card"}),this.emit("ready",{sessionId:this.config.sessionId})}reportVaultLoadFailure(){this.telemetryReporter?.error({errorCode:"VAULT_LOAD_FAILED",failureCategory:"provider_runtime",stage:"vault_mount",provider:"pcivault",paymentMethodCategory:"card"})}on(e,t){let r=this.listeners.get(e);return r||(r=new Set,this.listeners.set(e,r)),r.add(t),()=>{this.listeners.get(e)?.delete(t)}}unmount(){this.hideActionRequiredOverlay(),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.container&&(this.container.replaceChildren(),this.container=null),this.messageToken=null,this.expectedOrigin=null,this.ownsTelemetryReporter&&(this.telemetryReporter?.destroy(),this.telemetryReporter=void 0)}injectWidget(e,t){e.innerHTML=t;let r=Array.from(e.querySelectorAll("script"));for(let o of r){let s=document.createElement("script");for(let i of Array.from(o.attributes))s.setAttribute(i.name,i.value);s.text=o.text,o.replaceWith(s)}}attachMessageListener(){if(this.messageHandler)return;let e=t=>{if(this.expectedOrigin&&t.origin!==this.expectedOrigin)return;let r=t.data;if(Kt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;this.applyHeight(r.height);return}if(Bt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;let l=r.messages.filter(c=>typeof c=="string"&&c.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:l||void 0});return}if(!zt(r)||this.messageToken&&r.messageToken!==this.messageToken)return;let o=this.config.sessionId,s=typeof r.sessionId=="string"?r.sessionId:void 0;if(o&&s&&s!==o||(r.type==="complete"||r.type==="decline")&&o&&s!==o)return;let i=jt(r.paymentMethod),a={...r.sessionId??this.config.sessionId?{sessionId:r.sessionId??this.config.sessionId}:{},...r.outcome?{outcome:r.outcome}:{},...r.paymentId?{paymentId:r.paymentId}:{},...r.authorizationExpiresAt?{authorizationExpiresAt:r.authorizationExpiresAt}:{},...r.failureOutcome?{failureOutcome:r.failureOutcome}:{},...r.intentId?{intentId:r.intentId}:{},...r.declineReason?{declineReason:r.declineReason}:{},...r.message?{message:r.message}:{},...i?{paymentMethod:i}:{}};r.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??M()),J(Vt(r,this.submissionStarted,this.config.captureMethod,this.config.operation)),this.reportOutcome(r),r.type==="ready"&&(this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder()),r.type==="action_required"&&r.nextActionRedirectUrl&&this.showActionRequiredOverlay(r.nextActionRedirectUrl),(r.type==="complete"||r.type==="decline"||r.type==="error"||r.type==="submitting")&&this.hideActionRequiredOverlay(),r.type!=="action_required"&&this.emit(r.type,a)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;let{type:r}=e;if(r==="ready"&&!this.vaultReadyReported&&(this.vaultReadyReported=!0,t.performance({stage:"vault_ready",durationMs:Math.max(0,t.now()-this.mountStartedAt),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"})),r==="complete"||r==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:Ge(e,this.config.captureMethod,this.config.operation),provider:"pcivault",paymentMethodCategory:"card"});return}if(r==="error"){let i=Ye(this.submissionStarted);t.log({name:"vault.terminal",stage:i.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...i,provider:"pcivault",paymentMethodCategory:"card"});return}if(r==="action_required"){t.log({name:"vault.action.required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"}),t.log({name:"vault.three_ds.handoff",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});let i=this.submissionStartedAt;this.submissionStartedAt=null,i!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-i),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[o,s]=$e[r];t.log({name:o,stage:s,provider:"pcivault",paymentMethodCategory:"card"})}applyTheme(e){this.theme=e,this.postTheme()}postTheme(){if(!this.theme||!this.container)return;let t=this.container.querySelector("iframe")?.contentWindow;if(t)try{t.postMessage({source:"flopay-vault-host",type:"theme",theme:this.theme},"*")}catch{}}setSubmitGate(e){this.submitGateBlocked=e,this.postSubmitGate()}postSubmitGate(){if(!this.container)return;let t=this.container.querySelector("iframe")?.contentWindow;if(t)try{t.postMessage({source:"flopay-vault-host",type:"gate",blocked:this.submitGateBlocked},"*")}catch{}}setCardFieldOrder(e,t){this.cardFieldOrder=e,this.cardAutoFocus=t,this.postCardFieldOrder()}postCardFieldOrder(){if(!this.container)return;let t=this.container.querySelector("iframe")?.contentWindow;if(t)try{t.postMessage({source:"flopay-vault-host",type:"fieldOrder",order:this.cardFieldOrder,autoFocus:this.cardAutoFocus},"*")}catch{}}emit(e,t){for(let r of this.listeners.get(e)??[])r(t)}showActionRequiredOverlay(e){if(typeof document>"u")return;if(this.actionOverlay){let i=this.actionOverlay.querySelector("iframe");i instanceof HTMLIFrameElement&&(i.src=e);return}let t=document.createElement("div");t.setAttribute("data-flopay-action-required","1"),t.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 r=document.createElement("iframe");r.setAttribute("title","Card authentication"),r.setAttribute("allow","payment"),r.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(";"),r.src=e,t.appendChild(r);let o=document.createElement("button");o.type="button",o.setAttribute("aria-label","Close card authentication"),o.textContent="\xD7",o.style.cssText=["position:fixed","top:20px","right:20px","width:40px","height:40px","border:0","border-radius:9999px","background:#fff","color:#0f172a","font-size:28px","line-height:40px","cursor:pointer","box-shadow:0 4px 14px rgba(0,0,0,0.25)"].join(";"),o.addEventListener("click",()=>this.abandonActionRequiredOverlay()),t.appendChild(o),t.addEventListener("click",i=>{i.target===t&&this.abandonActionRequiredOverlay()});let s=i=>{if(i.source!==r.contentWindow)return;let a=i.data;if(!a||typeof a!="object")return;let l=a;l.source==="flopay-vault-3ds-return"&&(J(me("vault.three_ds.returned","three_ds_return")),this.telemetryReporter?.log({name:"vault.three_ds.returned",stage:"three_ds_return",provider:"pcivault",paymentMethodCategory:"card"}),this.hideActionRequiredOverlay(),this.postActionCompleted(l.status))};window.addEventListener("message",s),this.threeDsReturnHandler=s,document.body.appendChild(t),this.actionOverlay=t,J(me("vault.three_ds.handoff","three_ds_handoff"))}postActionCompleted(e){if(!this.container)return;let r=this.container.querySelector("iframe")?.contentWindow;if(r)try{r.postMessage({source:"flopay-vault-host",type:"action_completed",status:typeof e=="string"?e:"unknown"},"*")}catch{}}abandonActionRequiredOverlay(){if(!this.actionOverlay)return;let e=(0,T.buildTelemetryTerminalEvent)({eventId:"77777777-7777-4777-8777-777777777777",outcome:"customer_abandoned",stage:"three_ds_handoff",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});J(e),this.telemetryReporter?.terminal({outcome:"customer_abandoned",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"}),this.hideActionRequiredOverlay(),this.postActionCompleted("abandoned")}hideActionRequiredOverlay(){this.threeDsReturnHandler&&(window.removeEventListener("message",this.threeDsReturnHandler),this.threeDsReturnHandler=null),this.actionOverlay&&(this.actionOverlay.parentNode?.removeChild(this.actionOverlay),this.actionOverlay=null)}applyHeight(e){let t=this.container?.querySelector("iframe");if(!t)return;let r=Math.max(0,Math.min(Math.ceil(e),2e3));t.style.height=`${r}px`}};function We(n,e){let t=L;return new t(n,{reporter:e})}var Je=Symbol.for("@flopay/js.telemetry.bridge.v1");function Qe(n,e,t){let r=()=>e?.now()??t();Object.defineProperty(n,Je,{configurable:!1,enumerable:!1,writable:!1,value:{error:s=>e?.error(s),log:s=>e?.log(s),performance:s=>e?.performance(s),terminal:s=>e?.terminal(s),now:r,elapsed:s=>Math.max(0,r()-s),setCheckoutContext:s=>e?.setCheckoutContext(s),beginCheckout:(s={})=>e?.beginCheckout(s)??r(),disable:()=>e?.disable(),subscribe:s=>e?.subscribe(s)??(()=>{})}})}function Xe(n){return n[Je]}function $(n){if(!n)return!1;let e=n.code?.toLowerCase()??"";return!!n.declineCode||e.includes("declin")}function Ht(n){return n==="stripe"||n==="paypal"||n==="pcivault"?n:"other"}var Q=class{constructor(e,t,r){this.currentElements=null;this.provider=e,this.config=t,this.telemetryReporter=r??new _({billingApiUrl:(0,C.resolveBillingApiUrl)(t.billingApiUrl),sdkVersion:C.SDK_VERSION,enabled:t.telemetry!==!1}),Qe(this,this.telemetryReporter,M)}now(){return this.telemetryReporter?.now?.()??M()}elements(e){return this.currentElements&&this.currentElements.destroy(),this.currentElements=new K(this.provider,{appearance:this.config.appearance,...e}),this.currentElements}async submitElements(){return this.provider.submitElements()}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?We({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new L({sessionId:e?.sessionId,captureMethod:e?.captureMethod,telemetry:!1})}async confirmPayPalPayment(e){let t=this.now();this.telemetryReporter?.log({name:"payment.method.selected",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.log({name:"payment.intent.started",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create"});try{let r=await this.provider.confirmPayPalPayment(e);return this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-t,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),r.error||this.telemetryReporter?.log({name:"payment.intent.completed",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create",statusClass:"2xx"}),r.status==="requires_action"?(this.telemetryReporter?.log({name:"payment.three_ds.handoff",stage:"three_ds_handoff",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.log({name:"provider.redirect.started",stage:"redirect",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.terminal({outcome:"action_required",stage:"redirect",provider:"paypal",paymentMethodCategory:"paypal"})):r.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:"paypal",paymentMethodCategory:"paypal"}):r.status!=="processing"&&($(r.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"}):r.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"}):r.error&&this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create"})),r}catch(r){if(this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-t,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),r instanceof C.FloPayError&&$(r))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(r instanceof C.FloPayError&&r.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let o=(0,C.classifyTelemetryFailure)(r,"PAYMENT_PROCESSING_FAILED","unknown");this.telemetryReporter?.error({...o,failureCategory:o.failureCategory??"provider_runtime",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create"})}throw r}}async resumePayPalPayment(){let e=this.now();try{let t=await this.provider.resumePayPalPayment();return t===null?null:(this.telemetryReporter?.log({name:"provider.redirect.resumed",stage:"redirect_resume",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.performance({stage:"redirect_resume",durationMs:this.now()-e,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),t.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:"paypal",paymentMethodCategory:"paypal"}):$(t.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"}):t.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"}):t.error&&this.telemetryReporter?.error({errorCode:"REDIRECT_RESUME_FAILED",failureCategory:"provider_runtime",stage:"redirect_resume",provider:"paypal",paymentMethodCategory:"paypal"}),t)}catch(t){if(this.telemetryReporter?.performance({stage:"redirect_resume",durationMs:this.now()-e,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),t instanceof C.FloPayError&&$(t))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(t instanceof C.FloPayError&&t.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let r=(0,C.classifyTelemetryFailure)(t,"REDIRECT_RESUME_FAILED","unknown");this.telemetryReporter?.error({...r,failureCategory:r.failureCategory??"provider_runtime",stage:"redirect_resume",provider:"paypal",paymentMethodCategory:"paypal"})}throw t}}async confirmPayment(e){if(e.paymentMethodCategory!=="wallet"&&e.paymentMethodCategory!=="apm"||!e.paymentMethodType?.trim()||e.paymentMethodType.trim().toLowerCase()==="card")throw new C.FloPayError("A supported non-card payment method is required.","validation_error",{param:"paymentMethodType"});let t=this.now(),r=Ht(this.provider.name);this.telemetryReporter?.log({name:"payment.processing.started",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory});try{let o=await this.provider.confirmPayment(e),s=this.now()-t;return this.telemetryReporter?.performance({stage:"processing",durationMs:s,durationMode:"machine",provider:r,paymentMethodCategory:e.paymentMethodCategory}),o.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:r,paymentMethodCategory:e.paymentMethodCategory}):$(o.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):o.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:r,paymentMethodCategory:e.paymentMethodCategory}):o.status==="requires_action"?(this.telemetryReporter?.log({name:"payment.three_ds.handoff",stage:"three_ds_handoff",provider:r,paymentMethodCategory:e.paymentMethodCategory}),this.telemetryReporter?.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:r,paymentMethodCategory:e.paymentMethodCategory})):o.status==="failed"&&o.error&&this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),o.status==="succeeded"||o.status==="failed"?this.telemetryReporter?.log({name:"payment.processing.completed",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}):this.telemetryReporter?.log({name:"operation.state_transition",stage:o.status==="requires_action"?"three_ds_handoff":"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),o}catch(o){throw this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-t,durationMode:"machine",provider:r,paymentMethodCategory:e.paymentMethodCategory}),o instanceof C.FloPayError&&$(o)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):o instanceof C.FloPayError&&o.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:r,paymentMethodCategory:e.paymentMethodCategory}):this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),o}}async retrieveSession(e,t){if(!e)throw new C.FloPayError("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let r=await this.retrieveUnifiedSession(e,t);if(!r.data.session)throw new C.FloPayError("Session not found","api_error");return r.data.session}async retrieveUnifiedSession(e,t){if(!e)throw new C.FloPayError("sessionId is required.","validation_error",{param:"sessionId"});let r=(0,C.resolveBillingApiUrl)(t??this.config.billingApiUrl),o=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let s,i=He(r,{now:()=>this.telemetryReporter?.now()??M(),onFirstByte:a=>{s=a},onRetry:(a,l)=>{this.telemetryReporter?.log({name:"operation.retry",stage:a==="session_read"?"session_read":"processing",requestCategory:a,attempt:l})}});try{let a=await i.getUnifiedCheckoutSession(e);return s!==void 0&&(this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:s,durationMode:"machine",requestCategory:"session_read",statusClass:"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()-o,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),a}catch(a){let l=(0,C.classifyTelemetryFailure)(a,a instanceof C.FloPayError&&a.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...l,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-o,durationMode:"machine",requestCategory:"session_read",statusClass:l.statusClass}),a}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.currentElements?.destroy(),this.currentElements=null,this.provider.destroy()}};function Ze(n,e,t){let r=Q;return new r(n,e,t)}var E=require("@flopay/shared");var f=require("@flopay/shared"),rt=require("@stripe/stripe-js");function et(n){return{payment:"payment",address:"address"}[n]}function X(n){switch(n){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function nt(n){return{...n,theme:X(n.theme)}}function Se(n){return n?JSON.stringify(n.map(e=>e.trim().toLowerCase())):null}function tt(n){let e=n;return{mount(t){e.mount(t)},unmount(){e.unmount()},update(t){e.update(t)},on(t,r){e.on?.(t,r)},off(t,r){e.off?.(t,r)},destroy(){e.destroy()}}}function $t(n){return{billing_details:{...n.email?{email:n.email}:{},...n.name?{name:n.name}:{},...n.address?{address:{...n.address.country?{country:n.address.country}:{},...n.address.postal_code?{postal_code:n.address.postal_code}:{},...n.address.city?{city:n.address.city}:{},...n.address.line1?{line1:n.address.line1}:{},...n.address.line2?{line2:n.address.line2}:{},...n.address.state?{state:n.address.state}:{}}}:{}}}}var Y=class{constructor(){this.name="stripe";this.stripe=null;this.elements=null;this.appliedAppearanceKey=null;this.appliedPaymentMethodTypesKey=null;this.appliedClientSecret=null;this.verifiedClientSecret=null;this.verifiedPaymentMethodTypesKey=null}async initialize(e){if(typeof window>"u")return;let t=await(0,rt.loadStripe)(e.publishableKey,{locale:e.locale??"auto"});if(!t)throw new f.FloPayError("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=t}getElements(e){if(!this.stripe)throw new f.FloPayError("StripeAdapter not initialized. Call initialize() first.","api_error");let t=e?.appearance?{theme:X(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}:void 0,r=t?JSON.stringify(t):null,o=Se(e?.paymentMethodTypes),s=e?.clientSecret??null;if(this.elements&&o&&(o!==this.appliedPaymentMethodTypesKey||s!==this.appliedClientSecret)&&(this.elements=null,this.appliedAppearanceKey=null,this.appliedPaymentMethodTypesKey=null,this.appliedClientSecret=null,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null),this.elements)r!==this.appliedAppearanceKey&&(this.elements.update({appearance:t??{}}),this.appliedAppearanceKey=r);else{let i,a=e?.amount??0,l=(e?.currency??"usd").toLowerCase(),c=e?.paymentMethodCreation??"manual";e?.clientSecret?i={clientSecret:e.clientSecret}:a>0?(i={mode:"payment",amount:a,currency:l,paymentMethodCreation:c},e?.setupFutureUsage&&(i.setupFutureUsage=e.setupFutureUsage)):i={mode:"setup",currency:l,paymentMethodCreation:c},!e?.clientSecret&&e?.paymentMethodTypes&&(i.paymentMethodTypes=e.paymentMethodTypes),t&&(i.appearance=t),this.elements=this.stripe.elements(i),this.appliedAppearanceKey=r,this.appliedPaymentMethodTypesKey=o,this.appliedClientSecret=s,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null}return this.elements}async assertClientSecretPaymentMethods(e,t){if(!this.stripe)throw new f.FloPayError("StripeAdapter not initialized. Call initialize() first.","api_error");let r,o=!1;if((0,f.isSetupIntentClientSecret)(e)){let{setupIntent:l,error:c}=await this.stripe.retrieveSetupIntent(e);r=l,o=!!c}else{let{paymentIntent:l,error:c}=await this.stripe.retrievePaymentIntent(e);r=l,o=!!c}let s=r?.payment_method_types;if(o||!Array.isArray(s))throw new f.FloPayError("Unable to verify the payment methods configured for this client secret.","api_error",{param:"clientSecret"});let i=new Set(t.map(l=>l.toLowerCase()));if(s.some(l=>typeof l!="string"||!i.has(l.trim().toLowerCase()))||s.length===0)throw new f.FloPayError("The client-secret intent must enable only declared non-card payment methods.","validation_error",{param:"clientSecret"})}async createElement(e,t){let r=t;if(e==="payment"){let l=t.paymentMethodTypes?.map(c=>c.trim()).filter(c=>c&&c.toLowerCase()!=="card");if(!l?.length)throw new f.FloPayError("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});if(r={...t,paymentMethodTypes:l},r.clientSecret){let c=Se(l);this.elements&&this.appliedClientSecret===r.clientSecret&&this.appliedPaymentMethodTypesKey===c&&this.verifiedClientSecret===r.clientSecret&&this.verifiedPaymentMethodTypesKey===c||await this.assertClientSecretPaymentMethods(r.clientSecret,l)}}let o=this.getElements(r);e==="payment"&&r.clientSecret&&(this.verifiedClientSecret=r.clientSecret,this.verifiedPaymentMethodTypesKey=Se(r.paymentMethodTypes));let s=et(e),i={};r.layout&&(i.layout=r.layout),r.defaultValues&&(i.defaultValues=r.defaultValues),r.readOnly&&(i.readOnly=r.readOnly),r.mode&&(i.mode=r.mode);let a=o.create(s,i);return tt(a)}getElement(e){if(!this.elements)return null;let t=et(e),r=this.elements.getElement(t);return r?tt(r):null}async submitElements(){if(!this.stripe||!this.elements)return{error:new f.FloPayError("Stripe not initialized","api_error")};let{error:e}=await this.elements.submit();return e?{error:new f.FloPayError(e.message??"Validation failed","validation_error")}:{}}async confirmPayment(e){if(!this.stripe||!this.elements)throw new f.FloPayError("StripeAdapter not initialized or no elements created.","api_error");let t=e.billingDetails,r=t?$t(t):void 0,{error:o,paymentIntent:s}=await this.stripe.confirmPayment({elements:this.elements,clientSecret:e.clientSecret,confirmParams:{return_url:e.returnUrl??window.location.href,...r?{payment_method_data:r}:{}},redirect:"if_required"});return o?{status:"failed",error:new f.FloPayError(o.message??"Payment failed","api_error",{code:o.code,declineCode:o.decline_code})}:s?{status:{succeeded:"succeeded",processing:"processing",requires_action:"requires_action",requires_payment_method:"failed",canceled:"failed"}[s.status]??"failed",paymentIntentId:s.id,paymentMethodId:this.extractPaymentMethodId(s.payment_method)}:{status:"failed",error:new f.FloPayError("No payment intent returned","api_error")}}extractPaymentMethodId(e){if(typeof e=="string"&&e.startsWith("pm_"))return e;if(e&&typeof e=="object"&&typeof e.id=="string")return e.id}async confirmPayPalPayment(e){if(!this.stripe)return{status:"failed",error:new f.FloPayError("Stripe not initialized","api_error")};let t=e.billingApiUrl.replace(/\/+$/,"");if(this.elements){let{error:s}=await this.elements.submit();if(s)return{status:"failed",error:new f.FloPayError(s.message??"PayPal payment failed","validation_error",{code:s.code})}}let r;try{let s=await new I(t).createSessionIntent(e.sessionId,e.nonce??"",{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",paymentMethodId:null,intentKind:"payment"});if(s.provider!=="stripe")throw new f.FloPayError("Invalid provider returned for PayPal intent","api_error");r=s.clientSecret}catch(s){return{status:"failed",error:s instanceof f.FloPayError?s:new f.FloPayError("Failed to create PayPal payment intent","api_error")}}let{error:o}=await this.stripe.confirmPayment({clientSecret:r,elements:this.elements??void 0,confirmParams:{return_url:e.returnUrl}});if(o){if(e.nonce)try{await new I(t).reportSessionIntentDecline(e.sessionId,e.nonce,{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:o.code??"provider_declined"})}catch{}return{status:"failed",error:new f.FloPayError(o.message??"PayPal payment failed","api_error",{code:o.code})}}return{status:"processing"}}async resumePayPalPayment(){if(!this.stripe||typeof window>"u")return null;let e=new URLSearchParams(window.location.search),t=e.get("payment_intent"),r=e.get("payment_intent_client_secret"),o=e.get("redirect_status");if(!t||!r)return null;if(o==="failed")return{status:"failed",error:new f.FloPayError("PayPal payment was declined. Please try again.","api_error")};let{paymentIntent:s,error:i}=await this.stripe.retrievePaymentIntent(r);if(i)return{status:"failed",error:new f.FloPayError(i.message??"Failed to retrieve PayPal payment","api_error")};if(s&&(0,f.isMoneySettledOutcome)(s.status)){let a=typeof s.payment_method=="string"?s.payment_method:s.payment_method?.id,l=new URL(window.location.href);return l.searchParams.delete("payment_intent"),l.searchParams.delete("payment_intent_client_secret"),l.searchParams.delete("redirect_status"),window.history.replaceState({},"",l.toString()),{status:s.status,paymentIntentId:s.id,paymentMethodId:a}}return{status:"failed",error:new f.FloPayError("PayPal payment was not completed. Please try again.","api_error")}}getRawProvider(){return this.stripe}createPayPalElements(e){if(!this.stripe)return null;let t={mode:"payment",amount:e.amount??0,currency:(e.currency??"usd").toLowerCase(),captureMethod:"manual"};return e.setupFutureUsage&&(t.setupFutureUsage=e.setupFutureUsage),e.appearance&&(t.appearance={theme:X(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}),this.stripe.elements(t)}destroy(){this.elements=null,this.appliedAppearanceKey=null,this.appliedPaymentMethodTypesKey=null,this.appliedClientSecret=null,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null,this.stripe=null}};var ot=new Map;function Me(n){return Array.isArray(n)?n.map(Me):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Me(t)])):n}function Yt(n,e){return JSON.stringify([n,(0,E.resolveBillingApiUrl)(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,Me(e?.appearance??null)])}var ye=new Map;async function st(n,e){if(!n){let a=new _({billingApiUrl:(0,E.resolveBillingApiUrl)(e?.billingApiUrl),sdkVersion:E.SDK_VERSION,enabled:e?.telemetry!==!1});throw a.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),a.flush().catch(()=>{}).finally(()=>a.destroy()),new E.FloPayError("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let t=Yt(n,e),r=ot.get(t);if(r)return e?.telemetry!==!1&&Xe(r)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),r;let o=ye.get(t);if(o)return o;let s={...e,publishableKey:n},i=(async()=>{let a=new _({billingApiUrl:(0,E.resolveBillingApiUrl)(s.billingApiUrl),sdkVersion:E.SDK_VERSION,enabled:s.telemetry!==!1}),l=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 c=new Y,u=a.now();try{await c.initialize(s)}catch(m){throw a.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),a.destroy(),m}let y=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:y-l,durationMode:"machine",provider:"stripe"}),a.performance({stage:"provider_ready",durationMs:y-u,durationMode:"machine",provider:"stripe"});let p=Ze(c,s,a);return ot.set(t,p),p})();ye.set(t,i);try{return await i}finally{ye.get(t)===i&&ye.delete(t)}}0&&(module.exports={FloPay,FloPayElements,PaymentAPI,PciVaultCardCapture,SESSION_CREATE_TELEMETRY,StripeAdapter,cacheSessionDisplayData,clearSessionDisplayData,createCheckoutSession,createCheckoutSessionWithRetries,dropThirdPartyOnlyError,getSessionDisplayData,loadFloPay,toStripeAppearance,toStripeAppearanceTheme});
|
|
1
|
+
"use strict";var pe=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var nt=(r,e)=>{for(var t in e)pe(r,t,{get:e[t],enumerable:!0})},it=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ot(e))!st.call(r,n)&&n!==t&&pe(r,n,{get:()=>e[n],enumerable:!(o=rt(e,n))||o.enumerable});return r};var at=r=>it(pe({},"__esModule",{value:!0}),r);var Vt={};nt(Vt,{FloPay:()=>G,PaymentAPI:()=>$,PciVaultCardCapture:()=>q,SESSION_CREATE_TELEMETRY:()=>Ce,StripeAdapter:()=>B,cacheSessionDisplayData:()=>D,clearSessionDisplayData:()=>ne,createCheckoutSession:()=>Ee,createCheckoutSessionWithRetries:()=>De,dropThirdPartyOnlyError:()=>et.dropThirdPartyOnlyError,getSessionDisplayData:()=>se,loadFloPay:()=>Ze,toStripeAppearance:()=>Qe,toStripeAppearanceTheme:()=>Te});module.exports=at(Vt);var et=require("@flopay/shared");var g=require("@flopay/shared");function I(r){return typeof r=="string"&&r.trim()?r:void 0}function ke(r){if(typeof r=="string")return r.trim()?r:void 0;if(Array.isArray(r))return r.filter(t=>typeof t=="string"&&t.trim().length>0).join("; ")||void 0}function x(r=12e3){let e=Number.isFinite(r)&&r>=0?r:12e3,t=new AbortController,o=setTimeout(()=>t.abort(),e);return{signal:t.signal,clear:()=>clearTimeout(o)}}function ct(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function N(r,e){let t=150*2**r,o=Math.round(t*(.75+Math.random()*.5));return new Promise((n,s)=>{let i,a=()=>e.removeEventListener("abort",c),c=()=>{i!==void 0&&clearTimeout(i),a(),s(ct())};if(e.aborted){c();return}i=setTimeout(()=>{a(),n()},o),e.addEventListener("abort",c,{once:!0})})}var ut="flopay_session_display:";var re=new Map;function oe(r){return`${ut}${r}`}function me(){if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}}function D(r,e,t){if(!r)return;let o=t?.ttlMs??36e5,n={data:e,expiresAt:Date.now()+o},s=me();if(s)try{s.setItem(oe(r),JSON.stringify(n));return}catch{}re.set(r,n)}function se(r){if(!r)return null;let e=me();if(e)try{let o=e.getItem(oe(r));if(o){let n=JSON.parse(o);if(n&&typeof n.expiresAt=="number"&&n.expiresAt>Date.now())return n.data;e.removeItem(oe(r))}}catch{}let t=re.get(r);if(t){if(t.expiresAt>Date.now())return t.data;re.delete(r)}return null}function ne(r){if(!r)return;re.delete(r);let e=me();if(e)try{e.removeItem(oe(r))}catch{}}var b=require("@flopay/shared"),lt="/v1/sdk-telemetry/events",ye=16,dt=64,pt=1500,Se=1e3,mt=64,yt="00000000-0000-4000-8000-000000000000",ht={technical_error:8,lifecycle:32,expected_outcome:32,performance:24};function V(){try{return globalThis.crypto.randomUUID()}catch{let r=new Uint8Array(16);try{globalThis.crypto.getRandomValues(r)}catch{for(let t=0;t<r.length;t+=1)r[t]=Math.floor(Math.random()*256)}r[6]=r[6]&15|64,r[8]=r[8]&63|128;let e=[...r].map(t=>t.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}}function gt(r){try{return new TextEncoder().encode(r).byteLength}catch{return r.length}}function ft(r){return JSON.stringify([r.code,r.failureCategory,r.stage,r.provider,r.attempt,r.statusClass,r.requestCategory,r.paymentMethodCategory,r.checkoutMode,r.layout])}function k(){return globalThis.performance?.now()??0}var v=class{constructor(e){this.ingestionDisabled=!1;this.queue=[];this.sequence=0;this.flushTimer=null;this.flushInFlight=null;this.reportedFailures=new Map;this.checkoutContext={};this.checkoutStartedAt=null;this.destroyed=!1;this.observers=new Set;this.pageExitHandler=()=>{this.drainQueue()};this.visibilityHandler=()=>{document.visibilityState==="hidden"&&this.flush()};this.eventCounts={technical_error:0,lifecycle:0,expected_outcome:0,performance:0};this.endpoint=`${e.billingApiUrl.replace(/\/+$/,"")}${lt}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=V(),this.merchantEnabled=e.enabled!==!1,this.clock=e.clock??k,this.browserTransportAvailable=typeof window<"u"&&typeof document<"u",this.browserTransportAvailable&&(window.addEventListener("pagehide",this.pageExitHandler),document.addEventListener("visibilitychange",this.visibilityHandler))}log(e){this.notify({...e,class:"lifecycle"}),this.canCollect()&&this.enqueue((0,b.buildTelemetryLogEvent)({...this.checkoutContext,...e,eventId:V(),sequence:this.sequence++}))}error(e){if(this.notify({...e,class:"technical_error"}),!this.canCollect())return;let t=(0,b.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:yt,sequence:0}),o=ft(t),n=this.now();this.pruneReportedFailures(n);let s=this.reportedFailures.get(o);if(s!==void 0&&n>=s&&n-s<Se){this.log({name:"operation.deduplicated",stage:e.stage,provider:e.provider,paymentMethodCategory:e.paymentMethodCategory,attempt:e.attempt});return}this.rememberReportedFailure(o,n),this.enqueue((0,b.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:V(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue((0,b.buildTelemetryPerformanceEvent)({...this.checkoutContext,...e,eventId:V(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue((0,b.buildTelemetryTerminalEvent)({...this.checkoutContext,...e,eventId:V(),sequence:this.sequence++})),e.outcome!=="action_required"&&this.checkoutStartedAt!==null)){let t=this.checkoutStartedAt;this.checkoutStartedAt=null,this.performance({stage:"total_journey",durationMs:Math.max(0,this.now()-t),durationMode:"total",provider:e.provider,paymentMethodCategory:e.paymentMethodCategory})}}now(){try{return this.clock()}catch{return k()}}subscribe(e){return this.destroyed?()=>{}:(this.observers.add(e),()=>this.observers.delete(e))}notify(e){if(!this.destroyed)for(let t of this.observers)try{t(e)}catch{}}pruneReportedFailures(e){for(let[t,o]of this.reportedFailures)(e<o||e-o>=Se)&&this.reportedFailures.delete(t)}rememberReportedFailure(e,t){for(;this.reportedFailures.size>=mt;){let o=this.reportedFailures.keys().next();if(o.done)break;this.reportedFailures.delete(o.value)}this.reportedFailures.set(e,t)}setCheckoutContext(e){this.checkoutContext={checkoutMode:e.checkoutMode,layout:e.layout}}beginCheckout(e={}){return this.canCollect()?(this.drainQueue(),this.setCheckoutContext(e),this.sequence=0,this.reportedFailures.clear(),this.eventCounts={technical_error:0,lifecycle:0,expected_outcome:0,performance:0},this.checkoutStartedAt=this.now(),this.checkoutStartedAt):0}enqueue(e){if(this.canCollect()&&!(this.queue.length>=dt||this.eventCounts[e.class]>=ht[e.class])){if(this.eventCounts[e.class]+=1,this.queue.push(e),this.queue.length>=ye){this.flush();return}this.scheduleFlush()}}canCollect(){return this.browserTransportAvailable&&this.merchantEnabled&&!this.ingestionDisabled&&!this.destroyed}async flush(){if(this.flushInFlight)return this.flushInFlight;if(!this.browserTransportAvailable||this.destroyed||this.ingestionDisabled||this.queue.length===0)return;this.clearFlushTimer();let e=this.queue.splice(0,ye);return this.flushInFlight=this.sendBatch(e).finally(()=>{this.flushInFlight=null,this.queue.length>0&&this.scheduleFlush()}),this.flushInFlight}destroy(){this.destroyed||(this.drainQueue(),this.destroyed=!0,this.clearFlushTimer(),this.browserTransportAvailable&&(window.removeEventListener("pagehide",this.pageExitHandler),document.removeEventListener("visibilitychange",this.visibilityHandler)),this.queue.splice(0),this.reportedFailures.clear(),this.observers.clear())}disable(){this.merchantEnabled=!1,this.queue.splice(0),this.reportedFailures.clear(),this.clearFlushTimer()}drainQueue(){if(!(!this.browserTransportAvailable||this.destroyed||this.ingestionDisabled||this.queue.length===0))for(this.clearFlushTimer();this.queue.length>0;){let e=this.queue.splice(0,ye);this.sendBatch(e)}}async sendBatch(e){if(!this.browserTransportAvailable||this.ingestionDisabled)return;let t=(0,b.serializeTelemetryBatch)(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:V()});if(gt(t)>b.TELEMETRY_MAX_BATCH_BYTES)return;let o=typeof AbortController>"u"?null:new AbortController,n=null;try{let s=fetch(this.endpoint,{method:"POST",headers:{"content-type":"text/plain;charset=UTF-8"},body:t,credentials:"omit",keepalive:!0,referrerPolicy:"no-referrer",signal:o?.signal}).then(async c=>c.status!==202?null:(await c.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(c=>{n=setTimeout(()=>{o?.abort(),c(null)},pt)});await Promise.race([s,i])==="disabled"&&this.disableFromIngestion()}catch{}finally{n&&clearTimeout(n)}}disableFromIngestion(){this.ingestionDisabled=!0,this.queue.splice(0),this.reportedFailures.clear(),this.clearFlushTimer()}scheduleFlush(){this.flushTimer||this.destroyed||this.ingestionDisabled||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flush()},0))}clearFlushTimer(){this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null)}},we=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),Ae=globalThis;Ae[we]===void 0&&Object.defineProperty(Ae,we,{configurable:!0,enumerable:!1,writable:!1,value:r=>new v(r)});var he=5,Me=new WeakSet;function Ct(r){(typeof r=="object"&&r!==null||typeof r=="function")&&Me.add(r)}function vt(r){return(typeof r=="object"&&r!==null||typeof r=="function")&&Me.has(r)}function Tt(r,e){let t=e?.error,o=I(e?.code)??I(t?.code)??`http_${r}`,n=I(e?.message)??I(t?.message)??bt(o,r);return new g.FloPayError(n,"api_error",{code:o,statusCode:r})}function bt(r,e){switch(r){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${he}.`;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 Re(r,e,t){let{billingApiUrl:o,checkoutBaseUrl:n,items:s=[],subscriptions:i=[],products:a,account:c,successUrl:l,cancelUrl:d,checkoutMode:y="confirm",captureMethod:p,couponCodes:m=[],tagsData:w,redirectParams:T={},setCookie:_=!0,clientId:_e,currency:K,utmMetadata:h,idempotencyKey:W}=r,J=(0,g.resolveIdempotencyKey)(W);if(m.length>he)throw new g.FloPayError(`Too many coupon codes \u2014 a checkout session accepts at most ${he}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let P=a??(0,g.foldIntoProducts)(s,i);(0,g.assertCaptureMethodEligible)({captureMethod:p,products:P});let R=(0,g.resolveSessionCurrency)(K,s,i,P);if(!R)throw new g.FloPayError("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 U={clientId:_e,checkoutVersion:g.SDK_VERSION,successUrl:l,cancelUrl:d,currency:R,checkoutMode:y,products:P.map(E=>(0,g.buildProductPayload)(E,R)),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:m};p==="manual"&&(U.captureMethod=p),w&&(U.tagsData=w),h?.length&&(U.utmMetadata=h);let H=`${o.replace(/\/+$/,"")}/v1/checkouts/sessions`,Q={"Content-Type":"application/json"};J&&(Q[g.IDEMPOTENCY_KEY_HEADER]=J);let L,X,tt={method:"POST",headers:Q,body:JSON.stringify(U),signal:e},Z;try{Z=await fetch(H,tt)}catch(E){throw Ct(E),E}try{t?.(Z.status)}catch{}L=Z.status;try{X=await Z.json()}catch{}if(L>=400)throw Tt(L,X);if(L===201){let E=X?.data?.uuid,de=X?.data?.nonce;if(!E)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!de)throw new g.FloPayError("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"});(P.length||R)&&D(E,{currency:R,products:P.map(f=>({code:f.code??f.providerItemId??f.providerPlanId,type:f.type,name:f.name??f.itemName??f.providerItemName??f.subscriptionName??f.providerPlanName??null,totalAmount:f.totalAmount,overrideAmount:f.overrideAmount,currency:f.currency??R}))});let ee=new URL(`${n.replace(/\/+$/,"")}/secure`);ee.searchParams.set("id",E);for(let[f,te]of Object.entries(T))ee.searchParams.set(f,te);if(_&&typeof window<"u"&&typeof document<"u"){let f=JSON.stringify({origin_url:d}),te=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(f)}; domain=.${te}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(de)}; domain=.${te}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=ee.toString()),{status:201,redirectUrl:ee.toString(),nonce:de}}return L===204?(typeof window<"u"&&(window.location.href=l),{status:204}):{status:L}}async function Ee(r){let e=Ie(r),t=Pe(e),o=x(r.timeoutMs);try{let n=await Re(r,o.signal,t);return xe(e,n),n}catch(n){throw ie(e,n),n}finally{o.clear(),z(e.reporter)}}function Pe(r){let e=!1;return t=>{if(e)return;e=!0;let o=(0,g.telemetryStatusClass)(t);r.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:o,attempt:r.attempt}),r.reporter.performance({stage:"session_first_byte",durationMs:r.reporter.now()-r.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o,attempt:r.attempt})}}function Ie(r){let e=new v({billingApiUrl:r.billingApiUrl,sdkVersion:g.SDK_VERSION,enabled:r.telemetry!==!1}),t=e.now();return e.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:e,startedAt:t,attempt:0}}function xe(r,e){let t=(0,g.telemetryStatusClass)(e.status);r.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:t}),r.reporter.performance({stage:"session_create",durationMs:r.reporter.now()-r.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:t,attempt:r.attempt})}function ie(r,e){let{reporter:t}=r,o=(0,g.classifyTelemetryFailure)(e,"CHECKOUT_SESSION_CREATE_FAILED");if(t.performance({stage:"session_create",durationMs:t.now()-r.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:r.attempt}),e instanceof g.FloPayError&&e.type==="validation_error"){t.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(o.statusClass==="4xx"){t.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}t.error({...o,stage:"session_create",requestCategory:"session_create"})}function z(r){r.flush().catch(()=>{}).finally(()=>r.destroy())}async function De(r){let{maxRetries:e=2,...t}=r,o=Ie(r),n=Pe(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"}),z(o.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let s={...t,idempotencyKey:(0,g.resolveIdempotencyKey)(t.idempotencyKey)},i=x(t.timeoutMs),a;for(let c=0;c<=e;c++){o.attempt=c;try{let l=await Re(s,i.signal,n);return xe(o,l),i.clear(),z(o.reporter),l}catch(l){a=l;let d=l instanceof Error&&l.name==="AbortError",y=vt(l),p=l instanceof g.FloPayError&&l.code===g.IDEMPOTENCY_IN_PROGRESS_CODE;if((d||y||p)&&!i.signal.aborted&&c<e){o.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:c+1});try{await N(c,i.signal)}catch(m){throw ie(o,m),i.clear(),z(o.reporter),m}continue}throw ie(o,l),i.clear(),z(o.reporter),l}}throw ie(o,a),i.clear(),z(o.reporter),a??new Error("Unknown error during checkout session creation")}var S=require("@flopay/shared");var u=require("@flopay/shared");var Fe=1e3,_t=500,kt=15e3,St=3e3,wt=1e4,At=1e4;function Mt(r){return typeof r=="object"&&r!==null}function j(r,e){return I(r?.[e])}function Oe(r,e){return ke(r?.[e])}function Rt(r,e){let t=r?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Ue(r){return new Promise(e=>setTimeout(e,r))}function ae(){return new u.FloPayError("Checkout is still processing. Please try again shortly.","api_error",{code:"checkout_processing_timeout"})}async function F(r,e){let t=await r.json().catch(()=>null),o=Mt(t?.error)?t.error:null,n=Oe(t,"message")??Oe(o,"message")??e,s=j(t,"code")??j(t,"gatewayErrorCode")??j(o,"code")??`http_${r.status}`;return new u.FloPayError(n,"api_error",{code:s,statusCode:r.status})}async function Et(r){let e=r.status===400?await r.clone().json().catch(()=>null):null;return(0,u.classifyPaymentRejection)(r.status,e)}function qe(r){return r===400||r===422}var ce=2;async function fe(r,e,t=ce,o){let n;for(let s=0;;s++)try{return await fetch(r,e)}catch(i){if(e?.signal?.aborted||i instanceof Error&&i.name==="AbortError")throw i;if(n=i,s>=t)throw n;try{o?.(s+1)}catch{}await Ue(150*2**s)}}var Ce=Symbol.for("@flopay/js.session-create.telemetry.v1");function Pt(r){return r[Ce]}function It(r){return"now"in r||"onFirstByte"in r||"onSessionCreateFailure"in r||"onRetry"in r}function Le(r){return{userId:r.userId,firstName:r.firstName??null,lastName:r.lastName??null,email:r.email,country:r.country??null,gender:r.gender??null,city:r.city??null,state:r.state??null,zip:r.zip??null,addressLine1:r.addressLine1??null,addressLine2:r.addressLine2??null}}function Ne(r,e){e.tagsData&&(r.tagsData=e.tagsData),e.utmMetadata?.length&&(r.utmMetadata=e.utmMetadata),e.avsCheck!==void 0&&(r.avsCheck=e.avsCheck),e.checkoutType&&(r.checkoutType=e.checkoutType),e.checkoutLayout&&(r.checkoutLayout=e.checkoutLayout),e.avsConfig&&(r.avsConfig=e.avsConfig)}function xt(r,e){let t={clientId:r.clientId,checkoutVersion:u.SDK_VERSION,successUrl:r.successUrl,cancelUrl:r.cancelUrl,currency:e,checkoutMode:"full",deferDataAttachment:!0};return r.captureMethod==="manual"&&(t.captureMethod=r.captureMethod),r.account.country&&(t.accountData={country:r.account.country}),Ne(t,r),t}function Dt(r,e,t){return{currency:e,products:t.map(o=>(0,u.buildProductPayload)(o,e)),couponCodes:r.couponCodes??[],accountData:Le(r.account)}}var O=class O{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let o=It(t);this.telemetryHooks=o?t:void 0,this.directTelemetry=o||t.telemetry===!1?void 0:new v({billingApiUrl:this.baseUrl,sdkVersion:u.SDK_VERSION})}destroy(){this.directTelemetry?.destroy()}reportDirectFailure(e,t,o,n,s="unknown"){let i=(0,u.classifyTelemetryFailure)(e,t);this.directTelemetry?.error({...i,stage:o,requestCategory:n,paymentMethodCategory:s})}reportAccountSnapshotFailure(e,t){let o=(0,u.classifyTelemetryFailure)(e,"NETWORK_REQUEST_FAILED");if(t==="best_effort"&&o.errorCode==="REQUEST_TIMEOUT"){this.directTelemetry?.log({name:"operation.fallback",stage:"processing",requestCategory:"account_snapshot",statusClass:"timeout"});return}this.directTelemetry?.error({...o,stage:"processing",requestCategory:"account_snapshot",paymentMethodCategory:"unknown"})}telemetryTimestamp(){try{return this.telemetryHooks?.now?.()??this.directTelemetry?.now()??k()}catch{return k()}}beginDirectTelemetryCheckout(e){!this.directTelemetry||this.directTelemetryCheckoutId===e||(this.directTelemetryCheckoutId=e,this.directTelemetry.beginCheckout())}beginDirectTelemetryOperation(){this.directTelemetry&&(this.directTelemetryCheckoutId=void 0,this.directTelemetry.beginCheckout())}adoptDirectTelemetryCheckout(e){e&&(this.directTelemetryCheckoutId=e)}async getCheckoutSession(e,t){this.beginDirectTelemetryCheckout(e);let o=this.telemetryTimestamp();this.directTelemetry?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let n={[u.FLO_SDK_VERSION_HEADER]:u.SDK_VERSION};t&&(n["x-checkout-session-token"]=t);try{let s=await fe(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:n},ce,l=>{this.telemetryHooks?.onRetry?.("session_read",l),this.directTelemetry?.log({name:"operation.retry",stage:"session_read",requestCategory:"session_read",attempt:l})}),i=Math.max(0,this.telemetryTimestamp()-o);try{this.telemetryHooks?.onFirstByte?.(i)}catch{}let a=`${Math.floor(s.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:a}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:a}),!s.ok)throw await F(s,"Failed to get checkout session");let c=await s.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:a}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"session_read",statusClass:a}),{...c,data:this.mergeCachedDisplayData(c.data)}}catch(s){throw this.directTelemetry?.error({...(0,u.classifyTelemetryFailure)(s,"NETWORK_REQUEST_FAILED"),stage:"session_read",requestCategory:"session_read"}),s}}cacheSessionDisplayData(e,t,o){D(e,t,o)}clearSessionDisplayData(e){ne(e)}async getVaultCapture(e,t){let o=`${this.baseUrl}\0${e}\0${t??""}`,n=O.activeVaultCaptureRequests.get(o);if(n)return n;let s=this.requestVaultCapture(e,t);O.activeVaultCaptureRequests.set(o,s);try{return await s}finally{O.activeVaultCaptureRequests.get(o)===s&&O.activeVaultCaptureRequests.delete(o)}}async requestVaultCapture(e,t){let o=new AbortController,n=setTimeout(()=>o.abort(),At);this.beginDirectTelemetryCheckout(e);let s=this.telemetryTimestamp();this.directTelemetry?.log({name:"vault.capture.requested",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card"});let i={"Content-Type":"application/json"};t&&(i["x-checkout-session-token"]=t);try{let a=await fe(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:o.signal},ce,l=>{this.telemetryHooks?.onRetry?.("vault_capture",l),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:l})});if(!a.ok)throw await F(a,"Failed to load the secure card form");let c=await a.json();return this.directTelemetry?.performance({stage:"vault_request",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"vault_capture",paymentMethodCategory:"card",statusClass:"2xx"}),this.toVaultBlock(c)}catch(a){let c=o.signal.aborted?new u.FloPayError("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):a;throw this.reportDirectFailure(c,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),c}finally{clearTimeout(n)}}async getUnifiedCheckoutSession(e,t){let o=await this.getCheckoutSession(e,t),n=this.normalizeRawSession(o.data),s=o.vault;return s&&n.data.session&&(n.data.session.vault=this.toVaultBlock(s)),n}async processPayment(e,t,o){if(this.beginDirectTelemetryCheckout(t.sessionId),!t.nonce)throw this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"process_payment"}),new u.FloPayError("processPayment requires `nonce` \u2014 pass the value returned from session creation.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let n=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.processing.started",stage:"processing",requestCategory:"process_payment"});let{nonce:s,...i}=t,a;try{a=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(t.sessionId)}/process`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":s},body:JSON.stringify(i)})}catch(c){throw this.reportDirectFailure(c,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),c}if(!a.ok&&a.status!==202){let c=await Et(a);return c?this.directTelemetry?.terminal({outcome:c,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:(0,u.telemetryStatusClass)(a.status),failureCategory:a.status>=500?"server_error":void 0}),a}try{let c=await this.resolveProcessResponse(a,t.sessionId,{...o,nonce:s});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:(0,u.telemetryStatusClass)(c.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-n),durationMode:"machine",requestCategory:"process_payment",statusClass:(0,u.telemetryStatusClass)(c.status)}),c}catch(c){throw c instanceof u.FloPayError&&c.code==="checkout_processing_timeout"||this.reportDirectFailure(c,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),c}}async patchAccountSnapshot(e,t,o,n){this.beginDirectTelemetryCheckout(e);let s=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.state_transition",stage:"processing",requestCategory:"account_snapshot"});let i=n?.timeoutMs??wt,a=new AbortController,c=()=>a.abort();n?.signal&&(n.signal.aborted?a.abort():n.signal.addEventListener("abort",c,{once:!0}));let l=setTimeout(()=>a.abort(),i);try{let d;try{d=await fe(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/account`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t},body:JSON.stringify(o),signal:a.signal},ce,y=>{this.telemetryHooks?.onRetry?.("account_snapshot",y),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:y})})}finally{clearTimeout(l),n?.signal?.removeEventListener("abort",c)}if(!d.ok)throw await F(d,"Failed to persist account snapshot");this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"account_snapshot",statusClass:"2xx"})}catch(d){throw this.reportAccountSnapshotFailure(d,n?.telemetryMode??"blocking"),d}}async createSessionIntent(e,t,o,n){if(!t)throw new u.FloPayError("createSessionIntent requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=o,i=s.paymentMethodType,a=typeof i=="string"&&i.trim().toLowerCase()==="card",c=typeof i=="string"&&i.length>0&&!a&&(typeof s.paymentMethodId=="string"||s.paymentMethodId===null),l=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm")&&(s.intentKind==="payment"||s.intentKind==="setup"),d=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodId===null&&(s.paymentMethodType==="paypal"&&s.intentKind==="payment"||s.paymentMethodType===u.PAYPAL_VAULTED_PAYMENT_METHOD_TYPE&&(s.intentKind==="payment"||s.intentKind==="setup"));if(!c||!l&&!d)throw new u.FloPayError("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let y=s.authorizationAttemptId;if(y!==void 0&&!(0,u.isUuidV4)(y))throw new u.FloPayError("authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.","validation_error",{code:"InvalidAuthorizationAttemptId",param:"authorizationAttemptId"});let p=(0,u.isUuidV4)(y)?y:(0,u.randomUuidV4)();this.beginDirectTelemetryCheckout(e);let m=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.intent.started",stage:"processing",requestCategory:"intent_create"});let w={"Content-Type":"application/json","x-checkout-session-token":t,[u.IDEMPOTENCY_KEY_HEADER]:n?.idempotencyKey||p},T=!1;try{let _=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:w,body:JSON.stringify({...o,authorizationAttemptId:p}),signal:n?.signal});if(!_.ok){T=!0;let H=await F(_,"Failed to create checkout intent"),Q=(0,u.classifyTelemetryFailure)(H,"PAYMENT_PROCESSING_FAILED");throw qe(H.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...Q,stage:"processing",requestCategory:"intent_create"}),H}let K=(await _.json()).data;if(!K||typeof K!="object")throw new u.FloPayError("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let h=K,W=h.paymentMethodType,J=(h.paymentMethodCategory==="wallet"||h.paymentMethodCategory==="apm")&&typeof W=="string"&&W.trim().toLowerCase()!=="card"&&(typeof h.paymentMethodId=="string"||h.paymentMethodId===null)&&typeof h.providerObjectId=="string",P=h.provider==="stripe"&&(h.intentKind==="payment"||h.intentKind==="setup")&&typeof h.clientSecret=="string",R=h.provider==="paypal"&&h.paymentMethodCategory==="wallet"&&h.paymentMethodId===null&&(h.paymentMethodType==="paypal"&&h.intentKind==="payment"&&(h.providerObjectType==="order"||h.providerObjectType==="subscription")||h.paymentMethodType===u.PAYPAL_VAULTED_PAYMENT_METHOD_TYPE&&h.intentKind==="payment"&&h.providerObjectType==="order"||h.paymentMethodType===u.PAYPAL_VAULTED_PAYMENT_METHOD_TYPE&&h.intentKind==="setup"&&h.providerObjectType==="setup_token")&&h.clientSecret===null,U=h.provider===o.provider&&h.paymentMethodCategory===o.paymentMethodCategory&&h.paymentMethodType===o.paymentMethodType&&h.paymentMethodId===o.paymentMethodId&&h.intentKind===o.intentKind;if(!J||!P&&!R||!U)throw new u.FloPayError("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});return this.directTelemetry?.log({name:"payment.intent.completed",stage:"processing",requestCategory:"intent_create",statusClass:(0,u.telemetryStatusClass)(_.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-m),durationMode:"machine",requestCategory:"intent_create",statusClass:(0,u.telemetryStatusClass)(_.status)}),h}catch(_){throw T||this.reportDirectFailure(_,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),_}}async reportSessionIntentDecline(e,t,o,n){if(!t)throw new u.FloPayError("reportSessionIntentDecline requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=o,i=s.providerDeclineReason,a=s.paymentMethodType,c=typeof i=="string"&&/^[a-z0-9][a-z0-9_.:-]{0,63}$/i.test(i)&&!/^(?:pm|pi|seti|tok|src|cus|sess|sk|pk)_/i.test(i),l=typeof a=="string"&&a.length>0&&a.trim().toLowerCase()!=="card"&&c,d=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm"),y=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodType==="paypal";if(!l||!d&&!y)throw new u.FloPayError("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let p=y?{provider:"paypal",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:i}:{provider:"stripe",paymentMethodCategory:s.paymentMethodCategory,paymentMethodType:s.paymentMethodType,providerDeclineReason:i},m=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents/decline`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":t},body:JSON.stringify(p),signal:n?.signal});if(!m.ok)throw await F(m,"Failed to report checkout decline")}async getPaymentsByEmail(e,t){this.beginDirectTelemetryOperation();let o=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.recovery.started",stage:"recovery",requestCategory:"other",paymentMethodCategory:"saved"});let n=t?.page??1,s=t?.limit??1,i=new URLSearchParams({email:e,page:String(n),limit:String(s),sortField:"createdAt",sortDirection:"DESC"});try{let a=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!a.ok)throw new u.FloPayError("Failed to fetch payments","api_error",{statusCode:a.status});let c=await a.json();return this.directTelemetry?.log({name:"operation.recovery.completed",stage:"recovery",requestCategory:"other",paymentMethodCategory:"saved",statusClass:"2xx"}),this.directTelemetry?.performance({stage:"recovery",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"other",paymentMethodCategory:"saved",statusClass:"2xx"}),c}catch(a){throw this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","other","saved"),a}}async createAndFetchSession(e){if((0,u.isDetachedSessionEligible)(e))return(await this.createDetachedSession(e)).claimed;this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),o=x(e.timeoutMs??12e3),n={attempt:0,statusClass:"unknown"};this.directTelemetry?.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"});try{let s=await this.createAndFetchSessionRequest(e,t,o.signal,n);return this.adoptDirectTelemetryCheckout(s.data.session?.id),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:n.statusClass}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:n.statusClass,attempt:n.attempt}),s}catch(s){throw this.reportSessionCreateFailure(s,t,n),s}finally{o.clear()}}async createAndFetchSessionRequest(e,t,o,n){let s=e.products??(0,u.foldIntoProducts)(e.items,e.subscriptions);(0,u.assertCaptureMethodEligible)({captureMethod:e.captureMethod,products:s});let i=(0,u.resolveSessionCurrency)(e.currency,e.items,e.subscriptions,s);if(!i)throw new u.FloPayError("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 a={clientId:e.clientId,checkoutVersion:u.SDK_VERSION,successUrl:e.successUrl,cancelUrl:e.cancelUrl,currency:i,checkoutMode:e.checkoutMode??"full",products:s.map(p=>(0,u.buildProductPayload)(p,i)),accountData:Le(e.account),couponCodes:e.couponCodes??[]};e.captureMethod==="manual"&&(a.captureMethod=e.captureMethod),e.tokenizedData&&(a.tokenizedData=e.tokenizedData),Ne(a,e);let l=await(await this.postCheckoutSessionCreate(a,e,t,o,n)).json();if(l.data&&"gateways"in l.data){this.autoCacheDisplayData(l.data.uuid,e);let p=this.mergeCachedDisplayData(l.data),m=this.normalizeRawSession(p);return l.vault&&m.data.session&&(m.data.session.vault=this.toVaultBlock(l.vault)),{...m,autoProcessingError:l.autoProcessingError,autoProcessingAttempted:l.autoProcessingAttempted,autoProcessingPending:l.autoProcessingPending}}let d=l.data?.uuid;if(!d)throw new u.FloPayError("No session ID returned","api_error",{code:"InvalidCheckoutSessionResponse"});return this.autoCacheDisplayData(d,e),this.adoptDirectTelemetryCheckout(d),{...await this.getUnifiedCheckoutSession(d),autoProcessingError:l.autoProcessingError,autoProcessingAttempted:l.autoProcessingAttempted,autoProcessingPending:l.autoProcessingPending}}async postCheckoutSessionCreate(e,t,o,n,s){let i={"Content-Type":"application/json",[u.FLO_SDK_VERSION_HEADER]:u.SDK_VERSION},a=(0,u.resolveIdempotencyKey)(t.idempotencyKey);a&&(i[u.IDEMPOTENCY_KEY_HEADER]=a);let c,l=!1,d=Pt(t),y=p=>{try{this.telemetryHooks?.onRetry?.("session_create",p),this.directTelemetry?.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:p})}catch{}};for(let p=0;p<3;p++){s.attempt=p;try{d?.onAttempt?.(p)}catch{}try{c=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:i,body:JSON.stringify(e),signal:n})}catch(T){if(s.statusClass=n.aborted||T instanceof Error&&T.name==="AbortError"?"timeout":"network_error",n.aborted||T instanceof Error&&T.name==="AbortError"||p>=2)throw T;let _=p+1;y(_),await N(p,n);continue}let m=(0,u.telemetryStatusClass)(c.status);if(s.statusClass=m,l||(l=!0,this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:m,attempt:p}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"session_create",statusClass:m,attempt:p})),c.status===204)throw new u.FloPayError("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(c.ok)break;let w=await F(c,"Failed to create checkout session");if(w.code===u.IDEMPOTENCY_IN_PROGRESS_CODE&&p<2){y(p+1),await N(p,n);continue}throw w}if(!c)throw new TypeError("Checkout-session creation exhausted its retry budget.");return c}async createDetachedSession(e){this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),o=x(e.timeoutMs??12e3),n={attempt:0,statusClass:"unknown"};this.directTelemetry?.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"});let s=e.products??(0,u.foldIntoProducts)(e.items,e.subscriptions);try{(0,u.assertCaptureMethodEligible)({captureMethod:e.captureMethod,products:s})}catch(m){throw o.clear(),this.reportSessionCreateFailure(m,t,n),m}let i=(0,u.resolveSessionCurrency)(e.currency,e.items,e.subscriptions,s);if(!i)throw o.clear(),this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),new u.FloPayError("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 a;try{a=Dt(e,i,s)}catch(m){throw o.clear(),this.reportSessionCreateFailure(m,t,n),m}let c,l;try{if(l=await(await this.postCheckoutSessionCreate(xt(e,i),e,t,o.signal,n)).json(),!l.data||!("gateways"in l.data))throw new u.FloPayError("The billing API returned no session shell for a detached create. It must support `deferDataAttachment` (TeamFloPay/backend#1099).","api_error",{code:"InvalidCheckoutSessionResponse"});c=this.normalizeRawSession(this.mergeCachedDisplayData(l.data)),l.vault&&c.data.session&&(c.data.session.vault=this.toVaultBlock(l.vault))}catch(m){throw o.clear(),this.reportSessionCreateFailure(m,t,n),m}let d=c.data.session?.id??l.data.uuid??"",y=c.data.session?.clientSecret??l.data.nonce??"";if(!d||!y){o.clear();let m=new u.FloPayError("Checkout session shell was created without a session id or nonce.","api_error",{code:"InvalidCheckoutSessionResponse"});throw this.reportSessionCreateFailure(m,t,n),m}this.adoptDirectTelemetryCheckout(d),this.directTelemetry?.log({name:"session.shell.ready",stage:"session_shell",requestCategory:"session_create",statusClass:n.statusClass,paymentMethodCategory:"card"}),this.directTelemetry?.performance({stage:"session_shell",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:n.statusClass,attempt:n.attempt,paymentMethodCategory:"card"});let p=this.claimCheckoutSession(d,y,a,{params:e,startedAt:t,deadline:o,createAttempt:n.attempt});return p.catch(()=>{}),{shell:c,sessionId:d,nonce:y,claimed:p}}async claimCheckoutSession(e,t,o,n){let s=n?.startedAt??this.telemetryTimestamp(),i=this.telemetryTimestamp(),a=n?.deadline??x(12e3),c=JSON.stringify(o),l="unknown",d=0;this.directTelemetry?.log({name:"session.claim.started",stage:"session_claim",requestCategory:"session_claim"});try{let y;for(d=0;d<3;d++){try{y=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/claim`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t,[u.FLO_SDK_VERSION_HEADER]:u.SDK_VERSION},body:c,signal:a.signal})}catch(w){let T=a.signal.aborted||w instanceof Error&&w.name==="AbortError";if(l=T?"timeout":"network_error",T||d>=2)throw w;try{this.telemetryHooks?.onRetry?.("session_claim",d+1),this.directTelemetry?.log({name:"operation.retry",stage:"session_claim",requestCategory:"session_claim",attempt:d+1})}catch{}await N(d,a.signal);continue}if(l=(0,u.telemetryStatusClass)(y.status),y.ok)break;throw await F(y,"Failed to attach checkout session data")}if(!y)throw new TypeError("Checkout-session claim exhausted its retry budget.");let p=await y.json();if(!p.data?.gateways)throw new u.FloPayError("The billing API returned no checkout session with gateways after claiming it.","api_error",{code:"InvalidCheckoutSessionResponse"});n?.params&&this.autoCacheDisplayData(p.data.uuid??e,n.params);let m=this.normalizeRawSession(this.mergeCachedDisplayData(p.data));return p.vault&&m.data.session&&(m.data.session.vault=this.toVaultBlock(p.vault)),this.directTelemetry?.log({name:"session.claim.completed",stage:"session_claim",requestCategory:"session_claim",statusClass:l}),this.directTelemetry?.performance({stage:"session_claim",durationMs:Math.max(0,this.telemetryTimestamp()-i),durationMode:"machine",requestCategory:"session_claim",statusClass:l,attempt:d}),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:l}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"session_create",statusClass:l,attempt:n?.createAttempt??d}),m}catch(y){throw this.reportSessionCreateFailure(y,s,{attempt:d,statusClass:l},"session_claim"),y}finally{a.clear()}}reportSessionCreateFailure(e,t,o,n="session_create"){if(!(e instanceof u.FloPayError&&e.code==="session_auto_completed"))try{this.telemetryHooks?.onSessionCreateFailure?.(e)}catch{}let s=(0,u.classifyTelemetryFailure)(e,"CHECKOUT_SESSION_CREATE_FAILED");if(this.directTelemetry?.performance({stage:n,durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:n==="session_claim"?"session_claim":"session_create",statusClass:s.statusClass,attempt:o.attempt}),e instanceof u.FloPayError&&e.type==="validation_error"||e instanceof u.FloPayError&&qe(e.statusCode)){this.directTelemetry?.terminal({outcome:"validation_rejected",stage:n,requestCategory:n==="session_claim"?"session_claim":"session_create",...e.type==="validation_error"?{}:{statusClass:"4xx"}});return}e instanceof u.FloPayError&&e.code==="session_auto_completed"||this.directTelemetry?.error({...s,stage:n,requestCategory:n==="session_claim"?"session_claim":"session_create"})}async waitForCheckoutSessionCompletion(e,t){this.beginDirectTelemetryCheckout(e);let o=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.recovery.started",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved"});let n=t?.timeoutMs??kt,s=Date.now()+n,i=this.clampRetryAfterMs(t?.initialDelayMs??Fe),a=0;try{for(;;){let c=s-Date.now();if(c<=0)throw ae();if(i>0){try{a+=1,this.telemetryHooks?.onRetry?.("session_read",a),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:a})}catch{}if(await Ue(Math.min(i,c)),Date.now()>=s)throw ae()}let l=await this.getUnifiedCheckoutSession(e,t?.nonce),d=l.data.session?.status;if(d==="authorized"||d==="complete"||d==="expired")return this.directTelemetry?.log({name:"operation.recovery.completed",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved"}),this.directTelemetry?.performance({stage:"recovery",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"session_read",paymentMethodCategory:"saved"}),l;if(Date.now()>=s)throw ae();i=this.clampRetryAfterMs(Math.max(i*2,_t))}}catch(c){throw c instanceof u.FloPayError&&c.code==="checkout_processing_timeout"&&this.reportDirectFailure(c,"RECOVERY_FAILED","recovery","session_read","saved"),c}}normalizeRawSession(e){let t=e.gateways??{},o=[],n={session:this.toCheckoutSession(e)},s=t.stripe;if(s?.publishableKey){o.push("stripe");let c=[e.stripeClientSecret,s.stripeClientSecret].find(l=>typeof l=="string"&&l.length>0);n.stripe={clientSecret:c??"",publishableKey:s.publishableKey??void 0,paypalPublishableKey:s.paypalPublishableKey??void 0,environment:s.environment,enabledPaymentMethods:Array.isArray(s.enabledPaymentMethods)?s.enabledPaymentMethods.filter(l=>typeof l=="string"):void 0}}let i=t.paypal;return i?.publishableKey&&(o.push("paypal"),n.paypal={publishableKey:i.publishableKey,environment:i.environment,providerObjectType:i.providerObjectType}),{providers:o,mode:"tokenize",data:n,raw:{data:e}}}toCheckoutSession(e){let t=e.products??[],o=typeof e.totalAmount=="number"&&Number.isFinite(e.totalAmount),n=t.reduce((l,d)=>l+(d.overrideAmount??d.totalAmount??0),0),s=o?e.totalAmount:n,i=Math.round(s*100),a=e.currency??t[0]?.currency??"USD",c=e.checkoutMode==="setup"?"setup":t.some(l=>l.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:c,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:a,captureMethod:e.captureMethod,paymentId:e.paymentId,authorizationExpiresAt:e.authorizationExpiresAt,failureOutcome:(0,u.normalizeCheckoutFailureOutcome)(e.outcome)??(0,u.normalizeCheckoutFailureOutcome)(e.failureReason)??(e.status==="expired"&&e.captureMethod==="manual"?"authorization_expired":void 0),customer:{id:e.accountData.userId,email:e.accountData.email,firstName:e.accountData.firstName,lastName:e.accountData.lastName,country:e.accountData.country??void 0,city:e.accountData.city??void 0,state:e.accountData.state??void 0,zip:e.accountData.zip??void 0,gender:e.accountData.gender??void 0,line1:e.accountData.addressLine1??void 0,line2:e.accountData.addressLine2??void 0},metadata:{},checkoutMode:e.checkoutMode,providerPaymentMethodId:typeof e.providerPaymentMethodId=="string"?e.providerPaymentMethodId:null,products:t.map(l=>({...l,totalAmount:typeof l.totalAmount=="number"?l.totalAmount:void 0,overrideAmount:typeof l.overrideAmount=="number"?l.overrideAmount:null,currency:typeof l.currency=="string"?l.currency:void 0,metadata:l.metadata??null})),successUrl:e.successUrl,cancelUrl:e.cancelUrl,coupons:e.coupons,subtotalAmount:e.subtotalAmount,discountAmount:e.discountAmount,totalAmount:e.totalAmount,createdAt:e.createdAt,gateways:e.gateways,accountData:e.accountData,tagsData:e.tagsData}}toVaultBlock(e){return{html:typeof e.html=="string"?e.html:void 0,url:typeof e.url=="string"?e.url:void 0,messageToken:typeof e.messageToken=="string"?e.messageToken:void 0,expectedOrigin:typeof e.expectedOrigin=="string"?e.expectedOrigin:void 0}}toCheckoutSessionStatus(e){return e==="completed"?"complete":e==="authorized"?"authorized":e==="expired"?"expired":"open"}async resolveProcessResponse(e,t,o){if(e.status!==202)return e;let n=await e.json().catch(()=>null),s=this.toCheckoutProcessingPending(n,e,t),i=await this.waitForCheckoutSessionCompletion(s.sessionId,{initialDelayMs:s.retryAfterMs,timeoutMs:o?.pollTimeoutMs,nonce:o?.nonce});if(i.data.session?.status==="complete")return new Response(null,{status:204,statusText:"No Content"});if(i.data.session?.status==="authorized"){let a=i.data.session;return new Response(JSON.stringify({status:"authorized",paymentId:a.paymentId,sessionId:a.id||t,authorizationExpiresAt:a.authorizationExpiresAt}),{status:200,headers:{"Content-Type":"application/json"}})}if(i.data.session?.status==="expired"){let a=i.data.session.failureOutcome==="authorization_expired"||i.data.session.captureMethod==="manual";throw new u.FloPayError(a?"Authorization has expired.":"Checkout session has expired.","api_error",{code:a?"authorization_expired":"checkout_session_expired"})}throw ae()}toCheckoutProcessingPending(e,t,o){let n=t.headers.get("Retry-After"),s=n===null||n.trim()===""?void 0:Number(n),i=s!==void 0&&Number.isFinite(s)?s*1e3:void 0;return{type:"checkout_processing",sessionId:j(e,"sessionId")??o,retryAfterMs:this.clampRetryAfterMs(Rt(e,"retryAfterMs")??i??Fe),statusUrl:j(e,"statusUrl"),sessionUrl:j(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,St))}autoCacheDisplayData(e,t){if(!e)return;let o=t.products??(0,u.foldIntoProducts)(t.items,t.subscriptions);if(o.length===0&&!t.currency)return;let n=t.products!==void 0,s=(0,u.resolveSessionCurrency)(t.currency,n?void 0:t.items,n?void 0:t.subscriptions,o);D(e,{currency:s??void 0,products:o.map(i=>({code:i.code??i.providerItemId??i.providerPlanId,type:i.type,name:i.name??i.itemName??i.providerItemName??i.subscriptionName??i.providerPlanName??null,totalAmount:i.totalAmount,overrideAmount:i.overrideAmount,currency:i.currency??s??void 0}))})}mergeCachedDisplayData(e){let t=se(e.uuid),o=new Map,n=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let a=n(i.code);a&&o.set(a,i)}let s=(e.products??[]).map(i=>{let a=n(i.code),c=a?o.get(a):void 0;return{...i,name:i.name??c?.name??null,totalAmount:i.totalAmount??c?.totalAmount,overrideAmount:i.overrideAmount??c?.overrideAmount,currency:i.currency??c?.currency}});return{...e,currency:e.currency??t?.currency,products:s}}};O.activeVaultCaptureRequests=new Map;var $=O;function Ve(r,e){let t=$;return new t(r,e)}var C=require("@flopay/shared");var ve="flopay-vault",ze={ready:["vault.widget.ready","vault_ready"],submitting:["vault.submission.started","vault_submit"],blocked:["operation.state_transition","vault_submit"],action_required:["vault.action.required","three_ds_handoff"]};function Y(r){let e={class:r.class,stage:r.stage};"code"in r&&(e.code=r.code),"provider"in r&&r.provider&&(e.provider=r.provider),"paymentMethodCategory"in r&&r.paymentMethodCategory&&(e.paymentMethodCategory=r.paymentMethodCategory),"outcome"in r&&(e.outcome=r.outcome),"durationMs"in r&&r.durationMs!==void 0&&(e.durationMs=r.durationMs),"durationMode"in r&&r.durationMode&&(e.durationMode=r.durationMode);try{globalThis.Sentry?.addBreadcrumb?.({category:"flopay.telemetry",level:r.class==="technical_error"?"error":"info",message:r.class==="lifecycle"?r.name:r.class==="technical_error"?r.code:r.class==="expected_outcome"?r.outcome:"sdk.performance",data:e})}catch{}}function ue(r,e){return(0,C.buildTelemetryLogEvent)({eventId:"11111111-1111-4111-8111-111111111111",name:r,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function je(r){return r?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function Be(r,e,t="checkout"){return t==="card_setup"?r.type==="decline"?"card_setup_declined":"card_setup_succeeded":r.type==="decline"?"payment_declined":r.outcome==="authorized"||e==="manual"?"payment_authorized":"payment_succeeded"}function Ft(r,e,t,o="checkout"){let{type:n}=r;if(n==="complete"||n==="decline")return(0,C.buildTelemetryTerminalEvent)({eventId:"22222222-2222-4222-8222-222222222222",outcome:Be(r,t,o),sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(n==="error"){let a=je(e);return(0,C.buildTelemetryErrorEvent)({eventId:"33333333-3333-4333-8333-333333333333",...a,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[s,i]=ze[n];return ue(s,i)}function Ot(r){if(typeof r!="object"||r===null)return!1;let e=r;return e.source===ve&&(e.type==="ready"||e.type==="submitting"||e.type==="blocked"||e.type==="complete"||e.type==="decline"||e.type==="error"||e.type==="action_required")}function qt(r){if(typeof r!="object"||r===null)return;let e=r,t=e.status;if(!(typeof e.id!="string"||e.id.trim()===""||typeof e.brand!="string"||e.brand.trim()===""||typeof e.lastFour!="string"||!/^\d{4}$/.test(e.lastFour)||typeof e.expiryMonth!="number"||!Number.isInteger(e.expiryMonth)||e.expiryMonth<1||e.expiryMonth>12||typeof e.expiryYear!="number"||!Number.isInteger(e.expiryYear)||e.expiryYear<1970||e.expiryYear>9999||t!=="pending"&&t!=="active"&&t!=="deleted"))return{id:e.id,brand:e.brand,lastFour:e.lastFour,expiryMonth:e.expiryMonth,expiryYear:e.expiryYear,status:t}}function Ut(r){if(typeof r!="object"||r===null)return!1;let e=r;return e.source===ve&&e.type==="validation"&&Array.isArray(e.messages)}function Lt(r){if(typeof r!="object"||r===null)return!1;let e=r;return e.source===ve&&e.type==="resize"&&typeof e.height=="number"&&Number.isFinite(e.height)}var q=class{constructor(e={},t){this.provider="pcivault";this.container=null;this.messageHandler=null;this.actionOverlay=null;this.threeDsReturnHandler=null;this.messageToken=null;this.expectedOrigin=null;this.theme=null;this.submitGateBlocked=!1;this.cardFieldOrder=null;this.cardAutoFocus=!0;this.mountStartedAt=0;this.vaultReadyReported=!1;this.submissionStarted=!1;this.submissionStartedAt=null;this.listeners=new Map;this.config=e,this.ownsTelemetryReporter=!t&&e.telemetry!==!1,this.telemetryReporter=t?.reporter??(this.ownsTelemetryReporter?new v({billingApiUrl:(0,C.resolveBillingApiUrl)(),sdkVersion:C.SDK_VERSION}):void 0)}async mount(e,t){this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new v({billingApiUrl:(0,C.resolveBillingApiUrl)(),sdkVersion:C.SDK_VERSION}));let o=this.telemetryReporter;if(this.config.operation==="card_setup"&&o&&this.setupTelemetryReporter!==o){this.setupTelemetryReporter=o;try{o.beginCheckout({checkoutMode:"setup"})}catch{}}if(this.mountStartedAt=this.telemetryReporter?.now?.()??k(),this.vaultReadyReported=!1,this.submissionStarted=!1,this.submissionStartedAt=null,typeof window>"u"||typeof document>"u")throw this.reportVaultLoadFailure(),new C.FloPayError("The vault card form is only available in the browser.","api_error",{code:"card_capture_no_window"});if(!t?.html?.trim())throw this.reportVaultLoadFailure(),new C.FloPayError("No vault capture widget HTML was provided to mount the secure card form.","api_error",{code:"card_capture_no_widget_html"});this.container=e,this.messageToken=t.messageToken??null,this.expectedOrigin=t.expectedOrigin??this.config.expectedOrigin??null,this.theme=t.theme??null;try{this.attachMessageListener(),this.injectWidget(e,t.html)}catch(n){throw this.reportVaultLoadFailure(),n}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),Y(ue("vault.widget.mounted","vault_mount")),this.telemetryReporter?.log({name:"vault.widget.mounted",stage:"vault_mount",provider:"pcivault",paymentMethodCategory:"card"}),this.emit("ready",{sessionId:this.config.sessionId})}reportVaultLoadFailure(){this.telemetryReporter?.error({errorCode:"VAULT_LOAD_FAILED",failureCategory:"provider_runtime",stage:"vault_mount",provider:"pcivault",paymentMethodCategory:"card"})}on(e,t){let o=this.listeners.get(e);return o||(o=new Set,this.listeners.set(e,o)),o.add(t),()=>{this.listeners.get(e)?.delete(t)}}unmount(){this.hideActionRequiredOverlay(),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.container&&(this.container.replaceChildren(),this.container=null),this.messageToken=null,this.expectedOrigin=null,this.ownsTelemetryReporter&&(this.telemetryReporter?.destroy(),this.telemetryReporter=void 0)}injectWidget(e,t){e.innerHTML=t;let o=Array.from(e.querySelectorAll("script"));for(let n of o){let s=document.createElement("script");for(let i of Array.from(n.attributes))s.setAttribute(i.name,i.value);s.text=n.text,n.replaceWith(s)}}attachMessageListener(){if(this.messageHandler)return;let e=t=>{if(this.expectedOrigin&&t.origin!==this.expectedOrigin)return;let o=t.data;if(Lt(o)){if(this.messageToken&&o.messageToken!==this.messageToken)return;this.applyHeight(o.height);return}if(Ut(o)){if(this.messageToken&&o.messageToken!==this.messageToken)return;let c=o.messages.filter(l=>typeof l=="string"&&l.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:c||void 0});return}if(!Ot(o)||this.messageToken&&o.messageToken!==this.messageToken)return;let n=this.config.sessionId,s=typeof o.sessionId=="string"?o.sessionId:void 0;if(n&&s&&s!==n||(o.type==="complete"||o.type==="decline")&&n&&s!==n)return;let i=qt(o.paymentMethod),a={...o.sessionId??this.config.sessionId?{sessionId:o.sessionId??this.config.sessionId}:{},...o.outcome?{outcome:o.outcome}:{},...o.paymentId?{paymentId:o.paymentId}:{},...o.authorizationExpiresAt?{authorizationExpiresAt:o.authorizationExpiresAt}:{},...o.failureOutcome?{failureOutcome:o.failureOutcome}:{},...o.intentId?{intentId:o.intentId}:{},...o.declineReason?{declineReason:o.declineReason}:{},...o.message?{message:o.message}:{},...i?{paymentMethod:i}:{}};o.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??k()),Y(Ft(o,this.submissionStarted,this.config.captureMethod,this.config.operation)),this.reportOutcome(o),o.type==="ready"&&(this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder()),o.type==="action_required"&&o.nextActionRedirectUrl&&this.showActionRequiredOverlay(o.nextActionRedirectUrl),(o.type==="complete"||o.type==="decline"||o.type==="error"||o.type==="submitting")&&this.hideActionRequiredOverlay(),o.type!=="action_required"&&this.emit(o.type,a)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;let{type:o}=e;if(o==="ready"&&!this.vaultReadyReported&&(this.vaultReadyReported=!0,t.performance({stage:"vault_ready",durationMs:Math.max(0,t.now()-this.mountStartedAt),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"})),o==="complete"||o==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:Be(e,this.config.captureMethod,this.config.operation),provider:"pcivault",paymentMethodCategory:"card"});return}if(o==="error"){let i=je(this.submissionStarted);t.log({name:"vault.terminal",stage:i.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...i,provider:"pcivault",paymentMethodCategory:"card"});return}if(o==="action_required"){t.log({name:"vault.action.required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"}),t.log({name:"vault.three_ds.handoff",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});let i=this.submissionStartedAt;this.submissionStartedAt=null,i!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-i),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[n,s]=ze[o];t.log({name:n,stage:s,provider:"pcivault",paymentMethodCategory:"card"})}applyTheme(e){this.theme=e,this.postTheme()}postTheme(){if(!this.theme||!this.container)return;let t=this.container.querySelector("iframe")?.contentWindow;if(t)try{t.postMessage({source:"flopay-vault-host",type:"theme",theme:this.theme},"*")}catch{}}setSubmitGate(e){this.submitGateBlocked=e,this.postSubmitGate()}postSubmitGate(){if(!this.container)return;let t=this.container.querySelector("iframe")?.contentWindow;if(t)try{t.postMessage({source:"flopay-vault-host",type:"gate",blocked:this.submitGateBlocked},"*")}catch{}}setCardFieldOrder(e,t){this.cardFieldOrder=e,this.cardAutoFocus=t,this.postCardFieldOrder()}postCardFieldOrder(){if(!this.container)return;let t=this.container.querySelector("iframe")?.contentWindow;if(t)try{t.postMessage({source:"flopay-vault-host",type:"fieldOrder",order:this.cardFieldOrder,autoFocus:this.cardAutoFocus},"*")}catch{}}emit(e,t){for(let o of this.listeners.get(e)??[])o(t)}showActionRequiredOverlay(e){if(typeof document>"u")return;if(this.actionOverlay){let i=this.actionOverlay.querySelector("iframe");i instanceof HTMLIFrameElement&&(i.src=e);return}let t=document.createElement("div");t.setAttribute("data-flopay-action-required","1"),t.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 o=document.createElement("iframe");o.setAttribute("title","Card authentication"),o.setAttribute("allow","payment"),o.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(";"),o.src=e,t.appendChild(o);let n=document.createElement("button");n.type="button",n.setAttribute("aria-label","Close card authentication"),n.textContent="\xD7",n.style.cssText=["position:fixed","top:20px","right:20px","width:40px","height:40px","border:0","border-radius:9999px","background:#fff","color:#0f172a","font-size:28px","line-height:40px","cursor:pointer","box-shadow:0 4px 14px rgba(0,0,0,0.25)"].join(";"),n.addEventListener("click",()=>this.abandonActionRequiredOverlay()),t.appendChild(n),t.addEventListener("click",i=>{i.target===t&&this.abandonActionRequiredOverlay()});let s=i=>{if(i.source!==o.contentWindow)return;let a=i.data;if(!a||typeof a!="object")return;let c=a;c.source==="flopay-vault-3ds-return"&&(Y(ue("vault.three_ds.returned","three_ds_return")),this.telemetryReporter?.log({name:"vault.three_ds.returned",stage:"three_ds_return",provider:"pcivault",paymentMethodCategory:"card"}),this.hideActionRequiredOverlay(),this.postActionCompleted(c.status))};window.addEventListener("message",s),this.threeDsReturnHandler=s,document.body.appendChild(t),this.actionOverlay=t,Y(ue("vault.three_ds.handoff","three_ds_handoff"))}postActionCompleted(e){if(!this.container)return;let o=this.container.querySelector("iframe")?.contentWindow;if(o)try{o.postMessage({source:"flopay-vault-host",type:"action_completed",status:typeof e=="string"?e:"unknown"},"*")}catch{}}abandonActionRequiredOverlay(){if(!this.actionOverlay)return;let e=(0,C.buildTelemetryTerminalEvent)({eventId:"77777777-7777-4777-8777-777777777777",outcome:"customer_abandoned",stage:"three_ds_handoff",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});Y(e),this.telemetryReporter?.terminal({outcome:"customer_abandoned",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"}),this.hideActionRequiredOverlay(),this.postActionCompleted("abandoned")}hideActionRequiredOverlay(){this.threeDsReturnHandler&&(window.removeEventListener("message",this.threeDsReturnHandler),this.threeDsReturnHandler=null),this.actionOverlay&&(this.actionOverlay.parentNode?.removeChild(this.actionOverlay),this.actionOverlay=null)}applyHeight(e){let t=this.container?.querySelector("iframe");if(!t)return;let o=Math.max(0,Math.min(Math.ceil(e),2e3));t.style.height=`${o}px`}};function Ke(r,e){let t=q;return new t(r,{reporter:e})}var He=Symbol.for("@flopay/js.telemetry.bridge.v1");function $e(r,e,t){let o=()=>e?.now()??t();Object.defineProperty(r,He,{configurable:!1,enumerable:!1,writable:!1,value:{error:s=>e?.error(s),log:s=>e?.log(s),performance:s=>e?.performance(s),terminal:s=>e?.terminal(s),now:o,elapsed:s=>Math.max(0,o()-s),setCheckoutContext:s=>e?.setCheckoutContext(s),beginCheckout:(s={})=>e?.beginCheckout(s)??o(),disable:()=>e?.disable(),subscribe:s=>e?.subscribe(s)??(()=>{})}})}function Ye(r){return r[He]}var G=class{now(){return this.telemetryReporter?.now?.()??k()}constructor(e,t,o){this.provider=e,this.config=t,this.telemetryReporter=o??new v({billingApiUrl:(0,S.resolveBillingApiUrl)(t.billingApiUrl),sdkVersion:S.SDK_VERSION,enabled:t.telemetry!==!1}),$e(this,this.telemetryReporter,k)}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?Ke({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new q({sessionId:e?.sessionId,captureMethod:e?.captureMethod,telemetry:!1})}async retrieveSession(e,t){if(!e)throw new S.FloPayError("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let o=await this.retrieveUnifiedSession(e,t);if(!o.data.session)throw new S.FloPayError("Session not found","api_error");return o.data.session}async retrieveUnifiedSession(e,t){if(!e)throw new S.FloPayError("sessionId is required.","validation_error",{param:"sessionId"});let o=(0,S.resolveBillingApiUrl)(t??this.config.billingApiUrl),n=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let s,i=Ve(o,{now:()=>this.telemetryReporter?.now()??k(),onFirstByte:a=>{s=a},onRetry:(a,c)=>{this.telemetryReporter?.log({name:"operation.retry",stage:a==="session_read"?"session_read":"processing",requestCategory:a,attempt:c})}});try{let a=await i.getUnifiedCheckoutSession(e);return s!==void 0&&(this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:s,durationMode:"machine",requestCategory:"session_read",statusClass:"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()-n,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),a}catch(a){let c=(0,S.classifyTelemetryFailure)(a,a instanceof S.FloPayError&&a.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...c,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-n,durationMode:"machine",requestCategory:"session_read",statusClass:c.statusClass}),a}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.provider.destroy()}};function Ge(r,e,t){let o=G;return new o(r,e,t)}var M=require("@flopay/shared");var We=require("@flopay/shared"),Je=require("@stripe/stripe-js");function Te(r){switch(r){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function Qe(r){return{...r,theme:Te(r.theme)}}var B=class{constructor(){this.name="stripe";this.stripe=null}async initialize(e){if(typeof window>"u")return;let t=await(0,Je.loadStripe)(e.publishableKey,{locale:e.locale??"auto"});if(!t)throw new We.FloPayError("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=t}getRawProvider(){return this.stripe}destroy(){this.stripe=null}};var Xe=new Map;function be(r){return Array.isArray(r)?r.map(be):r&&typeof r=="object"?Object.fromEntries(Object.entries(r).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,be(t)])):r}function Nt(r,e){return JSON.stringify([r,(0,M.resolveBillingApiUrl)(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,be(e?.appearance??null)])}var le=new Map;async function Ze(r,e){if(!r){let a=new v({billingApiUrl:(0,M.resolveBillingApiUrl)(e?.billingApiUrl),sdkVersion:M.SDK_VERSION,enabled:e?.telemetry!==!1});throw a.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),a.flush().catch(()=>{}).finally(()=>a.destroy()),new M.FloPayError("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let t=Nt(r,e),o=Xe.get(t);if(o)return e?.telemetry!==!1&&Ye(o)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),o;let n=le.get(t);if(n)return n;let s={...e,publishableKey:r},i=(async()=>{let a=new v({billingApiUrl:(0,M.resolveBillingApiUrl)(s.billingApiUrl),sdkVersion:M.SDK_VERSION,enabled:s.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 l=new B,d=a.now();try{await l.initialize(s)}catch(m){throw a.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),a.destroy(),m}let y=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:y-c,durationMode:"machine",provider:"stripe"}),a.performance({stage:"provider_ready",durationMs:y-d,durationMode:"machine",provider:"stripe"});let p=Ge(l,s,a);return Xe.set(t,p),p})();le.set(t,i);try{return await i}finally{le.get(t)===i&&le.delete(t)}}0&&(module.exports={FloPay,PaymentAPI,PciVaultCardCapture,SESSION_CREATE_TELEMETRY,StripeAdapter,cacheSessionDisplayData,clearSessionDisplayData,createCheckoutSession,createCheckoutSessionWithRetries,dropThirdPartyOnlyError,getSessionDisplayData,loadFloPay,toStripeAppearance,toStripeAppearanceTheme});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CaptureMethod, CardCaptureAdapter, PayPalPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance } from '@flopay/shared';
|
|
1
|
+
import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance } from '@flopay/shared';
|
|
3
2
|
export { SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
|
|
4
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-B8II-Etg.cjs';
|
|
5
4
|
|
|
@@ -22,61 +21,18 @@ declare function createCheckoutSessionWithRetries(options: CreateSessionParams &
|
|
|
22
21
|
maxRetries?: number;
|
|
23
22
|
}): Promise<CheckoutSessionResult>;
|
|
24
23
|
|
|
25
|
-
/**
|
|
26
|
-
* Manages the creation and lifecycle of payment elements.
|
|
27
|
-
*
|
|
28
|
-
* Each `FloPayElements` instance is bound to a single provider adapter
|
|
29
|
-
* and tracks all created elements for cleanup.
|
|
30
|
-
*/
|
|
31
|
-
declare class FloPayElements {
|
|
32
|
-
private readonly provider;
|
|
33
|
-
private readonly elementMap;
|
|
34
|
-
private readonly baseOptions;
|
|
35
|
-
constructor(provider: PaymentProviderAdapter, options?: ElementOptions);
|
|
36
|
-
/**
|
|
37
|
-
* Creates a new element of the given type.
|
|
38
|
-
* If an element of that type already exists, it is destroyed first.
|
|
39
|
-
*/
|
|
40
|
-
create(type: ElementType, options?: ElementOptions): Promise<MountedElement>;
|
|
41
|
-
/** Returns a previously created element, or `null`. */
|
|
42
|
-
getElement(type: ElementType): MountedElement | null;
|
|
43
|
-
/**
|
|
44
|
-
* Submits all mounted elements for validation.
|
|
45
|
-
*
|
|
46
|
-
* Returns an object with an optional error if validation fails.
|
|
47
|
-
* This does NOT confirm the payment — call `floPay.confirmPayment()` for that.
|
|
48
|
-
*/
|
|
49
|
-
submit(): Promise<{
|
|
50
|
-
error?: FloPayError;
|
|
51
|
-
}>;
|
|
52
|
-
/** Destroys all created elements and clears the internal map. */
|
|
53
|
-
destroy(): void;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
24
|
/**
|
|
57
25
|
* The main FloPay SDK instance.
|
|
58
26
|
*
|
|
59
|
-
* Created via `loadFloPay(publishableKey)`. Provides
|
|
60
|
-
*
|
|
27
|
+
* Created via `loadFloPay(publishableKey)`. Provides hosted card capture,
|
|
28
|
+
* raw-provider access, and session retrieval.
|
|
61
29
|
*/
|
|
62
30
|
declare class FloPay {
|
|
63
31
|
private readonly provider;
|
|
64
32
|
private readonly config;
|
|
65
33
|
private readonly telemetryReporter?;
|
|
66
|
-
private currentElements;
|
|
67
34
|
private now;
|
|
68
35
|
constructor(provider: PaymentProviderAdapter, config: FloPayConfig);
|
|
69
|
-
/**
|
|
70
|
-
* Creates a new `FloPayElements` group for mounting payment fields.
|
|
71
|
-
*
|
|
72
|
-
* Only one elements group is active at a time. Creating a new one
|
|
73
|
-
* destroys the previous group.
|
|
74
|
-
*/
|
|
75
|
-
elements(options?: ElementOptions): FloPayElements;
|
|
76
|
-
/** Submit elements for validation. */
|
|
77
|
-
submitElements(): Promise<{
|
|
78
|
-
error?: _flopay_shared.FloPayError;
|
|
79
|
-
}>;
|
|
80
36
|
/**
|
|
81
37
|
* Create a {@link CardCaptureAdapter} for collecting card details through the
|
|
82
38
|
* backend-rendered hosted vault PCI widget (TeamFloPay/backend#823).
|
|
@@ -94,22 +50,6 @@ declare class FloPay {
|
|
|
94
50
|
/** Capture behavior used to classify legacy vault outcomes safely. */
|
|
95
51
|
captureMethod?: CaptureMethod;
|
|
96
52
|
}): CardCaptureAdapter;
|
|
97
|
-
/** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */
|
|
98
|
-
confirmPayPalPayment(params: {
|
|
99
|
-
billingApiUrl: string;
|
|
100
|
-
sessionId: string;
|
|
101
|
-
email: string;
|
|
102
|
-
returnUrl: string;
|
|
103
|
-
/**
|
|
104
|
-
* Session-bound checkout token forwarded to the session-scoped non-card
|
|
105
|
-
* intent contract as `x-checkout-session-token`.
|
|
106
|
-
*/
|
|
107
|
-
nonce?: string;
|
|
108
|
-
}): Promise<PayPalPaymentResult>;
|
|
109
|
-
/** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */
|
|
110
|
-
resumePayPalPayment(): Promise<PayPalPaymentResult | null>;
|
|
111
|
-
/** Confirms a non-card wallet/APM payment using the mounted PaymentElement. */
|
|
112
|
-
confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;
|
|
113
53
|
/**
|
|
114
54
|
* Retrieves a checkout session by ID via the billing API.
|
|
115
55
|
*
|
|
@@ -130,8 +70,7 @@ declare class FloPay {
|
|
|
130
70
|
retrieveUnifiedSession(sessionId: string, billingApiUrl?: string): Promise<NormalizedCheckoutSession>;
|
|
131
71
|
/**
|
|
132
72
|
* Returns the raw underlying provider instance (e.g. Stripe object).
|
|
133
|
-
* Used internally by components that need direct provider access
|
|
134
|
-
* such as PayPal which requires its own Elements instance.
|
|
73
|
+
* Used internally by components that need direct provider access.
|
|
135
74
|
*/
|
|
136
75
|
getRawProvider(): unknown;
|
|
137
76
|
/** Tears down the SDK instance and releases resources. */
|
|
@@ -155,17 +94,16 @@ declare class FloPay {
|
|
|
155
94
|
* import { loadFloPay } from '@flopay/js';
|
|
156
95
|
*
|
|
157
96
|
* const flopay = await loadFloPay('pk_test_...');
|
|
158
|
-
* const
|
|
159
|
-
*
|
|
160
|
-
* paymentElement.mount('#payment-container');
|
|
97
|
+
* const session = await flopay.retrieveSession('session_uuid');
|
|
98
|
+
* console.log(session.status);
|
|
161
99
|
* ```
|
|
162
100
|
*/
|
|
163
101
|
declare function loadFloPay(publishableKey: string, options?: Omit<FloPayConfig, 'publishableKey'>): Promise<FloPay>;
|
|
164
102
|
|
|
165
103
|
/**
|
|
166
104
|
* A `FloPayAppearance` whose `theme` has been normalized to the set Stripe's
|
|
167
|
-
* Appearance API accepts, so it can be handed straight to
|
|
168
|
-
*
|
|
105
|
+
* Appearance API accepts, so it can be handed straight to
|
|
106
|
+
* `@stripe/react-stripe-js`'s `<Elements options={{ appearance }}>` without
|
|
169
107
|
* tripping Stripe.js's `Invalid value … provided to "theme"` warning.
|
|
170
108
|
*/
|
|
171
109
|
interface StripeSafeAppearance {
|
|
@@ -173,62 +111,17 @@ interface StripeSafeAppearance {
|
|
|
173
111
|
variables?: FloPayThemeVariables;
|
|
174
112
|
rules?: Record<string, Record<string, string>>;
|
|
175
113
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Maps a `FloPayAppearance.theme` ('default' | 'flat' | 'night' | 'none') to a
|
|
178
|
-
* Stripe Elements Appearance `theme` ('stripe' | 'flat' | 'night'). Stripe's
|
|
179
|
-
* Appearance API only accepts those three; anything else triggers a console
|
|
180
|
-
* warning and silently falls back. We normalize here so the bundles can keep
|
|
181
|
-
* `'default'` as their public token.
|
|
182
|
-
*/
|
|
114
|
+
/** Maps FloPay's public appearance token to Stripe's accepted theme set. */
|
|
183
115
|
declare function toStripeAppearanceTheme(theme: 'default' | 'flat' | 'night' | 'none' | undefined): 'stripe' | 'night' | 'flat';
|
|
184
|
-
/**
|
|
185
|
-
* Normalizes a whole `FloPayAppearance` into a Stripe-safe appearance by mapping
|
|
186
|
-
* FloPay's public `theme` token onto Stripe's accepted set via
|
|
187
|
-
* {@link toStripeAppearanceTheme}. `variables` and `rules` (including FloPay's
|
|
188
|
-
* superset variable keys, which Stripe ignores at runtime) pass through
|
|
189
|
-
* untouched. Every site that forwards an appearance to `@stripe/react-stripe-js`
|
|
190
|
-
* must route it through here so `theme: 'default'` never reaches Stripe.js —
|
|
191
|
-
* `StripeAdapter` already normalizes via `toStripeAppearanceTheme` internally,
|
|
192
|
-
* and this keeps the React-mounted Elements groups on the same mapping.
|
|
193
|
-
*/
|
|
116
|
+
/** Normalizes a FloPay appearance before React passes it to Stripe Elements. */
|
|
194
117
|
declare function toStripeAppearance(appearance: FloPayAppearance): StripeSafeAppearance;
|
|
195
|
-
/**
|
|
196
|
-
* Payment provider adapter backed by Stripe.
|
|
197
|
-
*
|
|
198
|
-
* Implements the `PaymentProviderAdapter` interface so that FloPay consumers
|
|
199
|
-
* interact with a stable API regardless of the upstream provider.
|
|
200
|
-
*/
|
|
118
|
+
/** Payment provider adapter backed by Stripe. */
|
|
201
119
|
declare class StripeAdapter implements PaymentProviderAdapter {
|
|
202
120
|
readonly name = "stripe";
|
|
203
121
|
private stripe;
|
|
204
|
-
private elements;
|
|
205
|
-
private appliedAppearanceKey;
|
|
206
|
-
private appliedPaymentMethodTypesKey;
|
|
207
|
-
private appliedClientSecret;
|
|
208
|
-
private verifiedClientSecret;
|
|
209
|
-
private verifiedPaymentMethodTypesKey;
|
|
210
122
|
initialize(config: FloPayConfig): Promise<void>;
|
|
211
|
-
/** Lazily creates the Stripe Elements group for the given options. */
|
|
212
|
-
private getElements;
|
|
213
|
-
private assertClientSecretPaymentMethods;
|
|
214
|
-
createElement(type: ElementType, options: ElementOptions): Promise<MountedElement>;
|
|
215
|
-
getElement(type: ElementType): MountedElement | null;
|
|
216
|
-
submitElements(): Promise<{
|
|
217
|
-
error?: FloPayError;
|
|
218
|
-
}>;
|
|
219
|
-
confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;
|
|
220
|
-
private extractPaymentMethodId;
|
|
221
|
-
confirmPayPalPayment(params: {
|
|
222
|
-
billingApiUrl: string;
|
|
223
|
-
sessionId: string;
|
|
224
|
-
email: string;
|
|
225
|
-
returnUrl: string;
|
|
226
|
-
nonce?: string;
|
|
227
|
-
}): Promise<PayPalPaymentResult>;
|
|
228
|
-
resumePayPalPayment(): Promise<PayPalPaymentResult | null>;
|
|
229
123
|
getRawProvider(): unknown;
|
|
230
|
-
createPayPalElements(options: ElementOptions): unknown;
|
|
231
124
|
destroy(): void;
|
|
232
125
|
}
|
|
233
126
|
|
|
234
|
-
export { FloPay,
|
|
127
|
+
export { FloPay, StripeAdapter, type StripeSafeAppearance, createCheckoutSession, createCheckoutSessionWithRetries, loadFloPay, toStripeAppearance, toStripeAppearanceTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CaptureMethod, CardCaptureAdapter, PayPalPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance } from '@flopay/shared';
|
|
1
|
+
import { CreateSessionParams, CheckoutSessionResult, PaymentProviderAdapter, FloPayConfig, CaptureMethod, CardCaptureAdapter, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance } from '@flopay/shared';
|
|
3
2
|
export { SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
|
|
4
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-B8II-Etg.js';
|
|
5
4
|
|
|
@@ -22,61 +21,18 @@ declare function createCheckoutSessionWithRetries(options: CreateSessionParams &
|
|
|
22
21
|
maxRetries?: number;
|
|
23
22
|
}): Promise<CheckoutSessionResult>;
|
|
24
23
|
|
|
25
|
-
/**
|
|
26
|
-
* Manages the creation and lifecycle of payment elements.
|
|
27
|
-
*
|
|
28
|
-
* Each `FloPayElements` instance is bound to a single provider adapter
|
|
29
|
-
* and tracks all created elements for cleanup.
|
|
30
|
-
*/
|
|
31
|
-
declare class FloPayElements {
|
|
32
|
-
private readonly provider;
|
|
33
|
-
private readonly elementMap;
|
|
34
|
-
private readonly baseOptions;
|
|
35
|
-
constructor(provider: PaymentProviderAdapter, options?: ElementOptions);
|
|
36
|
-
/**
|
|
37
|
-
* Creates a new element of the given type.
|
|
38
|
-
* If an element of that type already exists, it is destroyed first.
|
|
39
|
-
*/
|
|
40
|
-
create(type: ElementType, options?: ElementOptions): Promise<MountedElement>;
|
|
41
|
-
/** Returns a previously created element, or `null`. */
|
|
42
|
-
getElement(type: ElementType): MountedElement | null;
|
|
43
|
-
/**
|
|
44
|
-
* Submits all mounted elements for validation.
|
|
45
|
-
*
|
|
46
|
-
* Returns an object with an optional error if validation fails.
|
|
47
|
-
* This does NOT confirm the payment — call `floPay.confirmPayment()` for that.
|
|
48
|
-
*/
|
|
49
|
-
submit(): Promise<{
|
|
50
|
-
error?: FloPayError;
|
|
51
|
-
}>;
|
|
52
|
-
/** Destroys all created elements and clears the internal map. */
|
|
53
|
-
destroy(): void;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
24
|
/**
|
|
57
25
|
* The main FloPay SDK instance.
|
|
58
26
|
*
|
|
59
|
-
* Created via `loadFloPay(publishableKey)`. Provides
|
|
60
|
-
*
|
|
27
|
+
* Created via `loadFloPay(publishableKey)`. Provides hosted card capture,
|
|
28
|
+
* raw-provider access, and session retrieval.
|
|
61
29
|
*/
|
|
62
30
|
declare class FloPay {
|
|
63
31
|
private readonly provider;
|
|
64
32
|
private readonly config;
|
|
65
33
|
private readonly telemetryReporter?;
|
|
66
|
-
private currentElements;
|
|
67
34
|
private now;
|
|
68
35
|
constructor(provider: PaymentProviderAdapter, config: FloPayConfig);
|
|
69
|
-
/**
|
|
70
|
-
* Creates a new `FloPayElements` group for mounting payment fields.
|
|
71
|
-
*
|
|
72
|
-
* Only one elements group is active at a time. Creating a new one
|
|
73
|
-
* destroys the previous group.
|
|
74
|
-
*/
|
|
75
|
-
elements(options?: ElementOptions): FloPayElements;
|
|
76
|
-
/** Submit elements for validation. */
|
|
77
|
-
submitElements(): Promise<{
|
|
78
|
-
error?: _flopay_shared.FloPayError;
|
|
79
|
-
}>;
|
|
80
36
|
/**
|
|
81
37
|
* Create a {@link CardCaptureAdapter} for collecting card details through the
|
|
82
38
|
* backend-rendered hosted vault PCI widget (TeamFloPay/backend#823).
|
|
@@ -94,22 +50,6 @@ declare class FloPay {
|
|
|
94
50
|
/** Capture behavior used to classify legacy vault outcomes safely. */
|
|
95
51
|
captureMethod?: CaptureMethod;
|
|
96
52
|
}): CardCaptureAdapter;
|
|
97
|
-
/** Confirm a PayPal payment: create intent via billing API → confirm → redirect if needed. */
|
|
98
|
-
confirmPayPalPayment(params: {
|
|
99
|
-
billingApiUrl: string;
|
|
100
|
-
sessionId: string;
|
|
101
|
-
email: string;
|
|
102
|
-
returnUrl: string;
|
|
103
|
-
/**
|
|
104
|
-
* Session-bound checkout token forwarded to the session-scoped non-card
|
|
105
|
-
* intent contract as `x-checkout-session-token`.
|
|
106
|
-
*/
|
|
107
|
-
nonce?: string;
|
|
108
|
-
}): Promise<PayPalPaymentResult>;
|
|
109
|
-
/** Resume a PayPal payment after redirect return. Returns null if no PayPal params in URL. */
|
|
110
|
-
resumePayPalPayment(): Promise<PayPalPaymentResult | null>;
|
|
111
|
-
/** Confirms a non-card wallet/APM payment using the mounted PaymentElement. */
|
|
112
|
-
confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;
|
|
113
53
|
/**
|
|
114
54
|
* Retrieves a checkout session by ID via the billing API.
|
|
115
55
|
*
|
|
@@ -130,8 +70,7 @@ declare class FloPay {
|
|
|
130
70
|
retrieveUnifiedSession(sessionId: string, billingApiUrl?: string): Promise<NormalizedCheckoutSession>;
|
|
131
71
|
/**
|
|
132
72
|
* Returns the raw underlying provider instance (e.g. Stripe object).
|
|
133
|
-
* Used internally by components that need direct provider access
|
|
134
|
-
* such as PayPal which requires its own Elements instance.
|
|
73
|
+
* Used internally by components that need direct provider access.
|
|
135
74
|
*/
|
|
136
75
|
getRawProvider(): unknown;
|
|
137
76
|
/** Tears down the SDK instance and releases resources. */
|
|
@@ -155,17 +94,16 @@ declare class FloPay {
|
|
|
155
94
|
* import { loadFloPay } from '@flopay/js';
|
|
156
95
|
*
|
|
157
96
|
* const flopay = await loadFloPay('pk_test_...');
|
|
158
|
-
* const
|
|
159
|
-
*
|
|
160
|
-
* paymentElement.mount('#payment-container');
|
|
97
|
+
* const session = await flopay.retrieveSession('session_uuid');
|
|
98
|
+
* console.log(session.status);
|
|
161
99
|
* ```
|
|
162
100
|
*/
|
|
163
101
|
declare function loadFloPay(publishableKey: string, options?: Omit<FloPayConfig, 'publishableKey'>): Promise<FloPay>;
|
|
164
102
|
|
|
165
103
|
/**
|
|
166
104
|
* A `FloPayAppearance` whose `theme` has been normalized to the set Stripe's
|
|
167
|
-
* Appearance API accepts, so it can be handed straight to
|
|
168
|
-
*
|
|
105
|
+
* Appearance API accepts, so it can be handed straight to
|
|
106
|
+
* `@stripe/react-stripe-js`'s `<Elements options={{ appearance }}>` without
|
|
169
107
|
* tripping Stripe.js's `Invalid value … provided to "theme"` warning.
|
|
170
108
|
*/
|
|
171
109
|
interface StripeSafeAppearance {
|
|
@@ -173,62 +111,17 @@ interface StripeSafeAppearance {
|
|
|
173
111
|
variables?: FloPayThemeVariables;
|
|
174
112
|
rules?: Record<string, Record<string, string>>;
|
|
175
113
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Maps a `FloPayAppearance.theme` ('default' | 'flat' | 'night' | 'none') to a
|
|
178
|
-
* Stripe Elements Appearance `theme` ('stripe' | 'flat' | 'night'). Stripe's
|
|
179
|
-
* Appearance API only accepts those three; anything else triggers a console
|
|
180
|
-
* warning and silently falls back. We normalize here so the bundles can keep
|
|
181
|
-
* `'default'` as their public token.
|
|
182
|
-
*/
|
|
114
|
+
/** Maps FloPay's public appearance token to Stripe's accepted theme set. */
|
|
183
115
|
declare function toStripeAppearanceTheme(theme: 'default' | 'flat' | 'night' | 'none' | undefined): 'stripe' | 'night' | 'flat';
|
|
184
|
-
/**
|
|
185
|
-
* Normalizes a whole `FloPayAppearance` into a Stripe-safe appearance by mapping
|
|
186
|
-
* FloPay's public `theme` token onto Stripe's accepted set via
|
|
187
|
-
* {@link toStripeAppearanceTheme}. `variables` and `rules` (including FloPay's
|
|
188
|
-
* superset variable keys, which Stripe ignores at runtime) pass through
|
|
189
|
-
* untouched. Every site that forwards an appearance to `@stripe/react-stripe-js`
|
|
190
|
-
* must route it through here so `theme: 'default'` never reaches Stripe.js —
|
|
191
|
-
* `StripeAdapter` already normalizes via `toStripeAppearanceTheme` internally,
|
|
192
|
-
* and this keeps the React-mounted Elements groups on the same mapping.
|
|
193
|
-
*/
|
|
116
|
+
/** Normalizes a FloPay appearance before React passes it to Stripe Elements. */
|
|
194
117
|
declare function toStripeAppearance(appearance: FloPayAppearance): StripeSafeAppearance;
|
|
195
|
-
/**
|
|
196
|
-
* Payment provider adapter backed by Stripe.
|
|
197
|
-
*
|
|
198
|
-
* Implements the `PaymentProviderAdapter` interface so that FloPay consumers
|
|
199
|
-
* interact with a stable API regardless of the upstream provider.
|
|
200
|
-
*/
|
|
118
|
+
/** Payment provider adapter backed by Stripe. */
|
|
201
119
|
declare class StripeAdapter implements PaymentProviderAdapter {
|
|
202
120
|
readonly name = "stripe";
|
|
203
121
|
private stripe;
|
|
204
|
-
private elements;
|
|
205
|
-
private appliedAppearanceKey;
|
|
206
|
-
private appliedPaymentMethodTypesKey;
|
|
207
|
-
private appliedClientSecret;
|
|
208
|
-
private verifiedClientSecret;
|
|
209
|
-
private verifiedPaymentMethodTypesKey;
|
|
210
122
|
initialize(config: FloPayConfig): Promise<void>;
|
|
211
|
-
/** Lazily creates the Stripe Elements group for the given options. */
|
|
212
|
-
private getElements;
|
|
213
|
-
private assertClientSecretPaymentMethods;
|
|
214
|
-
createElement(type: ElementType, options: ElementOptions): Promise<MountedElement>;
|
|
215
|
-
getElement(type: ElementType): MountedElement | null;
|
|
216
|
-
submitElements(): Promise<{
|
|
217
|
-
error?: FloPayError;
|
|
218
|
-
}>;
|
|
219
|
-
confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;
|
|
220
|
-
private extractPaymentMethodId;
|
|
221
|
-
confirmPayPalPayment(params: {
|
|
222
|
-
billingApiUrl: string;
|
|
223
|
-
sessionId: string;
|
|
224
|
-
email: string;
|
|
225
|
-
returnUrl: string;
|
|
226
|
-
nonce?: string;
|
|
227
|
-
}): Promise<PayPalPaymentResult>;
|
|
228
|
-
resumePayPalPayment(): Promise<PayPalPaymentResult | null>;
|
|
229
123
|
getRawProvider(): unknown;
|
|
230
|
-
createPayPalElements(options: ElementOptions): unknown;
|
|
231
124
|
destroy(): void;
|
|
232
125
|
}
|
|
233
126
|
|
|
234
|
-
export { FloPay,
|
|
127
|
+
export { FloPay, StripeAdapter, type StripeSafeAppearance, createCheckoutSession, createCheckoutSessionWithRetries, loadFloPay, toStripeAppearance, toStripeAppearanceTheme };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as E,b as K,c as Z,d as j,e as Re,f as Te,g as x,h as g,i as ke,j as O,k as ee,l as z,m as te}from"./chunk-CR4J5H7I.mjs";import{dropThirdPartyOnlyError as Tt}from"@flopay/shared";import{assertCaptureMethodEligible as be,buildProductPayload as Ae,classifyTelemetryFailure as Ie,FloPayError as _,foldIntoProducts as Fe,IDEMPOTENCY_IN_PROGRESS_CODE as xe,IDEMPOTENCY_KEY_HEADER as Oe,resolveIdempotencyKey as re,resolveSessionCurrency as Ue,SDK_VERSION as ne,telemetryStatusClass as ae}from"@flopay/shared";var V=5,oe=new WeakSet;function De(r){(typeof r=="object"&&r!==null||typeof r=="function")&&oe.add(r)}function qe(r){return(typeof r=="object"&&r!==null||typeof r=="function")&&oe.has(r)}function Le(r,e){let n=e?.error,t=E(e?.code)??E(n?.code)??`http_${r}`,o=E(e?.message)??E(n?.message)??Ne(t,r);return new _(o,"api_error",{code:t,statusCode:r})}function Ne(r,e){switch(r){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${V}.`;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 ie(r,e,n){let{billingApiUrl:t,checkoutBaseUrl:o,items:a=[],subscriptions:l=[],products:s,account:i,successUrl:d,cancelUrl:h,checkoutMode:C="confirm",captureMethod:y,couponCodes:f=[],tagsData:J,redirectParams:Pe={},setCookie:ve=!0,clientId:we,currency:_e,utmMetadata:W,idempotencyKey:Se}=r,Q=re(Se);if(f.length>V)throw new _(`Too many coupon codes \u2014 a checkout session accepts at most ${V}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let M=s??Fe(a,l);be({captureMethod:y,products:M});let P=Ue(_e,a,l,M);if(!P)throw new _("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 k={clientId:we,checkoutVersion:ne,successUrl:d,cancelUrl:h,currency:P,checkoutMode:C,products:M.map(u=>Ae(u,P)),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:f};y==="manual"&&(k.captureMethod=y),J&&(k.tagsData=J),W?.length&&(k.utmMetadata=W);let Me=`${t.replace(/\/+$/,"")}/v1/checkouts/sessions`,X={"Content-Type":"application/json"};Q&&(X[Oe]=Q);let v,b,Ee={method:"POST",headers:X,body:JSON.stringify(k),signal:e},A;try{A=await fetch(Me,Ee)}catch(u){throw De(u),u}try{n?.(A.status)}catch{}v=A.status;try{b=await A.json()}catch{}if(v>=400)throw Le(v,b);if(v===201){let u=b?.data?.uuid,N=b?.data?.nonce;if(!u)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!N)throw new _("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"});(M.length||P)&&j(u,{currency:P,products:M.map(c=>({code:c.code??c.providerItemId??c.providerPlanId,type:c.type,name:c.name??c.itemName??c.providerItemName??c.subscriptionName??c.providerPlanName??null,totalAmount:c.totalAmount,overrideAmount:c.overrideAmount,currency:c.currency??P}))});let I=new URL(`${o.replace(/\/+$/,"")}/secure`);I.searchParams.set("id",u);for(let[c,F]of Object.entries(Pe))I.searchParams.set(c,F);if(ve&&typeof window<"u"&&typeof document<"u"){let c=JSON.stringify({origin_url:h}),F=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(c)}; domain=.${F}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(N)}; domain=.${F}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=I.toString()),{status:201,redirectUrl:I.toString(),nonce:N}}return v===204?(typeof window<"u"&&(window.location.href=d),{status:204}):{status:v}}async function Ke(r){let e=le(r),n=se(e),t=K(r.timeoutMs);try{let o=await ie(r,t.signal,n);return de(e,o),o}catch(o){throw U(e,o),o}finally{t.clear(),w(e.reporter)}}function se(r){let e=!1;return n=>{if(e)return;e=!0;let t=ae(n);r.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:t,attempt:r.attempt}),r.reporter.performance({stage:"session_first_byte",durationMs:r.reporter.now()-r.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:t,attempt:r.attempt})}}function le(r){let e=new g({billingApiUrl:r.billingApiUrl,sdkVersion:ne,enabled:r.telemetry!==!1}),n=e.now();return e.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:e,startedAt:n,attempt:0}}function de(r,e){let n=ae(e.status);r.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:n}),r.reporter.performance({stage:"session_create",durationMs:r.reporter.now()-r.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:n,attempt:r.attempt})}function U(r,e){let{reporter:n}=r,t=Ie(e,"CHECKOUT_SESSION_CREATE_FAILED");if(n.performance({stage:"session_create",durationMs:n.now()-r.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:t.statusClass,attempt:r.attempt}),e instanceof _&&e.type==="validation_error"){n.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(t.statusClass==="4xx"){n.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}n.error({...t,stage:"session_create",requestCategory:"session_create"})}function w(r){r.flush().catch(()=>{}).finally(()=>r.destroy())}async function je(r){let{maxRetries:e=2,...n}=r,t=le(r),o=se(t);if(!Number.isFinite(e)||!Number.isInteger(e)||e<0||e>=3)throw t.reporter.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),w(t.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let a={...n,idempotencyKey:re(n.idempotencyKey)},l=K(n.timeoutMs),s;for(let i=0;i<=e;i++){t.attempt=i;try{let d=await ie(a,l.signal,o);return de(t,d),l.clear(),w(t.reporter),d}catch(d){s=d;let h=d instanceof Error&&d.name==="AbortError",C=qe(d),y=d instanceof _&&d.code===xe;if((h||C||y)&&!l.signal.aborted&&i<e){t.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:i+1});try{await Z(i,l.signal)}catch(f){throw U(t,f),l.clear(),w(t.reporter),f}continue}throw U(t,d),l.clear(),w(t.reporter),d}}throw U(t,s),l.clear(),w(t.reporter),s??new Error("Unknown error during checkout session creation")}import{FloPayError as ze}from"@flopay/shared";var R=class{constructor(e,n){this.elementMap=new Map;this.provider=e,this.baseOptions=n??{}}async create(e,n){let t={...this.baseOptions,...n};if(e==="payment"){let s=t.paymentMethodTypes?.map(i=>i.trim()).filter(i=>i&&i.toLowerCase()!=="card");if(!s?.length)throw new ze("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});t.paymentMethodTypes=s}let o=this.provider.getElement(e);if(o)return this.elementMap.set(e,o),o;let a=this.elementMap.get(e);a&&a.destroy();let l=await this.provider.createElement(e,t);return this.elementMap.set(e,l),l}getElement(e){return this.elementMap.get(e)??null}async submit(){return{}}destroy(){for(let e of this.elementMap.values())e.destroy();this.elementMap.clear()}};import{classifyTelemetryFailure as $,FloPayError as m,resolveBillingApiUrl as ye,SDK_VERSION as Be}from"@flopay/shared";var pe=Symbol.for("@flopay/js.telemetry.bridge.v1");function ce(r,e,n){let t=()=>e?.now()??n();Object.defineProperty(r,pe,{configurable:!1,enumerable:!1,writable:!1,value:{error:a=>e?.error(a),log:a=>e?.log(a),performance:a=>e?.performance(a),terminal:a=>e?.terminal(a),now:t,elapsed:a=>Math.max(0,t()-a),setCheckoutContext:a=>e?.setCheckoutContext(a),beginCheckout:(a={})=>e?.beginCheckout(a)??t(),disable:()=>e?.disable(),subscribe:a=>e?.subscribe(a)??(()=>{})}})}function me(r){return r[pe]}function S(r){if(!r)return!1;let e=r.code?.toLowerCase()??"";return!!r.declineCode||e.includes("declin")}function Ve(r){return r==="stripe"||r==="paypal"||r==="pcivault"?r:"other"}var D=class{constructor(e,n,t){this.currentElements=null;this.provider=e,this.config=n,this.telemetryReporter=t??new g({billingApiUrl:ye(n.billingApiUrl),sdkVersion:Be,enabled:n.telemetry!==!1}),ce(this,this.telemetryReporter,x)}now(){return this.telemetryReporter?.now?.()??x()}elements(e){return this.currentElements&&this.currentElements.destroy(),this.currentElements=new R(this.provider,{appearance:this.config.appearance,...e}),this.currentElements}async submitElements(){return this.provider.submitElements()}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?te({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new z({sessionId:e?.sessionId,captureMethod:e?.captureMethod,telemetry:!1})}async confirmPayPalPayment(e){let n=this.now();this.telemetryReporter?.log({name:"payment.method.selected",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.log({name:"payment.intent.started",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create"});try{let t=await this.provider.confirmPayPalPayment(e);return this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-n,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),t.error||this.telemetryReporter?.log({name:"payment.intent.completed",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create",statusClass:"2xx"}),t.status==="requires_action"?(this.telemetryReporter?.log({name:"payment.three_ds.handoff",stage:"three_ds_handoff",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.log({name:"provider.redirect.started",stage:"redirect",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.terminal({outcome:"action_required",stage:"redirect",provider:"paypal",paymentMethodCategory:"paypal"})):t.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:"paypal",paymentMethodCategory:"paypal"}):t.status!=="processing"&&(S(t.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"}):t.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"}):t.error&&this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create"})),t}catch(t){if(this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-n,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),t instanceof m&&S(t))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(t instanceof m&&t.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let o=$(t,"PAYMENT_PROCESSING_FAILED","unknown");this.telemetryReporter?.error({...o,failureCategory:o.failureCategory??"provider_runtime",stage:"processing",provider:"paypal",paymentMethodCategory:"paypal",requestCategory:"intent_create"})}throw t}}async resumePayPalPayment(){let e=this.now();try{let n=await this.provider.resumePayPalPayment();return n===null?null:(this.telemetryReporter?.log({name:"provider.redirect.resumed",stage:"redirect_resume",provider:"paypal",paymentMethodCategory:"paypal"}),this.telemetryReporter?.performance({stage:"redirect_resume",durationMs:this.now()-e,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),n.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:"paypal",paymentMethodCategory:"paypal"}):S(n.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"}):n.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"}):n.error&&this.telemetryReporter?.error({errorCode:"REDIRECT_RESUME_FAILED",failureCategory:"provider_runtime",stage:"redirect_resume",provider:"paypal",paymentMethodCategory:"paypal"}),n)}catch(n){if(this.telemetryReporter?.performance({stage:"redirect_resume",durationMs:this.now()-e,durationMode:"machine",provider:"paypal",paymentMethodCategory:"paypal"}),n instanceof m&&S(n))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(n instanceof m&&n.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let t=$(n,"REDIRECT_RESUME_FAILED","unknown");this.telemetryReporter?.error({...t,failureCategory:t.failureCategory??"provider_runtime",stage:"redirect_resume",provider:"paypal",paymentMethodCategory:"paypal"})}throw n}}async confirmPayment(e){if(e.paymentMethodCategory!=="wallet"&&e.paymentMethodCategory!=="apm"||!e.paymentMethodType?.trim()||e.paymentMethodType.trim().toLowerCase()==="card")throw new m("A supported non-card payment method is required.","validation_error",{param:"paymentMethodType"});let n=this.now(),t=Ve(this.provider.name);this.telemetryReporter?.log({name:"payment.processing.started",stage:"processing",provider:t,paymentMethodCategory:e.paymentMethodCategory});try{let o=await this.provider.confirmPayment(e),a=this.now()-n;return this.telemetryReporter?.performance({stage:"processing",durationMs:a,durationMode:"machine",provider:t,paymentMethodCategory:e.paymentMethodCategory}),o.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:t,paymentMethodCategory:e.paymentMethodCategory}):S(o.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:t,paymentMethodCategory:e.paymentMethodCategory}):o.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:t,paymentMethodCategory:e.paymentMethodCategory}):o.status==="requires_action"?(this.telemetryReporter?.log({name:"payment.three_ds.handoff",stage:"three_ds_handoff",provider:t,paymentMethodCategory:e.paymentMethodCategory}),this.telemetryReporter?.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:t,paymentMethodCategory:e.paymentMethodCategory})):o.status==="failed"&&o.error&&this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:t,paymentMethodCategory:e.paymentMethodCategory}),o.status==="succeeded"||o.status==="failed"?this.telemetryReporter?.log({name:"payment.processing.completed",stage:"processing",provider:t,paymentMethodCategory:e.paymentMethodCategory}):this.telemetryReporter?.log({name:"operation.state_transition",stage:o.status==="requires_action"?"three_ds_handoff":"processing",provider:t,paymentMethodCategory:e.paymentMethodCategory}),o}catch(o){throw this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-n,durationMode:"machine",provider:t,paymentMethodCategory:e.paymentMethodCategory}),o instanceof m&&S(o)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:t,paymentMethodCategory:e.paymentMethodCategory}):o instanceof m&&o.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:t,paymentMethodCategory:e.paymentMethodCategory}):this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:t,paymentMethodCategory:e.paymentMethodCategory}),o}}async retrieveSession(e,n){if(!e)throw new m("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let t=await this.retrieveUnifiedSession(e,n);if(!t.data.session)throw new m("Session not found","api_error");return t.data.session}async retrieveUnifiedSession(e,n){if(!e)throw new m("sessionId is required.","validation_error",{param:"sessionId"});let t=ye(n??this.config.billingApiUrl),o=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let a,l=ee(t,{now:()=>this.telemetryReporter?.now()??x(),onFirstByte:s=>{a=s},onRetry:(s,i)=>{this.telemetryReporter?.log({name:"operation.retry",stage:s==="session_read"?"session_read":"processing",requestCategory:s,attempt:i})}});try{let s=await l.getUnifiedCheckoutSession(e);return a!==void 0&&(this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:a,durationMode:"machine",requestCategory:"session_read",statusClass:"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()-o,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),s}catch(s){let i=$(s,s instanceof m&&s.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...i,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-o,durationMode:"machine",requestCategory:"session_read",statusClass:i.statusClass}),s}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.currentElements?.destroy(),this.currentElements=null,this.provider.destroy()}};function ue(r,e,n){let t=D;return new t(r,e,n)}import{FloPayError as We,resolveBillingApiUrl as G,SDK_VERSION as ge}from"@flopay/shared";import{FloPayError as p,isMoneySettledOutcome as $e,isSetupIntentClientSecret as Ye}from"@flopay/shared";import{loadStripe as Ge}from"@stripe/stripe-js";function he(r){return{payment:"payment",address:"address"}[r]}function q(r){switch(r){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function He(r){return{...r,theme:q(r.theme)}}function Y(r){return r?JSON.stringify(r.map(e=>e.trim().toLowerCase())):null}function fe(r){let e=r;return{mount(n){e.mount(n)},unmount(){e.unmount()},update(n){e.update(n)},on(n,t){e.on?.(n,t)},off(n,t){e.off?.(n,t)},destroy(){e.destroy()}}}function Je(r){return{billing_details:{...r.email?{email:r.email}:{},...r.name?{name:r.name}:{},...r.address?{address:{...r.address.country?{country:r.address.country}:{},...r.address.postal_code?{postal_code:r.address.postal_code}:{},...r.address.city?{city:r.address.city}:{},...r.address.line1?{line1:r.address.line1}:{},...r.address.line2?{line2:r.address.line2}:{},...r.address.state?{state:r.address.state}:{}}}:{}}}}var T=class{constructor(){this.name="stripe";this.stripe=null;this.elements=null;this.appliedAppearanceKey=null;this.appliedPaymentMethodTypesKey=null;this.appliedClientSecret=null;this.verifiedClientSecret=null;this.verifiedPaymentMethodTypesKey=null}async initialize(e){if(typeof window>"u")return;let n=await Ge(e.publishableKey,{locale:e.locale??"auto"});if(!n)throw new p("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=n}getElements(e){if(!this.stripe)throw new p("StripeAdapter not initialized. Call initialize() first.","api_error");let n=e?.appearance?{theme:q(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}:void 0,t=n?JSON.stringify(n):null,o=Y(e?.paymentMethodTypes),a=e?.clientSecret??null;if(this.elements&&o&&(o!==this.appliedPaymentMethodTypesKey||a!==this.appliedClientSecret)&&(this.elements=null,this.appliedAppearanceKey=null,this.appliedPaymentMethodTypesKey=null,this.appliedClientSecret=null,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null),this.elements)t!==this.appliedAppearanceKey&&(this.elements.update({appearance:n??{}}),this.appliedAppearanceKey=t);else{let l,s=e?.amount??0,i=(e?.currency??"usd").toLowerCase(),d=e?.paymentMethodCreation??"manual";e?.clientSecret?l={clientSecret:e.clientSecret}:s>0?(l={mode:"payment",amount:s,currency:i,paymentMethodCreation:d},e?.setupFutureUsage&&(l.setupFutureUsage=e.setupFutureUsage)):l={mode:"setup",currency:i,paymentMethodCreation:d},!e?.clientSecret&&e?.paymentMethodTypes&&(l.paymentMethodTypes=e.paymentMethodTypes),n&&(l.appearance=n),this.elements=this.stripe.elements(l),this.appliedAppearanceKey=t,this.appliedPaymentMethodTypesKey=o,this.appliedClientSecret=a,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null}return this.elements}async assertClientSecretPaymentMethods(e,n){if(!this.stripe)throw new p("StripeAdapter not initialized. Call initialize() first.","api_error");let t,o=!1;if(Ye(e)){let{setupIntent:i,error:d}=await this.stripe.retrieveSetupIntent(e);t=i,o=!!d}else{let{paymentIntent:i,error:d}=await this.stripe.retrievePaymentIntent(e);t=i,o=!!d}let a=t?.payment_method_types;if(o||!Array.isArray(a))throw new p("Unable to verify the payment methods configured for this client secret.","api_error",{param:"clientSecret"});let l=new Set(n.map(i=>i.toLowerCase()));if(a.some(i=>typeof i!="string"||!l.has(i.trim().toLowerCase()))||a.length===0)throw new p("The client-secret intent must enable only declared non-card payment methods.","validation_error",{param:"clientSecret"})}async createElement(e,n){let t=n;if(e==="payment"){let i=n.paymentMethodTypes?.map(d=>d.trim()).filter(d=>d&&d.toLowerCase()!=="card");if(!i?.length)throw new p("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});if(t={...n,paymentMethodTypes:i},t.clientSecret){let d=Y(i);this.elements&&this.appliedClientSecret===t.clientSecret&&this.appliedPaymentMethodTypesKey===d&&this.verifiedClientSecret===t.clientSecret&&this.verifiedPaymentMethodTypesKey===d||await this.assertClientSecretPaymentMethods(t.clientSecret,i)}}let o=this.getElements(t);e==="payment"&&t.clientSecret&&(this.verifiedClientSecret=t.clientSecret,this.verifiedPaymentMethodTypesKey=Y(t.paymentMethodTypes));let a=he(e),l={};t.layout&&(l.layout=t.layout),t.defaultValues&&(l.defaultValues=t.defaultValues),t.readOnly&&(l.readOnly=t.readOnly),t.mode&&(l.mode=t.mode);let s=o.create(a,l);return fe(s)}getElement(e){if(!this.elements)return null;let n=he(e),t=this.elements.getElement(n);return t?fe(t):null}async submitElements(){if(!this.stripe||!this.elements)return{error:new p("Stripe not initialized","api_error")};let{error:e}=await this.elements.submit();return e?{error:new p(e.message??"Validation failed","validation_error")}:{}}async confirmPayment(e){if(!this.stripe||!this.elements)throw new p("StripeAdapter not initialized or no elements created.","api_error");let n=e.billingDetails,t=n?Je(n):void 0,{error:o,paymentIntent:a}=await this.stripe.confirmPayment({elements:this.elements,clientSecret:e.clientSecret,confirmParams:{return_url:e.returnUrl??window.location.href,...t?{payment_method_data:t}:{}},redirect:"if_required"});return o?{status:"failed",error:new p(o.message??"Payment failed","api_error",{code:o.code,declineCode:o.decline_code})}:a?{status:{succeeded:"succeeded",processing:"processing",requires_action:"requires_action",requires_payment_method:"failed",canceled:"failed"}[a.status]??"failed",paymentIntentId:a.id,paymentMethodId:this.extractPaymentMethodId(a.payment_method)}:{status:"failed",error:new p("No payment intent returned","api_error")}}extractPaymentMethodId(e){if(typeof e=="string"&&e.startsWith("pm_"))return e;if(e&&typeof e=="object"&&typeof e.id=="string")return e.id}async confirmPayPalPayment(e){if(!this.stripe)return{status:"failed",error:new p("Stripe not initialized","api_error")};let n=e.billingApiUrl.replace(/\/+$/,"");if(this.elements){let{error:a}=await this.elements.submit();if(a)return{status:"failed",error:new p(a.message??"PayPal payment failed","validation_error",{code:a.code})}}let t;try{let a=await new O(n).createSessionIntent(e.sessionId,e.nonce??"",{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",paymentMethodId:null,intentKind:"payment"});if(a.provider!=="stripe")throw new p("Invalid provider returned for PayPal intent","api_error");t=a.clientSecret}catch(a){return{status:"failed",error:a instanceof p?a:new p("Failed to create PayPal payment intent","api_error")}}let{error:o}=await this.stripe.confirmPayment({clientSecret:t,elements:this.elements??void 0,confirmParams:{return_url:e.returnUrl}});if(o){if(e.nonce)try{await new O(n).reportSessionIntentDecline(e.sessionId,e.nonce,{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:o.code??"provider_declined"})}catch{}return{status:"failed",error:new p(o.message??"PayPal payment failed","api_error",{code:o.code})}}return{status:"processing"}}async resumePayPalPayment(){if(!this.stripe||typeof window>"u")return null;let e=new URLSearchParams(window.location.search),n=e.get("payment_intent"),t=e.get("payment_intent_client_secret"),o=e.get("redirect_status");if(!n||!t)return null;if(o==="failed")return{status:"failed",error:new p("PayPal payment was declined. Please try again.","api_error")};let{paymentIntent:a,error:l}=await this.stripe.retrievePaymentIntent(t);if(l)return{status:"failed",error:new p(l.message??"Failed to retrieve PayPal payment","api_error")};if(a&&$e(a.status)){let s=typeof a.payment_method=="string"?a.payment_method:a.payment_method?.id,i=new URL(window.location.href);return i.searchParams.delete("payment_intent"),i.searchParams.delete("payment_intent_client_secret"),i.searchParams.delete("redirect_status"),window.history.replaceState({},"",i.toString()),{status:a.status,paymentIntentId:a.id,paymentMethodId:s}}return{status:"failed",error:new p("PayPal payment was not completed. Please try again.","api_error")}}getRawProvider(){return this.stripe}createPayPalElements(e){if(!this.stripe)return null;let n={mode:"payment",amount:e.amount??0,currency:(e.currency??"usd").toLowerCase(),captureMethod:"manual"};return e.setupFutureUsage&&(n.setupFutureUsage=e.setupFutureUsage),e.appearance&&(n.appearance={theme:q(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}),this.stripe.elements(n)}destroy(){this.elements=null,this.appliedAppearanceKey=null,this.appliedPaymentMethodTypesKey=null,this.appliedClientSecret=null,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null,this.stripe=null}};var Ce=new Map;function H(r){return Array.isArray(r)?r.map(H):r&&typeof r=="object"?Object.fromEntries(Object.entries(r).filter(([,e])=>e!==void 0).sort(([e],[n])=>e.localeCompare(n)).map(([e,n])=>[e,H(n)])):r}function Qe(r,e){return JSON.stringify([r,G(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,H(e?.appearance??null)])}var L=new Map;async function Xe(r,e){if(!r){let s=new g({billingApiUrl:G(e?.billingApiUrl),sdkVersion:ge,enabled:e?.telemetry!==!1});throw s.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),s.flush().catch(()=>{}).finally(()=>s.destroy()),new We("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let n=Qe(r,e),t=Ce.get(n);if(t)return e?.telemetry!==!1&&me(t)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),t;let o=L.get(n);if(o)return o;let a={...e,publishableKey:r},l=(async()=>{let s=new g({billingApiUrl:G(a.billingApiUrl),sdkVersion:ge,enabled:a.telemetry!==!1}),i=s.now();s.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),s.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),s.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let d=new T,h=s.now();try{await d.initialize(a)}catch(f){throw s.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),s.destroy(),f}let C=s.now();s.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),s.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),s.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),s.performance({stage:"sdk_initialize",durationMs:C-i,durationMode:"machine",provider:"stripe"}),s.performance({stage:"provider_ready",durationMs:C-h,durationMode:"machine",provider:"stripe"});let y=ue(d,a,s);return Ce.set(n,y),y})();L.set(n,l);try{return await l}finally{L.get(n)===l&&L.delete(n)}}export{D as FloPay,R as FloPayElements,O as PaymentAPI,z as PciVaultCardCapture,ke as SESSION_CREATE_TELEMETRY,T as StripeAdapter,j as cacheSessionDisplayData,Te as clearSessionDisplayData,Ke as createCheckoutSession,je as createCheckoutSessionWithRetries,Tt as dropThirdPartyOnlyError,Re as getSessionDisplayData,Xe as loadFloPay,He as toStripeAppearance,q as toStripeAppearanceTheme};
|
|
1
|
+
import{a as S,b as U,c as Y,d as N,e as Ce,f as we,g as E,h as y,i as be,j as Pe,k as W,l as D,m as G}from"./chunk-CR4J5H7I.mjs";import{dropThirdPartyOnlyError as mt}from"@flopay/shared";import{assertCaptureMethodEligible as Se,buildProductPayload as _e,classifyTelemetryFailure as ke,FloPayError as b,foldIntoProducts as ve,IDEMPOTENCY_IN_PROGRESS_CODE as Re,IDEMPOTENCY_KEY_HEADER as Te,resolveIdempotencyKey as H,resolveSessionCurrency as Ae,SDK_VERSION as J,telemetryStatusClass as Q}from"@flopay/shared";var j=5,X=new WeakSet;function Ee(t){(typeof t=="object"&&t!==null||typeof t=="function")&&X.add(t)}function Ie(t){return(typeof t=="object"&&t!==null||typeof t=="function")&&X.has(t)}function Fe(t,e){let r=e?.error,o=S(e?.code)??S(r?.code)??`http_${t}`,a=S(e?.message)??S(r?.message)??xe(o,t);return new b(a,"api_error",{code:o,statusCode:t})}function xe(t,e){switch(t){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${j}.`;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 Z(t,e,r){let{billingApiUrl:o,checkoutBaseUrl:a,items:n=[],subscriptions:l=[],products:s,account:i,successUrl:c,cancelUrl:f,checkoutMode:g="confirm",captureMethod:u,couponCodes:m=[],tagsData:L,redirectParams:ue={},setCookie:pe=!0,clientId:me,currency:ye,utmMetadata:K,idempotencyKey:fe}=t,V=H(fe);if(m.length>j)throw new b(`Too many coupon codes \u2014 a checkout session accepts at most ${j}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let P=s??ve(n,l);Se({captureMethod:u,products:P});let h=Ae(ye,n,l,P);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 k={clientId:me,checkoutVersion:J,successUrl:c,cancelUrl:f,currency:h,checkoutMode:g,products:P.map(p=>_e(p,h)),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:m};u==="manual"&&(k.captureMethod=u),L&&(k.tagsData=L),K?.length&&(k.utmMetadata=K);let ge=`${o.replace(/\/+$/,"")}/v1/checkouts/sessions`,$={"Content-Type":"application/json"};V&&($[Te]=V);let C,v,he={method:"POST",headers:$,body:JSON.stringify(k),signal:e},R;try{R=await fetch(ge,he)}catch(p){throw Ee(p),p}try{r?.(R.status)}catch{}C=R.status;try{v=await R.json()}catch{}if(C>=400)throw Fe(C,v);if(C===201){let p=v?.data?.uuid,O=v?.data?.nonce;if(!p)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"});(P.length||h)&&N(p,{currency:h,products:P.map(d=>({code:d.code??d.providerItemId??d.providerPlanId,type:d.type,name:d.name??d.itemName??d.providerItemName??d.subscriptionName??d.providerPlanName??null,totalAmount:d.totalAmount,overrideAmount:d.overrideAmount,currency:d.currency??h}))});let T=new URL(`${a.replace(/\/+$/,"")}/secure`);T.searchParams.set("id",p);for(let[d,A]of Object.entries(ue))T.searchParams.set(d,A);if(pe&&typeof window<"u"&&typeof document<"u"){let d=JSON.stringify({origin_url:f}),A=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(d)}; domain=.${A}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(O)}; domain=.${A}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=T.toString()),{status:201,redirectUrl:T.toString(),nonce:O}}return C===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:C}}async function Me(t){let e=te(t),r=ee(e),o=U(t.timeoutMs);try{let a=await Z(t,o.signal,r);return re(e,a),a}catch(a){throw I(e,a),a}finally{o.clear(),w(e.reporter)}}function ee(t){let e=!1;return r=>{if(e)return;e=!0;let o=Q(r);t.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:o,attempt:t.attempt}),t.reporter.performance({stage:"session_first_byte",durationMs:t.reporter.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o,attempt:t.attempt})}}function te(t){let e=new y({billingApiUrl:t.billingApiUrl,sdkVersion:J,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 re(t,e){let r=Q(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 I(t,e){let{reporter:r}=t,o=ke(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 Oe(t){let{maxRetries:e=2,...r}=t,o=te(t),a=ee(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:H(r.idempotencyKey)},l=U(r.timeoutMs),s;for(let i=0;i<=e;i++){o.attempt=i;try{let c=await Z(n,l.signal,a);return re(o,c),l.clear(),w(o.reporter),c}catch(c){s=c;let f=c instanceof Error&&c.name==="AbortError",g=Ie(c),u=c instanceof b&&c.code===Re;if((f||g||u)&&!l.signal.aborted&&i<e){o.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:i+1});try{await Y(i,l.signal)}catch(m){throw I(o,m),l.clear(),w(o.reporter),m}continue}throw I(o,c),l.clear(),w(o.reporter),c}}throw I(o,s),l.clear(),w(o.reporter),s??new Error("Unknown error during checkout session creation")}import{classifyTelemetryFailure as Ue,FloPayError as F,resolveBillingApiUrl as ie,SDK_VERSION as Ne}from"@flopay/shared";var oe=Symbol.for("@flopay/js.telemetry.bridge.v1");function se(t,e,r){let o=()=>e?.now()??r();Object.defineProperty(t,oe,{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)??(()=>{})}})}function ne(t){return t[oe]}var x=class{now(){return this.telemetryReporter?.now?.()??E()}constructor(e,r,o){this.provider=e,this.config=r,this.telemetryReporter=o??new y({billingApiUrl:ie(r.billingApiUrl),sdkVersion:Ne,enabled:r.telemetry!==!1}),se(this,this.telemetryReporter,E)}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?G({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new D({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=ie(r??this.config.billingApiUrl),a=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let n,l=W(o,{now:()=>this.telemetryReporter?.now()??E(),onFirstByte:s=>{n=s},onRetry:(s,i)=>{this.telemetryReporter?.log({name:"operation.retry",stage:s==="session_read"?"session_read":"processing",requestCategory:s,attempt:i})}});try{let s=await l.getUnifiedCheckoutSession(e);return n!==void 0&&(this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:n,durationMode:"machine",requestCategory:"session_read",statusClass:"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()-a,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),s}catch(s){let i=Ue(s,s instanceof F&&s.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...i,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-a,durationMode:"machine",requestCategory:"session_read",statusClass:i.statusClass}),s}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.provider.destroy()}};function ae(t,e,r){let o=x;return new o(t,e,r)}import{FloPayError as ze,resolveBillingApiUrl as z,SDK_VERSION as le}from"@flopay/shared";import{FloPayError as De}from"@flopay/shared";import{loadStripe as qe}from"@stripe/stripe-js";function ce(t){switch(t){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function je(t){return{...t,theme:ce(t.theme)}}var _=class{constructor(){this.name="stripe";this.stripe=null}async initialize(e){if(typeof window>"u")return;let r=await qe(e.publishableKey,{locale:e.locale??"auto"});if(!r)throw new De("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=r}getRawProvider(){return this.stripe}destroy(){this.stripe=null}};var de=new Map;function B(t){return Array.isArray(t)?t.map(B):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[r])=>e.localeCompare(r)).map(([e,r])=>[e,B(r)])):t}function Be(t,e){return JSON.stringify([t,z(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,B(e?.appearance??null)])}var M=new Map;async function Le(t,e){if(!t){let s=new y({billingApiUrl:z(e?.billingApiUrl),sdkVersion:le,enabled:e?.telemetry!==!1});throw s.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),s.flush().catch(()=>{}).finally(()=>s.destroy()),new ze("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let r=Be(t,e),o=de.get(r);if(o)return e?.telemetry!==!1&&ne(o)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),o;let a=M.get(r);if(a)return a;let n={...e,publishableKey:t},l=(async()=>{let s=new y({billingApiUrl:z(n.billingApiUrl),sdkVersion:le,enabled:n.telemetry!==!1}),i=s.now();s.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),s.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),s.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new _,f=s.now();try{await c.initialize(n)}catch(m){throw s.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),s.destroy(),m}let g=s.now();s.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),s.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),s.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),s.performance({stage:"sdk_initialize",durationMs:g-i,durationMode:"machine",provider:"stripe"}),s.performance({stage:"provider_ready",durationMs:g-f,durationMode:"machine",provider:"stripe"});let u=ae(c,n,s);return de.set(r,u),u})();M.set(r,l);try{return await l}finally{M.get(r)===l&&M.delete(r)}}export{x as FloPay,Pe as PaymentAPI,D as PciVaultCardCapture,be as SESSION_CREATE_TELEMETRY,_ as StripeAdapter,N as cacheSessionDisplayData,we as clearSessionDisplayData,Me as createCheckoutSession,Oe as createCheckoutSessionWithRetries,mt as dropThirdPartyOnlyError,Ce as getSessionDisplayData,Le as loadFloPay,je as toStripeAppearance,ce as toStripeAppearanceTheme};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flopay/js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.2",
|
|
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.8.0",
|
|
35
|
-
"@flopay/shared": "1.
|
|
35
|
+
"@flopay/shared": "1.8.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"jsdom": "^29.1.1",
|