@flopay/js 1.4.16 → 1.4.17
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 +44 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +73 -1
- package/dist/index.d.ts +73 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -225,6 +225,50 @@ UX ceiling.
|
|
|
225
225
|
create flow: `generateIdempotencyKey()`, `resolveIdempotencyKey(supplied?)`,
|
|
226
226
|
`IDEMPOTENCY_KEY_HEADER`, and `MAX_IDEMPOTENCY_KEY_LENGTH`.
|
|
227
227
|
|
|
228
|
+
### Detached session creation (default)
|
|
229
|
+
|
|
230
|
+
Inline session creation is **detached** by default (TeamFloPay/backend#1099).
|
|
231
|
+
Instead of one request that resolves buyer identity and the catalog inline, the
|
|
232
|
+
SDK issues two:
|
|
233
|
+
|
|
234
|
+
1. `POST /v1/checkouts/sessions` with `deferDataAttachment: true` — a
|
|
235
|
+
lightweight *shell*. It runs no catalog validation and takes none of the
|
|
236
|
+
buyer-identity advisory locks that serialise concurrent checkouts for the
|
|
237
|
+
same customer. The backend routes a gateway for it from `currency` and the
|
|
238
|
+
buyer's `country`, so the response already carries `gateways` and the hosted
|
|
239
|
+
`vault` block: **the card form can mount from it.**
|
|
240
|
+
2. `PATCH /v1/checkouts/sessions/{id}/claim` — attaches buyer identity,
|
|
241
|
+
address, products and coupons in the background, and returns the fully
|
|
242
|
+
populated session.
|
|
243
|
+
|
|
244
|
+
`PaymentAPI.createDetachedSession(params)` exposes both phases:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
const { shell, sessionId, nonce, claimed } = await api.createDetachedSession(params);
|
|
248
|
+
|
|
249
|
+
mountCardForm(shell.data.session?.vault); // interactive immediately
|
|
250
|
+
const session = await claimed; // cart, coupons, totals, buyer
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Nothing may be charged before `claimed` settles: the billing API rejects
|
|
254
|
+
process / intent / decline calls on an unclaimed session with
|
|
255
|
+
`409 checkout_session_data_attachment_required`, and holds an unclaimed vault
|
|
256
|
+
charge with a retryable `503`. `@flopay/react` gates the card widget's submit
|
|
257
|
+
button for exactly this window.
|
|
258
|
+
|
|
259
|
+
`createAndFetchSession` uses the same two-phase flow but awaits the claim, so
|
|
260
|
+
its resolved value is unchanged — existing callers get the reduced create
|
|
261
|
+
contention with no code change. Detached creation requires
|
|
262
|
+
`checkoutMode: 'full'`, is skipped when `tokenizedData` is supplied, and there
|
|
263
|
+
is **no fallback** to the one-shot create: it needs a billing API with the claim
|
|
264
|
+
endpoint. Pass `deferDataAttachment: false` to force the one-shot create.
|
|
265
|
+
|
|
266
|
+
Because catalog validation moves to the claim, an invalid product or coupon
|
|
267
|
+
surfaces as the same `422` — later in the flow, but with identical semantics.
|
|
268
|
+
The claim body is fingerprinted server-side, so the SDK replays a byte-identical
|
|
269
|
+
payload across transport retries; a materially different claim for an
|
|
270
|
+
already-claimed session returns `409` and is surfaced without retrying.
|
|
271
|
+
|
|
228
272
|
Coupon validation errors are surfaced as `FloPayError` with structured `code`:
|
|
229
273
|
|
|
230
274
|
- `CouponLimitExceeded` — more than 5 coupon codes supplied (also enforced client-side before the request leaves the browser).
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var ge=Object.defineProperty;var nt=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var it=(n,e)=>{for(var t in e)ge(n,t,{get:e[t],enumerable:!0})},at=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ot(e))!st.call(n,s)&&s!==t&&ge(n,s,{get:()=>e[s],enumerable:!(r=nt(e,s))||r.enumerable});return n};var lt=n=>at(ge({},"__esModule",{value:!0}),n);var Vt={};it(Vt,{FloPay:()=>ee,FloPayElements:()=>$,PaymentAPI:()=>O,PciVaultCardCapture:()=>V,SESSION_CREATE_TELEMETRY:()=>Te,StripeAdapter:()=>H,cacheSessionDisplayData:()=>U,clearSessionDisplayData:()=>le,createCheckoutSession:()=>Qe,createCheckoutSessionWithRetries:()=>tt,getSessionDisplayData:()=>ae,loadFloPay:()=>Ye,toStripeAppearance:()=>Le,toStripeAppearanceTheme:()=>X});module.exports=lt(Vt);var A=require("@flopay/shared");var Ue=require("@stripe/stripe-js"),y=require("@flopay/shared");var d=require("@flopay/shared");function q(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}var ct="flopay_session_display:";var se=new Map;function ie(n){return`${ct}${n}`}function fe(){if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}}function U(n,e,t){if(!n)return;let r=t?.ttlMs??36e5,s={data:e,expiresAt:Date.now()+r},o=fe();if(o)try{o.setItem(ie(n),JSON.stringify(s));return}catch{}se.set(n,s)}function ae(n){if(!n)return null;let e=fe();if(e)try{let r=e.getItem(ie(n));if(r){let s=JSON.parse(r);if(s&&typeof s.expiresAt=="number"&&s.expiresAt>Date.now())return s.data;e.removeItem(ie(n))}}catch{}let t=se.get(n);if(t){if(t.expiresAt>Date.now())return t.data;se.delete(n)}return null}function le(n){if(!n)return;se.delete(n);let e=fe();if(e)try{e.removeItem(ie(n))}catch{}}var P=require("@flopay/shared"),dt="/v1/sdk-telemetry/events",Ce=16,ut=64,pt=1500,Me=1e3,mt=64,yt="00000000-0000-4000-8000-000000000000",ht={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 gt(n){try{return new TextEncoder().encode(n).byteLength}catch{return n.length}}function ft(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 E(){return globalThis.performance?.now()??0}var w=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.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(/\/+$/,"")}${dt}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=j(),this.merchantEnabled=e.enabled!==!1,this.clock=e.clock??E,this.browserTransportAvailable=typeof window<"u"&&typeof document<"u",this.browserTransportAvailable&&(window.addEventListener("pagehide",this.pageExitHandler),document.addEventListener("visibilitychange",this.visibilityHandler))}log(e){this.canCollect()&&this.enqueue((0,P.buildTelemetryLogEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}error(e){if(!this.canCollect())return;let t=(0,P.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:yt,sequence:0}),r=ft(t),s=this.now();this.pruneReportedFailures(s);let o=this.reportedFailures.get(r);if(o!==void 0&&s>=o&&s-o<Me){this.log({name:"operation.deduplicated",stage:e.stage,provider:e.provider,paymentMethodCategory:e.paymentMethodCategory,attempt:e.attempt});return}this.rememberReportedFailure(r,s),this.enqueue((0,P.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue((0,P.buildTelemetryPerformanceEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue((0,P.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 E()}}pruneReportedFailures(e){for(let[t,r]of this.reportedFailures)(e<r||e-r>=Me)&&this.reportedFailures.delete(t)}rememberReportedFailure(e,t){for(;this.reportedFailures.size>=mt;){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>=ut||this.eventCounts[e.class]>=ht[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())}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,P.serializeTelemetryBatch)(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:j()});if(gt(t)>P.TELEMETRY_MAX_BATCH_BYTES)return;let r=typeof AbortController>"u"?null:new AbortController,s=null;try{let o=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 a=>a.status!==202?null:(await a.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(a=>{s=setTimeout(()=>{r?.abort(),a(null)},pt)});await Promise.race([o,i])==="disabled"&&this.disableFromIngestion()}catch{}finally{s&&clearTimeout(s)}}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)}},Ee=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),ke=globalThis;ke[Ee]===void 0&&Object.defineProperty(ke,Ee,{configurable:!0,enumerable:!1,writable:!1,value:n=>new w(n)});function J(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 Ct(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function Q(n,e){let t=150*2**n,r=Math.round(t*(.75+Math.random()*.5));return new Promise((s,o)=>{let i,l=()=>e.removeEventListener("abort",a),a=()=>{i!==void 0&&clearTimeout(i),l(),o(Ct())};if(e.aborted){a();return}i=setTimeout(()=>{l(),s()},r),e.addEventListener("abort",a,{once:!0})})}var Re=1e3,Tt=500,_t=15e3,wt=3e3,bt=1e4,St=1e4;function De(n){return typeof n=="object"&&n!==null}function z(n,e){return q(n?.[e])}function Ae(n,e){return Pe(n?.[e])}function Pt(n,e){let t=n?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function xe(n){return new Promise(e=>setTimeout(e,n))}function ce(){return new d.FloPayError("Checkout is still processing. Please try again shortly.","api_error",{code:"checkout_processing_timeout"})}async function K(n,e){let t=await n.json().catch(()=>null),r=De(t?.error)?t.error:null,s=Ae(t,"message")??Ae(r,"message")??e,o=z(t,"code")??z(t,"gatewayErrorCode")??z(r,"code")??`http_${n.status}`;return new d.FloPayError(s,"api_error",{code:o,statusCode:n.status})}async function Mt(n){if(n.status!==400&&n.status!==422)return;if(n.status===422)return"validation_rejected";let e=await n.clone().json().catch(()=>null);return De(e)&&Array.isArray(e.fields)?"validation_rejected":"payment_declined"}function Ie(n){return n===400||n===422}var de=2;async function ve(n,e,t=de,r){let s;for(let o=0;;o++)try{return await fetch(n,e)}catch(i){if(e?.signal?.aborted||i instanceof Error&&i.name==="AbortError")throw i;if(s=i,o>=t)throw s;try{r?.(o+1)}catch{}await xe(150*2**o)}}var Te=Symbol.for("@flopay/js.session-create.telemetry.v1");function Et(n){return n[Te]}function kt(n){return"now"in n||"onFirstByte"in n||"onSessionCreateFailure"in n||"onRetry"in n}var L=class L{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let r=kt(t);this.telemetryHooks=r?t:void 0,this.directTelemetry=r||t.telemetry===!1?void 0:new w({billingApiUrl:this.baseUrl,sdkVersion:d.SDK_VERSION})}destroy(){this.directTelemetry?.destroy()}reportDirectFailure(e,t,r,s,o="unknown"){let i=(0,d.classifyTelemetryFailure)(e,t);this.directTelemetry?.error({...i,stage:r,requestCategory:s,paymentMethodCategory:o})}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()??E()}catch{return E()}}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 s={[d.FLO_SDK_VERSION_HEADER]:d.SDK_VERSION};t&&(s["x-checkout-session-token"]=t);try{let o=await ve(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:s},de,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 l=`${Math.floor(o.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:l}),!o.ok)throw await K(o,"Failed to get checkout session");let a=await o.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",statusClass:l}),{...a,data:this.mergeCachedDisplayData(a.data)}}catch(o){throw this.directTelemetry?.error({...(0,d.classifyTelemetryFailure)(o,"NETWORK_REQUEST_FAILED"),stage:"session_read",requestCategory:"session_read"}),o}}cacheSessionDisplayData(e,t,r){U(e,t,r)}clearSessionDisplayData(e){le(e)}async getVaultCapture(e,t){let r=`${this.baseUrl}\0${e}\0${t??""}`,s=L.activeVaultCaptureRequests.get(r);if(s)return s;let o=this.requestVaultCapture(e,t);L.activeVaultCaptureRequests.set(r,o);try{return await o}finally{L.activeVaultCaptureRequests.get(r)===o&&L.activeVaultCaptureRequests.delete(r)}}async requestVaultCapture(e,t){let r=new AbortController,s=setTimeout(()=>r.abort(),St);this.beginDirectTelemetryCheckout(e);let o=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 l=await ve(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:r.signal},de,c=>{this.telemetryHooks?.onRetry?.("vault_capture",c),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:c})});if(!l.ok)throw await K(l,"Failed to load the secure card form");let a=await l.json();return this.directTelemetry?.performance({stage:"vault_request",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"vault_capture",paymentMethodCategory:"card",statusClass:"2xx"}),this.toVaultBlock(a)}catch(l){let a=r.signal.aborted?new d.FloPayError("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):l;throw this.reportDirectFailure(a,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),a}finally{clearTimeout(s)}}async getUnifiedCheckoutSession(e,t){let r=await this.getCheckoutSession(e,t),s=this.normalizeRawSession(r.data),o=r.vault;return o&&s.data.session&&(s.data.session.vault=this.toVaultBlock(o)),s}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 s=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.processing.started",stage:"processing",requestCategory:"process_payment"});let{nonce:o,...i}=t,l;try{l=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(t.sessionId)}/process`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":o},body:JSON.stringify(i)})}catch(a){throw this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}if(!l.ok&&l.status!==202){let a=await Mt(l);return a?this.directTelemetry?.terminal({outcome:a,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(l.status),failureCategory:l.status>=500?"server_error":void 0}),l}try{let a=await this.resolveProcessResponse(l,t.sessionId,{...r,nonce:o});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(a.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(a.status)}),a}catch(a){throw a instanceof d.FloPayError&&a.code==="checkout_processing_timeout"||this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}}async patchAccountSnapshot(e,t,r,s){this.beginDirectTelemetryCheckout(e);let o=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.state_transition",stage:"processing",requestCategory:"account_snapshot"});let i=s?.timeoutMs??bt,l=new AbortController,a=()=>l.abort();s?.signal&&(s.signal.aborted?l.abort():s.signal.addEventListener("abort",a,{once:!0}));let c=setTimeout(()=>l.abort(),i);try{let u;try{u=await ve(`${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:l.signal},de,f=>{this.telemetryHooks?.onRetry?.("account_snapshot",f),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:f})})}finally{clearTimeout(c),s?.signal?.removeEventListener("abort",a)}if(!u.ok)throw await K(u,"Failed to persist account snapshot");this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"account_snapshot",statusClass:"2xx"})}catch(u){throw this.reportAccountSnapshotFailure(u,s?.telemetryMode??"blocking"),u}}async createSessionIntent(e,t,r,s){if(!t)throw new d.FloPayError("createSessionIntent requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let o=r,i=o.paymentMethodType,l=typeof i=="string"&&i.trim().toLowerCase()==="card",a=typeof i=="string"&&i.length>0&&!l&&(typeof o.paymentMethodId=="string"||o.paymentMethodId===null),c=o.provider==="stripe"&&(o.paymentMethodCategory==="wallet"||o.paymentMethodCategory==="apm")&&(o.intentKind==="payment"||o.intentKind==="setup"),u=o.provider==="paypal"&&o.paymentMethodCategory==="wallet"&&o.paymentMethodType==="paypal"&&o.paymentMethodId===null&&o.intentKind==="payment";if(!a||!c&&!u)throw new d.FloPayError("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let f=o.authorizationAttemptId;if(f!==void 0&&!(0,d.isUuidV4)(f))throw new d.FloPayError("authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.","validation_error",{code:"InvalidAuthorizationAttemptId",param:"authorizationAttemptId"});let b=(0,d.isUuidV4)(f)?f:(0,d.randomUuidV4)();this.beginDirectTelemetryCheckout(e);let _=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.intent.started",stage:"processing",requestCategory:"intent_create"});let C={"Content-Type":"application/json","x-checkout-session-token":t,[d.IDEMPOTENCY_KEY_HEADER]:s?.idempotencyKey||b},R=!1;try{let k=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:C,body:JSON.stringify({...r,authorizationAttemptId:b}),signal:s?.signal});if(!k.ok){R=!0;let B=await K(k,"Failed to create checkout intent"),x=(0,d.classifyTelemetryFailure)(B,"PAYMENT_PROCESSING_FAILED");throw Ie(B.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...x,stage:"processing",requestCategory:"intent_create"}),B}let S=(await k.json()).data;if(!S||typeof S!="object")throw new d.FloPayError("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let p=S,M=p.paymentMethodType,I=(p.paymentMethodCategory==="wallet"||p.paymentMethodCategory==="apm")&&typeof M=="string"&&M.trim().toLowerCase()!=="card"&&(typeof p.paymentMethodId=="string"||p.paymentMethodId===null)&&typeof p.providerObjectId=="string",D=p.provider==="stripe"&&(p.intentKind==="payment"||p.intentKind==="setup")&&typeof p.clientSecret=="string",W=p.provider==="paypal"&&p.paymentMethodCategory==="wallet"&&p.paymentMethodType==="paypal"&&p.paymentMethodId===null&&p.intentKind==="payment"&&(p.providerObjectType==="order"||p.providerObjectType==="subscription")&&p.clientSecret===null,ye=p.provider===r.provider&&p.paymentMethodCategory===r.paymentMethodCategory&&p.paymentMethodType===r.paymentMethodType&&p.paymentMethodId===r.paymentMethodId&&p.intentKind===r.intentKind;if(!I||!D&&!W||!ye)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)(k.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-_),durationMode:"machine",requestCategory:"intent_create",statusClass:(0,d.telemetryStatusClass)(k.status)}),p}catch(k){throw R||this.reportDirectFailure(k,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),k}}async reportSessionIntentDecline(e,t,r,s){if(!t)throw new d.FloPayError("reportSessionIntentDecline requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let o=r,i=o.providerDeclineReason,l=o.paymentMethodType,a=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 l=="string"&&l.length>0&&l.trim().toLowerCase()!=="card"&&a,u=o.provider==="stripe"&&(o.paymentMethodCategory==="wallet"||o.paymentMethodCategory==="apm"),f=o.provider==="paypal"&&o.paymentMethodCategory==="wallet"&&o.paymentMethodType==="paypal";if(!c||!u&&!f)throw new d.FloPayError("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let b=f?{provider:"paypal",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:i}:{provider:"stripe",paymentMethodCategory:o.paymentMethodCategory,paymentMethodType:o.paymentMethodType,providerDeclineReason:i},_=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(b),signal:s?.signal});if(!_.ok)throw await K(_,"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 s=t?.page??1,o=t?.limit??1,i=new URLSearchParams({email:e,page:String(s),limit:String(o),sortField:"createdAt",sortDirection:"DESC"});try{let l=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!l.ok)throw new d.FloPayError("Failed to fetch payments","api_error",{statusCode:l.status});let a=await l.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"}),a}catch(l){throw this.reportDirectFailure(l,"RECOVERY_FAILED","recovery","other","saved"),l}}async createAndFetchSession(e){this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),r=J(e.timeoutMs??12e3),s={attempt:0,statusClass:"unknown"};this.directTelemetry?.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"});try{let o=await this.createAndFetchSessionRequest(e,t,r.signal,s);return this.adoptDirectTelemetryCheckout(o.data.session?.id),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:s.statusClass}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:s.statusClass,attempt:s.attempt}),o}catch(o){if(!(o instanceof d.FloPayError&&o.code==="session_auto_completed"))try{this.telemetryHooks?.onSessionCreateFailure?.(o)}catch{}let i=(0,d.classifyTelemetryFailure)(o,"CHECKOUT_SESSION_CREATE_FAILED");throw this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:i.statusClass,attempt:s.attempt}),o instanceof d.FloPayError&&o.type==="validation_error"?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}):o instanceof d.FloPayError&&Ie(o.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"}):o instanceof d.FloPayError&&o.code==="session_auto_completed"||this.directTelemetry?.error({...i,stage:"session_create",requestCategory:"session_create"}),o}finally{r.clear()}}async createAndFetchSessionRequest(e,t,r,s){let o=e.products??(0,d.foldIntoProducts)(e.items,e.subscriptions),i=(0,d.resolveSessionCurrency)(e.currency,e.items,e.subscriptions,o);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 l={clientId:e.clientId,checkoutVersion:d.SDK_VERSION,successUrl:e.successUrl,cancelUrl:e.cancelUrl,currency:i,checkoutMode:e.checkoutMode??"full",products:o.map(h=>(0,d.buildProductPayload)(h,i)),accountData:{userId:e.account.userId,firstName:e.account.firstName??null,lastName:e.account.lastName??null,email:e.account.email,country:e.account.country??null,gender:e.account.gender??null,city:e.account.city??null,state:e.account.state??null,zip:e.account.zip??null,addressLine1:e.account.addressLine1??null,addressLine2:e.account.addressLine2??null},couponCodes:e.couponCodes??[]};e.tokenizedData&&(l.tokenizedData=e.tokenizedData),e.tagsData&&(l.tagsData=e.tagsData),e.utmMetadata?.length&&(l.utmMetadata=e.utmMetadata),e.avsCheck!==void 0&&(l.avsCheck=e.avsCheck),e.checkoutType&&(l.checkoutType=e.checkoutType),e.checkoutLayout&&(l.checkoutLayout=e.checkoutLayout),e.avsConfig&&(l.avsConfig=e.avsConfig);let a={"Content-Type":"application/json",[d.FLO_SDK_VERSION_HEADER]:d.SDK_VERSION},c=(0,d.resolveIdempotencyKey)(e.idempotencyKey);c&&(a[d.IDEMPOTENCY_KEY_HEADER]=c);let u,f=!1,b=Et(e),_=h=>{try{this.telemetryHooks?.onRetry?.("session_create",h),this.directTelemetry?.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:h})}catch{}};for(let h=0;h<3;h++){s.attempt=h;try{b?.onAttempt?.(h)}catch{}try{u=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:a,body:JSON.stringify(l),signal:r})}catch(M){if(s.statusClass=r.aborted||M instanceof Error&&M.name==="AbortError"?"timeout":"network_error",r.aborted||M instanceof Error&&M.name==="AbortError"||h>=2)throw M;let I=h+1;_(I),await Q(h,r);continue}let S=(0,d.telemetryStatusClass)(u.status);if(s.statusClass=S,f||(f=!0,this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:S,attempt:h}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:S,attempt:h})),u.status===204)throw new d.FloPayError("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(u.ok)break;let p=await K(u,"Failed to create checkout session");if(p.code===d.IDEMPOTENCY_IN_PROGRESS_CODE&&h<2){_(h+1),await Q(h,r);continue}throw p}if(!u)throw new TypeError("Checkout-session creation exhausted its retry budget.");let C=await u.json();if(C.data&&"gateways"in C.data){this.autoCacheDisplayData(C.data.uuid,e);let h=this.mergeCachedDisplayData(C.data),S=this.normalizeRawSession(h);return C.vault&&S.data.session&&(S.data.session.vault=this.toVaultBlock(C.vault)),{...S,autoProcessingError:C.autoProcessingError,autoProcessingAttempted:C.autoProcessingAttempted,autoProcessingPending:C.autoProcessingPending}}let R=C.data?.uuid;if(!R)throw new d.FloPayError("No session ID returned","api_error",{code:"InvalidCheckoutSessionResponse"});return this.autoCacheDisplayData(R,e),this.adoptDirectTelemetryCheckout(R),{...await this.getUnifiedCheckoutSession(R),autoProcessingError:C.autoProcessingError,autoProcessingAttempted:C.autoProcessingAttempted,autoProcessingPending:C.autoProcessingPending}}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 s=t?.timeoutMs??_t,o=Date.now()+s,i=this.clampRetryAfterMs(t?.initialDelayMs??Re),l=0;try{for(;;){let a=o-Date.now();if(a<=0)throw ce();if(i>0){try{l+=1,this.telemetryHooks?.onRetry?.("session_read",l),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:l})}catch{}if(await xe(Math.min(i,a)),Date.now()>=o)throw ce()}let c=await this.getUnifiedCheckoutSession(e,t?.nonce),u=c.data.session?.status;if(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()>=o)throw ce();i=this.clampRetryAfterMs(Math.max(i*2,Tt))}}catch(a){throw a instanceof d.FloPayError&&a.code==="checkout_processing_timeout"&&this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","session_read","saved"),a}}normalizeRawSession(e){let t=e.gateways??{},r=[],s={session:this.toCheckoutSession(e)},o=t.stripe;if(o?.publishableKey){r.push("stripe");let a=[e.stripeClientSecret,o.stripeClientSecret].find(c=>typeof c=="string"&&c.length>0);s.stripe={clientSecret:a??"",publishableKey:o.publishableKey??void 0,paypalPublishableKey:o.paypalPublishableKey??void 0,environment:o.environment,enabledPaymentMethods:Array.isArray(o.enabledPaymentMethods)?o.enabledPaymentMethods.filter(c=>typeof c=="string"):void 0}}let i=t.paypal;return i?.publishableKey&&(r.push("paypal"),s.paypal={publishableKey:i.publishableKey,environment:i.environment}),{providers:r,mode:"tokenize",data:s,raw:{data:e}}}toCheckoutSession(e){let t=e.products??[],r=typeof e.totalAmount=="number"&&Number.isFinite(e.totalAmount),s=t.reduce((c,u)=>c+(u.overrideAmount??u.totalAmount??0),0),o=r?e.totalAmount:s,i=Math.round(o*100),l=e.currency??t[0]?.currency??"USD",a=t.some(c=>c.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:a,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:l,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==="expired"?"expired":"open"}async resolveProcessResponse(e,t,r){if(e.status!==202)return e;let s=await e.json().catch(()=>null),o=this.toCheckoutProcessingPending(s,e,t),i=await this.waitForCheckoutSessionCompletion(o.sessionId,{initialDelayMs:o.retryAfterMs,timeoutMs:r?.pollTimeoutMs,nonce:r?.nonce});if(i.data.session?.status==="complete")return new Response(null,{status:204,statusText:"No Content"});throw i.data.session?.status==="expired"?new d.FloPayError("Checkout session has expired.","api_error",{code:"checkout_session_expired"}):ce()}toCheckoutProcessingPending(e,t,r){let s=t.headers.get("Retry-After"),o=s===null||s.trim()===""?void 0:Number(s),i=o!==void 0&&Number.isFinite(o)?o*1e3:void 0;return{type:"checkout_processing",sessionId:z(e,"sessionId")??r,retryAfterMs:this.clampRetryAfterMs(Pt(e,"retryAfterMs")??i??Re),statusUrl:z(e,"statusUrl"),sessionUrl:z(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,wt))}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 s=t.products!==void 0,o=(0,d.resolveSessionCurrency)(t.currency,s?void 0:t.items,s?void 0:t.subscriptions,r);U(e,{currency:o??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??o??void 0}))})}mergeCachedDisplayData(e){let t=ae(e.uuid),r=new Map,s=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let l=s(i.code);l&&r.set(l,i)}let o=(e.products??[]).map(i=>{let l=s(i.code),a=l?r.get(l):void 0;return{...i,name:i.name??a?.name??null,totalAmount:i.totalAmount??a?.totalAmount,overrideAmount:i.overrideAmount??a?.overrideAmount,currency:i.currency??a?.currency}});return{...e,currency:e.currency??t?.currency,products:o}}};L.activeVaultCaptureRequests=new Map;var O=L;function Fe(n,e){let t=O;return new t(n,e)}function Oe(n){return{payment:"payment",address:"address"}[n]}function X(n){switch(n){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function Le(n){return{...n,theme:X(n.theme)}}function _e(n){return n?JSON.stringify(n.map(e=>e.trim().toLowerCase())):null}function qe(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 Rt(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 H=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,Ue.loadStripe)(e.publishableKey,{locale:e.locale??"auto"});if(!t)throw new y.FloPayError("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=t}getElements(e){if(!this.stripe)throw new y.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,s=_e(e?.paymentMethodTypes),o=e?.clientSecret??null;if(this.elements&&s&&(s!==this.appliedPaymentMethodTypesKey||o!==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,l=e?.amount??0,a=(e?.currency??"usd").toLowerCase(),c=e?.paymentMethodCreation??"manual";e?.clientSecret?i={clientSecret:e.clientSecret}:l>0?(i={mode:"payment",amount:l,currency:a,paymentMethodCreation:c},e?.setupFutureUsage&&(i.setupFutureUsage=e.setupFutureUsage)):i={mode:"setup",currency:a,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=s,this.appliedClientSecret=o,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null}return this.elements}async assertClientSecretPaymentMethods(e,t){if(!this.stripe)throw new y.FloPayError("StripeAdapter not initialized. Call initialize() first.","api_error");let r,s=!1;if((0,y.isSetupIntentClientSecret)(e)){let{setupIntent:a,error:c}=await this.stripe.retrieveSetupIntent(e);r=a,s=!!c}else{let{paymentIntent:a,error:c}=await this.stripe.retrievePaymentIntent(e);r=a,s=!!c}let o=r?.payment_method_types;if(s||!Array.isArray(o))throw new y.FloPayError("Unable to verify the payment methods configured for this client secret.","api_error",{param:"clientSecret"});let i=new Set(t.map(a=>a.toLowerCase()));if(o.some(a=>typeof a!="string"||!i.has(a.trim().toLowerCase()))||o.length===0)throw new y.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 a=t.paymentMethodTypes?.map(c=>c.trim()).filter(c=>c&&c.toLowerCase()!=="card");if(!a?.length)throw new y.FloPayError("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});if(r={...t,paymentMethodTypes:a},r.clientSecret){let c=_e(a);this.elements&&this.appliedClientSecret===r.clientSecret&&this.appliedPaymentMethodTypesKey===c&&this.verifiedClientSecret===r.clientSecret&&this.verifiedPaymentMethodTypesKey===c||await this.assertClientSecretPaymentMethods(r.clientSecret,a)}}let s=this.getElements(r);e==="payment"&&r.clientSecret&&(this.verifiedClientSecret=r.clientSecret,this.verifiedPaymentMethodTypesKey=_e(r.paymentMethodTypes));let o=Oe(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 l=s.create(o,i);return qe(l)}getElement(e){if(!this.elements)return null;let t=Oe(e),r=this.elements.getElement(t);return r?qe(r):null}async submitElements(){if(!this.stripe||!this.elements)return{error:new y.FloPayError("Stripe not initialized","api_error")};let{error:e}=await this.elements.submit();return e?{error:new y.FloPayError(e.message??"Validation failed","validation_error")}:{}}async confirmPayment(e){if(!this.stripe||!this.elements)throw new y.FloPayError("StripeAdapter not initialized or no elements created.","api_error");let t=e.billingDetails,r=t?Rt(t):void 0,{error:s,paymentIntent:o}=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 s?{status:"failed",error:new y.FloPayError(s.message??"Payment failed","api_error",{code:s.code,declineCode:s.decline_code})}:o?{status:{succeeded:"succeeded",processing:"processing",requires_action:"requires_action",requires_payment_method:"failed",canceled:"failed"}[o.status]??"failed",paymentIntentId:o.id,paymentMethodId:this.extractPaymentMethodId(o.payment_method)}:{status:"failed",error:new y.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 y.FloPayError("Stripe not initialized","api_error")};let t=e.billingApiUrl.replace(/\/+$/,"");if(this.elements){let{error:o}=await this.elements.submit();if(o)return{status:"failed",error:new y.FloPayError(o.message??"PayPal payment failed","validation_error",{code:o.code})}}let r;try{let o=await new O(t).createSessionIntent(e.sessionId,e.nonce??"",{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",paymentMethodId:null,intentKind:"payment"});if(o.provider!=="stripe")throw new y.FloPayError("Invalid provider returned for PayPal intent","api_error");r=o.clientSecret}catch(o){return{status:"failed",error:o instanceof y.FloPayError?o:new y.FloPayError("Failed to create PayPal payment intent","api_error")}}let{error:s}=await this.stripe.confirmPayment({clientSecret:r,elements:this.elements??void 0,confirmParams:{return_url:e.returnUrl}});if(s){if(e.nonce)try{await new O(t).reportSessionIntentDecline(e.sessionId,e.nonce,{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:s.code??"provider_declined"})}catch{}return{status:"failed",error:new y.FloPayError(s.message??"PayPal payment failed","api_error",{code:s.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"),s=e.get("redirect_status");if(!t||!r)return null;if(s==="failed")return{status:"failed",error:new y.FloPayError("PayPal payment was declined. Please try again.","api_error")};let{paymentIntent:o,error:i}=await this.stripe.retrievePaymentIntent(r);if(i)return{status:"failed",error:new y.FloPayError(i.message??"Failed to retrieve PayPal payment","api_error")};if(o&&(o.status==="requires_capture"||o.status==="succeeded")){let l=typeof o.payment_method=="string"?o.payment_method:o.payment_method?.id,a=new URL(window.location.href);return a.searchParams.delete("payment_intent"),a.searchParams.delete("payment_intent_client_secret"),a.searchParams.delete("redirect_status"),window.history.replaceState({},"",a.toString()),{status:o.status,paymentIntentId:o.id,paymentMethodId:l}}return{status:"failed",error:new y.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 g=require("@flopay/shared");var Ne=require("@flopay/shared"),$=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 l=r.paymentMethodTypes?.map(a=>a.trim()).filter(a=>a&&a.toLowerCase()!=="card");if(!l?.length)throw new Ne.FloPayError("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});r.paymentMethodTypes=l}let s=this.provider.getElement(e);if(s)return this.elementMap.set(e,s),s;let o=this.elementMap.get(e);o&&o.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 T=require("@flopay/shared");var we="flopay-vault",Ve={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 Z(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 ue(n,e){return(0,T.buildTelemetryLogEvent)({eventId:"11111111-1111-4111-8111-111111111111",name:n,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function Be(n){return n?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function At(n,e){if(n==="complete"||n==="decline")return(0,T.buildTelemetryTerminalEvent)({eventId:"22222222-2222-4222-8222-222222222222",outcome:n==="complete"?"payment_succeeded":"payment_declined",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(n==="error"){let s=Be(e);return(0,T.buildTelemetryErrorEvent)({eventId:"33333333-3333-4333-8333-333333333333",...s,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[t,r]=Ve[n];return ue(t,r)}function It(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 Dt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===we&&e.type==="validation"&&Array.isArray(e.messages)}function xt(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 V=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 w({billingApiUrl:(0,T.resolveBillingApiUrl)(),sdkVersion:T.SDK_VERSION}):void 0)}async mount(e,t){if(this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new w({billingApiUrl:(0,T.resolveBillingApiUrl)(),sdkVersion:T.SDK_VERSION})),this.mountStartedAt=this.telemetryReporter?.now?.()??E(),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||!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(r){throw this.reportVaultLoadFailure(),r}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),Z(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 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 s of r){let o=document.createElement("script");for(let i of Array.from(s.attributes))o.setAttribute(i.name,i.value);o.text=s.text,s.replaceWith(o)}}attachMessageListener(){if(this.messageHandler)return;let e=t=>{if(this.expectedOrigin&&t.origin!==this.expectedOrigin)return;let r=t.data;if(xt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;this.applyHeight(r.height);return}if(Dt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;let l=r.messages.filter(a=>typeof a=="string"&&a.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:l||void 0});return}if(!It(r)||this.messageToken&&r.messageToken!==this.messageToken)return;let s=this.config.sessionId,o=typeof r.sessionId=="string"?r.sessionId:void 0;if(s&&o&&o!==s||(r.type==="complete"||r.type==="decline")&&s&&o!==s)return;let i={sessionId:r.sessionId??this.config.sessionId,intentId:r.intentId,declineReason:r.declineReason,message:r.message,nextActionRedirectUrl:r.nextActionRedirectUrl};r.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??E()),Z(At(r.type,this.submissionStarted)),this.reportOutcome(r.type),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(),this.emit(r.type,i)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;if(e==="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"})),e==="complete"||e==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:e==="complete"?"payment_succeeded":"payment_declined",provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="error"){let o=Be(this.submissionStarted);t.log({name:"vault.terminal",stage:o.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...o,provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="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 o=this.submissionStartedAt;this.submissionStartedAt=null,o!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-o),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[r,s]=Ve[e];t.log({name:r,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 s=document.createElement("button");s.type="button",s.setAttribute("aria-label","Close card authentication"),s.textContent="\xD7",s.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(";"),s.addEventListener("click",()=>this.abandonActionRequiredOverlay()),t.appendChild(s),t.addEventListener("click",i=>{i.target===t&&this.abandonActionRequiredOverlay()});let o=i=>{if(i.source!==r.contentWindow)return;let l=i.data;if(!l||typeof l!="object")return;let a=l;a.source==="flopay-vault-3ds-return"&&(Z(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(a.status))};window.addEventListener("message",o),this.threeDsReturnHandler=o,document.body.appendChild(t),this.actionOverlay=t,Z(ue("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"});Z(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 je(n,e){let t=V;return new t(n,{reporter:e})}var Ke=Symbol.for("@flopay/js.telemetry.bridge.v1");function ze(n,e,t){let r=()=>e?.now()??t();Object.defineProperty(n,Ke,{configurable:!1,enumerable:!1,writable:!1,value:{error:o=>e?.error(o),log:o=>e?.log(o),performance:o=>e?.performance(o),terminal:o=>e?.terminal(o),now:r,elapsed:o=>Math.max(0,r()-o),setCheckoutContext:o=>e?.setCheckoutContext(o),beginCheckout:(o={})=>e?.beginCheckout(o)??r(),disable:()=>e?.disable()}})}function He(n){return n[Ke]}function G(n){if(!n)return!1;let e=n.code?.toLowerCase()??"";return!!n.declineCode||e.includes("declin")}function Ft(n){return n==="stripe"||n==="paypal"||n==="pcivault"?n:"other"}var ee=class{constructor(e,t,r){this.currentElements=null;this.provider=e,this.config=t,this.telemetryReporter=r??new w({billingApiUrl:(0,g.resolveBillingApiUrl)(t.billingApiUrl),sdkVersion:g.SDK_VERSION,enabled:t.telemetry!==!1}),ze(this,this.telemetryReporter,E)}now(){return this.telemetryReporter?.now?.()??E()}elements(e){return this.currentElements&&this.currentElements.destroy(),this.currentElements=new $(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?je({sessionId:e?.sessionId},this.telemetryReporter):new V({sessionId:e?.sessionId,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:"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"&&(G(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 g.FloPayError&&G(r))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(r instanceof g.FloPayError&&r.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let s=(0,g.classifyTelemetryFailure)(r,"PAYMENT_PROCESSING_FAILED","unknown");this.telemetryReporter?.error({...s,failureCategory:s.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"}):G(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 g.FloPayError&&G(t))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(t instanceof g.FloPayError&&t.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let r=(0,g.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 g.FloPayError("A supported non-card payment method is required.","validation_error",{param:"paymentMethodType"});let t=this.now(),r=Ft(this.provider.name);this.telemetryReporter?.log({name:"payment.processing.started",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory});try{let s=await this.provider.confirmPayment(e),o=this.now()-t;return this.telemetryReporter?.performance({stage:"processing",durationMs:o,durationMode:"machine",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:r,paymentMethodCategory:e.paymentMethodCategory}):G(s.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s.status==="requires_action"?this.telemetryReporter?.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s.status==="failed"&&s.error&&this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s.status==="succeeded"||s.status==="failed"?this.telemetryReporter?.log({name:"payment.processing.completed",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}):this.telemetryReporter?.log({name:"operation.state_transition",stage:s.status==="requires_action"?"three_ds_handoff":"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s}catch(s){throw this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-t,durationMode:"machine",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s instanceof g.FloPayError&&G(s)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s instanceof g.FloPayError&&s.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}),s}}async retrieveSession(e,t){if(!e)throw new g.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 g.FloPayError("Session not found","api_error");return r.data.session}async retrieveUnifiedSession(e,t){if(!e)throw new g.FloPayError("sessionId is required.","validation_error",{param:"sessionId"});let r=(0,g.resolveBillingApiUrl)(t??this.config.billingApiUrl),s=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let o,i=Fe(r,{now:()=>this.telemetryReporter?.now()??E(),onFirstByte:l=>{o=l},onRetry:(l,a)=>{this.telemetryReporter?.log({name:"operation.retry",stage:l==="session_read"?"session_read":"processing",requestCategory:l,attempt:a})}});try{let l=await i.getUnifiedCheckoutSession(e);return o!==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:o,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()-s,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),l}catch(l){let a=(0,g.classifyTelemetryFailure)(l,l instanceof g.FloPayError&&l.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...a,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-s,durationMode:"machine",requestCategory:"session_read",statusClass:a.statusClass}),l}}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 $e(n,e,t){let r=ee;return new r(n,e,t)}var Ge=new Map;function be(n){return Array.isArray(n)?n.map(be):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,be(t)])):n}function Ot(n,e){return JSON.stringify([n,(0,A.resolveBillingApiUrl)(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,be(e?.appearance??null)])}var pe=new Map;async function Ye(n,e){if(!n){let l=new w({billingApiUrl:(0,A.resolveBillingApiUrl)(e?.billingApiUrl),sdkVersion:A.SDK_VERSION,enabled:e?.telemetry!==!1});throw l.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),l.flush().catch(()=>{}).finally(()=>l.destroy()),new A.FloPayError("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let t=Ot(n,e),r=Ge.get(t);if(r)return e?.telemetry!==!1&&He(r)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),r;let s=pe.get(t);if(s)return s;let o={...e,publishableKey:n},i=(async()=>{let l=new w({billingApiUrl:(0,A.resolveBillingApiUrl)(o.billingApiUrl),sdkVersion:A.SDK_VERSION,enabled:o.telemetry!==!1}),a=l.now();l.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),l.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),l.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new H,u=l.now();try{await c.initialize(o)}catch(_){throw l.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),l.destroy(),_}let f=l.now();l.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),l.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),l.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),l.performance({stage:"sdk_initialize",durationMs:f-a,durationMode:"machine",provider:"stripe"}),l.performance({stage:"provider_ready",durationMs:f-u,durationMode:"machine",provider:"stripe"});let b=$e(c,o,l);return Ge.set(t,b),b})();pe.set(t,i);try{return await i}finally{pe.get(t)===i&&pe.delete(t)}}var m=require("@flopay/shared");var Se=5,We=new WeakSet;function qt(n){(typeof n=="object"&&n!==null||typeof n=="function")&&We.add(n)}function Ut(n){return(typeof n=="object"&&n!==null||typeof n=="function")&&We.has(n)}function Lt(n,e){let t=e?.error,r=q(e?.code)??q(t?.code)??`http_${n}`,s=q(e?.message)??q(t?.message)??Nt(r,n);return new m.FloPayError(s,"api_error",{code:r,statusCode:n})}function Nt(n,e){switch(n){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${Se}.`;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 Je(n,e,t){let{billingApiUrl:r,checkoutBaseUrl:s,items:o=[],subscriptions:i=[],products:l,account:a,successUrl:c,cancelUrl:u,checkoutMode:f="confirm",couponCodes:b=[],tagsData:_,redirectParams:C={},setCookie:R=!0,clientId:k,currency:h,utmMetadata:S,idempotencyKey:p}=n,M=(0,m.resolveIdempotencyKey)(p);if(b.length>Se)throw new m.FloPayError(`Too many coupon codes \u2014 a checkout session accepts at most ${Se}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let I=l??(0,m.foldIntoProducts)(o,i),D=(0,m.resolveSessionCurrency)(h,o,i,I);if(!D)throw new m.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 W={clientId:k,checkoutVersion:m.SDK_VERSION,successUrl:c,cancelUrl:u,currency:D,checkoutMode:f,products:I.map(F=>(0,m.buildProductPayload)(F,D)),accountData:{userId:a.userId,firstName:a.firstName??null,lastName:a.lastName??null,email:a.email,country:a.country??null,gender:a.gender??null,city:a.city??null,state:a.state??null,zip:a.zip??null,addressLine1:a.addressLine1??null,addressLine2:a.addressLine2??null},couponCodes:b};_&&(W.tagsData=_),S?.length&&(W.utmMetadata=S);let ye=`${r.replace(/\/+$/,"")}/v1/checkouts/sessions`,B={"Content-Type":"application/json"};M&&(B[m.IDEMPOTENCY_KEY_HEADER]=M);let x,te,rt={method:"POST",headers:B,body:JSON.stringify(W),signal:e},re;try{re=await fetch(ye,rt)}catch(F){throw qt(F),F}try{t?.(re.status)}catch{}x=re.status;try{te=await re.json()}catch{}if(x>=400)throw Lt(x,te);if(x===201){let F=te?.data?.uuid,he=te?.data?.nonce;if(!F)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!he)throw new m.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"});(I.length||D)&&U(F,{currency:D,products:I.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??D}))});let ne=new URL(`${s.replace(/\/+$/,"")}/secure`);ne.searchParams.set("id",F);for(let[v,oe]of Object.entries(C))ne.searchParams.set(v,oe);if(R&&typeof window<"u"&&typeof document<"u"){let v=JSON.stringify({origin_url:u}),oe=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(v)}; domain=.${oe}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(he)}; domain=.${oe}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=ne.toString()),{status:201,redirectUrl:ne.toString(),nonce:he}}return x===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:x}}async function Qe(n){let e=Ze(n),t=Xe(e),r=J(n.timeoutMs);try{let s=await Je(n,r.signal,t);return et(e,s),s}catch(s){throw me(e,s),s}finally{r.clear(),Y(e.reporter)}}function Xe(n){let e=!1;return t=>{if(e)return;e=!0;let r=(0,m.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 Ze(n){let e=new w({billingApiUrl:n.billingApiUrl,sdkVersion:m.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 et(n,e){let t=(0,m.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 me(n,e){let{reporter:t}=n,r=(0,m.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 m.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 Y(n){n.flush().catch(()=>{}).finally(()=>n.destroy())}async function tt(n){let{maxRetries:e=2,...t}=n,r=Ze(n),s=Xe(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"}),Y(r.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let o={...t,idempotencyKey:(0,m.resolveIdempotencyKey)(t.idempotencyKey)},i=J(t.timeoutMs),l;for(let a=0;a<=e;a++){r.attempt=a;try{let c=await Je(o,i.signal,s);return et(r,c),i.clear(),Y(r.reporter),c}catch(c){l=c;let u=c instanceof Error&&c.name==="AbortError",f=Ut(c),b=c instanceof m.FloPayError&&c.code===m.IDEMPOTENCY_IN_PROGRESS_CODE;if((u||f||b)&&!i.signal.aborted&&a<e){r.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:a+1});try{await Q(a,i.signal)}catch(_){throw me(r,_),i.clear(),Y(r.reporter),_}continue}throw me(r,c),i.clear(),Y(r.reporter),c}}throw me(r,l),i.clear(),Y(r.reporter),l??new Error("Unknown error during checkout session creation")}0&&(module.exports={FloPay,FloPayElements,PaymentAPI,PciVaultCardCapture,SESSION_CREATE_TELEMETRY,StripeAdapter,cacheSessionDisplayData,clearSessionDisplayData,createCheckoutSession,createCheckoutSessionWithRetries,getSessionDisplayData,loadFloPay,toStripeAppearance,toStripeAppearanceTheme});
|
|
1
|
+
"use strict";var he=Object.defineProperty;var it=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames;var lt=Object.prototype.hasOwnProperty;var ct=(n,e)=>{for(var t in e)he(n,t,{get:e[t],enumerable:!0})},dt=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of at(e))!lt.call(n,o)&&o!==t&&he(n,o,{get:()=>e[o],enumerable:!(r=it(e,o))||r.enumerable});return n};var ut=n=>dt(he({},"__esModule",{value:!0}),n);var zt={};ct(zt,{FloPay:()=>Z,FloPayElements:()=>$,PaymentAPI:()=>D,PciVaultCardCapture:()=>L,SESSION_CREATE_TELEMETRY:()=>Te,StripeAdapter:()=>H,cacheSessionDisplayData:()=>F,clearSessionDisplayData:()=>ae,createCheckoutSession:()=>et,createCheckoutSessionWithRetries:()=>st,getSessionDisplayData:()=>ie,loadFloPay:()=>Qe,toStripeAppearance:()=>Be,toStripeAppearanceTheme:()=>Q});module.exports=ut(zt);var E=require("@flopay/shared");var Ve=require("@stripe/stripe-js"),f=require("@flopay/shared");var d=require("@flopay/shared");function x(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}var pt="flopay_session_display:";var se=new Map;function oe(n){return`${pt}${n}`}function ge(){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=ge();if(s)try{s.setItem(oe(n),JSON.stringify(o));return}catch{}se.set(n,o)}function ie(n){if(!n)return null;let e=ge();if(e)try{let r=e.getItem(oe(n));if(r){let o=JSON.parse(r);if(o&&typeof o.expiresAt=="number"&&o.expiresAt>Date.now())return o.data;e.removeItem(oe(n))}}catch{}let t=se.get(n);if(t){if(t.expiresAt>Date.now())return t.data;se.delete(n)}return null}function ae(n){if(!n)return;se.delete(n);let e=ge();if(e)try{e.removeItem(oe(n))}catch{}}var S=require("@flopay/shared"),mt="/v1/sdk-telemetry/events",fe=16,yt=64,ht=1500,Me=1e3,gt=64,ft="00000000-0000-4000-8000-000000000000",Ct={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 vt(n){try{return new TextEncoder().encode(n).byteLength}catch{return n.length}}function Tt(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 k(){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.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(/\/+$/,"")}${mt}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=j(),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.canCollect()&&this.enqueue((0,S.buildTelemetryLogEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}error(e){if(!this.canCollect())return;let t=(0,S.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:ft,sequence:0}),r=Tt(t),o=this.now();this.pruneReportedFailures(o);let s=this.reportedFailures.get(r);if(s!==void 0&&o>=s&&o-s<Me){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,S.buildTelemetryErrorEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue((0,S.buildTelemetryPerformanceEvent)({...this.checkoutContext,...e,eventId:j(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue((0,S.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 k()}}pruneReportedFailures(e){for(let[t,r]of this.reportedFailures)(e<r||e-r>=Me)&&this.reportedFailures.delete(t)}rememberReportedFailure(e,t){for(;this.reportedFailures.size>=gt;){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>=yt||this.eventCounts[e.class]>=Ct[e.class])){if(this.eventCounts[e.class]+=1,this.queue.push(e),this.queue.length>=fe){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,fe);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())}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,fe);this.sendBatch(e)}}async sendBatch(e){if(!this.browserTransportAvailable||this.ingestionDisabled)return;let t=(0,S.serializeTelemetryBatch)(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:j()});if(vt(t)>S.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 a=>a.status!==202?null:(await a.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(a=>{o=setTimeout(()=>{r?.abort(),a(null)},ht)});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)}},Ee=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),Re=globalThis;Re[Ee]===void 0&&Object.defineProperty(Re,Ee,{configurable:!0,enumerable:!1,writable:!1,value:n=>new _(n)});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 _t(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function K(n,e){let t=150*2**n,r=Math.round(t*(.75+Math.random()*.5));return new Promise((o,s)=>{let i,l=()=>e.removeEventListener("abort",a),a=()=>{i!==void 0&&clearTimeout(i),l(),s(_t())};if(e.aborted){a();return}i=setTimeout(()=>{l(),o()},r),e.addEventListener("abort",a,{once:!0})})}var Ae=1e3,wt=500,St=15e3,bt=3e3,kt=1e4,Pt=1e4;function xe(n){return typeof n=="object"&&n!==null}function z(n,e){return x(n?.[e])}function Ie(n,e){return Pe(n?.[e])}function Mt(n,e){let t=n?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Fe(n){return new Promise(e=>setTimeout(e,n))}function le(){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=xe(t?.error)?t.error:null,o=Ie(t,"message")??Ie(r,"message")??e,s=z(t,"code")??z(t,"gatewayErrorCode")??z(r,"code")??`http_${n.status}`;return new d.FloPayError(o,"api_error",{code:s,statusCode:n.status})}async function Et(n){if(n.status!==400&&n.status!==422)return;if(n.status===422)return"validation_rejected";let e=await n.clone().json().catch(()=>null);return xe(e)&&Array.isArray(e.fields)?"validation_rejected":"payment_declined"}function De(n){return n===400||n===422}var ce=2;async function ve(n,e,t=ce,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 Fe(150*2**s)}}var Te=Symbol.for("@flopay/js.session-create.telemetry.v1");function Rt(n){return n[Te]}function At(n){return"now"in n||"onFirstByte"in n||"onSessionCreateFailure"in n||"onRetry"in n}function Oe(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 qe(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 It(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.account.country&&(t.accountData={country:n.account.country}),qe(t,n),t}function Dt(n,e,t){return{currency:e,products:t.map(r=>(0,d.buildProductPayload)(r,e)),couponCodes:n.couponCodes??[],accountData:Oe(n.account)}}var U=class U{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let r=At(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()??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 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 ve(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:o},ce,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 l=`${Math.floor(s.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:l}),!s.ok)throw await q(s,"Failed to get checkout session");let a=await s.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",statusClass:l}),{...a,data:this.mergeCachedDisplayData(a.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){ae(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(),Pt);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 l=await ve(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:r.signal},ce,c=>{this.telemetryHooks?.onRetry?.("vault_capture",c),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:c})});if(!l.ok)throw await q(l,"Failed to load the secure card form");let a=await l.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(a)}catch(l){let a=r.signal.aborted?new d.FloPayError("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):l;throw this.reportDirectFailure(a,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),a}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,l;try{l=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(a){throw this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}if(!l.ok&&l.status!==202){let a=await Et(l);return a?this.directTelemetry?.terminal({outcome:a,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(l.status),failureCategory:l.status>=500?"server_error":void 0}),l}try{let a=await this.resolveProcessResponse(l,t.sessionId,{...r,nonce:s});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(a.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"process_payment",statusClass:(0,d.telemetryStatusClass)(a.status)}),a}catch(a){throw a instanceof d.FloPayError&&a.code==="checkout_processing_timeout"||this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}}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??kt,l=new AbortController,a=()=>l.abort();o?.signal&&(o.signal.aborted?l.abort():o.signal.addEventListener("abort",a,{once:!0}));let c=setTimeout(()=>l.abort(),i);try{let u;try{u=await ve(`${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:l.signal},ce,m=>{this.telemetryHooks?.onRetry?.("account_snapshot",m),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:m})})}finally{clearTimeout(c),o?.signal?.removeEventListener("abort",a)}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,l=typeof i=="string"&&i.trim().toLowerCase()==="card",a=typeof i=="string"&&i.length>0&&!l&&(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.paymentMethodType==="paypal"&&s.paymentMethodId===null&&s.intentKind==="payment";if(!a||!c&&!u)throw new d.FloPayError("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let m=s.authorizationAttemptId;if(m!==void 0&&!(0,d.isUuidV4)(m))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)(m)?m:(0,d.randomUuidV4)();this.beginDirectTelemetryCheckout(e);let y=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.intent.started",stage:"processing",requestCategory:"intent_create"});let P={"Content-Type":"application/json","x-checkout-session-token":t,[d.IDEMPOTENCY_KEY_HEADER]:o?.idempotencyKey||p},w=!1;try{let b=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:P,body:JSON.stringify({...r,authorizationAttemptId:p}),signal:o?.signal});if(!b.ok){w=!0;let B=await q(b,"Failed to create checkout intent"),A=(0,d.classifyTelemetryFailure)(B,"PAYMENT_PROCESSING_FAILED");throw De(B.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...A,stage:"processing",requestCategory:"intent_create"}),B}let N=(await b.json()).data;if(!N||typeof N!="object")throw new d.FloPayError("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let g=N,W=g.paymentMethodType,V=(g.paymentMethodCategory==="wallet"||g.paymentMethodCategory==="apm")&&typeof W=="string"&&W.trim().toLowerCase()!=="card"&&(typeof g.paymentMethodId=="string"||g.paymentMethodId===null)&&typeof g.providerObjectId=="string",R=g.provider==="stripe"&&(g.intentKind==="payment"||g.intentKind==="setup")&&typeof g.clientSecret=="string",J=g.provider==="paypal"&&g.paymentMethodCategory==="wallet"&&g.paymentMethodType==="paypal"&&g.paymentMethodId===null&&g.intentKind==="payment"&&(g.providerObjectType==="order"||g.providerObjectType==="subscription")&&g.clientSecret===null,me=g.provider===r.provider&&g.paymentMethodCategory===r.paymentMethodCategory&&g.paymentMethodType===r.paymentMethodType&&g.paymentMethodId===r.paymentMethodId&&g.intentKind===r.intentKind;if(!V||!R&&!J||!me)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)(b.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-y),durationMode:"machine",requestCategory:"intent_create",statusClass:(0,d.telemetryStatusClass)(b.status)}),g}catch(b){throw w||this.reportDirectFailure(b,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),b}}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,l=s.paymentMethodType,a=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 l=="string"&&l.length>0&&l.trim().toLowerCase()!=="card"&&a,u=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm"),m=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodType==="paypal";if(!c||!u&&!m)throw new d.FloPayError("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let p=m?{provider:"paypal",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:i}:{provider:"stripe",paymentMethodCategory:s.paymentMethodCategory,paymentMethodType:s.paymentMethodType,providerDeclineReason:i},y=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(!y.ok)throw await q(y,"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 l=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!l.ok)throw new d.FloPayError("Failed to fetch payments","api_error",{statusCode:l.status});let a=await l.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"}),a}catch(l){throw this.reportDirectFailure(l,"RECOVERY_FAILED","recovery","other","saved"),l}}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),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 l={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:Oe(e.account),couponCodes:e.couponCodes??[]};e.tokenizedData&&(l.tokenizedData=e.tokenizedData),qe(l,e);let c=await(await this.postCheckoutSessionCreate(l,e,t,r,o)).json();if(c.data&&"gateways"in c.data){this.autoCacheDisplayData(c.data.uuid,e);let p=this.mergeCachedDisplayData(c.data),y=this.normalizeRawSession(p);return c.vault&&y.data.session&&(y.data.session.vault=this.toVaultBlock(c.vault)),{...y,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},l=(0,d.resolveIdempotencyKey)(t.idempotencyKey);l&&(i[d.IDEMPOTENCY_KEY_HEADER]=l);let a,c=!1,u=Rt(t),m=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{a=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:i,body:JSON.stringify(e),signal:o})}catch(w){if(s.statusClass=o.aborted||w instanceof Error&&w.name==="AbortError"?"timeout":"network_error",o.aborted||w instanceof Error&&w.name==="AbortError"||p>=2)throw w;let b=p+1;m(b),await K(p,o);continue}let y=(0,d.telemetryStatusClass)(a.status);if(s.statusClass=y,c||(c=!0,this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:y,attempt:p}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_create",statusClass:y,attempt:p})),a.status===204)throw new d.FloPayError("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(a.ok)break;let P=await q(a,"Failed to create checkout session");if(P.code===d.IDEMPOTENCY_IN_PROGRESS_CODE&&p<2){m(p+1),await K(p,o);continue}throw P}if(!a)throw new TypeError("Checkout-session creation exhausted its retry budget.");return a}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),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 l;try{l=Dt(e,i,s)}catch(y){throw r.clear(),this.reportSessionCreateFailure(y,t,o),y}let a,c;try{if(c=await(await this.postCheckoutSessionCreate(It(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"});a=this.normalizeRawSession(this.mergeCachedDisplayData(c.data)),c.vault&&a.data.session&&(a.data.session.vault=this.toVaultBlock(c.vault))}catch(y){throw r.clear(),this.reportSessionCreateFailure(y,t,o),y}let u=a.data.session?.id??c.data.uuid??"",m=a.data.session?.clientSecret??c.data.nonce??"";if(!u||!m){r.clear();let y=new d.FloPayError("Checkout session shell was created without a session id or nonce.","api_error",{code:"InvalidCheckoutSessionResponse"});throw this.reportSessionCreateFailure(y,t,o),y}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,m,l,{params:e,startedAt:t,deadline:r,createAttempt:o.attempt});return p.catch(()=>{}),{shell:a,sessionId:u,nonce:m,claimed:p}}async claimCheckoutSession(e,t,r,o){let s=o?.startedAt??this.telemetryTimestamp(),i=this.telemetryTimestamp(),l=o?.deadline??O(12e3),a=JSON.stringify(r),c="unknown",u=0;this.directTelemetry?.log({name:"session.claim.started",stage:"session_claim",requestCategory:"session_claim"});try{let m;for(u=0;u<3;u++){try{m=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:a,signal:l.signal})}catch(P){let w=l.signal.aborted||P instanceof Error&&P.name==="AbortError";if(c=w?"timeout":"network_error",w||u>=2)throw P;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 K(u,l.signal);continue}if(c=(0,d.telemetryStatusClass)(m.status),m.ok)break;throw await q(m,"Failed to attach checkout session data")}if(!m)throw new TypeError("Checkout-session claim exhausted its retry budget.");let p=await m.json();if(!p.data||!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 y=this.normalizeRawSession(this.mergeCachedDisplayData(p.data));return p.vault&&y.data.session&&(y.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}),y}catch(m){throw this.reportSessionCreateFailure(m,s,{attempt:u,statusClass:c},"session_claim"),m}finally{l.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&&De(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??St,s=Date.now()+o,i=this.clampRetryAfterMs(t?.initialDelayMs??Ae),l=0;try{for(;;){let a=s-Date.now();if(a<=0)throw le();if(i>0){try{l+=1,this.telemetryHooks?.onRetry?.("session_read",l),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:l})}catch{}if(await Fe(Math.min(i,a)),Date.now()>=s)throw le()}let c=await this.getUnifiedCheckoutSession(e,t?.nonce),u=c.data.session?.status;if(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 le();i=this.clampRetryAfterMs(Math.max(i*2,wt))}}catch(a){throw a instanceof d.FloPayError&&a.code==="checkout_processing_timeout"&&this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","session_read","saved"),a}}normalizeRawSession(e){let t=e.gateways??{},r=[],o={session:this.toCheckoutSession(e)},s=t.stripe;if(s?.publishableKey){r.push("stripe");let a=[e.stripeClientSecret,s.stripeClientSecret].find(c=>typeof c=="string"&&c.length>0);o.stripe={clientSecret:a??"",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}),{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),l=e.currency??t[0]?.currency??"USD",a=t.some(c=>c.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:a,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:l,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==="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"});throw i.data.session?.status==="expired"?new d.FloPayError("Checkout session has expired.","api_error",{code:"checkout_session_expired"}):le()}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:z(e,"sessionId")??r,retryAfterMs:this.clampRetryAfterMs(Mt(e,"retryAfterMs")??i??Ae),statusUrl:z(e,"statusUrl"),sessionUrl:z(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,bt))}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=ie(e.uuid),r=new Map,o=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let l=o(i.code);l&&r.set(l,i)}let s=(e.products??[]).map(i=>{let l=o(i.code),a=l?r.get(l):void 0;return{...i,name:i.name??a?.name??null,totalAmount:i.totalAmount??a?.totalAmount,overrideAmount:i.overrideAmount??a?.overrideAmount,currency:i.currency??a?.currency}});return{...e,currency:e.currency??t?.currency,products:s}}};U.activeVaultCaptureRequests=new Map;var D=U;function Ue(n,e){let t=D;return new t(n,e)}function Le(n){return{payment:"payment",address:"address"}[n]}function Q(n){switch(n){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function Be(n){return{...n,theme:Q(n.theme)}}function _e(n){return n?JSON.stringify(n.map(e=>e.trim().toLowerCase())):null}function Ne(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 xt(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 H=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,Ve.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:Q(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}:void 0,r=t?JSON.stringify(t):null,o=_e(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,l=e?.amount??0,a=(e?.currency??"usd").toLowerCase(),c=e?.paymentMethodCreation??"manual";e?.clientSecret?i={clientSecret:e.clientSecret}:l>0?(i={mode:"payment",amount:l,currency:a,paymentMethodCreation:c},e?.setupFutureUsage&&(i.setupFutureUsage=e.setupFutureUsage)):i={mode:"setup",currency:a,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:a,error:c}=await this.stripe.retrieveSetupIntent(e);r=a,o=!!c}else{let{paymentIntent:a,error:c}=await this.stripe.retrievePaymentIntent(e);r=a,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(a=>a.toLowerCase()));if(s.some(a=>typeof a!="string"||!i.has(a.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 a=t.paymentMethodTypes?.map(c=>c.trim()).filter(c=>c&&c.toLowerCase()!=="card");if(!a?.length)throw new f.FloPayError("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});if(r={...t,paymentMethodTypes:a},r.clientSecret){let c=_e(a);this.elements&&this.appliedClientSecret===r.clientSecret&&this.appliedPaymentMethodTypesKey===c&&this.verifiedClientSecret===r.clientSecret&&this.verifiedPaymentMethodTypesKey===c||await this.assertClientSecretPaymentMethods(r.clientSecret,a)}}let o=this.getElements(r);e==="payment"&&r.clientSecret&&(this.verifiedClientSecret=r.clientSecret,this.verifiedPaymentMethodTypesKey=_e(r.paymentMethodTypes));let s=Le(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 l=o.create(s,i);return Ne(l)}getElement(e){if(!this.elements)return null;let t=Le(e),r=this.elements.getElement(t);return r?Ne(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?xt(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 D(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 D(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&&(s.status==="requires_capture"||s.status==="succeeded")){let l=typeof s.payment_method=="string"?s.payment_method:s.payment_method?.id,a=new URL(window.location.href);return a.searchParams.delete("payment_intent"),a.searchParams.delete("payment_intent_client_secret"),a.searchParams.delete("redirect_status"),window.history.replaceState({},"",a.toString()),{status:s.status,paymentIntentId:s.id,paymentMethodId:l}}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:Q(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 C=require("@flopay/shared");var je=require("@flopay/shared"),$=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 l=r.paymentMethodTypes?.map(a=>a.trim()).filter(a=>a&&a.toLowerCase()!=="card");if(!l?.length)throw new je.FloPayError("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});r.paymentMethodTypes=l}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 T=require("@flopay/shared");var we="flopay-vault",Ke={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 X(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 de(n,e){return(0,T.buildTelemetryLogEvent)({eventId:"11111111-1111-4111-8111-111111111111",name:n,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function ze(n){return n?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function Ft(n,e){if(n==="complete"||n==="decline")return(0,T.buildTelemetryTerminalEvent)({eventId:"22222222-2222-4222-8222-222222222222",outcome:n==="complete"?"payment_succeeded":"payment_declined",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(n==="error"){let o=ze(e);return(0,T.buildTelemetryErrorEvent)({eventId:"33333333-3333-4333-8333-333333333333",...o,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[t,r]=Ke[n];return de(t,r)}function Ot(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 qt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===we&&e.type==="validation"&&Array.isArray(e.messages)}function Ut(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){if(this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new _({billingApiUrl:(0,T.resolveBillingApiUrl)(),sdkVersion:T.SDK_VERSION})),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 T.FloPayError("The vault card form is only available in the browser.","api_error",{code:"card_capture_no_window"});if(!t?.html||!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(r){throw this.reportVaultLoadFailure(),r}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),X(de("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(Ut(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;this.applyHeight(r.height);return}if(qt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;let l=r.messages.filter(a=>typeof a=="string"&&a.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:l||void 0});return}if(!Ot(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={sessionId:r.sessionId??this.config.sessionId,intentId:r.intentId,declineReason:r.declineReason,message:r.message,nextActionRedirectUrl:r.nextActionRedirectUrl};r.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??k()),X(Ft(r.type,this.submissionStarted)),this.reportOutcome(r.type),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(),this.emit(r.type,i)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;if(e==="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"})),e==="complete"||e==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:e==="complete"?"payment_succeeded":"payment_declined",provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="error"){let s=ze(this.submissionStarted);t.log({name:"vault.terminal",stage:s.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...s,provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="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 s=this.submissionStartedAt;this.submissionStartedAt=null,s!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-s),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[r,o]=Ke[e];t.log({name:r,stage:o,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 l=i.data;if(!l||typeof l!="object")return;let a=l;a.source==="flopay-vault-3ds-return"&&(X(de("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(a.status))};window.addEventListener("message",s),this.threeDsReturnHandler=s,document.body.appendChild(t),this.actionOverlay=t,X(de("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"});X(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 He(n,e){let t=L;return new t(n,{reporter:e})}var $e=Symbol.for("@flopay/js.telemetry.bridge.v1");function Ge(n,e,t){let r=()=>e?.now()??t();Object.defineProperty(n,$e,{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()}})}function Ye(n){return n[$e]}function G(n){if(!n)return!1;let e=n.code?.toLowerCase()??"";return!!n.declineCode||e.includes("declin")}function Lt(n){return n==="stripe"||n==="paypal"||n==="pcivault"?n:"other"}var Z=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}),Ge(this,this.telemetryReporter,k)}now(){return this.telemetryReporter?.now?.()??k()}elements(e){return this.currentElements&&this.currentElements.destroy(),this.currentElements=new $(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?He({sessionId:e?.sessionId},this.telemetryReporter):new L({sessionId:e?.sessionId,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:"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"&&(G(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&&G(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"}):G(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&&G(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=Lt(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}):G(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?.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&&G(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=Ue(r,{now:()=>this.telemetryReporter?.now()??k(),onFirstByte:l=>{s=l},onRetry:(l,a)=>{this.telemetryReporter?.log({name:"operation.retry",stage:l==="session_read"?"session_read":"processing",requestCategory:l,attempt:a})}});try{let l=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"}),l}catch(l){let a=(0,C.classifyTelemetryFailure)(l,l instanceof C.FloPayError&&l.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...a,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-o,durationMode:"machine",requestCategory:"session_read",statusClass:a.statusClass}),l}}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 We(n,e,t){let r=Z;return new r(n,e,t)}var Je=new Map;function Se(n){return Array.isArray(n)?n.map(Se):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Se(t)])):n}function Nt(n,e){return JSON.stringify([n,(0,E.resolveBillingApiUrl)(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,Se(e?.appearance??null)])}var ue=new Map;async function Qe(n,e){if(!n){let l=new _({billingApiUrl:(0,E.resolveBillingApiUrl)(e?.billingApiUrl),sdkVersion:E.SDK_VERSION,enabled:e?.telemetry!==!1});throw l.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),l.flush().catch(()=>{}).finally(()=>l.destroy()),new E.FloPayError("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let t=Nt(n,e),r=Je.get(t);if(r)return e?.telemetry!==!1&&Ye(r)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),r;let o=ue.get(t);if(o)return o;let s={...e,publishableKey:n},i=(async()=>{let l=new _({billingApiUrl:(0,E.resolveBillingApiUrl)(s.billingApiUrl),sdkVersion:E.SDK_VERSION,enabled:s.telemetry!==!1}),a=l.now();l.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),l.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),l.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new H,u=l.now();try{await c.initialize(s)}catch(y){throw l.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),l.destroy(),y}let m=l.now();l.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),l.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),l.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),l.performance({stage:"sdk_initialize",durationMs:m-a,durationMode:"machine",provider:"stripe"}),l.performance({stage:"provider_ready",durationMs:m-u,durationMode:"machine",provider:"stripe"});let p=We(c,s,l);return Je.set(t,p),p})();ue.set(t,i);try{return await i}finally{ue.get(t)===i&&ue.delete(t)}}var h=require("@flopay/shared");var be=5,Xe=new WeakSet;function Vt(n){(typeof n=="object"&&n!==null||typeof n=="function")&&Xe.add(n)}function Bt(n){return(typeof n=="object"&&n!==null||typeof n=="function")&&Xe.has(n)}function jt(n,e){let t=e?.error,r=x(e?.code)??x(t?.code)??`http_${n}`,o=x(e?.message)??x(t?.message)??Kt(r,n);return new h.FloPayError(o,"api_error",{code:r,statusCode:n})}function Kt(n,e){switch(n){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${be}.`;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 Ze(n,e,t){let{billingApiUrl:r,checkoutBaseUrl:o,items:s=[],subscriptions:i=[],products:l,account:a,successUrl:c,cancelUrl:u,checkoutMode:m="confirm",couponCodes:p=[],tagsData:y,redirectParams:P={},setCookie:w=!0,clientId:b,currency:ke,utmMetadata:N,idempotencyKey:g}=n,W=(0,h.resolveIdempotencyKey)(g);if(p.length>be)throw new h.FloPayError(`Too many coupon codes \u2014 a checkout session accepts at most ${be}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let V=l??(0,h.foldIntoProducts)(s,i),R=(0,h.resolveSessionCurrency)(ke,s,i,V);if(!R)throw new h.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 J={clientId:b,checkoutVersion:h.SDK_VERSION,successUrl:c,cancelUrl:u,currency:R,checkoutMode:m,products:V.map(I=>(0,h.buildProductPayload)(I,R)),accountData:{userId:a.userId,firstName:a.firstName??null,lastName:a.lastName??null,email:a.email,country:a.country??null,gender:a.gender??null,city:a.city??null,state:a.state??null,zip:a.zip??null,addressLine1:a.addressLine1??null,addressLine2:a.addressLine2??null},couponCodes:p};y&&(J.tagsData=y),N?.length&&(J.utmMetadata=N);let me=`${r.replace(/\/+$/,"")}/v1/checkouts/sessions`,B={"Content-Type":"application/json"};W&&(B[h.IDEMPOTENCY_KEY_HEADER]=W);let A,ee,ot={method:"POST",headers:B,body:JSON.stringify(J),signal:e},te;try{te=await fetch(me,ot)}catch(I){throw Vt(I),I}try{t?.(te.status)}catch{}A=te.status;try{ee=await te.json()}catch{}if(A>=400)throw jt(A,ee);if(A===201){let I=ee?.data?.uuid,ye=ee?.data?.nonce;if(!I)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!ye)throw new h.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"});(V.length||R)&&F(I,{currency:R,products:V.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 re=new URL(`${o.replace(/\/+$/,"")}/secure`);re.searchParams.set("id",I);for(let[v,ne]of Object.entries(P))re.searchParams.set(v,ne);if(w&&typeof window<"u"&&typeof document<"u"){let v=JSON.stringify({origin_url:u}),ne=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(v)}; domain=.${ne}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(ye)}; domain=.${ne}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=re.toString()),{status:201,redirectUrl:re.toString(),nonce:ye}}return A===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:A}}async function et(n){let e=rt(n),t=tt(e),r=O(n.timeoutMs);try{let o=await Ze(n,r.signal,t);return nt(e,o),o}catch(o){throw pe(e,o),o}finally{r.clear(),Y(e.reporter)}}function tt(n){let e=!1;return t=>{if(e)return;e=!0;let r=(0,h.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 rt(n){let e=new _({billingApiUrl:n.billingApiUrl,sdkVersion:h.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 nt(n,e){let t=(0,h.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 pe(n,e){let{reporter:t}=n,r=(0,h.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 h.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 Y(n){n.flush().catch(()=>{}).finally(()=>n.destroy())}async function st(n){let{maxRetries:e=2,...t}=n,r=rt(n),o=tt(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"}),Y(r.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let s={...t,idempotencyKey:(0,h.resolveIdempotencyKey)(t.idempotencyKey)},i=O(t.timeoutMs),l;for(let a=0;a<=e;a++){r.attempt=a;try{let c=await Ze(s,i.signal,o);return nt(r,c),i.clear(),Y(r.reporter),c}catch(c){l=c;let u=c instanceof Error&&c.name==="AbortError",m=Bt(c),p=c instanceof h.FloPayError&&c.code===h.IDEMPOTENCY_IN_PROGRESS_CODE;if((u||m||p)&&!i.signal.aborted&&a<e){r.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:a+1});try{await K(a,i.signal)}catch(y){throw pe(r,y),i.clear(),Y(r.reporter),y}continue}throw pe(r,c),i.clear(),Y(r.reporter),c}}throw pe(r,l),i.clear(),Y(r.reporter),l??new Error("Unknown error during checkout session creation")}0&&(module.exports={FloPay,FloPayElements,PaymentAPI,PciVaultCardCapture,SESSION_CREATE_TELEMETRY,StripeAdapter,cacheSessionDisplayData,clearSessionDisplayData,createCheckoutSession,createCheckoutSessionWithRetries,getSessionDisplayData,loadFloPay,toStripeAppearance,toStripeAppearanceTheme});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _flopay_shared from '@flopay/shared';
|
|
2
|
-
import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CardCaptureAdapter, PayPalPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance, CheckoutGateways, VaultCaptureBlock, ProcessPaymentParams, CreateSessionIntentRequest, SessionIntent, SessionIntentDeclineRequest, InlineSessionDraft, CardCaptureProviderId, CardCaptureMountOptions, CardCaptureEventType, CardCaptureOutcomeEvent, VaultCardThemeColors, VaultCardFieldKey, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
|
|
2
|
+
import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CardCaptureAdapter, PayPalPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance, CheckoutGateways, VaultCaptureBlock, ProcessPaymentParams, CreateSessionIntentRequest, SessionIntent, SessionIntentDeclineRequest, InlineSessionDraft, DetachedCheckoutSession, CardCaptureProviderId, CardCaptureMountOptions, CardCaptureEventType, CardCaptureOutcomeEvent, VaultCardThemeColors, VaultCardFieldKey, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Manages the creation and lifecycle of payment elements.
|
|
@@ -527,9 +527,81 @@ declare class PaymentAPI {
|
|
|
527
527
|
* instead of just a UUID — eliminating the need for a second GET.
|
|
528
528
|
*
|
|
529
529
|
* Falls back to create + GET if the backend doesn't support `expand`.
|
|
530
|
+
*
|
|
531
|
+
* Eligible sessions are created through the **detached** shell + claim flow
|
|
532
|
+
* (see {@link PaymentAPI.createDetachedSession}) and this method awaits the
|
|
533
|
+
* claim, so its resolved value is unchanged — callers still receive one
|
|
534
|
+
* fully-populated session. The win here is server-side: the create no longer
|
|
535
|
+
* contends on buyer-identity advisory locks. Callers that want to render from
|
|
536
|
+
* the shell *before* the claim lands — mounting the card form early — should
|
|
537
|
+
* call {@link PaymentAPI.createDetachedSession} directly. Pass
|
|
538
|
+
* `deferDataAttachment: false` to force the original one-shot create.
|
|
530
539
|
*/
|
|
531
540
|
createAndFetchSession(params: InlineSessionDraft): Promise<NormalizedCheckoutSession>;
|
|
532
541
|
private createAndFetchSessionRequest;
|
|
542
|
+
/**
|
|
543
|
+
* `POST /v1/checkouts/sessions` with the SDK's bounded retry budget.
|
|
544
|
+
*
|
|
545
|
+
* Network failures and the backend's documented in-progress replay share one
|
|
546
|
+
* attempt budget and one operation-wide abort signal, so the two retry modes
|
|
547
|
+
* cannot multiply into nine POSTs during an outage. The idempotency key is
|
|
548
|
+
* resolved once, before the loop — an invalid merchant-supplied key throws
|
|
549
|
+
* before any request, and every attempt of this logical create replays the
|
|
550
|
+
* same key so a timeout cannot mint a second session
|
|
551
|
+
* (TeamFloPay/backend#972).
|
|
552
|
+
*/
|
|
553
|
+
private postCheckoutSessionCreate;
|
|
554
|
+
/**
|
|
555
|
+
* Create a checkout session **detached** from its buyer and catalog data
|
|
556
|
+
* (TeamFloPay/backend#1099).
|
|
557
|
+
*
|
|
558
|
+
* Resolves as soon as the lightweight *shell* exists. That create runs no
|
|
559
|
+
* catalog validation and takes none of the buyer-identity advisory locks that
|
|
560
|
+
* serialise concurrent checkouts for the same customer, and the backend routes
|
|
561
|
+
* a gateway for it from `currency` + the buyer's country — so the shell
|
|
562
|
+
* already carries the session id, nonce, `gateways` and the hosted `vault`
|
|
563
|
+
* block. The card form can mount from it immediately.
|
|
564
|
+
*
|
|
565
|
+
* Buyer identity, address, products and coupons are attached by the returned
|
|
566
|
+
* {@link DetachedCheckoutSession.claimed} promise, which is already in flight
|
|
567
|
+
* when this resolves. **Nothing may be charged until it settles** — the
|
|
568
|
+
* billing API rejects process / intent / decline calls on an unclaimed
|
|
569
|
+
* session with `409 checkout_session_data_attachment_required`, and holds an
|
|
570
|
+
* unclaimed vault charge with a retryable `503`.
|
|
571
|
+
*
|
|
572
|
+
* Requires a billing API with `PATCH /v1/checkouts/sessions/{id}/claim`; there
|
|
573
|
+
* is no fallback to the one-shot create. Callers that want the original
|
|
574
|
+
* single-request behaviour should pass `deferDataAttachment: false` and use
|
|
575
|
+
* {@link PaymentAPI.createAndFetchSession}.
|
|
576
|
+
*/
|
|
577
|
+
createDetachedSession(params: InlineSessionDraft): Promise<DetachedCheckoutSession>;
|
|
578
|
+
/**
|
|
579
|
+
* `PATCH /v1/checkouts/sessions/{id}/claim` — attach buyer identity, address,
|
|
580
|
+
* products and coupons to a detached session shell.
|
|
581
|
+
*
|
|
582
|
+
* The backend fingerprints the payload, so a transport retry replaying the
|
|
583
|
+
* identical body returns the same claimed session rather than conflicting; a
|
|
584
|
+
* *materially different* claim for an already-claimed session returns `409`,
|
|
585
|
+
* which is surfaced without retrying. Invalid catalog data surfaces here as
|
|
586
|
+
* the same `422` the one-shot create would have returned — later in the flow,
|
|
587
|
+
* but with identical semantics.
|
|
588
|
+
*/
|
|
589
|
+
claimCheckoutSession(checkoutSessionId: string, nonce: string, payload: Record<string, unknown>, internal?: {
|
|
590
|
+
params: InlineSessionDraft;
|
|
591
|
+
startedAt: number;
|
|
592
|
+
deadline: {
|
|
593
|
+
signal: AbortSignal;
|
|
594
|
+
clear(): void;
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
597
|
+
* Attempts the shell create needed. The `session_create` rollup below
|
|
598
|
+
* reports this rather than the claim's own attempt count, so an
|
|
599
|
+
* end-to-end span keeps meaning "attempts to create this session".
|
|
600
|
+
*/
|
|
601
|
+
createAttempt: number;
|
|
602
|
+
}): Promise<NormalizedCheckoutSession>;
|
|
603
|
+
/** Shared create/claim failure reporting so both phases classify identically. */
|
|
604
|
+
private reportSessionCreateFailure;
|
|
533
605
|
waitForCheckoutSessionCompletion(checkoutSessionId: string, options?: {
|
|
534
606
|
initialDelayMs?: number;
|
|
535
607
|
timeoutMs?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _flopay_shared from '@flopay/shared';
|
|
2
|
-
import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CardCaptureAdapter, PayPalPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance, CheckoutGateways, VaultCaptureBlock, ProcessPaymentParams, CreateSessionIntentRequest, SessionIntent, SessionIntentDeclineRequest, InlineSessionDraft, CardCaptureProviderId, CardCaptureMountOptions, CardCaptureEventType, CardCaptureOutcomeEvent, VaultCardThemeColors, VaultCardFieldKey, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
|
|
2
|
+
import { PaymentProviderAdapter, ElementOptions, ElementType, MountedElement, FloPayError, FloPayConfig, CardCaptureAdapter, PayPalPaymentResult, ConfirmPaymentParams, PaymentResult, CheckoutSession, NormalizedCheckoutSession, FloPayThemeVariables, FloPayAppearance, CheckoutGateways, VaultCaptureBlock, ProcessPaymentParams, CreateSessionIntentRequest, SessionIntent, SessionIntentDeclineRequest, InlineSessionDraft, DetachedCheckoutSession, CardCaptureProviderId, CardCaptureMountOptions, CardCaptureEventType, CardCaptureOutcomeEvent, VaultCardThemeColors, VaultCardFieldKey, CreateSessionParams, CheckoutSessionResult } from '@flopay/shared';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Manages the creation and lifecycle of payment elements.
|
|
@@ -527,9 +527,81 @@ declare class PaymentAPI {
|
|
|
527
527
|
* instead of just a UUID — eliminating the need for a second GET.
|
|
528
528
|
*
|
|
529
529
|
* Falls back to create + GET if the backend doesn't support `expand`.
|
|
530
|
+
*
|
|
531
|
+
* Eligible sessions are created through the **detached** shell + claim flow
|
|
532
|
+
* (see {@link PaymentAPI.createDetachedSession}) and this method awaits the
|
|
533
|
+
* claim, so its resolved value is unchanged — callers still receive one
|
|
534
|
+
* fully-populated session. The win here is server-side: the create no longer
|
|
535
|
+
* contends on buyer-identity advisory locks. Callers that want to render from
|
|
536
|
+
* the shell *before* the claim lands — mounting the card form early — should
|
|
537
|
+
* call {@link PaymentAPI.createDetachedSession} directly. Pass
|
|
538
|
+
* `deferDataAttachment: false` to force the original one-shot create.
|
|
530
539
|
*/
|
|
531
540
|
createAndFetchSession(params: InlineSessionDraft): Promise<NormalizedCheckoutSession>;
|
|
532
541
|
private createAndFetchSessionRequest;
|
|
542
|
+
/**
|
|
543
|
+
* `POST /v1/checkouts/sessions` with the SDK's bounded retry budget.
|
|
544
|
+
*
|
|
545
|
+
* Network failures and the backend's documented in-progress replay share one
|
|
546
|
+
* attempt budget and one operation-wide abort signal, so the two retry modes
|
|
547
|
+
* cannot multiply into nine POSTs during an outage. The idempotency key is
|
|
548
|
+
* resolved once, before the loop — an invalid merchant-supplied key throws
|
|
549
|
+
* before any request, and every attempt of this logical create replays the
|
|
550
|
+
* same key so a timeout cannot mint a second session
|
|
551
|
+
* (TeamFloPay/backend#972).
|
|
552
|
+
*/
|
|
553
|
+
private postCheckoutSessionCreate;
|
|
554
|
+
/**
|
|
555
|
+
* Create a checkout session **detached** from its buyer and catalog data
|
|
556
|
+
* (TeamFloPay/backend#1099).
|
|
557
|
+
*
|
|
558
|
+
* Resolves as soon as the lightweight *shell* exists. That create runs no
|
|
559
|
+
* catalog validation and takes none of the buyer-identity advisory locks that
|
|
560
|
+
* serialise concurrent checkouts for the same customer, and the backend routes
|
|
561
|
+
* a gateway for it from `currency` + the buyer's country — so the shell
|
|
562
|
+
* already carries the session id, nonce, `gateways` and the hosted `vault`
|
|
563
|
+
* block. The card form can mount from it immediately.
|
|
564
|
+
*
|
|
565
|
+
* Buyer identity, address, products and coupons are attached by the returned
|
|
566
|
+
* {@link DetachedCheckoutSession.claimed} promise, which is already in flight
|
|
567
|
+
* when this resolves. **Nothing may be charged until it settles** — the
|
|
568
|
+
* billing API rejects process / intent / decline calls on an unclaimed
|
|
569
|
+
* session with `409 checkout_session_data_attachment_required`, and holds an
|
|
570
|
+
* unclaimed vault charge with a retryable `503`.
|
|
571
|
+
*
|
|
572
|
+
* Requires a billing API with `PATCH /v1/checkouts/sessions/{id}/claim`; there
|
|
573
|
+
* is no fallback to the one-shot create. Callers that want the original
|
|
574
|
+
* single-request behaviour should pass `deferDataAttachment: false` and use
|
|
575
|
+
* {@link PaymentAPI.createAndFetchSession}.
|
|
576
|
+
*/
|
|
577
|
+
createDetachedSession(params: InlineSessionDraft): Promise<DetachedCheckoutSession>;
|
|
578
|
+
/**
|
|
579
|
+
* `PATCH /v1/checkouts/sessions/{id}/claim` — attach buyer identity, address,
|
|
580
|
+
* products and coupons to a detached session shell.
|
|
581
|
+
*
|
|
582
|
+
* The backend fingerprints the payload, so a transport retry replaying the
|
|
583
|
+
* identical body returns the same claimed session rather than conflicting; a
|
|
584
|
+
* *materially different* claim for an already-claimed session returns `409`,
|
|
585
|
+
* which is surfaced without retrying. Invalid catalog data surfaces here as
|
|
586
|
+
* the same `422` the one-shot create would have returned — later in the flow,
|
|
587
|
+
* but with identical semantics.
|
|
588
|
+
*/
|
|
589
|
+
claimCheckoutSession(checkoutSessionId: string, nonce: string, payload: Record<string, unknown>, internal?: {
|
|
590
|
+
params: InlineSessionDraft;
|
|
591
|
+
startedAt: number;
|
|
592
|
+
deadline: {
|
|
593
|
+
signal: AbortSignal;
|
|
594
|
+
clear(): void;
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
597
|
+
* Attempts the shell create needed. The `session_create` rollup below
|
|
598
|
+
* reports this rather than the claim's own attempt count, so an
|
|
599
|
+
* end-to-end span keeps meaning "attempts to create this session".
|
|
600
|
+
*/
|
|
601
|
+
createAttempt: number;
|
|
602
|
+
}): Promise<NormalizedCheckoutSession>;
|
|
603
|
+
/** Shared create/claim failure reporting so both phases classify identically. */
|
|
604
|
+
private reportSessionCreateFailure;
|
|
533
605
|
waitForCheckoutSessionCompletion(checkoutSessionId: string, options?: {
|
|
534
606
|
initialDelayMs?: number;
|
|
535
607
|
timeoutMs?: number;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FloPayError as tr,resolveBillingApiUrl as we,SDK_VERSION as rt}from"@flopay/shared";import{loadStripe as jt}from"@stripe/stripe-js";import{FloPayError as h,isSetupIntentClientSecret as Kt}from"@flopay/shared";import{FloPayError as m,SDK_VERSION as oe,FLO_SDK_VERSION_HEADER as Ae,IDEMPOTENCY_KEY_HEADER as Ie,IDEMPOTENCY_IN_PROGRESS_CODE as Rt,buildProductPayload as At,classifyTelemetryFailure as Y,foldIntoProducts as De,isUuidV4 as xe,randomUuidV4 as It,resolveIdempotencyKey as Dt,resolveSessionCurrency as Fe,telemetryStatusClass as L}from"@flopay/shared";function I(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}var mt="flopay_session_display:";var re=new Map;function ne(n){return`${mt}${n}`}function ye(){if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}}function q(n,e,t){if(!n)return;let r=t?.ttlMs??36e5,s={data:e,expiresAt:Date.now()+r},o=ye();if(o)try{o.setItem(ne(n),JSON.stringify(s));return}catch{}re.set(n,s)}function he(n){if(!n)return null;let e=ye();if(e)try{let r=e.getItem(ne(n));if(r){let s=JSON.parse(r);if(s&&typeof s.expiresAt=="number"&&s.expiresAt>Date.now())return s.data;e.removeItem(ne(n))}}catch{}let t=re.get(n);if(t){if(t.expiresAt>Date.now())return t.data;re.delete(n)}return null}function ge(n){if(!n)return;re.delete(n);let e=ye();if(e)try{e.removeItem(ne(n))}catch{}}import{buildTelemetryErrorEvent as Me,buildTelemetryLogEvent as yt,buildTelemetryPerformanceEvent as ht,buildTelemetryTerminalEvent as gt,serializeTelemetryBatch as ft,TELEMETRY_MAX_BATCH_BYTES as Ct}from"@flopay/shared";var vt="/v1/sdk-telemetry/events",fe=16,Tt=64,_t=1500,Ee=1e3,wt=64,bt="00000000-0000-4000-8000-000000000000",St={technical_error:8,lifecycle:32,expected_outcome:32,performance:24};function U(){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 Pt(n){try{return new TextEncoder().encode(n).byteLength}catch{return n.length}}function Mt(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 b(){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.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(/\/+$/,"")}${vt}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=U(),this.merchantEnabled=e.enabled!==!1,this.clock=e.clock??b,this.browserTransportAvailable=typeof window<"u"&&typeof document<"u",this.browserTransportAvailable&&(window.addEventListener("pagehide",this.pageExitHandler),document.addEventListener("visibilitychange",this.visibilityHandler))}log(e){this.canCollect()&&this.enqueue(yt({...this.checkoutContext,...e,eventId:U(),sequence:this.sequence++}))}error(e){if(!this.canCollect())return;let t=Me({...this.checkoutContext,...e,eventId:bt,sequence:0}),r=Mt(t),s=this.now();this.pruneReportedFailures(s);let o=this.reportedFailures.get(r);if(o!==void 0&&s>=o&&s-o<Ee){this.log({name:"operation.deduplicated",stage:e.stage,provider:e.provider,paymentMethodCategory:e.paymentMethodCategory,attempt:e.attempt});return}this.rememberReportedFailure(r,s),this.enqueue(Me({...this.checkoutContext,...e,eventId:U(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue(ht({...this.checkoutContext,...e,eventId:U(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue(gt({...this.checkoutContext,...e,eventId:U(),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 b()}}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>=wt;){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>=Tt||this.eventCounts[e.class]>=St[e.class])){if(this.eventCounts[e.class]+=1,this.queue.push(e),this.queue.length>=fe){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,fe);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())}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,fe);this.sendBatch(e)}}async sendBatch(e){if(!this.browserTransportAvailable||this.ingestionDisabled)return;let t=ft(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:U()});if(Pt(t)>Ct)return;let r=typeof AbortController>"u"?null:new AbortController,s=null;try{let o=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 a=>a.status!==202?null:(await a.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(a=>{s=setTimeout(()=>{r?.abort(),a(null)},_t)});await Promise.race([o,i])==="disabled"&&this.disableFromIngestion()}catch{}finally{s&&clearTimeout(s)}}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)}},ke=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),Re=globalThis;Re[ke]===void 0&&Object.defineProperty(Re,ke,{configurable:!0,enumerable:!1,writable:!1,value:n=>new v(n)});function $(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 Et(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function G(n,e){let t=150*2**n,r=Math.round(t*(.75+Math.random()*.5));return new Promise((s,o)=>{let i,l=()=>e.removeEventListener("abort",a),a=()=>{i!==void 0&&clearTimeout(i),l(),o(Et())};if(e.aborted){a();return}i=setTimeout(()=>{l(),s()},r),e.addEventListener("abort",a,{once:!0})})}var Oe=1e3,xt=500,Ft=15e3,Ot=3e3,qt=1e4,Ut=1e4;function Le(n){return typeof n=="object"&&n!==null}function V(n,e){return I(n?.[e])}function qe(n,e){return Pe(n?.[e])}function Lt(n,e){let t=n?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Ne(n){return new Promise(e=>setTimeout(e,n))}function se(){return new m("Checkout is still processing. Please try again shortly.","api_error",{code:"checkout_processing_timeout"})}async function N(n,e){let t=await n.json().catch(()=>null),r=Le(t?.error)?t.error:null,s=qe(t,"message")??qe(r,"message")??e,o=V(t,"code")??V(t,"gatewayErrorCode")??V(r,"code")??`http_${n.status}`;return new m(s,"api_error",{code:o,statusCode:n.status})}async function Nt(n){if(n.status!==400&&n.status!==422)return;if(n.status===422)return"validation_rejected";let e=await n.clone().json().catch(()=>null);return Le(e)&&Array.isArray(e.fields)?"validation_rejected":"payment_declined"}function Ue(n){return n===400||n===422}var ie=2;async function Ce(n,e,t=ie,r){let s;for(let o=0;;o++)try{return await fetch(n,e)}catch(i){if(e?.signal?.aborted||i instanceof Error&&i.name==="AbortError")throw i;if(s=i,o>=t)throw s;try{r?.(o+1)}catch{}await Ne(150*2**o)}}var Ve=Symbol.for("@flopay/js.session-create.telemetry.v1");function Vt(n){return n[Ve]}function Bt(n){return"now"in n||"onFirstByte"in n||"onSessionCreateFailure"in n||"onRetry"in n}var D=class D{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let r=Bt(t);this.telemetryHooks=r?t:void 0,this.directTelemetry=r||t.telemetry===!1?void 0:new v({billingApiUrl:this.baseUrl,sdkVersion:oe})}destroy(){this.directTelemetry?.destroy()}reportDirectFailure(e,t,r,s,o="unknown"){let i=Y(e,t);this.directTelemetry?.error({...i,stage:r,requestCategory:s,paymentMethodCategory:o})}reportAccountSnapshotFailure(e,t){let r=Y(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()??b()}catch{return b()}}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 s={[Ae]:oe};t&&(s["x-checkout-session-token"]=t);try{let o=await Ce(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:s},ie,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 l=`${Math.floor(o.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:l}),!o.ok)throw await N(o,"Failed to get checkout session");let a=await o.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",statusClass:l}),{...a,data:this.mergeCachedDisplayData(a.data)}}catch(o){throw this.directTelemetry?.error({...Y(o,"NETWORK_REQUEST_FAILED"),stage:"session_read",requestCategory:"session_read"}),o}}cacheSessionDisplayData(e,t,r){q(e,t,r)}clearSessionDisplayData(e){ge(e)}async getVaultCapture(e,t){let r=`${this.baseUrl}\0${e}\0${t??""}`,s=D.activeVaultCaptureRequests.get(r);if(s)return s;let o=this.requestVaultCapture(e,t);D.activeVaultCaptureRequests.set(r,o);try{return await o}finally{D.activeVaultCaptureRequests.get(r)===o&&D.activeVaultCaptureRequests.delete(r)}}async requestVaultCapture(e,t){let r=new AbortController,s=setTimeout(()=>r.abort(),Ut);this.beginDirectTelemetryCheckout(e);let o=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 l=await Ce(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:r.signal},ie,c=>{this.telemetryHooks?.onRetry?.("vault_capture",c),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:c})});if(!l.ok)throw await N(l,"Failed to load the secure card form");let a=await l.json();return this.directTelemetry?.performance({stage:"vault_request",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"vault_capture",paymentMethodCategory:"card",statusClass:"2xx"}),this.toVaultBlock(a)}catch(l){let a=r.signal.aborted?new m("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):l;throw this.reportDirectFailure(a,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),a}finally{clearTimeout(s)}}async getUnifiedCheckoutSession(e,t){let r=await this.getCheckoutSession(e,t),s=this.normalizeRawSession(r.data),o=r.vault;return o&&s.data.session&&(s.data.session.vault=this.toVaultBlock(o)),s}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 m("processPayment requires `nonce` \u2014 pass the value returned from session creation.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.processing.started",stage:"processing",requestCategory:"process_payment"});let{nonce:o,...i}=t,l;try{l=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(t.sessionId)}/process`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":o},body:JSON.stringify(i)})}catch(a){throw this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}if(!l.ok&&l.status!==202){let a=await Nt(l);return a?this.directTelemetry?.terminal({outcome:a,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:L(l.status),failureCategory:l.status>=500?"server_error":void 0}),l}try{let a=await this.resolveProcessResponse(l,t.sessionId,{...r,nonce:o});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:L(a.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-s),durationMode:"machine",requestCategory:"process_payment",statusClass:L(a.status)}),a}catch(a){throw a instanceof m&&a.code==="checkout_processing_timeout"||this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}}async patchAccountSnapshot(e,t,r,s){this.beginDirectTelemetryCheckout(e);let o=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.state_transition",stage:"processing",requestCategory:"account_snapshot"});let i=s?.timeoutMs??qt,l=new AbortController,a=()=>l.abort();s?.signal&&(s.signal.aborted?l.abort():s.signal.addEventListener("abort",a,{once:!0}));let c=setTimeout(()=>l.abort(),i);try{let d;try{d=await Ce(`${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:l.signal},ie,y=>{this.telemetryHooks?.onRetry?.("account_snapshot",y),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:y})})}finally{clearTimeout(c),s?.signal?.removeEventListener("abort",a)}if(!d.ok)throw await N(d,"Failed to persist account snapshot");this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"account_snapshot",statusClass:"2xx"})}catch(d){throw this.reportAccountSnapshotFailure(d,s?.telemetryMode??"blocking"),d}}async createSessionIntent(e,t,r,s){if(!t)throw new m("createSessionIntent requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let o=r,i=o.paymentMethodType,l=typeof i=="string"&&i.trim().toLowerCase()==="card",a=typeof i=="string"&&i.length>0&&!l&&(typeof o.paymentMethodId=="string"||o.paymentMethodId===null),c=o.provider==="stripe"&&(o.paymentMethodCategory==="wallet"||o.paymentMethodCategory==="apm")&&(o.intentKind==="payment"||o.intentKind==="setup"),d=o.provider==="paypal"&&o.paymentMethodCategory==="wallet"&&o.paymentMethodType==="paypal"&&o.paymentMethodId===null&&o.intentKind==="payment";if(!a||!c&&!d)throw new m("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let y=o.authorizationAttemptId;if(y!==void 0&&!xe(y))throw new m("authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.","validation_error",{code:"InvalidAuthorizationAttemptId",param:"authorizationAttemptId"});let T=xe(y)?y:It();this.beginDirectTelemetryCheckout(e);let C=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.intent.started",stage:"processing",requestCategory:"intent_create"});let g={"Content-Type":"application/json","x-checkout-session-token":t,[Ie]:s?.idempotencyKey||T},M=!1;try{let S=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:g,body:JSON.stringify({...r,authorizationAttemptId:T}),signal:s?.signal});if(!S.ok){M=!0;let O=await N(S,"Failed to create checkout intent"),R=Y(O,"PAYMENT_PROCESSING_FAILED");throw Ue(O.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...R,stage:"processing",requestCategory:"intent_create"}),O}let _=(await S.json()).data;if(!_||typeof _!="object")throw new m("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let u=_,w=u.paymentMethodType,E=(u.paymentMethodCategory==="wallet"||u.paymentMethodCategory==="apm")&&typeof w=="string"&&w.trim().toLowerCase()!=="card"&&(typeof u.paymentMethodId=="string"||u.paymentMethodId===null)&&typeof u.providerObjectId=="string",k=u.provider==="stripe"&&(u.intentKind==="payment"||u.intentKind==="setup")&&typeof u.clientSecret=="string",H=u.provider==="paypal"&&u.paymentMethodCategory==="wallet"&&u.paymentMethodType==="paypal"&&u.paymentMethodId===null&&u.intentKind==="payment"&&(u.providerObjectType==="order"||u.providerObjectType==="subscription")&&u.clientSecret===null,pe=u.provider===r.provider&&u.paymentMethodCategory===r.paymentMethodCategory&&u.paymentMethodType===r.paymentMethodType&&u.paymentMethodId===r.paymentMethodId&&u.intentKind===r.intentKind;if(!E||!k&&!H||!pe)throw new m("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});return this.directTelemetry?.log({name:"payment.intent.completed",stage:"processing",requestCategory:"intent_create",statusClass:L(S.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-C),durationMode:"machine",requestCategory:"intent_create",statusClass:L(S.status)}),u}catch(S){throw M||this.reportDirectFailure(S,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),S}}async reportSessionIntentDecline(e,t,r,s){if(!t)throw new m("reportSessionIntentDecline requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let o=r,i=o.providerDeclineReason,l=o.paymentMethodType,a=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 l=="string"&&l.length>0&&l.trim().toLowerCase()!=="card"&&a,d=o.provider==="stripe"&&(o.paymentMethodCategory==="wallet"||o.paymentMethodCategory==="apm"),y=o.provider==="paypal"&&o.paymentMethodCategory==="wallet"&&o.paymentMethodType==="paypal";if(!c||!d&&!y)throw new m("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let T=y?{provider:"paypal",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:i}:{provider:"stripe",paymentMethodCategory:o.paymentMethodCategory,paymentMethodType:o.paymentMethodType,providerDeclineReason:i},C=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(T),signal:s?.signal});if(!C.ok)throw await N(C,"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 s=t?.page??1,o=t?.limit??1,i=new URLSearchParams({email:e,page:String(s),limit:String(o),sortField:"createdAt",sortDirection:"DESC"});try{let l=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!l.ok)throw new m("Failed to fetch payments","api_error",{statusCode:l.status});let a=await l.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"}),a}catch(l){throw this.reportDirectFailure(l,"RECOVERY_FAILED","recovery","other","saved"),l}}async createAndFetchSession(e){this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),r=$(e.timeoutMs??12e3),s={attempt:0,statusClass:"unknown"};this.directTelemetry?.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"});try{let o=await this.createAndFetchSessionRequest(e,t,r.signal,s);return this.adoptDirectTelemetryCheckout(o.data.session?.id),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:s.statusClass}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:s.statusClass,attempt:s.attempt}),o}catch(o){if(!(o instanceof m&&o.code==="session_auto_completed"))try{this.telemetryHooks?.onSessionCreateFailure?.(o)}catch{}let i=Y(o,"CHECKOUT_SESSION_CREATE_FAILED");throw this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:i.statusClass,attempt:s.attempt}),o instanceof m&&o.type==="validation_error"?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}):o instanceof m&&Ue(o.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"}):o instanceof m&&o.code==="session_auto_completed"||this.directTelemetry?.error({...i,stage:"session_create",requestCategory:"session_create"}),o}finally{r.clear()}}async createAndFetchSessionRequest(e,t,r,s){let o=e.products??De(e.items,e.subscriptions),i=Fe(e.currency,e.items,e.subscriptions,o);if(!i)throw new m("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 l={clientId:e.clientId,checkoutVersion:oe,successUrl:e.successUrl,cancelUrl:e.cancelUrl,currency:i,checkoutMode:e.checkoutMode??"full",products:o.map(p=>At(p,i)),accountData:{userId:e.account.userId,firstName:e.account.firstName??null,lastName:e.account.lastName??null,email:e.account.email,country:e.account.country??null,gender:e.account.gender??null,city:e.account.city??null,state:e.account.state??null,zip:e.account.zip??null,addressLine1:e.account.addressLine1??null,addressLine2:e.account.addressLine2??null},couponCodes:e.couponCodes??[]};e.tokenizedData&&(l.tokenizedData=e.tokenizedData),e.tagsData&&(l.tagsData=e.tagsData),e.utmMetadata?.length&&(l.utmMetadata=e.utmMetadata),e.avsCheck!==void 0&&(l.avsCheck=e.avsCheck),e.checkoutType&&(l.checkoutType=e.checkoutType),e.checkoutLayout&&(l.checkoutLayout=e.checkoutLayout),e.avsConfig&&(l.avsConfig=e.avsConfig);let a={"Content-Type":"application/json",[Ae]:oe},c=Dt(e.idempotencyKey);c&&(a[Ie]=c);let d,y=!1,T=Vt(e),C=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{T?.onAttempt?.(p)}catch{}try{d=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:a,body:JSON.stringify(l),signal:r})}catch(w){if(s.statusClass=r.aborted||w instanceof Error&&w.name==="AbortError"?"timeout":"network_error",r.aborted||w instanceof Error&&w.name==="AbortError"||p>=2)throw w;let E=p+1;C(E),await G(p,r);continue}let _=L(d.status);if(s.statusClass=_,y||(y=!0,this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:_,attempt:p}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-t),durationMode:"machine",requestCategory:"session_create",statusClass:_,attempt:p})),d.status===204)throw new m("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(d.ok)break;let u=await N(d,"Failed to create checkout session");if(u.code===Rt&&p<2){C(p+1),await G(p,r);continue}throw u}if(!d)throw new TypeError("Checkout-session creation exhausted its retry budget.");let g=await d.json();if(g.data&&"gateways"in g.data){this.autoCacheDisplayData(g.data.uuid,e);let p=this.mergeCachedDisplayData(g.data),_=this.normalizeRawSession(p);return g.vault&&_.data.session&&(_.data.session.vault=this.toVaultBlock(g.vault)),{..._,autoProcessingError:g.autoProcessingError,autoProcessingAttempted:g.autoProcessingAttempted,autoProcessingPending:g.autoProcessingPending}}let M=g.data?.uuid;if(!M)throw new m("No session ID returned","api_error",{code:"InvalidCheckoutSessionResponse"});return this.autoCacheDisplayData(M,e),this.adoptDirectTelemetryCheckout(M),{...await this.getUnifiedCheckoutSession(M),autoProcessingError:g.autoProcessingError,autoProcessingAttempted:g.autoProcessingAttempted,autoProcessingPending:g.autoProcessingPending}}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 s=t?.timeoutMs??Ft,o=Date.now()+s,i=this.clampRetryAfterMs(t?.initialDelayMs??Oe),l=0;try{for(;;){let a=o-Date.now();if(a<=0)throw se();if(i>0){try{l+=1,this.telemetryHooks?.onRetry?.("session_read",l),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:l})}catch{}if(await Ne(Math.min(i,a)),Date.now()>=o)throw se()}let c=await this.getUnifiedCheckoutSession(e,t?.nonce),d=c.data.session?.status;if(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()-r),durationMode:"machine",requestCategory:"session_read",paymentMethodCategory:"saved"}),c;if(Date.now()>=o)throw se();i=this.clampRetryAfterMs(Math.max(i*2,xt))}}catch(a){throw a instanceof m&&a.code==="checkout_processing_timeout"&&this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","session_read","saved"),a}}normalizeRawSession(e){let t=e.gateways??{},r=[],s={session:this.toCheckoutSession(e)},o=t.stripe;if(o?.publishableKey){r.push("stripe");let a=[e.stripeClientSecret,o.stripeClientSecret].find(c=>typeof c=="string"&&c.length>0);s.stripe={clientSecret:a??"",publishableKey:o.publishableKey??void 0,paypalPublishableKey:o.paypalPublishableKey??void 0,environment:o.environment,enabledPaymentMethods:Array.isArray(o.enabledPaymentMethods)?o.enabledPaymentMethods.filter(c=>typeof c=="string"):void 0}}let i=t.paypal;return i?.publishableKey&&(r.push("paypal"),s.paypal={publishableKey:i.publishableKey,environment:i.environment}),{providers:r,mode:"tokenize",data:s,raw:{data:e}}}toCheckoutSession(e){let t=e.products??[],r=typeof e.totalAmount=="number"&&Number.isFinite(e.totalAmount),s=t.reduce((c,d)=>c+(d.overrideAmount??d.totalAmount??0),0),o=r?e.totalAmount:s,i=Math.round(o*100),l=e.currency??t[0]?.currency??"USD",a=t.some(c=>c.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:a,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:l,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==="expired"?"expired":"open"}async resolveProcessResponse(e,t,r){if(e.status!==202)return e;let s=await e.json().catch(()=>null),o=this.toCheckoutProcessingPending(s,e,t),i=await this.waitForCheckoutSessionCompletion(o.sessionId,{initialDelayMs:o.retryAfterMs,timeoutMs:r?.pollTimeoutMs,nonce:r?.nonce});if(i.data.session?.status==="complete")return new Response(null,{status:204,statusText:"No Content"});throw i.data.session?.status==="expired"?new m("Checkout session has expired.","api_error",{code:"checkout_session_expired"}):se()}toCheckoutProcessingPending(e,t,r){let s=t.headers.get("Retry-After"),o=s===null||s.trim()===""?void 0:Number(s),i=o!==void 0&&Number.isFinite(o)?o*1e3:void 0;return{type:"checkout_processing",sessionId:V(e,"sessionId")??r,retryAfterMs:this.clampRetryAfterMs(Lt(e,"retryAfterMs")??i??Oe),statusUrl:V(e,"statusUrl"),sessionUrl:V(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,Ot))}autoCacheDisplayData(e,t){if(!e)return;let r=t.products??De(t.items,t.subscriptions);if(r.length===0&&!t.currency)return;let s=t.products!==void 0,o=Fe(t.currency,s?void 0:t.items,s?void 0:t.subscriptions,r);q(e,{currency:o??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??o??void 0}))})}mergeCachedDisplayData(e){let t=he(e.uuid),r=new Map,s=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let l=s(i.code);l&&r.set(l,i)}let o=(e.products??[]).map(i=>{let l=s(i.code),a=l?r.get(l):void 0;return{...i,name:i.name??a?.name??null,totalAmount:i.totalAmount??a?.totalAmount,overrideAmount:i.overrideAmount??a?.overrideAmount,currency:i.currency??a?.currency}});return{...e,currency:e.currency??t?.currency,products:o}}};D.activeVaultCaptureRequests=new Map;var F=D;function Be(n,e){let t=F;return new t(n,e)}function je(n){return{payment:"payment",address:"address"}[n]}function ae(n){switch(n){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function zt(n){return{...n,theme:ae(n.theme)}}function ve(n){return n?JSON.stringify(n.map(e=>e.trim().toLowerCase())):null}function Ke(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 Ht(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 W=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 jt(e.publishableKey,{locale:e.locale??"auto"});if(!t)throw new h("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=t}getElements(e){if(!this.stripe)throw new h("StripeAdapter not initialized. Call initialize() first.","api_error");let t=e?.appearance?{theme:ae(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}:void 0,r=t?JSON.stringify(t):null,s=ve(e?.paymentMethodTypes),o=e?.clientSecret??null;if(this.elements&&s&&(s!==this.appliedPaymentMethodTypesKey||o!==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,l=e?.amount??0,a=(e?.currency??"usd").toLowerCase(),c=e?.paymentMethodCreation??"manual";e?.clientSecret?i={clientSecret:e.clientSecret}:l>0?(i={mode:"payment",amount:l,currency:a,paymentMethodCreation:c},e?.setupFutureUsage&&(i.setupFutureUsage=e.setupFutureUsage)):i={mode:"setup",currency:a,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=s,this.appliedClientSecret=o,this.verifiedClientSecret=null,this.verifiedPaymentMethodTypesKey=null}return this.elements}async assertClientSecretPaymentMethods(e,t){if(!this.stripe)throw new h("StripeAdapter not initialized. Call initialize() first.","api_error");let r,s=!1;if(Kt(e)){let{setupIntent:a,error:c}=await this.stripe.retrieveSetupIntent(e);r=a,s=!!c}else{let{paymentIntent:a,error:c}=await this.stripe.retrievePaymentIntent(e);r=a,s=!!c}let o=r?.payment_method_types;if(s||!Array.isArray(o))throw new h("Unable to verify the payment methods configured for this client secret.","api_error",{param:"clientSecret"});let i=new Set(t.map(a=>a.toLowerCase()));if(o.some(a=>typeof a!="string"||!i.has(a.trim().toLowerCase()))||o.length===0)throw new h("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 a=t.paymentMethodTypes?.map(c=>c.trim()).filter(c=>c&&c.toLowerCase()!=="card");if(!a?.length)throw new h("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});if(r={...t,paymentMethodTypes:a},r.clientSecret){let c=ve(a);this.elements&&this.appliedClientSecret===r.clientSecret&&this.appliedPaymentMethodTypesKey===c&&this.verifiedClientSecret===r.clientSecret&&this.verifiedPaymentMethodTypesKey===c||await this.assertClientSecretPaymentMethods(r.clientSecret,a)}}let s=this.getElements(r);e==="payment"&&r.clientSecret&&(this.verifiedClientSecret=r.clientSecret,this.verifiedPaymentMethodTypesKey=ve(r.paymentMethodTypes));let o=je(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 l=s.create(o,i);return Ke(l)}getElement(e){if(!this.elements)return null;let t=je(e),r=this.elements.getElement(t);return r?Ke(r):null}async submitElements(){if(!this.stripe||!this.elements)return{error:new h("Stripe not initialized","api_error")};let{error:e}=await this.elements.submit();return e?{error:new h(e.message??"Validation failed","validation_error")}:{}}async confirmPayment(e){if(!this.stripe||!this.elements)throw new h("StripeAdapter not initialized or no elements created.","api_error");let t=e.billingDetails,r=t?Ht(t):void 0,{error:s,paymentIntent:o}=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 s?{status:"failed",error:new h(s.message??"Payment failed","api_error",{code:s.code,declineCode:s.decline_code})}:o?{status:{succeeded:"succeeded",processing:"processing",requires_action:"requires_action",requires_payment_method:"failed",canceled:"failed"}[o.status]??"failed",paymentIntentId:o.id,paymentMethodId:this.extractPaymentMethodId(o.payment_method)}:{status:"failed",error:new h("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 h("Stripe not initialized","api_error")};let t=e.billingApiUrl.replace(/\/+$/,"");if(this.elements){let{error:o}=await this.elements.submit();if(o)return{status:"failed",error:new h(o.message??"PayPal payment failed","validation_error",{code:o.code})}}let r;try{let o=await new F(t).createSessionIntent(e.sessionId,e.nonce??"",{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",paymentMethodId:null,intentKind:"payment"});if(o.provider!=="stripe")throw new h("Invalid provider returned for PayPal intent","api_error");r=o.clientSecret}catch(o){return{status:"failed",error:o instanceof h?o:new h("Failed to create PayPal payment intent","api_error")}}let{error:s}=await this.stripe.confirmPayment({clientSecret:r,elements:this.elements??void 0,confirmParams:{return_url:e.returnUrl}});if(s){if(e.nonce)try{await new F(t).reportSessionIntentDecline(e.sessionId,e.nonce,{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:s.code??"provider_declined"})}catch{}return{status:"failed",error:new h(s.message??"PayPal payment failed","api_error",{code:s.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"),s=e.get("redirect_status");if(!t||!r)return null;if(s==="failed")return{status:"failed",error:new h("PayPal payment was declined. Please try again.","api_error")};let{paymentIntent:o,error:i}=await this.stripe.retrievePaymentIntent(r);if(i)return{status:"failed",error:new h(i.message??"Failed to retrieve PayPal payment","api_error")};if(o&&(o.status==="requires_capture"||o.status==="succeeded")){let l=typeof o.payment_method=="string"?o.payment_method:o.payment_method?.id,a=new URL(window.location.href);return a.searchParams.delete("payment_intent"),a.searchParams.delete("payment_intent_client_secret"),a.searchParams.delete("redirect_status"),window.history.replaceState({},"",a.toString()),{status:o.status,paymentIntentId:o.id,paymentMethodId:l}}return{status:"failed",error:new h("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:ae(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}};import{FloPayError as P,classifyTelemetryFailure as _e,resolveBillingApiUrl as et,SDK_VERSION as Zt}from"@flopay/shared";import{FloPayError as $t}from"@flopay/shared";var J=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 l=r.paymentMethodTypes?.map(a=>a.trim()).filter(a=>a&&a.toLowerCase()!=="card");if(!l?.length)throw new $t("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});r.paymentMethodTypes=l}let s=this.provider.getElement(e);if(s)return this.elementMap.set(e,s),s;let o=this.elementMap.get(e);o&&o.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()}};import{buildTelemetryErrorEvent as Gt,buildTelemetryLogEvent as Yt,buildTelemetryTerminalEvent as Ge,FloPayError as ze,resolveBillingApiUrl as He,SDK_VERSION as $e}from"@flopay/shared";var Te="flopay-vault",Ye={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 Q(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 le(n,e){return Yt({eventId:"11111111-1111-4111-8111-111111111111",name:n,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function We(n){return n?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function Wt(n,e){if(n==="complete"||n==="decline")return Ge({eventId:"22222222-2222-4222-8222-222222222222",outcome:n==="complete"?"payment_succeeded":"payment_declined",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(n==="error"){let s=We(e);return Gt({eventId:"33333333-3333-4333-8333-333333333333",...s,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[t,r]=Ye[n];return le(t,r)}function Jt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===Te&&(e.type==="ready"||e.type==="submitting"||e.type==="blocked"||e.type==="complete"||e.type==="decline"||e.type==="error"||e.type==="action_required")}function Qt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===Te&&e.type==="validation"&&Array.isArray(e.messages)}function Xt(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===Te&&e.type==="resize"&&typeof e.height=="number"&&Number.isFinite(e.height)}var B=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:He(),sdkVersion:$e}):void 0)}async mount(e,t){if(this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new v({billingApiUrl:He(),sdkVersion:$e})),this.mountStartedAt=this.telemetryReporter?.now?.()??b(),this.vaultReadyReported=!1,this.submissionStarted=!1,this.submissionStartedAt=null,typeof window>"u"||typeof document>"u")throw this.reportVaultLoadFailure(),new ze("The vault card form is only available in the browser.","api_error",{code:"card_capture_no_window"});if(!t?.html||!t.html.trim())throw this.reportVaultLoadFailure(),new ze("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(r){throw this.reportVaultLoadFailure(),r}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),Q(le("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 s of r){let o=document.createElement("script");for(let i of Array.from(s.attributes))o.setAttribute(i.name,i.value);o.text=s.text,s.replaceWith(o)}}attachMessageListener(){if(this.messageHandler)return;let e=t=>{if(this.expectedOrigin&&t.origin!==this.expectedOrigin)return;let r=t.data;if(Xt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;this.applyHeight(r.height);return}if(Qt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;let l=r.messages.filter(a=>typeof a=="string"&&a.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:l||void 0});return}if(!Jt(r)||this.messageToken&&r.messageToken!==this.messageToken)return;let s=this.config.sessionId,o=typeof r.sessionId=="string"?r.sessionId:void 0;if(s&&o&&o!==s||(r.type==="complete"||r.type==="decline")&&s&&o!==s)return;let i={sessionId:r.sessionId??this.config.sessionId,intentId:r.intentId,declineReason:r.declineReason,message:r.message,nextActionRedirectUrl:r.nextActionRedirectUrl};r.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??b()),Q(Wt(r.type,this.submissionStarted)),this.reportOutcome(r.type),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(),this.emit(r.type,i)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;if(e==="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"})),e==="complete"||e==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:e==="complete"?"payment_succeeded":"payment_declined",provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="error"){let o=We(this.submissionStarted);t.log({name:"vault.terminal",stage:o.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...o,provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="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 o=this.submissionStartedAt;this.submissionStartedAt=null,o!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-o),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[r,s]=Ye[e];t.log({name:r,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 s=document.createElement("button");s.type="button",s.setAttribute("aria-label","Close card authentication"),s.textContent="\xD7",s.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(";"),s.addEventListener("click",()=>this.abandonActionRequiredOverlay()),t.appendChild(s),t.addEventListener("click",i=>{i.target===t&&this.abandonActionRequiredOverlay()});let o=i=>{if(i.source!==r.contentWindow)return;let l=i.data;if(!l||typeof l!="object")return;let a=l;a.source==="flopay-vault-3ds-return"&&(Q(le("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(a.status))};window.addEventListener("message",o),this.threeDsReturnHandler=o,document.body.appendChild(t),this.actionOverlay=t,Q(le("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=Ge({eventId:"77777777-7777-4777-8777-777777777777",outcome:"customer_abandoned",stage:"three_ds_handoff",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});Q(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 Je(n,e){let t=B;return new t(n,{reporter:e})}var Qe=Symbol.for("@flopay/js.telemetry.bridge.v1");function Xe(n,e,t){let r=()=>e?.now()??t();Object.defineProperty(n,Qe,{configurable:!1,enumerable:!1,writable:!1,value:{error:o=>e?.error(o),log:o=>e?.log(o),performance:o=>e?.performance(o),terminal:o=>e?.terminal(o),now:r,elapsed:o=>Math.max(0,r()-o),setCheckoutContext:o=>e?.setCheckoutContext(o),beginCheckout:(o={})=>e?.beginCheckout(o)??r(),disable:()=>e?.disable()}})}function Ze(n){return n[Qe]}function j(n){if(!n)return!1;let e=n.code?.toLowerCase()??"";return!!n.declineCode||e.includes("declin")}function er(n){return n==="stripe"||n==="paypal"||n==="pcivault"?n:"other"}var ce=class{constructor(e,t,r){this.currentElements=null;this.provider=e,this.config=t,this.telemetryReporter=r??new v({billingApiUrl:et(t.billingApiUrl),sdkVersion:Zt,enabled:t.telemetry!==!1}),Xe(this,this.telemetryReporter,b)}now(){return this.telemetryReporter?.now?.()??b()}elements(e){return this.currentElements&&this.currentElements.destroy(),this.currentElements=new J(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?Je({sessionId:e?.sessionId},this.telemetryReporter):new B({sessionId:e?.sessionId,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:"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"&&(j(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 P&&j(r))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(r instanceof P&&r.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let s=_e(r,"PAYMENT_PROCESSING_FAILED","unknown");this.telemetryReporter?.error({...s,failureCategory:s.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"}):j(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 P&&j(t))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(t instanceof P&&t.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let r=_e(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 P("A supported non-card payment method is required.","validation_error",{param:"paymentMethodType"});let t=this.now(),r=er(this.provider.name);this.telemetryReporter?.log({name:"payment.processing.started",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory});try{let s=await this.provider.confirmPayment(e),o=this.now()-t;return this.telemetryReporter?.performance({stage:"processing",durationMs:o,durationMode:"machine",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s.status==="succeeded"?this.telemetryReporter?.terminal({outcome:"payment_succeeded",provider:r,paymentMethodCategory:e.paymentMethodCategory}):j(s.error)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s.error?.type==="validation_error"?this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s.status==="requires_action"?this.telemetryReporter?.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s.status==="failed"&&s.error&&this.telemetryReporter?.error({errorCode:"PAYMENT_PROCESSING_FAILED",failureCategory:"provider_runtime",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s.status==="succeeded"||s.status==="failed"?this.telemetryReporter?.log({name:"payment.processing.completed",stage:"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}):this.telemetryReporter?.log({name:"operation.state_transition",stage:s.status==="requires_action"?"three_ds_handoff":"processing",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s}catch(s){throw this.telemetryReporter?.performance({stage:"processing",durationMs:this.now()-t,durationMode:"machine",provider:r,paymentMethodCategory:e.paymentMethodCategory}),s instanceof P&&j(s)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):s instanceof P&&s.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}),s}}async retrieveSession(e,t){if(!e)throw new P("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let r=await this.retrieveUnifiedSession(e,t);if(!r.data.session)throw new P("Session not found","api_error");return r.data.session}async retrieveUnifiedSession(e,t){if(!e)throw new P("sessionId is required.","validation_error",{param:"sessionId"});let r=et(t??this.config.billingApiUrl),s=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let o,i=Be(r,{now:()=>this.telemetryReporter?.now()??b(),onFirstByte:l=>{o=l},onRetry:(l,a)=>{this.telemetryReporter?.log({name:"operation.retry",stage:l==="session_read"?"session_read":"processing",requestCategory:l,attempt:a})}});try{let l=await i.getUnifiedCheckoutSession(e);return o!==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:o,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()-s,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),l}catch(l){let a=_e(l,l instanceof P&&l.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...a,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-s,durationMode:"machine",requestCategory:"session_read",statusClass:a.statusClass}),l}}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 tt(n,e,t){let r=ce;return new r(n,e,t)}var nt=new Map;function be(n){return Array.isArray(n)?n.map(be):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,be(t)])):n}function rr(n,e){return JSON.stringify([n,we(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,be(e?.appearance??null)])}var de=new Map;async function nr(n,e){if(!n){let l=new v({billingApiUrl:we(e?.billingApiUrl),sdkVersion:rt,enabled:e?.telemetry!==!1});throw l.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),l.flush().catch(()=>{}).finally(()=>l.destroy()),new tr("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let t=rr(n,e),r=nt.get(t);if(r)return e?.telemetry!==!1&&Ze(r)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),r;let s=de.get(t);if(s)return s;let o={...e,publishableKey:n},i=(async()=>{let l=new v({billingApiUrl:we(o.billingApiUrl),sdkVersion:rt,enabled:o.telemetry!==!1}),a=l.now();l.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),l.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),l.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new W,d=l.now();try{await c.initialize(o)}catch(C){throw l.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),l.destroy(),C}let y=l.now();l.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),l.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),l.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),l.performance({stage:"sdk_initialize",durationMs:y-a,durationMode:"machine",provider:"stripe"}),l.performance({stage:"provider_ready",durationMs:y-d,durationMode:"machine",provider:"stripe"});let T=tt(c,o,l);return nt.set(t,T),T})();de.set(t,i);try{return await i}finally{de.get(t)===i&&de.delete(t)}}import{FloPayError as z,IDEMPOTENCY_IN_PROGRESS_CODE as or,IDEMPOTENCY_KEY_HEADER as sr,SDK_VERSION as ot,buildProductPayload as ir,classifyTelemetryFailure as ar,foldIntoProducts as lr,resolveIdempotencyKey as st,resolveSessionCurrency as cr,telemetryStatusClass as it}from"@flopay/shared";var Se=5,at=new WeakSet;function dr(n){(typeof n=="object"&&n!==null||typeof n=="function")&&at.add(n)}function ur(n){return(typeof n=="object"&&n!==null||typeof n=="function")&&at.has(n)}function pr(n,e){let t=e?.error,r=I(e?.code)??I(t?.code)??`http_${n}`,s=I(e?.message)??I(t?.message)??mr(r,n);return new z(s,"api_error",{code:r,statusCode:n})}function mr(n,e){switch(n){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${Se}.`;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 lt(n,e,t){let{billingApiUrl:r,checkoutBaseUrl:s,items:o=[],subscriptions:i=[],products:l,account:a,successUrl:c,cancelUrl:d,checkoutMode:y="confirm",couponCodes:T=[],tagsData:C,redirectParams:g={},setCookie:M=!0,clientId:S,currency:p,utmMetadata:_,idempotencyKey:u}=n,w=st(u);if(T.length>Se)throw new z(`Too many coupon codes \u2014 a checkout session accepts at most ${Se}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let E=l??lr(o,i),k=cr(p,o,i,E);if(!k)throw new z("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 H={clientId:S,checkoutVersion:ot,successUrl:c,cancelUrl:d,currency:k,checkoutMode:y,products:E.map(A=>ir(A,k)),accountData:{userId:a.userId,firstName:a.firstName??null,lastName:a.lastName??null,email:a.email,country:a.country??null,gender:a.gender??null,city:a.city??null,state:a.state??null,zip:a.zip??null,addressLine1:a.addressLine1??null,addressLine2:a.addressLine2??null},couponCodes:T};C&&(H.tagsData=C),_?.length&&(H.utmMetadata=_);let pe=`${r.replace(/\/+$/,"")}/v1/checkouts/sessions`,O={"Content-Type":"application/json"};w&&(O[sr]=w);let R,X,pt={method:"POST",headers:O,body:JSON.stringify(H),signal:e},Z;try{Z=await fetch(pe,pt)}catch(A){throw dr(A),A}try{t?.(Z.status)}catch{}R=Z.status;try{X=await Z.json()}catch{}if(R>=400)throw pr(R,X);if(R===201){let A=X?.data?.uuid,me=X?.data?.nonce;if(!A)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!me)throw new z("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"});(E.length||k)&&q(A,{currency:k,products:E.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??k}))});let ee=new URL(`${s.replace(/\/+$/,"")}/secure`);ee.searchParams.set("id",A);for(let[f,te]of Object.entries(g))ee.searchParams.set(f,te);if(M&&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(me)}; domain=.${te}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=ee.toString()),{status:201,redirectUrl:ee.toString(),nonce:me}}return R===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:R}}async function yr(n){let e=dt(n),t=ct(e),r=$(n.timeoutMs);try{let s=await lt(n,r.signal,t);return ut(e,s),s}catch(s){throw ue(e,s),s}finally{r.clear(),K(e.reporter)}}function ct(n){let e=!1;return t=>{if(e)return;e=!0;let r=it(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 dt(n){let e=new v({billingApiUrl:n.billingApiUrl,sdkVersion:ot,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 ut(n,e){let t=it(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 ue(n,e){let{reporter:t}=n,r=ar(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 z&&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 K(n){n.flush().catch(()=>{}).finally(()=>n.destroy())}async function hr(n){let{maxRetries:e=2,...t}=n,r=dt(n),s=ct(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"}),K(r.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let o={...t,idempotencyKey:st(t.idempotencyKey)},i=$(t.timeoutMs),l;for(let a=0;a<=e;a++){r.attempt=a;try{let c=await lt(o,i.signal,s);return ut(r,c),i.clear(),K(r.reporter),c}catch(c){l=c;let d=c instanceof Error&&c.name==="AbortError",y=ur(c),T=c instanceof z&&c.code===or;if((d||y||T)&&!i.signal.aborted&&a<e){r.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:a+1});try{await G(a,i.signal)}catch(C){throw ue(r,C),i.clear(),K(r.reporter),C}continue}throw ue(r,c),i.clear(),K(r.reporter),c}}throw ue(r,l),i.clear(),K(r.reporter),l??new Error("Unknown error during checkout session creation")}export{ce as FloPay,J as FloPayElements,F as PaymentAPI,B as PciVaultCardCapture,Ve as SESSION_CREATE_TELEMETRY,W as StripeAdapter,q as cacheSessionDisplayData,ge as clearSessionDisplayData,yr as createCheckoutSession,hr as createCheckoutSessionWithRetries,he as getSessionDisplayData,nr as loadFloPay,zt as toStripeAppearance,ae as toStripeAppearanceTheme};
|
|
1
|
+
import{FloPayError as ir,resolveBillingApiUrl as ke,SDK_VERSION as it}from"@flopay/shared";import{loadStripe as Gt}from"@stripe/stripe-js";import{FloPayError as g,isSetupIntentClientSecret as Yt}from"@flopay/shared";import{FloPayError as h,SDK_VERSION as V,FLO_SDK_VERSION_HEADER as Ce,IDEMPOTENCY_KEY_HEADER as Fe,IDEMPOTENCY_IN_PROGRESS_CODE as Dt,buildProductPayload as Ne,classifyTelemetryFailure as Y,foldIntoProducts as ve,isDetachedSessionEligible as xt,isUuidV4 as Oe,randomUuidV4 as Ft,resolveIdempotencyKey as Ot,resolveSessionCurrency as Te,telemetryStatusClass as A}from"@flopay/shared";function E(n){return typeof n=="string"&&n.trim()?n:void 0}function Re(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}var ft="flopay_session_display:";var re=new Map;function ne(n){return`${ft}${n}`}function me(){if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}}function U(n,e,t){if(!n)return;let r=t?.ttlMs??36e5,o={data:e,expiresAt:Date.now()+r},s=me();if(s)try{s.setItem(ne(n),JSON.stringify(o));return}catch{}re.set(n,o)}function ye(n){if(!n)return null;let e=me();if(e)try{let r=e.getItem(ne(n));if(r){let o=JSON.parse(r);if(o&&typeof o.expiresAt=="number"&&o.expiresAt>Date.now())return o.data;e.removeItem(ne(n))}}catch{}let t=re.get(n);if(t){if(t.expiresAt>Date.now())return t.data;re.delete(n)}return null}function he(n){if(!n)return;re.delete(n);let e=me();if(e)try{e.removeItem(ne(n))}catch{}}import{buildTelemetryErrorEvent as Ae,buildTelemetryLogEvent as Ct,buildTelemetryPerformanceEvent as vt,buildTelemetryTerminalEvent as Tt,serializeTelemetryBatch as _t,TELEMETRY_MAX_BATCH_BYTES as wt}from"@flopay/shared";var St="/v1/sdk-telemetry/events",ge=16,bt=64,kt=1500,Ie=1e3,Pt=64,Mt="00000000-0000-4000-8000-000000000000",Et={technical_error:8,lifecycle:32,expected_outcome:32,performance:24};function L(){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 Rt(n){try{return new TextEncoder().encode(n).byteLength}catch{return n.length}}function At(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 _(){return globalThis.performance?.now()??0}var C=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.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(/\/+$/,"")}${St}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=L(),this.merchantEnabled=e.enabled!==!1,this.clock=e.clock??_,this.browserTransportAvailable=typeof window<"u"&&typeof document<"u",this.browserTransportAvailable&&(window.addEventListener("pagehide",this.pageExitHandler),document.addEventListener("visibilitychange",this.visibilityHandler))}log(e){this.canCollect()&&this.enqueue(Ct({...this.checkoutContext,...e,eventId:L(),sequence:this.sequence++}))}error(e){if(!this.canCollect())return;let t=Ae({...this.checkoutContext,...e,eventId:Mt,sequence:0}),r=At(t),o=this.now();this.pruneReportedFailures(o);let s=this.reportedFailures.get(r);if(s!==void 0&&o>=s&&o-s<Ie){this.log({name:"operation.deduplicated",stage:e.stage,provider:e.provider,paymentMethodCategory:e.paymentMethodCategory,attempt:e.attempt});return}this.rememberReportedFailure(r,o),this.enqueue(Ae({...this.checkoutContext,...e,eventId:L(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue(vt({...this.checkoutContext,...e,eventId:L(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue(Tt({...this.checkoutContext,...e,eventId:L(),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 _()}}pruneReportedFailures(e){for(let[t,r]of this.reportedFailures)(e<r||e-r>=Ie)&&this.reportedFailures.delete(t)}rememberReportedFailure(e,t){for(;this.reportedFailures.size>=Pt;){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>=bt||this.eventCounts[e.class]>=Et[e.class])){if(this.eventCounts[e.class]+=1,this.queue.push(e),this.queue.length>=ge){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,ge);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())}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,ge);this.sendBatch(e)}}async sendBatch(e){if(!this.browserTransportAvailable||this.ingestionDisabled)return;let t=_t(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:L()});if(Rt(t)>wt)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 a=>a.status!==202?null:(await a.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(a=>{o=setTimeout(()=>{r?.abort(),a(null)},kt)});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)}},De=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),xe=globalThis;xe[De]===void 0&&Object.defineProperty(xe,De,{configurable:!0,enumerable:!1,writable:!1,value:n=>new C(n)});function R(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 It(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function N(n,e){let t=150*2**n,r=Math.round(t*(.75+Math.random()*.5));return new Promise((o,s)=>{let i,l=()=>e.removeEventListener("abort",a),a=()=>{i!==void 0&&clearTimeout(i),l(),s(It())};if(e.aborted){a();return}i=setTimeout(()=>{l(),o()},r),e.addEventListener("abort",a,{once:!0})})}var qe=1e3,qt=500,Ut=15e3,Lt=3e3,Nt=1e4,Vt=1e4;function Ve(n){return typeof n=="object"&&n!==null}function B(n,e){return E(n?.[e])}function Ue(n,e){return Re(n?.[e])}function Bt(n,e){let t=n?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Be(n){return new Promise(e=>setTimeout(e,n))}function se(){return new h("Checkout is still processing. Please try again shortly.","api_error",{code:"checkout_processing_timeout"})}async function I(n,e){let t=await n.json().catch(()=>null),r=Ve(t?.error)?t.error:null,o=Ue(t,"message")??Ue(r,"message")??e,s=B(t,"code")??B(t,"gatewayErrorCode")??B(r,"code")??`http_${n.status}`;return new h(o,"api_error",{code:s,statusCode:n.status})}async function jt(n){if(n.status!==400&&n.status!==422)return;if(n.status===422)return"validation_rejected";let e=await n.clone().json().catch(()=>null);return Ve(e)&&Array.isArray(e.fields)?"validation_rejected":"payment_declined"}function Le(n){return n===400||n===422}var oe=2;async function _e(n,e,t=oe,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 Be(150*2**s)}}var je=Symbol.for("@flopay/js.session-create.telemetry.v1");function Kt(n){return n[je]}function zt(n){return"now"in n||"onFirstByte"in n||"onSessionCreateFailure"in n||"onRetry"in n}function Ke(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 ze(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 Ht(n,e){let t={clientId:n.clientId,checkoutVersion:V,successUrl:n.successUrl,cancelUrl:n.cancelUrl,currency:e,checkoutMode:"full",deferDataAttachment:!0};return n.account.country&&(t.accountData={country:n.account.country}),ze(t,n),t}function $t(n,e,t){return{currency:e,products:t.map(r=>Ne(r,e)),couponCodes:n.couponCodes??[],accountData:Ke(n.account)}}var D=class D{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let r=zt(t);this.telemetryHooks=r?t:void 0,this.directTelemetry=r||t.telemetry===!1?void 0:new C({billingApiUrl:this.baseUrl,sdkVersion:V})}destroy(){this.directTelemetry?.destroy()}reportDirectFailure(e,t,r,o,s="unknown"){let i=Y(e,t);this.directTelemetry?.error({...i,stage:r,requestCategory:o,paymentMethodCategory:s})}reportAccountSnapshotFailure(e,t){let r=Y(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()??_()}catch{return _()}}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={[Ce]:V};t&&(o["x-checkout-session-token"]=t);try{let s=await _e(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:o},oe,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 l=`${Math.floor(s.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:l}),!s.ok)throw await I(s,"Failed to get checkout session");let a=await s.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:l}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",statusClass:l}),{...a,data:this.mergeCachedDisplayData(a.data)}}catch(s){throw this.directTelemetry?.error({...Y(s,"NETWORK_REQUEST_FAILED"),stage:"session_read",requestCategory:"session_read"}),s}}cacheSessionDisplayData(e,t,r){U(e,t,r)}clearSessionDisplayData(e){he(e)}async getVaultCapture(e,t){let r=`${this.baseUrl}\0${e}\0${t??""}`,o=D.activeVaultCaptureRequests.get(r);if(o)return o;let s=this.requestVaultCapture(e,t);D.activeVaultCaptureRequests.set(r,s);try{return await s}finally{D.activeVaultCaptureRequests.get(r)===s&&D.activeVaultCaptureRequests.delete(r)}}async requestVaultCapture(e,t){let r=new AbortController,o=setTimeout(()=>r.abort(),Vt);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 l=await _e(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:r.signal},oe,c=>{this.telemetryHooks?.onRetry?.("vault_capture",c),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:c})});if(!l.ok)throw await I(l,"Failed to load the secure card form");let a=await l.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(a)}catch(l){let a=r.signal.aborted?new h("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):l;throw this.reportDirectFailure(a,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),a}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 h("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,l;try{l=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(a){throw this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}if(!l.ok&&l.status!==202){let a=await jt(l);return a?this.directTelemetry?.terminal({outcome:a,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:A(l.status),failureCategory:l.status>=500?"server_error":void 0}),l}try{let a=await this.resolveProcessResponse(l,t.sessionId,{...r,nonce:s});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:A(a.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"process_payment",statusClass:A(a.status)}),a}catch(a){throw a instanceof h&&a.code==="checkout_processing_timeout"||this.reportDirectFailure(a,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),a}}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??Nt,l=new AbortController,a=()=>l.abort();o?.signal&&(o.signal.aborted?l.abort():o.signal.addEventListener("abort",a,{once:!0}));let c=setTimeout(()=>l.abort(),i);try{let d;try{d=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:l.signal},oe,p=>{this.telemetryHooks?.onRetry?.("account_snapshot",p),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:p})})}finally{clearTimeout(c),o?.signal?.removeEventListener("abort",a)}if(!d.ok)throw await I(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,o?.telemetryMode??"blocking"),d}}async createSessionIntent(e,t,r,o){if(!t)throw new h("createSessionIntent requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=r,i=s.paymentMethodType,l=typeof i=="string"&&i.trim().toLowerCase()==="card",a=typeof i=="string"&&i.length>0&&!l&&(typeof s.paymentMethodId=="string"||s.paymentMethodId===null),c=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm")&&(s.intentKind==="payment"||s.intentKind==="setup"),d=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodType==="paypal"&&s.paymentMethodId===null&&s.intentKind==="payment";if(!a||!c&&!d)throw new h("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let p=s.authorizationAttemptId;if(p!==void 0&&!Oe(p))throw new h("authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.","validation_error",{code:"InvalidAuthorizationAttemptId",param:"authorizationAttemptId"});let u=Oe(p)?p:Ft();this.beginDirectTelemetryCheckout(e);let m=this.telemetryTimestamp();this.directTelemetry?.log({name:"payment.intent.started",stage:"processing",requestCategory:"intent_create"});let S={"Content-Type":"application/json","x-checkout-session-token":t,[Fe]:o?.idempotencyKey||u},v=!1;try{let T=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:S,body:JSON.stringify({...r,authorizationAttemptId:u}),signal:o?.signal});if(!T.ok){v=!0;let q=await I(T,"Failed to create checkout intent"),P=Y(q,"PAYMENT_PROCESSING_FAILED");throw Le(q.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...P,stage:"processing",requestCategory:"intent_create"}),q}let F=(await T.json()).data;if(!F||typeof F!="object")throw new h("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let y=F,$=y.paymentMethodType,O=(y.paymentMethodCategory==="wallet"||y.paymentMethodCategory==="apm")&&typeof $=="string"&&$.trim().toLowerCase()!=="card"&&(typeof y.paymentMethodId=="string"||y.paymentMethodId===null)&&typeof y.providerObjectId=="string",k=y.provider==="stripe"&&(y.intentKind==="payment"||y.intentKind==="setup")&&typeof y.clientSecret=="string",G=y.provider==="paypal"&&y.paymentMethodCategory==="wallet"&&y.paymentMethodType==="paypal"&&y.paymentMethodId===null&&y.intentKind==="payment"&&(y.providerObjectType==="order"||y.providerObjectType==="subscription")&&y.clientSecret===null,ue=y.provider===r.provider&&y.paymentMethodCategory===r.paymentMethodCategory&&y.paymentMethodType===r.paymentMethodType&&y.paymentMethodId===r.paymentMethodId&&y.intentKind===r.intentKind;if(!O||!k&&!G||!ue)throw new h("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});return this.directTelemetry?.log({name:"payment.intent.completed",stage:"processing",requestCategory:"intent_create",statusClass:A(T.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-m),durationMode:"machine",requestCategory:"intent_create",statusClass:A(T.status)}),y}catch(T){throw v||this.reportDirectFailure(T,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),T}}async reportSessionIntentDecline(e,t,r,o){if(!t)throw new h("reportSessionIntentDecline requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let s=r,i=s.providerDeclineReason,l=s.paymentMethodType,a=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 l=="string"&&l.length>0&&l.trim().toLowerCase()!=="card"&&a,d=s.provider==="stripe"&&(s.paymentMethodCategory==="wallet"||s.paymentMethodCategory==="apm"),p=s.provider==="paypal"&&s.paymentMethodCategory==="wallet"&&s.paymentMethodType==="paypal";if(!c||!d&&!p)throw new h("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let u=p?{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(u),signal:o?.signal});if(!m.ok)throw await I(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 l=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!l.ok)throw new h("Failed to fetch payments","api_error",{statusCode:l.status});let a=await l.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"}),a}catch(l){throw this.reportDirectFailure(l,"RECOVERY_FAILED","recovery","other","saved"),l}}async createAndFetchSession(e){if(xt(e))return(await this.createDetachedSession(e)).claimed;this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),r=R(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??ve(e.items,e.subscriptions),i=Te(e.currency,e.items,e.subscriptions,s);if(!i)throw new h("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 l={clientId:e.clientId,checkoutVersion:V,successUrl:e.successUrl,cancelUrl:e.cancelUrl,currency:i,checkoutMode:e.checkoutMode??"full",products:s.map(u=>Ne(u,i)),accountData:Ke(e.account),couponCodes:e.couponCodes??[]};e.tokenizedData&&(l.tokenizedData=e.tokenizedData),ze(l,e);let c=await(await this.postCheckoutSessionCreate(l,e,t,r,o)).json();if(c.data&&"gateways"in c.data){this.autoCacheDisplayData(c.data.uuid,e);let u=this.mergeCachedDisplayData(c.data),m=this.normalizeRawSession(u);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 d=c.data?.uuid;if(!d)throw new h("No session ID returned","api_error",{code:"InvalidCheckoutSessionResponse"});return this.autoCacheDisplayData(d,e),this.adoptDirectTelemetryCheckout(d),{...await this.getUnifiedCheckoutSession(d),autoProcessingError:c.autoProcessingError,autoProcessingAttempted:c.autoProcessingAttempted,autoProcessingPending:c.autoProcessingPending}}async postCheckoutSessionCreate(e,t,r,o,s){let i={"Content-Type":"application/json",[Ce]:V},l=Ot(t.idempotencyKey);l&&(i[Fe]=l);let a,c=!1,d=Kt(t),p=u=>{try{this.telemetryHooks?.onRetry?.("session_create",u),this.directTelemetry?.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:u})}catch{}};for(let u=0;u<3;u++){s.attempt=u;try{d?.onAttempt?.(u)}catch{}try{a=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:i,body:JSON.stringify(e),signal:o})}catch(v){if(s.statusClass=o.aborted||v instanceof Error&&v.name==="AbortError"?"timeout":"network_error",o.aborted||v instanceof Error&&v.name==="AbortError"||u>=2)throw v;let T=u+1;p(T),await N(u,o);continue}let m=A(a.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:u}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_create",statusClass:m,attempt:u})),a.status===204)throw new h("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(a.ok)break;let S=await I(a,"Failed to create checkout session");if(S.code===Dt&&u<2){p(u+1),await N(u,o);continue}throw S}if(!a)throw new TypeError("Checkout-session creation exhausted its retry budget.");return a}async createDetachedSession(e){this.beginDirectTelemetryOperation();let t=this.telemetryTimestamp(),r=R(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??ve(e.items,e.subscriptions),i=Te(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 h("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 l;try{l=$t(e,i,s)}catch(m){throw r.clear(),this.reportSessionCreateFailure(m,t,o),m}let a,c;try{if(c=await(await this.postCheckoutSessionCreate(Ht(e,i),e,t,r.signal,o)).json(),!c.data||!("gateways"in c.data))throw new h("The billing API returned no session shell for a detached create. It must support `deferDataAttachment` (TeamFloPay/backend#1099).","api_error",{code:"InvalidCheckoutSessionResponse"});a=this.normalizeRawSession(this.mergeCachedDisplayData(c.data)),c.vault&&a.data.session&&(a.data.session.vault=this.toVaultBlock(c.vault))}catch(m){throw r.clear(),this.reportSessionCreateFailure(m,t,o),m}let d=a.data.session?.id??c.data.uuid??"",p=a.data.session?.clientSecret??c.data.nonce??"";if(!d||!p){r.clear();let m=new h("Checkout session shell was created without a session id or nonce.","api_error",{code:"InvalidCheckoutSessionResponse"});throw this.reportSessionCreateFailure(m,t,o),m}this.adoptDirectTelemetryCheckout(d),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 u=this.claimCheckoutSession(d,p,l,{params:e,startedAt:t,deadline:r,createAttempt:o.attempt});return u.catch(()=>{}),{shell:a,sessionId:d,nonce:p,claimed:u}}async claimCheckoutSession(e,t,r,o){let s=o?.startedAt??this.telemetryTimestamp(),i=this.telemetryTimestamp(),l=o?.deadline??R(12e3),a=JSON.stringify(r),c="unknown",d=0;this.directTelemetry?.log({name:"session.claim.started",stage:"session_claim",requestCategory:"session_claim"});try{let p;for(d=0;d<3;d++){try{p=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/claim`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t,[Ce]:V},body:a,signal:l.signal})}catch(S){let v=l.signal.aborted||S instanceof Error&&S.name==="AbortError";if(c=v?"timeout":"network_error",v||d>=2)throw S;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,l.signal);continue}if(c=A(p.status),p.ok)break;throw await I(p,"Failed to attach checkout session data")}if(!p)throw new TypeError("Checkout-session claim exhausted its retry budget.");let u=await p.json();if(!u.data||!u.data.gateways)throw new h("The billing API returned no checkout session with gateways after claiming it.","api_error",{code:"InvalidCheckoutSessionResponse"});o?.params&&this.autoCacheDisplayData(u.data.uuid??e,o.params);let m=this.normalizeRawSession(this.mergeCachedDisplayData(u.data));return u.vault&&m.data.session&&(m.data.session.vault=this.toVaultBlock(u.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:d}),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??d}),m}catch(p){throw this.reportSessionCreateFailure(p,s,{attempt:d,statusClass:c},"session_claim"),p}finally{l.clear()}}reportSessionCreateFailure(e,t,r,o="session_create"){if(!(e instanceof h&&e.code==="session_auto_completed"))try{this.telemetryHooks?.onSessionCreateFailure?.(e)}catch{}let s=Y(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 h&&e.type==="validation_error"||e instanceof h&&Le(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 h&&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??Ut,s=Date.now()+o,i=this.clampRetryAfterMs(t?.initialDelayMs??qe),l=0;try{for(;;){let a=s-Date.now();if(a<=0)throw se();if(i>0){try{l+=1,this.telemetryHooks?.onRetry?.("session_read",l),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:l})}catch{}if(await Be(Math.min(i,a)),Date.now()>=s)throw se()}let c=await this.getUnifiedCheckoutSession(e,t?.nonce),d=c.data.session?.status;if(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()-r),durationMode:"machine",requestCategory:"session_read",paymentMethodCategory:"saved"}),c;if(Date.now()>=s)throw se();i=this.clampRetryAfterMs(Math.max(i*2,qt))}}catch(a){throw a instanceof h&&a.code==="checkout_processing_timeout"&&this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","session_read","saved"),a}}normalizeRawSession(e){let t=e.gateways??{},r=[],o={session:this.toCheckoutSession(e)},s=t.stripe;if(s?.publishableKey){r.push("stripe");let a=[e.stripeClientSecret,s.stripeClientSecret].find(c=>typeof c=="string"&&c.length>0);o.stripe={clientSecret:a??"",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}),{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,d)=>c+(d.overrideAmount??d.totalAmount??0),0),s=r?e.totalAmount:o,i=Math.round(s*100),l=e.currency??t[0]?.currency??"USD",a=t.some(c=>c.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:a,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:l,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==="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"});throw i.data.session?.status==="expired"?new h("Checkout session has expired.","api_error",{code:"checkout_session_expired"}):se()}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:B(e,"sessionId")??r,retryAfterMs:this.clampRetryAfterMs(Bt(e,"retryAfterMs")??i??qe),statusUrl:B(e,"statusUrl"),sessionUrl:B(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,Lt))}autoCacheDisplayData(e,t){if(!e)return;let r=t.products??ve(t.items,t.subscriptions);if(r.length===0&&!t.currency)return;let o=t.products!==void 0,s=Te(t.currency,o?void 0:t.items,o?void 0:t.subscriptions,r);U(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=ye(e.uuid),r=new Map,o=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let l=o(i.code);l&&r.set(l,i)}let s=(e.products??[]).map(i=>{let l=o(i.code),a=l?r.get(l):void 0;return{...i,name:i.name??a?.name??null,totalAmount:i.totalAmount??a?.totalAmount,overrideAmount:i.overrideAmount??a?.overrideAmount,currency:i.currency??a?.currency}});return{...e,currency:e.currency??t?.currency,products:s}}};D.activeVaultCaptureRequests=new Map;var x=D;function He(n,e){let t=x;return new t(n,e)}function $e(n){return{payment:"payment",address:"address"}[n]}function ie(n){switch(n){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function Wt(n){return{...n,theme:ie(n.theme)}}function we(n){return n?JSON.stringify(n.map(e=>e.trim().toLowerCase())):null}function Ge(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 Jt(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 W=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 Gt(e.publishableKey,{locale:e.locale??"auto"});if(!t)throw new g("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=t}getElements(e){if(!this.stripe)throw new g("StripeAdapter not initialized. Call initialize() first.","api_error");let t=e?.appearance?{theme:ie(e.appearance.theme),variables:e.appearance.variables,rules:e.appearance.rules}:void 0,r=t?JSON.stringify(t):null,o=we(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,l=e?.amount??0,a=(e?.currency??"usd").toLowerCase(),c=e?.paymentMethodCreation??"manual";e?.clientSecret?i={clientSecret:e.clientSecret}:l>0?(i={mode:"payment",amount:l,currency:a,paymentMethodCreation:c},e?.setupFutureUsage&&(i.setupFutureUsage=e.setupFutureUsage)):i={mode:"setup",currency:a,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 g("StripeAdapter not initialized. Call initialize() first.","api_error");let r,o=!1;if(Yt(e)){let{setupIntent:a,error:c}=await this.stripe.retrieveSetupIntent(e);r=a,o=!!c}else{let{paymentIntent:a,error:c}=await this.stripe.retrievePaymentIntent(e);r=a,o=!!c}let s=r?.payment_method_types;if(o||!Array.isArray(s))throw new g("Unable to verify the payment methods configured for this client secret.","api_error",{param:"clientSecret"});let i=new Set(t.map(a=>a.toLowerCase()));if(s.some(a=>typeof a!="string"||!i.has(a.trim().toLowerCase()))||s.length===0)throw new g("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 a=t.paymentMethodTypes?.map(c=>c.trim()).filter(c=>c&&c.toLowerCase()!=="card");if(!a?.length)throw new g("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});if(r={...t,paymentMethodTypes:a},r.clientSecret){let c=we(a);this.elements&&this.appliedClientSecret===r.clientSecret&&this.appliedPaymentMethodTypesKey===c&&this.verifiedClientSecret===r.clientSecret&&this.verifiedPaymentMethodTypesKey===c||await this.assertClientSecretPaymentMethods(r.clientSecret,a)}}let o=this.getElements(r);e==="payment"&&r.clientSecret&&(this.verifiedClientSecret=r.clientSecret,this.verifiedPaymentMethodTypesKey=we(r.paymentMethodTypes));let s=$e(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 l=o.create(s,i);return Ge(l)}getElement(e){if(!this.elements)return null;let t=$e(e),r=this.elements.getElement(t);return r?Ge(r):null}async submitElements(){if(!this.stripe||!this.elements)return{error:new g("Stripe not initialized","api_error")};let{error:e}=await this.elements.submit();return e?{error:new g(e.message??"Validation failed","validation_error")}:{}}async confirmPayment(e){if(!this.stripe||!this.elements)throw new g("StripeAdapter not initialized or no elements created.","api_error");let t=e.billingDetails,r=t?Jt(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 g(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 g("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 g("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 g(s.message??"PayPal payment failed","validation_error",{code:s.code})}}let r;try{let s=await new x(t).createSessionIntent(e.sessionId,e.nonce??"",{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",paymentMethodId:null,intentKind:"payment"});if(s.provider!=="stripe")throw new g("Invalid provider returned for PayPal intent","api_error");r=s.clientSecret}catch(s){return{status:"failed",error:s instanceof g?s:new g("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 x(t).reportSessionIntentDecline(e.sessionId,e.nonce,{provider:"stripe",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:o.code??"provider_declined"})}catch{}return{status:"failed",error:new g(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 g("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 g(i.message??"Failed to retrieve PayPal payment","api_error")};if(s&&(s.status==="requires_capture"||s.status==="succeeded")){let l=typeof s.payment_method=="string"?s.payment_method:s.payment_method?.id,a=new URL(window.location.href);return a.searchParams.delete("payment_intent"),a.searchParams.delete("payment_intent_client_secret"),a.searchParams.delete("redirect_status"),window.history.replaceState({},"",a.toString()),{status:s.status,paymentIntentId:s.id,paymentMethodId:l}}return{status:"failed",error:new g("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:ie(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}};import{FloPayError as w,classifyTelemetryFailure as be,resolveBillingApiUrl as st,SDK_VERSION as sr}from"@flopay/shared";import{FloPayError as Qt}from"@flopay/shared";var J=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 l=r.paymentMethodTypes?.map(a=>a.trim()).filter(a=>a&&a.toLowerCase()!=="card");if(!l?.length)throw new Qt("At least one supported non-card payment method is required.","validation_error",{param:"paymentMethodTypes"});r.paymentMethodTypes=l}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()}};import{buildTelemetryErrorEvent as Xt,buildTelemetryLogEvent as Zt,buildTelemetryTerminalEvent as Qe,FloPayError as Ye,resolveBillingApiUrl as We,SDK_VERSION as Je}from"@flopay/shared";var Se="flopay-vault",Xe={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 Q(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 ae(n,e){return Zt({eventId:"11111111-1111-4111-8111-111111111111",name:n,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function Ze(n){return n?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function er(n,e){if(n==="complete"||n==="decline")return Qe({eventId:"22222222-2222-4222-8222-222222222222",outcome:n==="complete"?"payment_succeeded":"payment_declined",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(n==="error"){let o=Ze(e);return Xt({eventId:"33333333-3333-4333-8333-333333333333",...o,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[t,r]=Xe[n];return ae(t,r)}function tr(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===Se&&(e.type==="ready"||e.type==="submitting"||e.type==="blocked"||e.type==="complete"||e.type==="decline"||e.type==="error"||e.type==="action_required")}function rr(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===Se&&e.type==="validation"&&Array.isArray(e.messages)}function nr(n){if(typeof n!="object"||n===null)return!1;let e=n;return e.source===Se&&e.type==="resize"&&typeof e.height=="number"&&Number.isFinite(e.height)}var j=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 C({billingApiUrl:We(),sdkVersion:Je}):void 0)}async mount(e,t){if(this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new C({billingApiUrl:We(),sdkVersion:Je})),this.mountStartedAt=this.telemetryReporter?.now?.()??_(),this.vaultReadyReported=!1,this.submissionStarted=!1,this.submissionStartedAt=null,typeof window>"u"||typeof document>"u")throw this.reportVaultLoadFailure(),new Ye("The vault card form is only available in the browser.","api_error",{code:"card_capture_no_window"});if(!t?.html||!t.html.trim())throw this.reportVaultLoadFailure(),new Ye("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(r){throw this.reportVaultLoadFailure(),r}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),Q(ae("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(nr(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;this.applyHeight(r.height);return}if(rr(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;let l=r.messages.filter(a=>typeof a=="string"&&a.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:l||void 0});return}if(!tr(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={sessionId:r.sessionId??this.config.sessionId,intentId:r.intentId,declineReason:r.declineReason,message:r.message,nextActionRedirectUrl:r.nextActionRedirectUrl};r.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??_()),Q(er(r.type,this.submissionStarted)),this.reportOutcome(r.type),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(),this.emit(r.type,i)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;if(e==="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"})),e==="complete"||e==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:e==="complete"?"payment_succeeded":"payment_declined",provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="error"){let s=Ze(this.submissionStarted);t.log({name:"vault.terminal",stage:s.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...s,provider:"pcivault",paymentMethodCategory:"card"});return}if(e==="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 s=this.submissionStartedAt;this.submissionStartedAt=null,s!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-s),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[r,o]=Xe[e];t.log({name:r,stage:o,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 l=i.data;if(!l||typeof l!="object")return;let a=l;a.source==="flopay-vault-3ds-return"&&(Q(ae("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(a.status))};window.addEventListener("message",s),this.threeDsReturnHandler=s,document.body.appendChild(t),this.actionOverlay=t,Q(ae("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=Qe({eventId:"77777777-7777-4777-8777-777777777777",outcome:"customer_abandoned",stage:"three_ds_handoff",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});Q(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 et(n,e){let t=j;return new t(n,{reporter:e})}var tt=Symbol.for("@flopay/js.telemetry.bridge.v1");function rt(n,e,t){let r=()=>e?.now()??t();Object.defineProperty(n,tt,{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()}})}function nt(n){return n[tt]}function K(n){if(!n)return!1;let e=n.code?.toLowerCase()??"";return!!n.declineCode||e.includes("declin")}function or(n){return n==="stripe"||n==="paypal"||n==="pcivault"?n:"other"}var le=class{constructor(e,t,r){this.currentElements=null;this.provider=e,this.config=t,this.telemetryReporter=r??new C({billingApiUrl:st(t.billingApiUrl),sdkVersion:sr,enabled:t.telemetry!==!1}),rt(this,this.telemetryReporter,_)}now(){return this.telemetryReporter?.now?.()??_()}elements(e){return this.currentElements&&this.currentElements.destroy(),this.currentElements=new J(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?et({sessionId:e?.sessionId},this.telemetryReporter):new j({sessionId:e?.sessionId,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:"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"&&(K(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 w&&K(r))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(r instanceof w&&r.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let o=be(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"}):K(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 w&&K(t))this.telemetryReporter?.terminal({outcome:"payment_declined",provider:"paypal",paymentMethodCategory:"paypal"});else if(t instanceof w&&t.type==="validation_error")this.telemetryReporter?.terminal({outcome:"validation_rejected",provider:"paypal",paymentMethodCategory:"paypal"});else{let r=be(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 w("A supported non-card payment method is required.","validation_error",{param:"paymentMethodType"});let t=this.now(),r=or(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}):K(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?.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 w&&K(o)?this.telemetryReporter?.terminal({outcome:"payment_declined",provider:r,paymentMethodCategory:e.paymentMethodCategory}):o instanceof w&&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 w("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let r=await this.retrieveUnifiedSession(e,t);if(!r.data.session)throw new w("Session not found","api_error");return r.data.session}async retrieveUnifiedSession(e,t){if(!e)throw new w("sessionId is required.","validation_error",{param:"sessionId"});let r=st(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()??_(),onFirstByte:l=>{s=l},onRetry:(l,a)=>{this.telemetryReporter?.log({name:"operation.retry",stage:l==="session_read"?"session_read":"processing",requestCategory:l,attempt:a})}});try{let l=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"}),l}catch(l){let a=be(l,l instanceof w&&l.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...a,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-o,durationMode:"machine",requestCategory:"session_read",statusClass:a.statusClass}),l}}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 ot(n,e,t){let r=le;return new r(n,e,t)}var at=new Map;function Pe(n){return Array.isArray(n)?n.map(Pe):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Pe(t)])):n}function ar(n,e){return JSON.stringify([n,ke(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,Pe(e?.appearance??null)])}var ce=new Map;async function lr(n,e){if(!n){let l=new C({billingApiUrl:ke(e?.billingApiUrl),sdkVersion:it,enabled:e?.telemetry!==!1});throw l.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),l.flush().catch(()=>{}).finally(()=>l.destroy()),new ir("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let t=ar(n,e),r=at.get(t);if(r)return e?.telemetry!==!1&&nt(r)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),r;let o=ce.get(t);if(o)return o;let s={...e,publishableKey:n},i=(async()=>{let l=new C({billingApiUrl:ke(s.billingApiUrl),sdkVersion:it,enabled:s.telemetry!==!1}),a=l.now();l.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),l.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),l.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new W,d=l.now();try{await c.initialize(s)}catch(m){throw l.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),l.destroy(),m}let p=l.now();l.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),l.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),l.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),l.performance({stage:"sdk_initialize",durationMs:p-a,durationMode:"machine",provider:"stripe"}),l.performance({stage:"provider_ready",durationMs:p-d,durationMode:"machine",provider:"stripe"});let u=ot(c,s,l);return at.set(t,u),u})();ce.set(t,i);try{return await i}finally{ce.get(t)===i&&ce.delete(t)}}import{FloPayError as H,IDEMPOTENCY_IN_PROGRESS_CODE as cr,IDEMPOTENCY_KEY_HEADER as dr,SDK_VERSION as lt,buildProductPayload as ur,classifyTelemetryFailure as pr,foldIntoProducts as mr,resolveIdempotencyKey as ct,resolveSessionCurrency as yr,telemetryStatusClass as dt}from"@flopay/shared";var Me=5,ut=new WeakSet;function hr(n){(typeof n=="object"&&n!==null||typeof n=="function")&&ut.add(n)}function gr(n){return(typeof n=="object"&&n!==null||typeof n=="function")&&ut.has(n)}function fr(n,e){let t=e?.error,r=E(e?.code)??E(t?.code)??`http_${n}`,o=E(e?.message)??E(t?.message)??Cr(r,n);return new H(o,"api_error",{code:r,statusCode:n})}function Cr(n,e){switch(n){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${Me}.`;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 pt(n,e,t){let{billingApiUrl:r,checkoutBaseUrl:o,items:s=[],subscriptions:i=[],products:l,account:a,successUrl:c,cancelUrl:d,checkoutMode:p="confirm",couponCodes:u=[],tagsData:m,redirectParams:S={},setCookie:v=!0,clientId:T,currency:Ee,utmMetadata:F,idempotencyKey:y}=n,$=ct(y);if(u.length>Me)throw new H(`Too many coupon codes \u2014 a checkout session accepts at most ${Me}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let O=l??mr(s,i),k=yr(Ee,s,i,O);if(!k)throw new H("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 G={clientId:T,checkoutVersion:lt,successUrl:c,cancelUrl:d,currency:k,checkoutMode:p,products:O.map(M=>ur(M,k)),accountData:{userId:a.userId,firstName:a.firstName??null,lastName:a.lastName??null,email:a.email,country:a.country??null,gender:a.gender??null,city:a.city??null,state:a.state??null,zip:a.zip??null,addressLine1:a.addressLine1??null,addressLine2:a.addressLine2??null},couponCodes:u};m&&(G.tagsData=m),F?.length&&(G.utmMetadata=F);let ue=`${r.replace(/\/+$/,"")}/v1/checkouts/sessions`,q={"Content-Type":"application/json"};$&&(q[dr]=$);let P,X,gt={method:"POST",headers:q,body:JSON.stringify(G),signal:e},Z;try{Z=await fetch(ue,gt)}catch(M){throw hr(M),M}try{t?.(Z.status)}catch{}P=Z.status;try{X=await Z.json()}catch{}if(P>=400)throw fr(P,X);if(P===201){let M=X?.data?.uuid,pe=X?.data?.nonce;if(!M)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!pe)throw new H("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"});(O.length||k)&&U(M,{currency:k,products:O.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??k}))});let ee=new URL(`${o.replace(/\/+$/,"")}/secure`);ee.searchParams.set("id",M);for(let[f,te]of Object.entries(S))ee.searchParams.set(f,te);if(v&&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(pe)}; domain=.${te}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=ee.toString()),{status:201,redirectUrl:ee.toString(),nonce:pe}}return P===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:P}}async function vr(n){let e=yt(n),t=mt(e),r=R(n.timeoutMs);try{let o=await pt(n,r.signal,t);return ht(e,o),o}catch(o){throw de(e,o),o}finally{r.clear(),z(e.reporter)}}function mt(n){let e=!1;return t=>{if(e)return;e=!0;let r=dt(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 yt(n){let e=new C({billingApiUrl:n.billingApiUrl,sdkVersion:lt,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 ht(n,e){let t=dt(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=pr(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 H&&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 z(n){n.flush().catch(()=>{}).finally(()=>n.destroy())}async function Tr(n){let{maxRetries:e=2,...t}=n,r=yt(n),o=mt(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"}),z(r.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let s={...t,idempotencyKey:ct(t.idempotencyKey)},i=R(t.timeoutMs),l;for(let a=0;a<=e;a++){r.attempt=a;try{let c=await pt(s,i.signal,o);return ht(r,c),i.clear(),z(r.reporter),c}catch(c){l=c;let d=c instanceof Error&&c.name==="AbortError",p=gr(c),u=c instanceof H&&c.code===cr;if((d||p||u)&&!i.signal.aborted&&a<e){r.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:a+1});try{await N(a,i.signal)}catch(m){throw de(r,m),i.clear(),z(r.reporter),m}continue}throw de(r,c),i.clear(),z(r.reporter),c}}throw de(r,l),i.clear(),z(r.reporter),l??new Error("Unknown error during checkout session creation")}export{le as FloPay,J as FloPayElements,x as PaymentAPI,j as PciVaultCardCapture,je as SESSION_CREATE_TELEMETRY,W as StripeAdapter,U as cacheSessionDisplayData,he as clearSessionDisplayData,vr as createCheckoutSession,Tr as createCheckoutSessionWithRetries,ye as getSessionDisplayData,lr as loadFloPay,Wt as toStripeAppearance,ie as toStripeAppearanceTheme};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flopay/js",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@stripe/stripe-js": "^9.8.0",
|
|
30
|
-
"@flopay/shared": "1.4.
|
|
30
|
+
"@flopay/shared": "1.4.17"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"jsdom": "^29.1.1",
|