@flopay/js 1.8.4 → 1.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as S,b as U,c as Y,d as N,e as Ce,f as we,g as E,h as y,i as be,j as Pe,k as W,l as D,m as G}from"./chunk-QRHEWEAL.mjs";import{dropThirdPartyOnlyError as mt}from"@flopay/shared";import{assertCaptureMethodEligible as Se,buildProductPayload as _e,classifyTelemetryFailure as ke,FloPayError as b,foldIntoProducts as ve,IDEMPOTENCY_IN_PROGRESS_CODE as Re,IDEMPOTENCY_KEY_HEADER as Te,resolveIdempotencyKey as H,resolveSessionCurrency as Ae,SDK_VERSION as J,telemetryStatusClass as Q}from"@flopay/shared";var j=5,X=new WeakSet;function Ee(t){(typeof t=="object"&&t!==null||typeof t=="function")&&X.add(t)}function Ie(t){return(typeof t=="object"&&t!==null||typeof t=="function")&&X.has(t)}function Fe(t,e){let r=e?.error,o=S(e?.code)??S(r?.code)??`http_${t}`,a=S(e?.message)??S(r?.message)??xe(o,t);return new b(a,"api_error",{code:o,statusCode:t})}function xe(t,e){switch(t){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${j}.`;case"CouponCurrencyUnsupported":return"One of the applied coupons has no price configured for the cart currency.";default:return`Failed to create checkout session (HTTP ${e}).`}}async function Z(t,e,r){let{billingApiUrl:o,checkoutBaseUrl:a,items:n=[],subscriptions:l=[],products:s,account:i,successUrl:c,cancelUrl:f,checkoutMode:g="confirm",captureMethod:u,couponCodes:m=[],tagsData:L,redirectParams:ue={},setCookie:pe=!0,clientId:me,currency:ye,utmMetadata:K,idempotencyKey:fe}=t,V=H(fe);if(m.length>j)throw new b(`Too many coupon codes \u2014 a checkout session accepts at most ${j}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let P=s??ve(n,l);Se({captureMethod:u,products:P});let h=Ae(ye,n,l,P);if(!h)throw new b("currency is required: pass `currency` on the session, or include a `currency` on the first item/subscription/product.","validation_error",{code:"CurrencyRequired",param:"currency"});let k={clientId:me,checkoutVersion:J,successUrl:c,cancelUrl:f,currency:h,checkoutMode:g,products:P.map(p=>_e(p,h)),accountData:{userId:i.userId,firstName:i.firstName??null,lastName:i.lastName??null,email:i.email,country:i.country??null,gender:i.gender??null,city:i.city??null,state:i.state??null,zip:i.zip??null,addressLine1:i.addressLine1??null,addressLine2:i.addressLine2??null},couponCodes:m};u==="manual"&&(k.captureMethod=u),L&&(k.tagsData=L),K?.length&&(k.utmMetadata=K);let ge=`${o.replace(/\/+$/,"")}/v1/checkouts/sessions`,$={"Content-Type":"application/json"};V&&($[Te]=V);let C,v,he={method:"POST",headers:$,body:JSON.stringify(k),signal:e},R;try{R=await fetch(ge,he)}catch(p){throw Ee(p),p}try{r?.(R.status)}catch{}C=R.status;try{v=await R.json()}catch{}if(C>=400)throw Fe(C,v);if(C===201){let p=v?.data?.uuid,O=v?.data?.nonce;if(!p)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!O)throw new b("Checkout session created but no `nonce` was returned by the billing API. Upgrade the billing service to TeamFloPay/backend#640 or later.","api_error",{code:"MissingCheckoutSessionToken"});(P.length||h)&&N(p,{currency:h,products:P.map(d=>({code:d.code??d.providerItemId??d.providerPlanId,type:d.type,name:d.name??d.itemName??d.providerItemName??d.subscriptionName??d.providerPlanName??null,totalAmount:d.totalAmount,overrideAmount:d.overrideAmount,currency:d.currency??h}))});let T=new URL(`${a.replace(/\/+$/,"")}/secure`);T.searchParams.set("id",p);for(let[d,A]of Object.entries(ue))T.searchParams.set(d,A);if(pe&&typeof window<"u"&&typeof document<"u"){let d=JSON.stringify({origin_url:f}),A=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(d)}; domain=.${A}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(O)}; domain=.${A}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=T.toString()),{status:201,redirectUrl:T.toString(),nonce:O}}return C===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:C}}async function Me(t){let e=te(t),r=ee(e),o=U(t.timeoutMs);try{let a=await Z(t,o.signal,r);return re(e,a),a}catch(a){throw I(e,a),a}finally{o.clear(),w(e.reporter)}}function ee(t){let e=!1;return r=>{if(e)return;e=!0;let o=Q(r);t.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:o,attempt:t.attempt}),t.reporter.performance({stage:"session_first_byte",durationMs:t.reporter.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o,attempt:t.attempt})}}function te(t){let e=new y({billingApiUrl:t.billingApiUrl,sdkVersion:J,enabled:t.telemetry!==!1}),r=e.now();return e.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:e,startedAt:r,attempt:0}}function re(t,e){let r=Q(e.status);t.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:r}),t.reporter.performance({stage:"session_create",durationMs:t.reporter.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:r,attempt:t.attempt})}function I(t,e){let{reporter:r}=t,o=ke(e,"CHECKOUT_SESSION_CREATE_FAILED");if(r.performance({stage:"session_create",durationMs:r.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:t.attempt}),e instanceof b&&e.type==="validation_error"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(o.statusClass==="4xx"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}r.error({...o,stage:"session_create",requestCategory:"session_create"})}function w(t){t.flush().catch(()=>{}).finally(()=>t.destroy())}async function Oe(t){let{maxRetries:e=2,...r}=t,o=te(t),a=ee(o);if(!Number.isFinite(e)||!Number.isInteger(e)||e<0||e>=3)throw o.reporter.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),w(o.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let n={...r,idempotencyKey:H(r.idempotencyKey)},l=U(r.timeoutMs),s;for(let i=0;i<=e;i++){o.attempt=i;try{let c=await Z(n,l.signal,a);return re(o,c),l.clear(),w(o.reporter),c}catch(c){s=c;let f=c instanceof Error&&c.name==="AbortError",g=Ie(c),u=c instanceof b&&c.code===Re;if((f||g||u)&&!l.signal.aborted&&i<e){o.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:i+1});try{await Y(i,l.signal)}catch(m){throw I(o,m),l.clear(),w(o.reporter),m}continue}throw I(o,c),l.clear(),w(o.reporter),c}}throw I(o,s),l.clear(),w(o.reporter),s??new Error("Unknown error during checkout session creation")}import{classifyTelemetryFailure as Ue,FloPayError as F,resolveBillingApiUrl as ie,SDK_VERSION as Ne}from"@flopay/shared";var oe=Symbol.for("@flopay/js.telemetry.bridge.v1");function se(t,e,r){let o=()=>e?.now()??r();Object.defineProperty(t,oe,{configurable:!1,enumerable:!1,writable:!1,value:{error:n=>e?.error(n),log:n=>e?.log(n),performance:n=>e?.performance(n),terminal:n=>e?.terminal(n),now:o,elapsed:n=>Math.max(0,o()-n),setCheckoutContext:n=>e?.setCheckoutContext(n),beginCheckout:(n={})=>e?.beginCheckout(n)??o(),disable:()=>e?.disable(),subscribe:n=>e?.subscribe(n)??(()=>{})}})}function ne(t){return t[oe]}var x=class{now(){return this.telemetryReporter?.now?.()??E()}constructor(e,r,o){this.provider=e,this.config=r,this.telemetryReporter=o??new y({billingApiUrl:ie(r.billingApiUrl),sdkVersion:Ne,enabled:r.telemetry!==!1}),se(this,this.telemetryReporter,E)}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?G({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new D({sessionId:e?.sessionId,captureMethod:e?.captureMethod,telemetry:!1})}async retrieveSession(e,r){if(!e)throw new F("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let o=await this.retrieveUnifiedSession(e,r);if(!o.data.session)throw new F("Session not found","api_error");return o.data.session}async retrieveUnifiedSession(e,r){if(!e)throw new F("sessionId is required.","validation_error",{param:"sessionId"});let o=ie(r??this.config.billingApiUrl),a=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let n,l=W(o,{now:()=>this.telemetryReporter?.now()??E(),onFirstByte:s=>{n=s},onRetry:(s,i)=>{this.telemetryReporter?.log({name:"operation.retry",stage:s==="session_read"?"session_read":"processing",requestCategory:s,attempt:i})}});try{let s=await l.getUnifiedCheckoutSession(e);return n!==void 0&&(this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:n,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"})),this.telemetryReporter?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.log({name:"checkout.data.ready",stage:"checkout_data_ready"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-a,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),s}catch(s){let i=Ue(s,s instanceof F&&s.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...i,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-a,durationMode:"machine",requestCategory:"session_read",statusClass:i.statusClass}),s}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.provider.destroy()}};function ae(t,e,r){let o=x;return new o(t,e,r)}import{FloPayError as ze,resolveBillingApiUrl as z,SDK_VERSION as le}from"@flopay/shared";import{FloPayError as De}from"@flopay/shared";import{loadStripe as qe}from"@stripe/stripe-js";function ce(t){switch(t){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function je(t){return{...t,theme:ce(t.theme)}}var _=class{constructor(){this.name="stripe";this.stripe=null}async initialize(e){if(typeof window>"u")return;let r=await qe(e.publishableKey,{locale:e.locale??"auto"});if(!r)throw new De("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=r}getRawProvider(){return this.stripe}destroy(){this.stripe=null}};var de=new Map;function B(t){return Array.isArray(t)?t.map(B):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[r])=>e.localeCompare(r)).map(([e,r])=>[e,B(r)])):t}function Be(t,e){return JSON.stringify([t,z(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,B(e?.appearance??null)])}var M=new Map;async function Le(t,e){if(!t){let s=new y({billingApiUrl:z(e?.billingApiUrl),sdkVersion:le,enabled:e?.telemetry!==!1});throw s.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),s.flush().catch(()=>{}).finally(()=>s.destroy()),new ze("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let r=Be(t,e),o=de.get(r);if(o)return e?.telemetry!==!1&&ne(o)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),o;let a=M.get(r);if(a)return a;let n={...e,publishableKey:t},l=(async()=>{let s=new y({billingApiUrl:z(n.billingApiUrl),sdkVersion:le,enabled:n.telemetry!==!1}),i=s.now();s.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),s.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),s.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new _,f=s.now();try{await c.initialize(n)}catch(m){throw s.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),s.destroy(),m}let g=s.now();s.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),s.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),s.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),s.performance({stage:"sdk_initialize",durationMs:g-i,durationMode:"machine",provider:"stripe"}),s.performance({stage:"provider_ready",durationMs:g-f,durationMode:"machine",provider:"stripe"});let u=ae(c,n,s);return de.set(r,u),u})();M.set(r,l);try{return await l}finally{M.get(r)===l&&M.delete(r)}}export{x as FloPay,Pe as PaymentAPI,D as PciVaultCardCapture,be as SESSION_CREATE_TELEMETRY,_ as StripeAdapter,N as cacheSessionDisplayData,we as clearSessionDisplayData,Me as createCheckoutSession,Oe as createCheckoutSessionWithRetries,mt as dropThirdPartyOnlyError,Ce as getSessionDisplayData,Le as loadFloPay,je as toStripeAppearance,ce as toStripeAppearanceTheme};
1
+ import{a as S,b as U,c as Y,d as N,e as Ce,f as we,g as E,h as y,i as be,j as Pe,k as W,l as D,m as G}from"./chunk-UOFQ6V54.mjs";import{dropThirdPartyOnlyError as mt}from"@flopay/shared";import{assertCaptureMethodEligible as Se,buildProductPayload as _e,classifyTelemetryFailure as ke,FloPayError as b,foldIntoProducts as ve,IDEMPOTENCY_IN_PROGRESS_CODE as Re,IDEMPOTENCY_KEY_HEADER as Te,resolveIdempotencyKey as H,resolveSessionCurrency as Ae,SDK_VERSION as J,telemetryStatusClass as Q}from"@flopay/shared";var j=5,X=new WeakSet;function Ee(t){(typeof t=="object"&&t!==null||typeof t=="function")&&X.add(t)}function Ie(t){return(typeof t=="object"&&t!==null||typeof t=="function")&&X.has(t)}function Fe(t,e){let r=e?.error,o=S(e?.code)??S(r?.code)??`http_${t}`,a=S(e?.message)??S(r?.message)??xe(o,t);return new b(a,"api_error",{code:o,statusCode:t})}function xe(t,e){switch(t){case"CouponLimitExceeded":return`Too many coupon codes \u2014 a checkout session accepts at most ${j}.`;case"CouponCurrencyUnsupported":return"One of the applied coupons has no price configured for the cart currency.";default:return`Failed to create checkout session (HTTP ${e}).`}}async function Z(t,e,r){let{billingApiUrl:o,checkoutBaseUrl:a,items:n=[],subscriptions:l=[],products:s,account:i,successUrl:c,cancelUrl:f,checkoutMode:g="confirm",captureMethod:u,couponCodes:m=[],tagsData:L,redirectParams:ue={},setCookie:pe=!0,clientId:me,currency:ye,utmMetadata:K,idempotencyKey:fe}=t,V=H(fe);if(m.length>j)throw new b(`Too many coupon codes \u2014 a checkout session accepts at most ${j}.`,"validation_error",{code:"CouponLimitExceeded",param:"couponCodes"});let P=s??ve(n,l);Se({captureMethod:u,products:P});let h=Ae(ye,n,l,P);if(!h)throw new b("currency is required: pass `currency` on the session, or include a `currency` on the first item/subscription/product.","validation_error",{code:"CurrencyRequired",param:"currency"});let k={clientId:me,checkoutVersion:J,successUrl:c,cancelUrl:f,currency:h,checkoutMode:g,products:P.map(p=>_e(p,h)),accountData:{userId:i.userId,firstName:i.firstName??null,lastName:i.lastName??null,email:i.email,country:i.country??null,gender:i.gender??null,city:i.city??null,state:i.state??null,zip:i.zip??null,addressLine1:i.addressLine1??null,addressLine2:i.addressLine2??null},couponCodes:m};u==="manual"&&(k.captureMethod=u),L&&(k.tagsData=L),K?.length&&(k.utmMetadata=K);let ge=`${o.replace(/\/+$/,"")}/v1/checkouts/sessions`,$={"Content-Type":"application/json"};V&&($[Te]=V);let C,v,he={method:"POST",headers:$,body:JSON.stringify(k),signal:e},R;try{R=await fetch(ge,he)}catch(p){throw Ee(p),p}try{r?.(R.status)}catch{}C=R.status;try{v=await R.json()}catch{}if(C>=400)throw Fe(C,v);if(C===201){let p=v?.data?.uuid,O=v?.data?.nonce;if(!p)throw new Error("Checkout session created but no UUID was returned by the billing API");if(!O)throw new b("Checkout session created but no `nonce` was returned by the billing API. Upgrade the billing service to TeamFloPay/backend#640 or later.","api_error",{code:"MissingCheckoutSessionToken"});(P.length||h)&&N(p,{currency:h,products:P.map(d=>({code:d.code??d.providerItemId??d.providerPlanId,type:d.type,name:d.name??d.itemName??d.providerItemName??d.subscriptionName??d.providerPlanName??null,totalAmount:d.totalAmount,overrideAmount:d.overrideAmount,currency:d.currency??h}))});let T=new URL(`${a.replace(/\/+$/,"")}/secure`);T.searchParams.set("id",p);for(let[d,A]of Object.entries(ue))T.searchParams.set(d,A);if(pe&&typeof window<"u"&&typeof document<"u"){let d=JSON.stringify({origin_url:f}),A=window.location.hostname.split(".").slice(-2).join(".");document.cookie=`checkout_data=${encodeURIComponent(d)}; domain=.${A}; path=/; max-age=3600; SameSite=Lax; Secure;`,document.cookie=`flopay_checkout_token=${encodeURIComponent(O)}; domain=.${A}; path=/; max-age=3600; SameSite=Lax; Secure;`}return typeof window<"u"&&(window.location.href=T.toString()),{status:201,redirectUrl:T.toString(),nonce:O}}return C===204?(typeof window<"u"&&(window.location.href=c),{status:204}):{status:C}}async function Me(t){let e=te(t),r=ee(e),o=U(t.timeoutMs);try{let a=await Z(t,o.signal,r);return re(e,a),a}catch(a){throw I(e,a),a}finally{o.clear(),w(e.reporter)}}function ee(t){let e=!1;return r=>{if(e)return;e=!0;let o=Q(r);t.reporter.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:o,attempt:t.attempt}),t.reporter.performance({stage:"session_first_byte",durationMs:t.reporter.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o,attempt:t.attempt})}}function te(t){let e=new y({billingApiUrl:t.billingApiUrl,sdkVersion:J,enabled:t.telemetry!==!1}),r=e.now();return e.log({name:"session.create.started",stage:"session_create",requestCategory:"session_create"}),{reporter:e,startedAt:r,attempt:0}}function re(t,e){let r=Q(e.status);t.reporter.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:r}),t.reporter.performance({stage:"session_create",durationMs:t.reporter.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:r,attempt:t.attempt})}function I(t,e){let{reporter:r}=t,o=ke(e,"CHECKOUT_SESSION_CREATE_FAILED");if(r.performance({stage:"session_create",durationMs:r.now()-t.startedAt,durationMode:"machine",requestCategory:"session_create",statusClass:o.statusClass,attempt:t.attempt}),e instanceof b&&e.type==="validation_error"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"});return}if(o.statusClass==="4xx"){r.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create",statusClass:"4xx"});return}r.error({...o,stage:"session_create",requestCategory:"session_create"})}function w(t){t.flush().catch(()=>{}).finally(()=>t.destroy())}async function Oe(t){let{maxRetries:e=2,...r}=t,o=te(t),a=ee(o);if(!Number.isFinite(e)||!Number.isInteger(e)||e<0||e>=3)throw o.reporter.terminal({outcome:"validation_rejected",stage:"session_create",requestCategory:"session_create"}),w(o.reporter),new Error(`Number of retries must be an integer between 0 and ${2}`);let n={...r,idempotencyKey:H(r.idempotencyKey)},l=U(r.timeoutMs),s;for(let i=0;i<=e;i++){o.attempt=i;try{let c=await Z(n,l.signal,a);return re(o,c),l.clear(),w(o.reporter),c}catch(c){s=c;let f=c instanceof Error&&c.name==="AbortError",g=Ie(c),u=c instanceof b&&c.code===Re;if((f||g||u)&&!l.signal.aborted&&i<e){o.reporter.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:i+1});try{await Y(i,l.signal)}catch(m){throw I(o,m),l.clear(),w(o.reporter),m}continue}throw I(o,c),l.clear(),w(o.reporter),c}}throw I(o,s),l.clear(),w(o.reporter),s??new Error("Unknown error during checkout session creation")}import{classifyTelemetryFailure as Ue,FloPayError as F,resolveBillingApiUrl as ie,SDK_VERSION as Ne}from"@flopay/shared";var oe=Symbol.for("@flopay/js.telemetry.bridge.v1");function se(t,e,r){let o=()=>e?.now()??r();Object.defineProperty(t,oe,{configurable:!1,enumerable:!1,writable:!1,value:{error:n=>e?.error(n),log:n=>e?.log(n),performance:n=>e?.performance(n),terminal:n=>e?.terminal(n),now:o,elapsed:n=>Math.max(0,o()-n),setCheckoutContext:n=>e?.setCheckoutContext(n),beginCheckout:(n={})=>e?.beginCheckout(n)??o(),disable:()=>e?.disable(),subscribe:n=>e?.subscribe(n)??(()=>{})}})}function ne(t){return t[oe]}var x=class{now(){return this.telemetryReporter?.now?.()??E()}constructor(e,r,o){this.provider=e,this.config=r,this.telemetryReporter=o??new y({billingApiUrl:ie(r.billingApiUrl),sdkVersion:Ne,enabled:r.telemetry!==!1}),se(this,this.telemetryReporter,E)}cardCapture(e){return this.telemetryReporter?.log({name:"vault.capture.requested",stage:"vault_request",provider:"pcivault",paymentMethodCategory:"card"}),this.telemetryReporter?G({sessionId:e?.sessionId,captureMethod:e?.captureMethod},this.telemetryReporter):new D({sessionId:e?.sessionId,captureMethod:e?.captureMethod,telemetry:!1})}async retrieveSession(e,r){if(!e)throw new F("sessionId is required to retrieve a session.","validation_error",{param:"sessionId"});let o=await this.retrieveUnifiedSession(e,r);if(!o.data.session)throw new F("Session not found","api_error");return o.data.session}async retrieveUnifiedSession(e,r){if(!e)throw new F("sessionId is required.","validation_error",{param:"sessionId"});let o=ie(r??this.config.billingApiUrl),a=this.now();this.telemetryReporter?.log({name:"session.read.started",stage:"session_read",requestCategory:"session_read"});let n,l=W(o,{now:()=>this.telemetryReporter?.now()??E(),onFirstByte:s=>{n=s},onRetry:(s,i)=>{this.telemetryReporter?.log({name:"operation.retry",stage:s==="session_read"?"session_read":"processing",requestCategory:s,attempt:i})}});try{let s=await l.getUnifiedCheckoutSession(e);return n!==void 0&&(this.telemetryReporter?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.performance({stage:"session_first_byte",durationMs:n,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"})),this.telemetryReporter?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:"2xx"}),this.telemetryReporter?.log({name:"checkout.data.ready",stage:"checkout_data_ready"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-a,durationMode:"machine",requestCategory:"session_read",statusClass:"2xx"}),s}catch(s){let i=Ue(s,s instanceof F&&s.code==="checkout_processing_timeout"?"REQUEST_TIMEOUT":"NETWORK_REQUEST_FAILED");throw this.telemetryReporter?.error({...i,stage:"session_read",provider:"flo",paymentMethodCategory:"unknown"}),this.telemetryReporter?.performance({stage:"session_complete",durationMs:this.now()-a,durationMode:"machine",requestCategory:"session_read",statusClass:i.statusClass}),s}}getRawProvider(){return this.provider.getRawProvider()}destroy(){this.telemetryReporter?.log({name:"checkout.unmount",stage:"unmount"}),this.telemetryReporter?.destroy(),this.provider.destroy()}};function ae(t,e,r){let o=x;return new o(t,e,r)}import{FloPayError as ze,resolveBillingApiUrl as z,SDK_VERSION as le}from"@flopay/shared";import{FloPayError as De}from"@flopay/shared";import{loadStripe as qe}from"@stripe/stripe-js";function ce(t){switch(t){case"night":return"night";case"flat":return"flat";default:return"stripe"}}function je(t){return{...t,theme:ce(t.theme)}}var _=class{constructor(){this.name="stripe";this.stripe=null}async initialize(e){if(typeof window>"u")return;let r=await qe(e.publishableKey,{locale:e.locale??"auto"});if(!r)throw new De("Failed to initialize Stripe. Check your publishable key.","authentication_error");this.stripe=r}getRawProvider(){return this.stripe}destroy(){this.stripe=null}};var de=new Map;function B(t){return Array.isArray(t)?t.map(B):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[r])=>e.localeCompare(r)).map(([e,r])=>[e,B(r)])):t}function Be(t,e){return JSON.stringify([t,z(e?.billingApiUrl),e?.telemetry!==!1,e?.locale??"auto",e?.apiVersion??null,B(e?.appearance??null)])}var M=new Map;async function Le(t,e){if(!t){let s=new y({billingApiUrl:z(e?.billingApiUrl),sdkVersion:le,enabled:e?.telemetry!==!1});throw s.error({errorCode:"CONFIGURATION_INVALID",stage:"sdk_initialize",paymentMethodCategory:"unknown"}),s.flush().catch(()=>{}).finally(()=>s.destroy()),new ze("A publishable key is required to initialize FloPay.","validation_error",{param:"publishableKey"})}let r=Be(t,e),o=de.get(r);if(o)return e?.telemetry!==!1&&ne(o)?.log({name:"sdk.cache.hit",stage:"sdk_initialize"}),o;let a=M.get(r);if(a)return a;let n={...e,publishableKey:t},l=(async()=>{let s=new y({billingApiUrl:z(n.billingApiUrl),sdkVersion:le,enabled:n.telemetry!==!1}),i=s.now();s.log({name:"sdk.initialize.started",stage:"sdk_initialize"}),s.log({name:"sdk.cache.miss",stage:"sdk_initialize"}),s.log({name:"provider.load.started",stage:"provider_load",provider:"stripe"});let c=new _,f=s.now();try{await c.initialize(n)}catch(m){throw s.error({errorCode:"SDK_INITIALIZATION_FAILED",failureCategory:"provider_runtime",stage:"sdk_initialize",provider:"stripe",paymentMethodCategory:"unknown"}),s.destroy(),m}let g=s.now();s.log({name:"provider.ready",stage:"provider_ready",provider:"stripe"}),s.log({name:"provider.availability.checked",stage:"provider_ready",provider:"stripe"}),s.log({name:"sdk.initialize.ready",stage:"sdk_initialize"}),s.performance({stage:"sdk_initialize",durationMs:g-i,durationMode:"machine",provider:"stripe"}),s.performance({stage:"provider_ready",durationMs:g-f,durationMode:"machine",provider:"stripe"});let u=ae(c,n,s);return de.set(r,u),u})();M.set(r,l);try{return await l}finally{M.get(r)===l&&M.delete(r)}}export{x as FloPay,Pe as PaymentAPI,D as PciVaultCardCapture,be as SESSION_CREATE_TELEMETRY,_ as StripeAdapter,N as cacheSessionDisplayData,we as clearSessionDisplayData,Me as createCheckoutSession,Oe as createCheckoutSessionWithRetries,mt as dropThirdPartyOnlyError,Ce as getSessionDisplayData,Le as loadFloPay,je as toStripeAppearance,ce as toStripeAppearanceTheme};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flopay/js",
3
- "version": "1.8.4",
3
+ "version": "1.8.7",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "publishConfig": {
@@ -32,13 +32,13 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@stripe/stripe-js": "^9.8.0",
35
- "@flopay/shared": "1.8.4"
35
+ "@flopay/shared": "1.8.7"
36
36
  },
37
37
  "devDependencies": {
38
38
  "jsdom": "^29.1.1",
39
39
  "tsup": "^8.3.0",
40
40
  "typescript": "^6.0.3",
41
- "vitest": "^4.1.10"
41
+ "vitest": "4.1.11"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsup",
@@ -1 +0,0 @@
1
- var De="flopay_session_display:";var x=new Map;function O(s){return`${De}${s}`}function z(){if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}}function B(s,e,t){if(!s)return;let r=t?.ttlMs??36e5,o={data:e,expiresAt:Date.now()+r},n=z();if(n)try{n.setItem(O(s),JSON.stringify(o));return}catch{}x.set(s,o)}function Z(s){if(!s)return null;let e=z();if(e)try{let r=e.getItem(O(s));if(r){let o=JSON.parse(r);if(o&&typeof o.expiresAt=="number"&&o.expiresAt>Date.now())return o.data;e.removeItem(O(s))}}catch{}let t=x.get(s);if(t){if(t.expiresAt>Date.now())return t.data;x.delete(s)}return null}function ee(s){if(!s)return;x.delete(s);let e=z();if(e)try{e.removeItem(O(s))}catch{}}import{assertCaptureMethodEligible as ae,buildProductPayload as ge,classifyPaymentRejection as Ge,classifyTelemetryFailure as P,FLO_SDK_VERSION_HEADER as H,FloPayError as h,foldIntoProducts as K,IDEMPOTENCY_IN_PROGRESS_CODE as Ye,IDEMPOTENCY_KEY_HEADER as ce,isDetachedSessionEligible as We,isUuidV4 as ue,isValidEmail as le,normalizeCheckoutFailureOutcome as de,PAYPAL_VAULTED_PAYMENT_METHOD_TYPE as $,randomUuidV4 as Je,resolveIdempotencyKey as Qe,resolveSessionCurrency as G,SDK_VERSION as E,telemetryStatusClass as k}from"@flopay/shared";function te(s){return typeof s=="string"&&s.trim()?s:void 0}function re(s){if(typeof s=="string")return s.trim()?s:void 0;if(Array.isArray(s))return s.filter(t=>typeof t=="string"&&t.trim().length>0).join("; ")||void 0}function R(s=12e3){let e=Number.isFinite(s)&&s>=0?s:12e3,t=new AbortController,r=setTimeout(()=>t.abort(),e);return{signal:t.signal,clear:()=>clearTimeout(r)}}function xe(){return Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function q(s,e){let t=150*2**s,r=Math.round(t*(.75+Math.random()*.5));return new Promise((o,n)=>{let i,a=()=>e.removeEventListener("abort",c),c=()=>{i!==void 0&&clearTimeout(i),a(),n(xe())};if(e.aborted){c();return}i=setTimeout(()=>{a(),o()},r),e.addEventListener("abort",c,{once:!0})})}import{buildTelemetryErrorEvent as se,buildTelemetryLogEvent as Oe,buildTelemetryPerformanceEvent as qe,buildTelemetryTerminalEvent as Fe,serializeTelemetryBatch as Le,TELEMETRY_MAX_BATCH_BYTES as Ue}from"@flopay/shared";var Ve="/v1/sdk-telemetry/events",j=16,Ne=64,ze=1500,ne=1e3,Be=64,je="00000000-0000-4000-8000-000000000000",He={technical_error:8,lifecycle:32,expected_outcome:32,performance:24};function A(){try{return globalThis.crypto.randomUUID()}catch{let s=new Uint8Array(16);try{globalThis.crypto.getRandomValues(s)}catch{for(let t=0;t<s.length;t+=1)s[t]=Math.floor(Math.random()*256)}s[6]=s[6]&15|64,s[8]=s[8]&63|128;let e=[...s].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 Ke(s){try{return new TextEncoder().encode(s).byteLength}catch{return s.length}}function $e(s){return JSON.stringify([s.code,s.failureCategory,s.stage,s.provider,s.attempt,s.statusClass,s.requestCategory,s.paymentMethodCategory,s.checkoutMode,s.layout])}function b(){return globalThis.performance?.now()??0}var _=class{constructor(e){this.ingestionDisabled=!1;this.queue=[];this.sequence=0;this.flushTimer=null;this.flushInFlight=null;this.reportedFailures=new Map;this.checkoutContext={};this.checkoutStartedAt=null;this.destroyed=!1;this.observers=new Set;this.pageExitHandler=()=>{this.drainQueue()};this.visibilityHandler=()=>{document.visibilityState==="hidden"&&this.flush()};this.eventCounts={technical_error:0,lifecycle:0,expected_outcome:0,performance:0};this.endpoint=`${e.billingApiUrl.replace(/\/+$/,"")}${Ve}`,this.sdkPackage=e.sdkPackage??"@flopay/js",this.sdkVersion=e.sdkVersion,this.correlationId=A(),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.notify({...e,class:"lifecycle"}),this.canCollect()&&this.enqueue(Oe({...this.checkoutContext,...e,eventId:A(),sequence:this.sequence++}))}error(e){if(this.notify({...e,class:"technical_error"}),!this.canCollect())return;let t=se({...this.checkoutContext,...e,eventId:je,sequence:0}),r=$e(t),o=this.now();this.pruneReportedFailures(o);let n=this.reportedFailures.get(r);if(n!==void 0&&o>=n&&o-n<ne){this.log({name:"operation.deduplicated",stage:e.stage,provider:e.provider,paymentMethodCategory:e.paymentMethodCategory,attempt:e.attempt});return}this.rememberReportedFailure(r,o),this.enqueue(se({...this.checkoutContext,...e,eventId:A(),sequence:this.sequence++}))}performance(e){this.canCollect()&&this.enqueue(qe({...this.checkoutContext,...e,eventId:A(),sequence:this.sequence++}))}terminal(e){if(this.canCollect()&&(this.enqueue(Fe({...this.checkoutContext,...e,eventId:A(),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()}}subscribe(e){return this.destroyed?()=>{}:(this.observers.add(e),()=>this.observers.delete(e))}notify(e){if(!this.destroyed)for(let t of this.observers)try{t(e)}catch{}}pruneReportedFailures(e){for(let[t,r]of this.reportedFailures)(e<r||e-r>=ne)&&this.reportedFailures.delete(t)}rememberReportedFailure(e,t){for(;this.reportedFailures.size>=Be;){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>=Ne||this.eventCounts[e.class]>=He[e.class])){if(this.eventCounts[e.class]+=1,this.queue.push(e),this.queue.length>=j){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,j);return this.flushInFlight=this.sendBatch(e).finally(()=>{this.flushInFlight=null,this.queue.length>0&&this.scheduleFlush()}),this.flushInFlight}destroy(){this.destroyed||(this.drainQueue(),this.destroyed=!0,this.clearFlushTimer(),this.browserTransportAvailable&&(window.removeEventListener("pagehide",this.pageExitHandler),document.removeEventListener("visibilitychange",this.visibilityHandler)),this.queue.splice(0),this.reportedFailures.clear(),this.observers.clear())}disable(){this.merchantEnabled=!1,this.queue.splice(0),this.reportedFailures.clear(),this.clearFlushTimer()}drainQueue(){if(!(!this.browserTransportAvailable||this.destroyed||this.ingestionDisabled||this.queue.length===0))for(this.clearFlushTimer();this.queue.length>0;){let e=this.queue.splice(0,j);this.sendBatch(e)}}async sendBatch(e){if(!this.browserTransportAvailable||this.ingestionDisabled)return;let t=Le(e,{correlationId:this.correlationId,sdkPackage:this.sdkPackage,sdkVersion:this.sdkVersion,batchId:A()});if(Ke(t)>Ue)return;let r=typeof AbortController>"u"?null:new AbortController,o=null;try{let n=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 c=>c.status!==202?null:(await c.json().catch(()=>null))?.status==="disabled"?"disabled":null).catch(()=>null),i=new Promise(c=>{o=setTimeout(()=>{r?.abort(),c(null)},ze)});await Promise.race([n,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)}},oe=Symbol.for("@flopay/js.telemetry.reporter-factory.v1"),ie=globalThis;ie[oe]===void 0&&Object.defineProperty(ie,oe,{configurable:!0,enumerable:!1,writable:!1,value:s=>new _(s)});var me=1e3,Xe=500,Ze=15e3,et=3e3,tt=1e4,rt=1e4;function st(s){return typeof s=="object"&&s!==null}function w(s,e){return te(s?.[e])}function pe(s,e){return re(s?.[e])}function nt(s,e){let t=s?.[e];return typeof t=="number"&&Number.isFinite(t)?t:void 0}function fe(s){return new Promise(e=>setTimeout(e,s))}function L(){return new h("Checkout is still processing. Please try again shortly.","api_error",{code:"checkout_processing_timeout"})}async function S(s,e){let t=await s.json().catch(()=>null),r=st(t?.error)?t.error:null,o=pe(t,"message")??pe(r,"message")??e,n=w(t,"code")??w(t,"gatewayErrorCode")??w(r,"code")??`http_${s.status}`;return new h(o,"api_error",{code:n,statusCode:s.status})}async function ot(s){let e=s.status===400?await s.clone().json().catch(()=>null):null;return Ge(s.status,e)}function he(s){return s===400||s===422}var U=2;async function Y(s,e,t=U,r){let o;for(let n=0;;n++)try{return await fetch(s,e)}catch(i){if(e?.signal?.aborted||i instanceof Error&&i.name==="AbortError")throw i;if(o=i,n>=t)throw o;try{r?.(n+1)}catch{}await fe(150*2**n)}}var it=Symbol.for("@flopay/js.session-create.telemetry.v1");function at(s){return s[it]}function ct(s){return"now"in s||"onFirstByte"in s||"onSessionCreateFailure"in s||"onRetry"in s}function Ce(s){return{userId:s.userId,firstName:s.firstName??null,lastName:s.lastName??null,email:s.email,country:s.country??null,gender:s.gender??null,city:s.city??null,state:s.state??null,zip:s.zip??null,addressLine1:s.addressLine1??null,addressLine2:s.addressLine2??null}}function ve(s,e){e.tagsData&&(s.tagsData=e.tagsData),e.utmMetadata?.length&&(s.utmMetadata=e.utmMetadata),e.avsCheck!==void 0&&(s.avsCheck=e.avsCheck),e.checkoutType&&(s.checkoutType=e.checkoutType),e.checkoutLayout&&(s.checkoutLayout=e.checkoutLayout),e.avsConfig&&(s.avsConfig=e.avsConfig)}function ut(s,e){let t={clientId:s.clientId,checkoutVersion:E,successUrl:s.successUrl,cancelUrl:s.cancelUrl,currency:e,checkoutMode:"full",deferDataAttachment:!0};return s.captureMethod==="manual"&&(t.captureMethod=s.captureMethod),s.account.country&&(t.accountData={country:s.account.country}),ve(t,s),t}function ye(s,e,t){return{currency:e,products:t.map(r=>ge(r,e)),couponCodes:s.couponCodes??[],accountData:Ce(s.account)}}var M=class M{constructor(e,t={}){this.baseUrl=e.replace(/\/+$/,"");let r=ct(t);this.telemetryHooks=r?t:void 0,this.directTelemetry=r||t.telemetry===!1?void 0:new _({billingApiUrl:this.baseUrl,sdkVersion:E})}destroy(){this.directTelemetry?.destroy()}reportDirectFailure(e,t,r,o,n="unknown"){let i=P(e,t);this.directTelemetry?.error({...i,stage:r,requestCategory:o,paymentMethodCategory:n})}reportAccountSnapshotFailure(e,t){let r=P(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 o={[H]:E};t&&(o["x-checkout-session-token"]=t);try{let n=await Y(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}`,{headers:o},U,u=>{this.telemetryHooks?.onRetry?.("session_read",u),this.directTelemetry?.log({name:"operation.retry",stage:"session_read",requestCategory:"session_read",attempt:u})}),i=Math.max(0,this.telemetryTimestamp()-r);try{this.telemetryHooks?.onFirstByte?.(i)}catch{}let a=`${Math.floor(n.status/100)}xx`;if(this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_read",statusClass:a}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:i,durationMode:"machine",requestCategory:"session_read",statusClass:a}),!n.ok)throw await S(n,"Failed to get checkout session");let c=await n.json();return this.directTelemetry?.log({name:"session.request.completed",stage:"session_complete",requestCategory:"session_read",statusClass:a}),this.directTelemetry?.performance({stage:"session_complete",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_read",statusClass:a}),{...c,data:this.mergeCachedDisplayData(c.data)}}catch(n){throw this.directTelemetry?.error({...P(n,"NETWORK_REQUEST_FAILED"),stage:"session_read",requestCategory:"session_read"}),n}}cacheSessionDisplayData(e,t,r){B(e,t,r)}clearSessionDisplayData(e){ee(e)}async getVaultCapture(e,t){let r=`${this.baseUrl}\0${e}\0${t??""}`,o=M.activeVaultCaptureRequests.get(r);if(o)return o;let n=this.requestVaultCapture(e,t);M.activeVaultCaptureRequests.set(r,n);try{return await n}finally{M.activeVaultCaptureRequests.get(r)===n&&M.activeVaultCaptureRequests.delete(r)}}async requestVaultCapture(e,t){let r=new AbortController,o=setTimeout(()=>r.abort(),rt);this.beginDirectTelemetryCheckout(e);let n=this.telemetryTimestamp();this.directTelemetry?.log({name:"vault.capture.requested",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card"});let i={"Content-Type":"application/json"};t&&(i["x-checkout-session-token"]=t);try{let a=await Y(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/vault/capture`,{method:"POST",headers:i,signal:r.signal},U,u=>{this.telemetryHooks?.onRetry?.("vault_capture",u),this.directTelemetry?.log({name:"operation.retry",stage:"vault_request",requestCategory:"vault_capture",paymentMethodCategory:"card",attempt:u})});if(!a.ok)throw await S(a,"Failed to load the secure card form");let c=await a.json();return this.directTelemetry?.performance({stage:"vault_request",durationMs:Math.max(0,this.telemetryTimestamp()-n),durationMode:"machine",requestCategory:"vault_capture",paymentMethodCategory:"card",statusClass:"2xx"}),this.toVaultBlock(c)}catch(a){let c=r.signal.aborted?new h("Timed out while loading the secure card form. Please try again.","api_error",{code:"vault_capture_timeout"}):a;throw this.reportDirectFailure(c,"VAULT_LOAD_FAILED","vault_request","vault_capture","card"),c}finally{clearTimeout(o)}}async getUnifiedCheckoutSession(e,t){let r=await this.getCheckoutSession(e,t),o=this.normalizeRawSession(r.data),n=r.vault;return n&&o.data.session&&(o.data.session.vault=this.toVaultBlock(n)),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:n,...i}=t,a;try{a=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(t.sessionId)}/process`,{method:"POST",headers:{"Content-Type":"application/json","x-checkout-session-token":n},body:JSON.stringify(i)})}catch(c){throw this.reportDirectFailure(c,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),c}if(!a.ok&&a.status!==202){let c=await ot(a);return c?this.directTelemetry?.terminal({outcome:c,stage:"processing",requestCategory:"process_payment",statusClass:"4xx"}):this.directTelemetry?.error({errorCode:"PAYMENT_PROCESSING_FAILED",stage:"processing",requestCategory:"process_payment",statusClass:k(a.status),failureCategory:a.status>=500?"server_error":void 0}),a}try{let c=await this.resolveProcessResponse(a,t.sessionId,{...r,nonce:n});return this.directTelemetry?.log({name:"payment.processing.completed",stage:"processing",requestCategory:"process_payment",statusClass:k(c.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-o),durationMode:"machine",requestCategory:"process_payment",statusClass:k(c.status)}),c}catch(c){throw c instanceof h&&c.code==="checkout_processing_timeout"||this.reportDirectFailure(c,"PAYMENT_PROCESSING_FAILED","processing","process_payment"),c}}async patchAccountSnapshot(e,t,r,o){this.beginDirectTelemetryCheckout(e);let n=this.telemetryTimestamp();this.directTelemetry?.log({name:"operation.state_transition",stage:"processing",requestCategory:"account_snapshot"});let i=o?.timeoutMs??tt,a=new AbortController,c=()=>a.abort();o?.signal&&(o.signal.aborted?a.abort():o.signal.addEventListener("abort",c,{once:!0}));let u=setTimeout(()=>a.abort(),i);try{let l;try{l=await Y(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/account`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t},body:JSON.stringify(r),signal:a.signal},U,p=>{this.telemetryHooks?.onRetry?.("account_snapshot",p),this.directTelemetry?.log({name:"operation.retry",stage:"processing",requestCategory:"account_snapshot",attempt:p})})}finally{clearTimeout(u),o?.signal?.removeEventListener("abort",c)}if(!l.ok)throw await S(l,"Failed to persist account snapshot");this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-n),durationMode:"machine",requestCategory:"account_snapshot",statusClass:"2xx"})}catch(l){throw this.reportAccountSnapshotFailure(l,o?.telemetryMode??"blocking"),l}}async createSessionIntent(e,t,r,o){if(!t)throw new h("createSessionIntent requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let n=r,i=n.paymentMethodType,a=typeof i=="string"&&i.trim().toLowerCase()==="card",c=typeof i=="string"&&i.length>0&&!a&&(typeof n.paymentMethodId=="string"||n.paymentMethodId===null),u=n.provider==="stripe"&&(n.paymentMethodCategory==="wallet"||n.paymentMethodCategory==="apm")&&(n.intentKind==="payment"||n.intentKind==="setup"),l=n.provider==="paypal"&&n.paymentMethodCategory==="wallet"&&n.paymentMethodId===null&&(n.paymentMethodType==="paypal"&&n.intentKind==="payment"||n.paymentMethodType===$&&(n.intentKind==="payment"||n.intentKind==="setup"));if(!c||!u&&!l)throw new h("Only wallet, APM, and PayPal session intents are supported.","validation_error",{code:"InvalidSessionIntentRequest"});let p=n.authorizationAttemptId;if(p!==void 0&&!ue(p))throw new h("authorizationAttemptId must be a v4 UUID identifying one buyer authorization attempt.","validation_error",{code:"InvalidAuthorizationAttemptId",param:"authorizationAttemptId"});let d=ue(p)?p:Je();this.beginDirectTelemetryCheckout(e);let y=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,[ce]:o?.idempotencyKey||d},f=!1;try{let v=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/intents`,{method:"POST",headers:C,body:JSON.stringify({...r,authorizationAttemptId:d}),signal:o?.signal});if(!v.ok){f=!0;let N=await S(v,"Failed to create checkout intent"),Pe=P(N,"PAYMENT_PROCESSING_FAILED");throw he(N.statusCode)?this.directTelemetry?.terminal({outcome:"validation_rejected",stage:"processing",requestCategory:"intent_create",statusClass:"4xx"}):this.directTelemetry?.error({...Pe,stage:"processing",requestCategory:"intent_create"}),N}let T=(await v.json()).data;if(!T||typeof T!="object")throw new h("Invalid checkout intent response.","api_error",{code:"InvalidSessionIntentResponse"});let m=T,X=m.paymentMethodType,Ee=(m.paymentMethodCategory==="wallet"||m.paymentMethodCategory==="apm")&&typeof X=="string"&&X.trim().toLowerCase()!=="card"&&(typeof m.paymentMethodId=="string"||m.paymentMethodId===null)&&typeof m.providerObjectId=="string",we=m.provider==="stripe"&&(m.intentKind==="payment"||m.intentKind==="setup")&&typeof m.clientSecret=="string",Re=m.provider==="paypal"&&m.paymentMethodCategory==="wallet"&&m.paymentMethodId===null&&(m.paymentMethodType==="paypal"&&m.intentKind==="payment"&&(m.providerObjectType==="order"||m.providerObjectType==="subscription")||m.paymentMethodType===$&&m.intentKind==="payment"&&m.providerObjectType==="order"||m.paymentMethodType===$&&m.intentKind==="setup"&&m.providerObjectType==="setup_token")&&m.clientSecret===null,Ie=m.provider===r.provider&&m.paymentMethodCategory===r.paymentMethodCategory&&m.paymentMethodType===r.paymentMethodType&&m.paymentMethodId===r.paymentMethodId&&m.intentKind===r.intentKind;if(!Ee||!we&&!Re||!Ie)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:k(v.status)}),this.directTelemetry?.performance({stage:"processing",durationMs:Math.max(0,this.telemetryTimestamp()-y),durationMode:"machine",requestCategory:"intent_create",statusClass:k(v.status)}),m}catch(v){throw f||this.reportDirectFailure(v,"PAYMENT_PROCESSING_FAILED","processing","intent_create"),v}}async reportSessionIntentDecline(e,t,r,o){if(!t)throw new h("reportSessionIntentDecline requires the checkout session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let n=r,i=n.providerDeclineReason,a=n.paymentMethodType,c=typeof i=="string"&&/^[a-z0-9][a-z0-9_.:-]{0,63}$/i.test(i)&&!/^(?:pm|pi|seti|tok|src|cus|sess|sk|pk)_/i.test(i),u=typeof a=="string"&&a.length>0&&a.trim().toLowerCase()!=="card"&&c,l=n.provider==="stripe"&&(n.paymentMethodCategory==="wallet"||n.paymentMethodCategory==="apm"),p=n.provider==="paypal"&&n.paymentMethodCategory==="wallet"&&n.paymentMethodType==="paypal";if(!u||!l&&!p)throw new h("Invalid non-card decline classification.","validation_error",{code:"InvalidSessionIntentDeclineRequest"});let d=p?{provider:"paypal",paymentMethodCategory:"wallet",paymentMethodType:"paypal",providerDeclineReason:i}:{provider:"stripe",paymentMethodCategory:n.paymentMethodCategory,paymentMethodType:n.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(d),signal:o?.signal});if(!y.ok)throw await S(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,n=t?.limit??1,i=new URLSearchParams({email:e,page:String(o),limit:String(n),sortField:"createdAt",sortDirection:"DESC"});try{let a=await fetch(`${this.baseUrl}/v1/payments?${i.toString()}`,{method:"GET",signal:t?.signal,keepalive:!0});if(!a.ok)throw new h("Failed to fetch payments","api_error",{statusCode:a.status});let c=await a.json();return this.directTelemetry?.log({name:"operation.recovery.completed",stage:"recovery",requestCategory:"other",paymentMethodCategory:"saved",statusClass:"2xx"}),this.directTelemetry?.performance({stage:"recovery",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"other",paymentMethodCategory:"saved",statusClass:"2xx"}),c}catch(a){throw this.reportDirectFailure(a,"RECOVERY_FAILED","recovery","other","saved"),a}}async createAndFetchSession(e){if(We(e)){if(!le(e.account.email?.trim()))throw new h("createAndFetchSession requires a valid buyer email. Use createDetachedSession and call claim() after collecting a valid one.","validation_error",{code:"BuyerEmailCollectionRequired",param:"account.email"});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 n=await this.createAndFetchSessionRequest(e,t,r.signal,o);return this.adoptDirectTelemetryCheckout(n.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}),n}catch(n){throw this.reportSessionCreateFailure(n,t,o),n}finally{r.clear()}}async createAndFetchSessionRequest(e,t,r,o){let n=e.products??K(e.items,e.subscriptions);ae({captureMethod:e.captureMethod,products:n});let i=G(e.currency,e.items,e.subscriptions,n);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 a={clientId:e.clientId,checkoutVersion:E,successUrl:e.successUrl,cancelUrl:e.cancelUrl,currency:i,checkoutMode:e.checkoutMode??"full",products:n.map(d=>ge(d,i)),accountData:Ce(e.account),couponCodes:e.couponCodes??[]};e.captureMethod==="manual"&&(a.captureMethod=e.captureMethod),e.tokenizedData&&(a.tokenizedData=e.tokenizedData),ve(a,e);let u=await(await this.postCheckoutSessionCreate(a,e,t,r,o)).json();if(u.data&&"gateways"in u.data){this.autoCacheDisplayData(u.data.uuid,e);let d=this.mergeCachedDisplayData(u.data),y=this.normalizeRawSession(d);return u.vault&&y.data.session&&(y.data.session.vault=this.toVaultBlock(u.vault)),{...y,autoProcessingError:u.autoProcessingError,autoProcessingAttempted:u.autoProcessingAttempted,autoProcessingPending:u.autoProcessingPending}}let l=u.data?.uuid;if(!l)throw new h("No session ID returned","api_error",{code:"InvalidCheckoutSessionResponse"});return this.autoCacheDisplayData(l,e),this.adoptDirectTelemetryCheckout(l),{...await this.getUnifiedCheckoutSession(l),autoProcessingError:u.autoProcessingError,autoProcessingAttempted:u.autoProcessingAttempted,autoProcessingPending:u.autoProcessingPending}}async postCheckoutSessionCreate(e,t,r,o,n){let i={"Content-Type":"application/json",[H]:E},a=Qe(t.idempotencyKey);a&&(i[ce]=a);let c,u=!1,l=at(t),p=d=>{try{this.telemetryHooks?.onRetry?.("session_create",d),this.directTelemetry?.log({name:"operation.retry",stage:"session_create",requestCategory:"session_create",attempt:d})}catch{}};for(let d=0;d<3;d++){n.attempt=d;try{l?.onAttempt?.(d)}catch{}try{c=await fetch(`${this.baseUrl}/v1/checkouts/sessions?expand=true`,{method:"POST",headers:i,body:JSON.stringify(e),signal:o})}catch(f){if(n.statusClass=o.aborted||f instanceof Error&&f.name==="AbortError"?"timeout":"network_error",o.aborted||f instanceof Error&&f.name==="AbortError"||d>=2)throw f;let v=d+1;p(v),await q(d,o);continue}let y=k(c.status);if(n.statusClass=y,u||(u=!0,this.directTelemetry?.log({name:"session.request.first_byte",stage:"session_first_byte",requestCategory:"session_create",statusClass:y,attempt:d}),this.directTelemetry?.performance({stage:"session_first_byte",durationMs:Math.max(0,this.telemetryTimestamp()-r),durationMode:"machine",requestCategory:"session_create",statusClass:y,attempt:d})),c.status===204)throw new h("Session auto-completed \u2014 payment method already on file","api_error",{code:"session_auto_completed"});if(c.ok)break;let C=await S(c,"Failed to create checkout session");if(C.code===Ye&&d<2){p(d+1),await q(d,o);continue}throw C}if(!c)throw new TypeError("Checkout-session creation exhausted its retry budget.");return c}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 n=e.products??K(e.items,e.subscriptions);try{ae({captureMethod:e.captureMethod,products:n})}catch(g){throw r.clear(),this.reportSessionCreateFailure(g,t,o),g}let i=G(e.currency,e.items,e.subscriptions,n);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"});try{ye(e,i,n)}catch(g){throw r.clear(),this.reportSessionCreateFailure(g,t,o),g}let a,c;try{if(c=await(await this.postCheckoutSessionCreate(ut(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(g){throw r.clear(),this.reportSessionCreateFailure(g,t,o),g}let u=a.data.session?.id??c.data.uuid??"",l=a.data.session?.clientSecret??c.data.nonce??"";if(!u||!l){r.clear();let g=new h("Checkout session shell was created without a session id or nonce.","api_error",{code:"InvalidCheckoutSessionResponse"});throw this.reportSessionCreateFailure(g,t,o),g}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=!e.account.email?.trim();p&&r.clear();let d,y,C=new Promise((g,T)=>{d=g,y=T}),f=!1,v=(g={})=>{if(f)return C;let T={...e,account:{...e.account,...g,email:g.email?.trim()||e.account.email?.trim()}};if(!le(T.account.email))return Promise.reject(new h("A valid buyer email is required before claiming checkout.","validation_error",{code:"BuyerEmailCollectionRequired",param:"account.email"}));f=!0;let m=p?R(e.timeoutMs??12e3):r;return this.claimCheckoutSession(u,l,ye(T,i,n),{params:T,startedAt:p?this.telemetryTimestamp():t,deadline:m,createAttempt:o.attempt}).then(d,y),C};return p||v(),C.catch(()=>{}),{shell:a,sessionId:u,nonce:l,claimed:C,claim:v}}async claimCheckoutSession(e,t,r,o){let n=o?.startedAt??this.telemetryTimestamp(),i=this.telemetryTimestamp(),a=o?.deadline??R(12e3),c=JSON.stringify(r),u="unknown",l=0;this.directTelemetry?.log({name:"session.claim.started",stage:"session_claim",requestCategory:"session_claim"});try{let p;for(l=0;l<3;l++){try{p=await fetch(`${this.baseUrl}/v1/checkouts/sessions/${encodeURIComponent(e)}/claim`,{method:"PATCH",headers:{"Content-Type":"application/json","x-checkout-session-token":t,[H]:E},body:c,signal:a.signal})}catch(C){let f=a.signal.aborted||C instanceof Error&&C.name==="AbortError";if(u=f?"timeout":"network_error",f||l>=2)throw C;try{this.telemetryHooks?.onRetry?.("session_claim",l+1),this.directTelemetry?.log({name:"operation.retry",stage:"session_claim",requestCategory:"session_claim",attempt:l+1})}catch{}await q(l,a.signal);continue}if(u=k(p.status),p.ok)break;throw await S(p,"Failed to attach checkout session data")}if(!p)throw new TypeError("Checkout-session claim exhausted its retry budget.");let d=await p.json();if(!d.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(d.data.uuid??e,o.params);let y=this.normalizeRawSession(this.mergeCachedDisplayData(d.data));return d.vault&&y.data.session&&(y.data.session.vault=this.toVaultBlock(d.vault)),this.directTelemetry?.log({name:"session.claim.completed",stage:"session_claim",requestCategory:"session_claim",statusClass:u}),this.directTelemetry?.performance({stage:"session_claim",durationMs:Math.max(0,this.telemetryTimestamp()-i),durationMode:"machine",requestCategory:"session_claim",statusClass:u,attempt:l}),this.directTelemetry?.log({name:"session.request.completed",stage:"session_create",requestCategory:"session_create",statusClass:u}),this.directTelemetry?.performance({stage:"session_create",durationMs:Math.max(0,this.telemetryTimestamp()-n),durationMode:"machine",requestCategory:"session_create",statusClass:u,attempt:o?.createAttempt??l}),y}catch(p){throw this.reportSessionCreateFailure(p,n,{attempt:l,statusClass:u},"session_claim"),p}finally{a.clear()}}reportSessionCreateFailure(e,t,r,o="session_create"){if(!(e instanceof h&&e.code==="session_auto_completed"))try{this.telemetryHooks?.onSessionCreateFailure?.(e)}catch{}let n=P(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:n.statusClass,attempt:r.attempt}),e instanceof h&&e.type==="validation_error"||e instanceof h&&he(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({...n,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??Ze,n=Date.now()+o,i=this.clampRetryAfterMs(t?.initialDelayMs??me),a=0;try{for(;;){let c=n-Date.now();if(c<=0)throw L();if(i>0){try{a+=1,this.telemetryHooks?.onRetry?.("session_read",a),this.directTelemetry?.log({name:"operation.retry",stage:"recovery",requestCategory:"session_read",paymentMethodCategory:"saved",attempt:a})}catch{}if(await fe(Math.min(i,c)),Date.now()>=n)throw L()}let u=await this.getUnifiedCheckoutSession(e,t?.nonce),l=u.data.session?.status;if(l==="authorized"||l==="complete"||l==="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"}),u;if(Date.now()>=n)throw L();i=this.clampRetryAfterMs(Math.max(i*2,Xe))}}catch(c){throw c instanceof h&&c.code==="checkout_processing_timeout"&&this.reportDirectFailure(c,"RECOVERY_FAILED","recovery","session_read","saved"),c}}normalizeRawSession(e){let t=e.gateways??{},r=[],o={session:this.toCheckoutSession(e)},n=t.stripe;if(n?.publishableKey){r.push("stripe");let c=[e.stripeClientSecret,n.stripeClientSecret].find(u=>typeof u=="string"&&u.length>0);o.stripe={clientSecret:c??"",publishableKey:n.publishableKey??void 0,paypalPublishableKey:n.paypalPublishableKey??void 0,environment:n.environment,enabledPaymentMethods:Array.isArray(n.enabledPaymentMethods)?n.enabledPaymentMethods.filter(u=>typeof u=="string"):void 0}}let i=t.paypal;return i?.publishableKey&&(r.push("paypal"),o.paypal={publishableKey:i.publishableKey,environment:i.environment,providerObjectType:i.providerObjectType}),{providers:r,mode:"tokenize",data:o,raw:{data:e}}}toCheckoutSession(e){let t=e.products??[],r=typeof e.totalAmount=="number"&&Number.isFinite(e.totalAmount),o=t.reduce((u,l)=>u+(l.overrideAmount??l.totalAmount??0),0),n=r?e.totalAmount:o,i=Math.round(n*100),a=e.currency??t[0]?.currency??"USD",c=e.checkoutMode==="setup"?"setup":t.some(u=>u.type==="subscription")?"subscription":"payment";return{id:e.uuid,clientSecret:e.nonce,mode:c,status:this.toCheckoutSessionStatus(e.status),amount:i,currency:a,captureMethod:e.captureMethod,paymentId:e.paymentId,authorizationExpiresAt:e.authorizationExpiresAt,failureOutcome:de(e.outcome)??de(e.failureReason)??(e.status==="expired"&&e.captureMethod==="manual"?"authorization_expired":void 0),customer:{id:e.accountData.userId,email:e.accountData.email,firstName:e.accountData.firstName,lastName:e.accountData.lastName,country:e.accountData.country??void 0,city:e.accountData.city??void 0,state:e.accountData.state??void 0,zip:e.accountData.zip??void 0,gender:e.accountData.gender??void 0,line1:e.accountData.addressLine1??void 0,line2:e.accountData.addressLine2??void 0},metadata:{},checkoutMode:e.checkoutMode,providerPaymentMethodId:typeof e.providerPaymentMethodId=="string"?e.providerPaymentMethodId:null,products:t.map(u=>({...u,totalAmount:typeof u.totalAmount=="number"?u.totalAmount:void 0,overrideAmount:typeof u.overrideAmount=="number"?u.overrideAmount:null,currency:typeof u.currency=="string"?u.currency:void 0,metadata:u.metadata??null})),successUrl:e.successUrl,cancelUrl:e.cancelUrl,coupons:e.coupons,subtotalAmount:e.subtotalAmount,discountAmount:e.discountAmount,totalAmount:e.totalAmount,createdAt:e.createdAt,gateways:e.gateways,accountData:e.accountData,tagsData:e.tagsData}}toVaultBlock(e){return{html:typeof e.html=="string"?e.html:void 0,url:typeof e.url=="string"?e.url:void 0,messageToken:typeof e.messageToken=="string"?e.messageToken:void 0,expectedOrigin:typeof e.expectedOrigin=="string"?e.expectedOrigin:void 0}}toCheckoutSessionStatus(e){return e==="completed"?"complete":e==="authorized"?"authorized":e==="expired"?"expired":"open"}async resolveProcessResponse(e,t,r){if(e.status!==202)return e;let o=await e.json().catch(()=>null),n=this.toCheckoutProcessingPending(o,e,t),i=await this.waitForCheckoutSessionCompletion(n.sessionId,{initialDelayMs:n.retryAfterMs,timeoutMs:r?.pollTimeoutMs,nonce:r?.nonce});if(i.data.session?.status==="complete")return new Response(null,{status:204,statusText:"No Content"});if(i.data.session?.status==="authorized"){let a=i.data.session;return new Response(JSON.stringify({status:"authorized",paymentId:a.paymentId,sessionId:a.id||t,authorizationExpiresAt:a.authorizationExpiresAt}),{status:200,headers:{"Content-Type":"application/json"}})}if(i.data.session?.status==="expired"){let a=i.data.session.failureOutcome==="authorization_expired"||i.data.session.captureMethod==="manual";throw new h(a?"Authorization has expired.":"Checkout session has expired.","api_error",{code:a?"authorization_expired":"checkout_session_expired"})}throw L()}toCheckoutProcessingPending(e,t,r){let o=t.headers.get("Retry-After"),n=o===null||o.trim()===""?void 0:Number(o),i=n!==void 0&&Number.isFinite(n)?n*1e3:void 0;return{type:"checkout_processing",sessionId:w(e,"sessionId")??r,retryAfterMs:this.clampRetryAfterMs(nt(e,"retryAfterMs")??i??me),statusUrl:w(e,"statusUrl"),sessionUrl:w(e,"sessionUrl")}}clampRetryAfterMs(e){return Math.max(0,Math.min(e,et))}autoCacheDisplayData(e,t){if(!e)return;let r=t.products??K(t.items,t.subscriptions);if(r.length===0&&!t.currency)return;let o=t.products!==void 0,n=G(t.currency,o?void 0:t.items,o?void 0:t.subscriptions,r);B(e,{currency:n??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??n??void 0}))})}mergeCachedDisplayData(e){let t=Z(e.uuid),r=new Map,o=i=>i?`code:${i}`:void 0;for(let i of t?.products??[]){let a=o(i.code);a&&r.set(a,i)}let n=(e.products??[]).map(i=>{let a=o(i.code),c=a?r.get(a):void 0;return{...i,name:i.name??c?.name??null,totalAmount:i.totalAmount??c?.totalAmount,overrideAmount:i.overrideAmount??c?.overrideAmount,currency:i.currency??c?.currency}});return{...e,currency:e.currency??t?.currency,products:n}}};M.activeVaultCaptureRequests=new Map;var W=M;function Et(s,e){let t=W;return new t(s,e)}import{buildTelemetryErrorEvent as lt,buildTelemetryLogEvent as dt,buildTelemetryTerminalEvent as ke,FloPayError as Te,resolveBillingApiUrl as be,SDK_VERSION as _e}from"@flopay/shared";var Q="flopay-vault",Se={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 D(s){let e={class:s.class,stage:s.stage};"code"in s&&(e.code=s.code),"provider"in s&&s.provider&&(e.provider=s.provider),"paymentMethodCategory"in s&&s.paymentMethodCategory&&(e.paymentMethodCategory=s.paymentMethodCategory),"outcome"in s&&(e.outcome=s.outcome),"durationMs"in s&&s.durationMs!==void 0&&(e.durationMs=s.durationMs),"durationMode"in s&&s.durationMode&&(e.durationMode=s.durationMode);try{globalThis.Sentry?.addBreadcrumb?.({category:"flopay.telemetry",level:s.class==="technical_error"?"error":"info",message:s.class==="lifecycle"?s.name:s.class==="technical_error"?s.code:s.class==="expected_outcome"?s.outcome:"sdk.performance",data:e})}catch{}}function V(s,e){return dt({eventId:"11111111-1111-4111-8111-111111111111",name:s,stage:e,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}function Me(s){return s?{errorCode:"VAULT_SUBMIT_FAILED",stage:"vault_submit",failureCategory:"provider_runtime"}:{errorCode:"VAULT_LOAD_FAILED",stage:"vault_mount",failureCategory:"provider_runtime"}}function Ae(s,e,t="checkout"){return t==="card_setup"?s.type==="decline"?"card_setup_declined":"card_setup_succeeded":s.type==="decline"?"payment_declined":s.outcome==="authorized"||e==="manual"?"payment_authorized":"payment_succeeded"}function mt(s,e,t,r="checkout"){let{type:o}=s;if(o==="complete"||o==="decline")return ke({eventId:"22222222-2222-4222-8222-222222222222",outcome:Ae(s,t,r),sequence:0,provider:"pcivault",paymentMethodCategory:"card"});if(o==="error"){let a=Me(e);return lt({eventId:"33333333-3333-4333-8333-333333333333",...a,sequence:0,provider:"pcivault",paymentMethodCategory:"card"})}let[n,i]=Se[o];return V(n,i)}function pt(s){if(typeof s!="object"||s===null)return!1;let e=s;return e.source===Q&&(e.type==="ready"||e.type==="submitting"||e.type==="blocked"||e.type==="complete"||e.type==="decline"||e.type==="error"||e.type==="action_required")}function ht(s){if(typeof s!="object"||s===null)return;let e=s,t=e.status;if(!(typeof e.id!="string"||e.id.trim()===""||typeof e.brand!="string"||e.brand.trim()===""||typeof e.lastFour!="string"||!/^\d{4}$/.test(e.lastFour)||typeof e.expiryMonth!="number"||!Number.isInteger(e.expiryMonth)||e.expiryMonth<1||e.expiryMonth>12||typeof e.expiryYear!="number"||!Number.isInteger(e.expiryYear)||e.expiryYear<1970||e.expiryYear>9999||t!=="pending"&&t!=="active"&&t!=="deleted"))return{id:e.id,brand:e.brand,lastFour:e.lastFour,expiryMonth:e.expiryMonth,expiryYear:e.expiryYear,status:t}}function yt(s){if(typeof s!="object"||s===null)return!1;let e=s;return e.source===Q&&e.type==="validation"&&Array.isArray(e.messages)}function gt(s){if(typeof s!="object"||s===null)return!1;let e=s;return e.source===Q&&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 _({billingApiUrl:be(),sdkVersion:_e}):void 0)}async mount(e,t){this.ownsTelemetryReporter&&!this.telemetryReporter&&(this.telemetryReporter=new _({billingApiUrl:be(),sdkVersion:_e}));let r=this.telemetryReporter;if(this.config.operation==="card_setup"&&r&&this.setupTelemetryReporter!==r){this.setupTelemetryReporter=r;try{r.beginCheckout({checkoutMode:"setup"})}catch{}}if(this.mountStartedAt=this.telemetryReporter?.now?.()??b(),this.vaultReadyReported=!1,this.submissionStarted=!1,this.submissionStartedAt=null,typeof window>"u"||typeof document>"u")throw this.reportVaultLoadFailure(),new Te("The vault card form is only available in the browser.","api_error",{code:"card_capture_no_window"});if(!t?.html?.trim())throw this.reportVaultLoadFailure(),new Te("No vault capture widget HTML was provided to mount the secure card form.","api_error",{code:"card_capture_no_widget_html"});this.container=e,this.messageToken=t.messageToken??null,this.expectedOrigin=t.expectedOrigin??this.config.expectedOrigin??null,this.theme=t.theme??null;try{this.attachMessageListener(),this.injectWidget(e,t.html)}catch(o){throw this.reportVaultLoadFailure(),o}this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder(),D(V("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 n=document.createElement("script");for(let i of Array.from(o.attributes))n.setAttribute(i.name,i.value);n.text=o.text,o.replaceWith(n)}}attachMessageListener(){if(this.messageHandler)return;let e=t=>{if(this.expectedOrigin&&t.origin!==this.expectedOrigin)return;let r=t.data;if(gt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;this.applyHeight(r.height);return}if(yt(r)){if(this.messageToken&&r.messageToken!==this.messageToken)return;let c=r.messages.filter(u=>typeof u=="string"&&u.trim()).join(" ");this.emit("validation",{sessionId:this.config.sessionId,message:c||void 0});return}if(!pt(r)||this.messageToken&&r.messageToken!==this.messageToken)return;let o=this.config.sessionId,n=typeof r.sessionId=="string"?r.sessionId:void 0;if(o&&n&&n!==o||(r.type==="complete"||r.type==="decline")&&o&&n!==o)return;let i=ht(r.paymentMethod),a={...r.sessionId??this.config.sessionId?{sessionId:r.sessionId??this.config.sessionId}:{},...r.outcome?{outcome:r.outcome}:{},...r.paymentId?{paymentId:r.paymentId}:{},...r.authorizationExpiresAt?{authorizationExpiresAt:r.authorizationExpiresAt}:{},...r.failureOutcome?{failureOutcome:r.failureOutcome}:{},...r.intentId?{intentId:r.intentId}:{},...r.declineReason?{declineReason:r.declineReason}:{},...r.message?{message:r.message}:{},...i?{paymentMethod:i}:{}};r.type==="submitting"&&(this.submissionStarted=!0,this.submissionStartedAt=this.telemetryReporter?.now?.()??b()),D(mt(r,this.submissionStarted,this.config.captureMethod,this.config.operation)),this.reportOutcome(r),r.type==="ready"&&(this.postTheme(),this.postSubmitGate(),this.postCardFieldOrder()),r.type==="action_required"&&r.nextActionRedirectUrl&&this.showActionRequiredOverlay(r.nextActionRedirectUrl),(r.type==="complete"||r.type==="decline"||r.type==="error"||r.type==="submitting")&&this.hideActionRequiredOverlay(),r.type!=="action_required"&&this.emit(r.type,a)};this.messageHandler=e,window.addEventListener("message",e)}reportOutcome(e){let t=this.telemetryReporter;if(!t)return;let{type:r}=e;if(r==="ready"&&!this.vaultReadyReported&&(this.vaultReadyReported=!0,t.performance({stage:"vault_ready",durationMs:Math.max(0,t.now()-this.mountStartedAt),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"})),r==="complete"||r==="decline"){t.log({name:"vault.terminal",stage:"completion",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:Ae(e,this.config.captureMethod,this.config.operation),provider:"pcivault",paymentMethodCategory:"card"});return}if(r==="error"){let i=Me(this.submissionStarted);t.log({name:"vault.terminal",stage:i.stage,provider:"pcivault",paymentMethodCategory:"card"}),t.error({...i,provider:"pcivault",paymentMethodCategory:"card"});return}if(r==="action_required"){t.log({name:"vault.action.required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"}),t.log({name:"vault.three_ds.handoff",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});let i=this.submissionStartedAt;this.submissionStartedAt=null,i!==null&&t.performance({stage:"three_ds_handoff",durationMs:Math.max(0,t.now()-i),durationMode:"machine",provider:"pcivault",paymentMethodCategory:"card"}),t.terminal({outcome:"action_required",stage:"three_ds_handoff",provider:"pcivault",paymentMethodCategory:"card"});return}let[o,n]=Se[r];t.log({name:o,stage:n,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 n=i=>{if(i.source!==r.contentWindow)return;let a=i.data;if(!a||typeof a!="object")return;let c=a;c.source==="flopay-vault-3ds-return"&&(D(V("vault.three_ds.returned","three_ds_return")),this.telemetryReporter?.log({name:"vault.three_ds.returned",stage:"three_ds_return",provider:"pcivault",paymentMethodCategory:"card"}),this.hideActionRequiredOverlay(),this.postActionCompleted(c.status))};window.addEventListener("message",n),this.threeDsReturnHandler=n,document.body.appendChild(t),this.actionOverlay=t,D(V("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=ke({eventId:"77777777-7777-4777-8777-777777777777",outcome:"customer_abandoned",stage:"three_ds_handoff",sequence:0,provider:"pcivault",paymentMethodCategory:"card"});D(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 Pt(s,e){let t=J;return new t(s,{reporter:e})}export{te as a,R as b,q as c,B as d,Z as e,ee as f,b as g,_ as h,it as i,W as j,Et as k,J as l,Pt as m};