PageSourceSearch

https://www.doodly.com/assets/projects/user_pages/stripe-checkout-4J37BNBN.js

js doodly.com collected 2026-09-24 10:09:06 UTC 78,261 bytes, 1,982 lines download raw bytes

1import {
2  CheckoutConfigurationErrorV1,
3  CheckoutCriticalError,
4  CheckoutExistingOrders,
5  CheckoutLoadingV1,
6  CheckoutMultiStepV2,
7  CheckoutShippingProfileSelectV1,
8  CheckoutSubmitButtonV1,
9  CheckoutSubmitNotificationV1,
10  CheckoutTosV1,
11  ERROR_CODES,
12  STRIPE_SKIP_SHIPPING_ID,
13  addressErrors,
14  buildCustomFields,
15  buildProductSelectBatched,
16  calculateStripeChangeResolveDetails,
17  calculateStripeLineItems,
18  checkValidCustomFields,
19  collectLeads,
20  contactErrors,
21  convertAddressFromSession,
22  convertAddressFromStripe,
23  convertToStripeAddress,
24  getCartEstimatedTotal,
25  getStripeMode,
26  hasErrors,
27  hasPhysicalProducts,
28  hasUpgradeDowngradeItems,
29  isActionableCheckoutError,
30  makeCurrentPageFetcher,
31  normalizeServerCheckoutError,
32  parseCssVars,
33  productErrors,
34  renderedHref,
35  scrollToFirstVisibleError,
36  serverCheckoutErrorMessage,
37  setupOrderSummaries,
38  shippingOptionErrors,
39  tosErrors
40} from "./chunk-5JJNRIKL.js";
41import "./chunk-W3RKY5WP.js";
42import {
43  CFFetcherError,
44  Fetcher,
45  MANUALLY_ABORTED,
46  checkoutNonceParams,
47  fetchCheckoutNonce,
48  init_fetcher,
49  init_nonce,
50  isBackendError,
51  isFetcherError,
52  isResponseError
53} from "./chunk-YSVSPNWW.js";
54import "./chunk-372FPXG6.js";
55import {
56  atom,
57  computed,
58  deepEqual,
59  formatNumberToCurrency,
60  init_general,
61  init_nanostores
62} from "./chunk-BY72GGKB.js";
63import "./chunk-4AIF3XZW.js";
64import "./chunk-Y32E43UA.js";
65import {
66  init_input_v1
67} from "./chunk-7HBS56XK.js";
68import {
69  IntlTel_initPhoneInput,
70  init_cf_utils,
71  uuidv4
72} from "./chunk-KIZY5IRN.js";
73import "./chunk-5NUE6T5P.js";
74import {
75  CF2Component,
76  init_runtime,
77  registerComponent
78} from "./chunk-NQUHJ6NR.js";
79import {
80  __publicField,
81  init_define_process
82} from "./chunk-RFSPGZ3L.js";
83
84// projects/lib/packages/yggdrasil-blueprints/__generated__/packs/stripe-checkout.ts
85init_define_process();
86
87// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/stripe-checkout.ts
88init_define_process();
89init_input_v1();
90
91// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/stripeCheckout.ts
92init_define_process();
93
94// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/summary.ts
95init_define_process();
96init_general();
97init_fetcher();
98var orderPreviewFetcher = makeCurrentPageFetcher({
99  customEvent: "CF2:OrderPreview"
100});
101var lastOrderPreviewData;
102var lastOrderPreviewResponse;
103function hasValidDataForLineItemSubtotal(payload) {
104  const { cart } = payload;
105  const productSelectErrors = productErrors(cart, true);
106  return !hasErrors(productSelectErrors);
107}
108async function fetchOrderPreview(payload, onStart) {
109  const dataToPreview = buildOrderPreviewPayload(payload);
110  if (lastOrderPreviewResponse && deepEqual(dataToPreview, lastOrderPreviewData)) {
111    return lastOrderPreviewResponse;
112  }
113  lastOrderPreviewData = dataToPreview;
114  if (onStart) onStart();
115  const response = await orderPreviewFetcher.post("/order_preview", dataToPreview);
116  if (!isResponseError(response)) {
117    lastOrderPreviewResponse = response;
118    return lastOrderPreviewResponse;
119  } else {
120    return response;
121  }
122}
123function processOrderPreviewResponseForSummary(summaryData) {
124  let nextInvoiceText;
125  if (summaryData.next_invoice_date) {
126    const nextInvoiceDate = new Date(summaryData.next_invoice_date);
127    const currentDate = /* @__PURE__ */ new Date();
128    const diff = nextInvoiceDate.getTime() - currentDate.getTime();
129    if (diff > 5 * 60 * 1e3) {
130      if (diff < 24 * 60 * 60 * 1e3) {
131        nextInvoiceText = nextInvoiceDate.toLocaleString();
132      } else {
133        nextInvoiceText = nextInvoiceDate.toLocaleDateString();
134      }
135    }
136  }
137  return {
138    currency: summaryData.currency,
139    line_items: summaryData.line_items,
140    total: {
141      amount: parseFloat(summaryData.total_amount?.amount),
142      formatted: summaryData.total_amount_formatted,
143      amount_cents: summaryData.total_amount_cents
144    },
145    discount: {
146      amount: parseFloat(summaryData.discount_amount?.amount),
147      formatted: summaryData.discount_amount_formatted,
148      amount_cents: summaryData.discount_amount_cents
149    },
150    lineItemSubtotal: {
151      amount: parseFloat(summaryData.line_item_subtotal?.amount),
152      formatted: summaryData.line_item_subtotal_formatted,
153      amount_cents: summaryData.line_item_subtotal_cents
154    },
155    discounts: (summaryData.discounts ?? []).map((discount) => {
156      return {
157        name: discount.name,
158        code: discount.code,
159        amount_formatted: "-" + formatNumberToCurrency(summaryData.currency_symbol, discount.amount)
160      };
161    }),
162    ...nextInvoiceText ? { next_invoice_date: nextInvoiceText } : {},
163    subtotal: {
164      amount: parseFloat(summaryData.subtotal_amount.amount),
165      formatted: summaryData.subtotal_amount_formatted,
166      amount_cents: summaryData.subtotal_amount_cents
167    },
168    shipping: {
169      amount: parseFloat(summaryData.shipping_amount.amount),
170      formatted: summaryData.shipping_amount_formatted,
171      amount_cents: summaryData.shipping_amount_cents
172    },
173    tax: {
174      amount: parseFloat(summaryData.tax_amount.amount),
175      formatted: summaryData.tax_amount_formatted,
176      amount_cents: summaryData.tax_amount_cents
177    },
178    ...summaryData.upcoming_invoice?.interim_amount ? {
179      interim: {
180        amount: parseFloat(summaryData.upcoming_invoice.interim_amount.amount),
181        formatted: summaryData.upcoming_invoice?.interim_amount_formatted,
182        amount_cents: summaryData.upcoming_invoice?.interim_amount_cents
183      }
184    } : {},
185    ...summaryData.upcoming_invoice ? {
186      upcoming_invoice: {
187        line_items: summaryData.upcoming_invoice.line_items.filter((i) => i.interim).map((item) => {
188          return {
189            variant_name: item.variant_name,
190            quantity: item.quantity,
191            amount: parseFloat(item.amount.amount),
192            formatted: item.amount_formatted
193          };
194        })
195      }
196    } : {}
197  };
198}
199function buildCartDetails(cart) {
200  const orderId = cart.order_id;
201  const lineItems = cart.items.map(({ price_id, line_item_id, variant_id, quantity }) => {
202    const data = {
203      variant_id,
204      price_id,
205      ...line_item_id ? { line_item_id } : {},
206      quantity
207    };
208    return data;
209  });
210  return { order_id: orderId, line_items: lineItems };
211}
212function buildOrderPreviewPayload(payload) {
213  const { address, shippingOption, cart, integrations_stripe_installation_id, coupon_code } = payload;
214  const isPhysical = hasPhysicalProducts(cart);
215  return {
216    integrations_stripe_installation_id,
217    order: {
218      full_preview: true,
219      coupon_codes: coupon_code,
220      ...address ? buildAddressParams(address, isPhysical) ?? {} : {},
221      ...buildCartDetails(cart),
222      ...shippingOption?.amount ? { selected_shipping_option: shippingOption } : {}
223    }
224  };
225}
226function buildAddressParams(address, isPhysical) {
227  const delivery_address = { ...address };
228  const billing_address = address.id ? { id: address.id } : { ...address };
229  if (isPhysical) {
230    return {
231      delivery_address,
232      billing_address
233    };
234  } else {
235    return { billing_address };
236  }
237}
238
239// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/consts.ts
240init_define_process();
241var stripeElementsForms = ["linkAuthentication", "shipping", "billing", "payment"];
242var FORM_STRUCTURE_BY_TOTAL_STEPS = {
243  1: [["linkAuthentication", "shipping", "billing", "shippingOption", "products", "payment", "tos"]],
244  2: [
245    ["linkAuthentication", "contact"],
246    ["shipping", "billing", "shippingOption", "products", "payment", "tos"]
247  ],
248  3: [["products"], ["linkAuthentication", "contact"], ["shipping", "billing", "shippingOption", "payment", "tos"]]
249};
250
251// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/errors.ts
252init_define_process();
253var StripeCheckoutErrorCode = /* @__PURE__ */ ((StripeCheckoutErrorCode2) => {
254  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["STRIPE_LIB_INITIALIZATION_ERROR"] = 1] = "STRIPE_LIB_INITIALIZATION_ERROR";
255  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["STRIPE_ADDRESS_ELEMENT_INITIALIZATION_ERROR"] = 2] = "STRIPE_ADDRESS_ELEMENT_INITIALIZATION_ERROR";
256  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["STRIPE_PAYMENT_ELEMENT_INITIALIZATION_ERROR"] = 4] = "STRIPE_PAYMENT_ELEMENT_INITIALIZATION_ERROR";
257  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["STRIPE_LINK_AUTHENTICATION_ELEMENT_INITIALIZATION_ERROR"] = 8] = "STRIPE_LINK_AUTHENTICATION_ELEMENT_INITIALIZATION_ERROR";
258  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["STRIPE_EXPRESS_CHECKOUT_ELEMENT_INITIALIZATION_ERROR"] = 16] = "STRIPE_EXPRESS_CHECKOUT_ELEMENT_INITIALIZATION_ERROR";
259  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["API_SESSION_INITIALIZATION_ERROR"] = 32] = "API_SESSION_INITIALIZATION_ERROR";
260  StripeCheckoutErrorCode2[StripeCheckoutErrorCode2["MOUNT_REJECTED_ERROR"] = 64] = "MOUNT_REJECTED_ERROR";
261  return StripeCheckoutErrorCode2;
262})(StripeCheckoutErrorCode || {});
263function getStripeCheckoutErrorMessage(stripeErrors) {
264  if (stripeErrors.length > 0) {
265    const errorCodeMask = `0x${Number(stripeErrors.reduce((acc, val) => acc | val, 0)).toString(16)}`;
266    return "Error initializing Checkout Element. Code: " + errorCodeMask;
267  }
268}
269function getInitialStripeCheckoutErrors() {
270  const initialCriticalErrors = [];
271  if (!globalThis.globalResourceData.productVariantWithNoBump?.id) {
272    initialCriticalErrors.push({ code: ERROR_CODES.EMPTY_PRODUCTS_ERROR });
273  }
274  return initialCriticalErrors;
275}
276
277// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/stripeCheckout.ts
278init_fetcher();
279init_cf_utils();
280
281// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/api.ts
282init_define_process();
283init_fetcher();
284init_nonce();
285function makeApiFetcher(options) {
286  const { headers, ...requestOptions } = options;
287  const fetcher = new Fetcher({
288    debug: true,
289    pathPrefix: "/user_pages/api/v1/",
290    headers: {
291      Accept: "application/json",
292      "Content-Type": "application/json",
293      ...headers ?? {}
294    },
295    requestOptions: {
296      retries: 3,
297      timeoutMS: 3e4,
298      timeoutAfterRetrial: 1e3,
299      shouldCaptureServerError: true,
300      convertThrowToErrorResponse: true,
301      ...requestOptions
302    }
303  });
304  return fetcher;
305}
306var stripeSessionApiFetcher = makeApiFetcher({
307  onlyOneInflightRequest: true,
308  simulateNetworkError: false,
309  // `stripe_get_session` only syncs the contact and mints a customer session, so a
310  // replay is harmless. It is also the call that fails when Stripe's per-object lock
311  // is held (ENG-7225) — the one case where retrying a 5xx is exactly the fix.
312  retryServerErrors: true,
313  // Same reasoning for a timed-out attempt. This is deliberately not switched on for
314  // `stripeSubmitFetcher` below: replaying a submit is a much heavier claim to make.
315  retryTimeouts: true,
316  // ...but bound the sequence in wall clock. Making `retries` finally apply to timeouts is
317  // a behaviour change, and on the inherited `timeoutMS: 30000` / `retries: 3` it would
318  // cost the buyer 3 x 30s + 2 x 1s = 92s of blank checkout before the banner, and issue 3
319  // backend requests per browser. Aborting a fetch does not stop the Rails request — Puma
320  // holds the thread until it responds — so those retries would amplify load onto a pool
321  // whose threads are already parked on the object-lock sleep, which is precisely when a
322  // timeout is most likely. 15s clears the server's 8s sleep budget plus a normal Stripe
323  // round trip, and 2 attempts keep the retry that actually fixes a transient lock while
324  // holding the worst case at ~31s — the same ceiling buyers saw before.
325  timeoutMS: 15e3,
326  retries: 2
327});
328var stripeSubmitFetcher = new Fetcher({
329  debug: true,
330  method: "POST",
331  headers: {
332    Accept: "application/json",
333    "Content-Type": "application/json",
334    "X-CF2-POST-TYPE": "submit"
335  },
336  requestOptions: {
337    retries: 3,
338    timeoutMS: 6e4,
339    timeoutAfterRetrial: 1e3,
340    shouldCaptureServerError: true,
341    convertThrowToErrorResponse: true,
342    onlyOneInflightRequest: true,
343    canAbort: false
344  }
345});
346function isStripeError(error) {
347  if (typeof error === "object") {
348    const stripeError = error;
349    if (stripeError?.code && stripeError?.message) {
350      return true;
351    }
352  }
353  return false;
354}
355async function postSubmit(payload) {
356  const nonce = await fetchCheckoutNonce();
357  const response = await stripeSubmitFetcher.fetch(
358    renderedHref(),
359    {
360      credentials: "same-origin",
361      body: JSON.stringify({ ...payload, ...checkoutNonceParams(nonce) })
362    },
363    {}
364  );
365  if (isResponseError(response)) {
366    return response;
367  } else {
368    let body;
369    if (response.headers.get("Content-Type").includes("text/html")) {
370      body = {
371        next_url: response.headers.get("Location")
372      };
373    } else {
374      body = await response.json();
375    }
376    if (response.ok) {
377      return {
378        ...body,
379        headers: {
380          get: (name) => response.headers?.get(name)
381        }
382      };
383    } else if (response.status === 422) {
384      return {
385        fetcherErrorType: 1 /* Backend */,
386        error: normalizeServerCheckoutError(body)
387      };
388    } else {
389      return {
390        fetcherErrorType: 0 /* Internal */,
391        error: `Unexpected response status ${response.status}`
392      };
393    }
394  }
395}
396
397// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/store.ts
398init_define_process();
399init_nanostores();
400function ensureCheckoutStoreInitialized() {
401  globalThis.Checkout.store = globalThis.Checkout.store ?? {
402    state: atom("start" /* START */),
403    coupons: {
404      appliedCode: atom(""),
405      currentCode: atom(""),
406      errorMessage: atom(""),
407      state: atom("ready" /* READY */)
408    },
409    summary: atom({
410      state: "waiting" /* WAITING */,
411      data: {}
412    }),
413    checkout: {
414      step: atom(0)
415    },
416    submitting: atom({
417      state: "idle" /* IDLE */
418    }),
419    criticalErrors: atom(getInitialStripeCheckoutErrors()),
420    featureFlags: {},
421    selectedOrderDetailId: atom(null)
422  };
423  globalThis.Checkout.computed = globalThis.Checkout.computed ?? {
424    checkoutCart: buildProductSelectBatched()
425  };
426  globalThis.Checkout.computed.isCouponReady = computed(
427    [globalThis.Checkout.store.state, globalThis.Checkout.computed.checkoutCart],
428    (state, cart) => {
429      const showAllProductErrors = true;
430      const pErrors = globalThis.Checkout.utils.productErrors(cart, showAllProductErrors);
431      return state == globalThis.Checkout.StoreStates.START && !globalThis.Checkout.utils.hasErrors(pErrors);
432    }
433  );
434  return {
435    ...globalThis.Checkout.store,
436    ...globalThis.Checkout.computed
437  };
438}
439
440// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/stripe.ts
441init_define_process();
442var Stripe;
443var stripeCurrency = "usd";
444var stripeInstallationId = "";
445function ensureStripeInitialized() {
446  if (!Stripe) {
447    const {
448      stripePublishableKey,
449      stripeAccountId,
450      stripeInstallationId: instalationId,
451      stripeCurrency: currency
452    } = document.querySelector("#payment-gateway-keys").dataset;
453    Stripe = globalThis.Stripe?.(stripePublishableKey, {
454      stripeAccount: stripeAccountId,
455      betas: ["disable_deferred_intent_client_validation_beta_1"]
456    });
457    stripeInstallationId = instalationId;
458    stripeCurrency = currency;
459  }
460  return Stripe;
461}
462function ensureStripeScriptLoaded() {
463  if (globalThis.Stripe) return Promise.resolve();
464  const lazyScript = document.querySelector('script[data-lazy-src*="stripe"]');
465  if (!lazyScript) return Promise.resolve();
466  return new Promise((resolve, reject) => {
467    const script = document.createElement("script");
468    script.src = lazyScript.getAttribute("data-lazy-src");
469    script.onload = () => resolve();
470    script.onerror = () => reject(new Error("Failed to load Stripe.js"));
471    lazyScript.parentNode.insertBefore(script, lazyScript);
472    lazyScript.remove();
473  });
474}
475function buildStripeFonts() {
476  const fonts = [];
477  const googleFontsSrc = document.getElementById("cf-lander-font-families")?.href;
478  if (googleFontsSrc) {
479    fonts.push({ cssSrc: googleFontsSrc });
480  }
481  try {
482    const serializedCustomFonts = JSON.parse(
483      document.getElementById("cf-lander-serialized-custom-fonts")?.textContent ?? "[]"
484    );
485    fonts.push(
486      ...serializedCustomFonts.map(
487        (customFont) => ({
488          family: customFont.family,
489          src: customFont.files.map((src) => `url(${new URL(src, document.location.href).toString()})`).join(",")
490        })
491      )
492    );
493  } catch (e) {
494    console.error("Error preparing custom fonts to stripe elements", e);
495  }
496  return fonts;
497}
498
499// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/enums.ts
500init_define_process();
501var CheckoutStates = /* @__PURE__ */ ((CheckoutStates2) => {
502  CheckoutStates2["GUEST"] = "guest";
503  CheckoutStates2["OTO"] = "oto";
504  CheckoutStates2["SAVED"] = "saved";
505  return CheckoutStates2;
506})(CheckoutStates || {});
507
508// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/StripeCheckout/stripeCheckout.ts
509init_cf_utils();
510function createInstance(component) {
511  const stripe = ensureStripeInitialized();
512  const store = ensureCheckoutStoreInitialized();
513  return new StripeCheckoutLogic(component, stripe, store);
514}
515var CHECKOUT_STATES = Object.values(CheckoutStates);
516var STRIPE_INSTRUMENT_REJECTION_CODES = /* @__PURE__ */ new Set([
517  "card_declined",
518  "card_not_supported",
519  "currency_not_supported",
520  "expired_card",
521  "incorrect_cvc",
522  "incorrect_number",
523  "incorrect_zip",
524  "processing_error"
525]);
526var StripeCheckoutLogic = class {
527  constructor(component, stripe, store) {
528    this.component = component;
529    this.stripe = stripe;
530    this.store = store;
531    __publicField(this, "_stripeData");
532    __publicField(this, "guestInputFields", {});
533    __publicField(this, "paymentDeclined", false);
534    __publicField(this, "submitedOnce", false);
535    __publicField(this, "checkoutData", { contact: {}, address: {} });
536    __publicField(this, "digitalPaymentData", { contact: {}, address: {}, shippingRateId: "" });
537    __publicField(this, "parsedAppearence");
538    __publicField(this, "summaryLineItemSubtotalCents");
539    __publicField(this, "summaryLineItems");
540    __publicField(this, "stripeElementOptions");
541    __publicField(this, "stripeFonts");
542    __publicField(this, "shippingComponents");
543    __publicField(this, "selectedShippingOption");
544    __publicField(this, "errors");
545    __publicField(this, "element");
546    __publicField(this, "loadingComponents");
547    __publicField(this, "submitButtons");
548    __publicField(this, "submitNotifications");
549    __publicField(this, "sendOrderPreviewTimer");
550    __publicField(this, "lastSubmitFailure", null);
551    __publicField(this, "setupErrors");
552    __publicField(this, "oldHasPhysical");
553    __publicField(this, "preventOrderPreview", false);
554    __publicField(this, "submitInFlight", false);
555    // Identity-tracked entry the summary subscriber pushes into `errors.globalErrors` so we
556    // can remove exactly it without clobbering globals set by submit-time flows.
557    __publicField(this, "summaryErrorEntry", null);
558    __publicField(this, "couponStateBeforeApplying");
559    __publicField(this, "sentToTracking", { email: null, firstName: null, lastName: null, phone: null });
560    __publicField(this, "trackingTimer");
561    this._stripeData = {};
562    CHECKOUT_STATES.forEach((state) => {
563      this._stripeData[state] = {
564        stripeElements: null,
565        mountedElements: {
566          shipping: {},
567          billing: {},
568          expressCheckout: {},
569          linkAuthentication: {},
570          payment: {}
571        }
572      };
573    });
574    this.element = component.element;
575    this.errors = { globalErrors: [], fields: {} };
576    this.setupErrors = [];
577    this.parsedAppearence = parseCssVars(component.element, this.component.appearance);
578    this.stripeFonts = buildStripeFonts();
579    const cart = this.store.checkoutCart.get();
580    if (globalThis.sessionData.contact.email) {
581      this.checkoutData.contact.email = globalThis.sessionData.contact.email;
582    }
583    this.updateWithShippingAddress(cart);
584    globalThis.montedElements = this.montedElements;
585    console.log("[Stripe] appearance => ", this.parsedAppearence);
586  }
587  triggerTrackingForStripeElement(data) {
588    clearTimeout(this.trackingTimer);
589    this.trackingTimer = setTimeout(() => {
590      try {
591        if (data.email && this.sentToTracking.email !== data.email) {
592          this.sentToTracking.email = data.email;
593          this.createTrackingInput("email", data.email);
594        }
595        if (data.firstName && this.sentToTracking.firstName !== data.firstName && !this.guestInputFields.first_name) {
596          this.sentToTracking.firstName = data.firstName;
597          this.createTrackingInput("first_name", data.firstName);
598        }
599        if (data.lastName && this.sentToTracking.lastName !== data.lastName && !this.guestInputFields.last_name) {
600          this.sentToTracking.lastName = data.lastName;
601          this.createTrackingInput("last_name", data.lastName);
602        }
603        if (data.phone && this.sentToTracking.phone !== data.phone && !this.guestInputFields.phone_number) {
604          this.sentToTracking.phone = data.phone;
605          this.createTrackingInput("phone_number", data.phone);
606        }
607      } catch (error) {
608        console.error("[Stripe] Tracking helper error:", error);
609      }
610    }, 200);
611  }
612  createTrackingInput(name, value) {
613    const input = document.createElement("input");
614    input.type = name.includes("email") ? "email" : "text";
615    input.name = name;
616    input.value = value;
617    input.style.cssText = "position:absolute;
617left:-9999px;opacity:0;pointer-events:none";
618    document.body.appendChild(input);
619    input.dispatchEvent(new Event("focusout", { bubbles: true }));
620    input.dispatchEvent(new Event("change", { bubbles: true }));
621    input.dispatchEvent(new Event("blur", { bubbles: true }));
622    document.body.removeChild(input);
623  }
624  async ensureStripeSession() {
625    const startedAt = Date.now();
626    const sessionResponse = await stripeSessionApiFetcher.post("checkouts/stripe_get_session", {
627      referrer_url: window.location.href,
628      integrations_stripe_installation_id: stripeInstallationId
629    });
630    if (isResponseError(sessionResponse)) {
631      const failureKind = this.sessionFailureKind(sessionResponse);
632      const durationMs = Date.now() - startedAt;
633      if (failureKind === "superseded" && !this.component.element.isConnected) {
634        globalThis.Honeybadger?.notify("StripeCheckout session superseded", {
635          context: { durationMs, checkoutState: this.getState() }
636        });
637        return null;
638      }
639      this.pushSetupError(32 /* API_SESSION_INITIALIZATION_ERROR */, void 0, {
640        failureKind,
641        durationMs
642      });
643    } else {
644      return sessionResponse;
645    }
646  }
647  // Maps the fetcher error to a stable label:
648  //   'timeout_error' — every attempt hit the fetcher's own 30s timer
649  //   'server_error'  — the endpoint 5xx'd on every attempt
650  //   'network_error' — the request itself failed
651  //   'superseded'    — a later request on the same fetcher replaced this one
652  sessionFailureKind(response) {
653    if (!isFetcherError(response)) return "backend_error";
654    const error = response.error;
655    if (error === MANUALLY_ABORTED) return "superseded";
656    if (error instanceof CFFetcherError) return error.type.toLowerCase();
657    return String(error);
658  }
659  backfillContactData() {
660    const shouldUseGarlic = this.getState() === "guest";
661    ["first_name", "last_name", "email", "phone_number", "name"].forEach((k) => {
662      if (k === "phone_number" && !this.hasPhoneNumber()) return;
663      const garlicValue = shouldUseGarlic ? globalThis.cfGarlicUtils.retrieve(k) : "";
664      const sessionValue = globalThis.sessionData.contact[k];
665      if (!garlicValue && !sessionValue) return;
666      if (k === "name" && !this.checkoutData.contact.first_name) {
667        const [first_name, ...last_names] = garlicValue.split(" ");
668        this.checkoutData.contact.first_name = first_name;
669        this.checkoutData.contact.last_name = last_names.join(" ");
670      } else {
671        this.checkoutData.contact[k] = sessionValue ?? garlicValue;
672      }
673    });
674    this.syncInputFields();
675  }
676  updateInputState(name, value) {
677    globalThis.cfGarlicUtils.store(name, value);
678    if (value) {
679      this.guestInputFields[name].closest('[data-page-element="Input/V1"]').classList.add("hasValue");
680    } else {
681      this.guestInputFields[name].closest('[data-page-element="Input/V1"]').classList.remove("hasValue");
682    }
683  }
684  storeShippingDataFromExpress(data) {
685    if (data.name) globalThis.cfGarlicUtils.store("name", data.name);
686    const address = convertAddressFromStripe(data.address);
687    Object.keys(address).forEach((k) => {
688      if (address[k]) globalThis.cfGarlicUtils.store(k, address[k]);
689    });
690  }
691  syncInputFields() {
692    Object.keys(this.guestInputFields).forEach((k) => {
693      const value = this.checkoutData.contact[k];
694      if (k == "phone_number") {
695        ;
696        this.guestInputFields[k].iti.setNumber(value ?? "");
697      } else {
698        this.guestInputFields[k].value = value ?? "";
699      }
700      this.updateInputState(k, value);
701    });
702  }
703  errorInputForInput(input) {
704    const id = input.closest("[data-page-element]").getAttribute("id");
705    return this.element.querySelector(`[data-input-id="${id}"]`);
706  }
707  updateWithShippingAddress(cart) {
708    this.checkoutData.address = {};
709    if (hasPhysicalProducts(cart)) {
710      const sessionShippingAddress = globalThis.sessionData.contact.shipping_addresses?.[0] ?? globalThis.sessionData.contact.billing_addresses?.[0];
711      if (sessionShippingAddress) {
712        this.checkoutData.address = convertAddressFromSession(sessionShippingAddress);
713      }
714    }
715    if (this.getState() == "oto" && !hasPhysicalProducts(cart)) {
716      const sessionBillingAddress = globalThis.sessionData.contact.billing_addresses?.[0];
717      if (sessionBillingAddress) {
718        this.checkoutData.address = convertAddressFromSession(sessionBillingAddress);
719      }
720    }
721    if (globalThis.sessionData.contact) {
722      this.checkoutData.contact.first_name = globalThis.sessionData.contact.first_name;
723      this.checkoutData.contact.last_name = globalThis.sessionData.contact.last_name;
724      this.checkoutData.contact.phone_number = globalThis.sessionData.contact.phone_number;
725      this.syncInputFields();
726    }
727  }
728  initializeElements(session, amount) {
729    const cart = this.store.checkoutCart.get();
730    this.stripeElementOptions = {
731      amount,
732      mode: getStripeMode(cart, amount),
733      currency: stripeCurrency.toLowerCase() ?? "usd",
734      appearance: this.parsedAppearence,
735      loader: "never",
736      fonts: this.stripeFonts,
737      locale: this.component.locale,
738      ...this.component.paymentGateway.disable_stripe_payment_method_future_usage ? {} : { setup_future_usage: "off_session" },
739      ...session?.can_use_dpm ? {} : { payment_method_types: ["card"] },
740      ...session?.stripe_options ?? {}
741    };
742    this.stripeElements = this.stripe.elements(this.stripeElementOptions);
743    globalThis.stripeElements = this.stripeElements;
744    this.stripeElements.on("update-end", () => {
745      this.updatingExpressEnded();
746    });
747  }
748  mount() {
749    if (!this.stripe) {
750      this.pushSetupError(1 /* STRIPE_LIB_INITIALIZATION_ERROR */);
751      return;
752    }
753    this.submitNotifications = this.component.getComponentGroup(CheckoutSubmitNotificationV1);
754    this.detectIfReturningFailedPayment();
755    this.backfillContactData();
756    Promise.all([
757      this.ensureStripeSession(),
758      CheckoutExistingOrders.fetch({
759        integrations_stripe_installation_id: stripeInstallationId
760      }).catch((error) => {
761        const cause = error instanceof CheckoutCriticalError ? error.cause : null;
762        if (cause !== MANUALLY_ABORTED) throw error;
763      }).then(() => {
764        this.updateSubmitButton();
765      })
766    ]).then(([sessionData]) => {
767      if (sessionData) {
768        const cart = this.store.checkoutCart.get();
769        const intialAmount = getCartEstimatedTotal(cart);
770        this.initializeElements(sessionData, intialAmount);
771        this.sendOrderPreview();
772        setTimeout(() => {
773          this.oneTimeListeners();
774        }, 1e3);
775      }
776    }).catch((error) => {
777      this.pushSetupError(64 /* MOUNT_REJECTED_ERROR */, void 0, {
778        failureKind: "mount_rejected",
779        mountError: String(error?.message ?? error),
780        // Keep the stack and any wrapped cause: the notify message is held constant per
781        // code for grouping, so context is the only place the specific failure survives.
782        mountErrorStack: error?.stack,
783        mountErrorCause: error?.cause ? String(error.cause?.message ?? error.cause) : void 0
784      });
785    });
786    setupOrderSummaries(this.component);
787    this.component.setHandlers(CheckoutMultiStepV2, {
788      onValidateStep: (step) => this.validateStep(step),
789      onStepChange: (oldStep, step) => {
790        this.stripeElements.update({ appearance: this.parsedAppearence });
791        const formStructure = FORM_STRUCTURE_BY_TOTAL_STEPS[this.getTotalSteps()];
792        if (formStructure[oldStep].includes("contact") && oldStep < step) {
793          collectLeads(this.checkoutData.contact);
794        }
795      }
796    });
797    this.component.setHandlers(CheckoutTosV1, {
798      onAcceptedChange: (accepted) => {
799        if (this.submitedOnce && accepted) {
800          this.clearErrors("tos");
801          this.showErrors();
802        }
803      }
804    });
805    this.shippingComponents = this.component.getComponentGroup(CheckoutShippingProfileSelectV1, {
806      onSelectOption: (option) => this.selectShippingOption(option)
807    });
808    window.addEventListener("ON_APPLY_COUPON", (event) => {
809      this.sendOrderPreview(event.detail);
810    });
811    window.addEventListener("ON_CLEAR_COUPON", (event) => {
812      this.sendOrderPreview(event.detail);
813    });
814    this.loadingComponents = this.component.getComponentGroup(CheckoutLoadingV1);
815    this.submitButtons = this.component.getComponentGroup(CheckoutSubmitButtonV1, {
816      // NOTE: returned so the button can tell a finished attempt from one that is
817      // still running, and unlock itself when we never got as far as the POST.
818      onSubmit: () => this.handleSubmit(this.selectedShippingOption)
819    });
820  }
821  detectIfReturningFailedPayment() {
822    const urlParams = new URLSearchParams(window.location.search);
823    const failedPaymentMessage = urlParams.get("failed_payment_message");
824    if (failedPaymentMessage) {
825      const decodedFailedMessage = decodeURIComponent(failedPaymentMessage.replace(/\+/g, " "));
826      this.handleError({ message: decodedFailedMessage }, true);
827      const visibleSubmitButton = this.getStateElement().querySelector("[data-page-element='CheckoutSubmitButton/V1']");
828      $("html, body").stop(true, true).animate(
829        {
830          scrollTop: $(visibleSubmitButton).offset().top - 100
831        },
832        500
833      );
834      this.submitedOnce = true;
835    }
836  }
837  submitCheckout(redirectOverride) {
838    return this.handleSubmit(this.selectedShippingOption, false, redirectOverride);
839  }
840  clearErrors(field) {
841    this.errors.globalErrors = [];
842    if (field) {
843      delete this.errors.fields[field];
844    }
845  }
846  clearAllErrors() {
847    this.errors.globalErrors = [];
848    this.errors.fields = {};
849  }
850  pushGlobalError(message) {
851    this.errors.globalErrors.push({ message });
852  }
853  pushFieldError(field, message) {
854    this.errors.fields[field] = { message };
855  }
856  showErrors({ shouldScrollToError } = { shouldScrollToError: false }) {
857    const stepStore = this.store.checkout.step;
858    const currentStep = stepStore.get();
859    const totalSteps = this.getTotalSteps();
860    let wrapperStateElement = this.getStateElement();
861    let hasFieldErrors = false;
862    let firstFieldWithError = null;
863    const formStructure = FORM_STRUCTURE_BY_TOTAL_STEPS[totalSteps];
864    for (let stepIndex = 0; stepIndex < formStructure.length; stepIndex++) {
865      const stepFields = formStructure[stepIndex];
866      for (const field of stepFields) {
867        if (this.errors.fields[field]) {
868          hasFieldErrors = true;
869          if (stepIndex !== currentStep) stepStore.set(stepIndex);
870          if (!firstFieldWithError) firstFieldWithError = field;
871          break;
872        }
873      }
874    }
875    if (totalSteps > 1) {
876      wrapperStateElement = wrapperStateElement.querySelector(
877        `.elMultiStepBody[data-step-number="${stepStore.get() + 1}"]`
878      );
879    }
880    Object.keys(this.guestInputFields).forEach((field) => {
881      if (this.errors.fields[field]) {
882        const errorfield = this.errorInputForInput(this.guestInputFields[field]);
883        errorfield.style.height = "20px";
884        errorfield.previousElementSibling.classList.add("elInputError");
885        errorfield.textContent = this.errors.fields[field].message;
886      }
887    });
888    const generalErrorsWrapper = wrapperStateElement.querySelector(".checkout-general-errors-wrapper");
889    this.component.element.querySelectorAll(".checkout-general-errors-wrapper").forEach((w) => {
890      w.classList.add("forceHide");
891      const span = w.querySelector("span");
892      if (span) span.innerHTML = "";
893    });
894    const hasGlobalErrors = this.errors.globalErrors.length && this.errors?.globalErrors?.[0]?.message;
895    if (hasGlobalErrors) {
896      const errorMessage = this.errors.globalErrors[0].message;
897      generalErrorsWrapper.querySelector("span").innerHTML = errorMessage;
898      generalErrorsWrapper.classList.remove("forceHide");
899    }
900    if (shouldScrollToError && (hasGlobalErrors || hasFieldErrors)) {
901      if (stripeElementsForms.includes(firstFieldWithError)) {
902        const scrollToElement = wrapperStateElement.querySelector(`.stripe-${firstFieldWithError}`);
903        scrollToFirstVisibleError(scrollToElement);
904      } else {
905        scrollToFirstVisibleError(generalErrorsWrapper);
906      }
907    }
908  }
909  removeSubmitNotification() {
910    this.submitNotifications.setStatus("", "", "");
911  }
912  setSubmitNotification(text, subtext, extraText) {
913    this.submitNotifications.setStatus(text, subtext, extraText);
914  }
915  get montedElements() {
916    return this._stripeData[this.getState()].mountedElements;
917  }
918  get stripeElements() {
919    return this._stripeData[this.getState()].stripeElements;
920  }
921  set stripeElements(stripeElement) {
922    this._stripeData[this.getState()].stripeElements = stripeElement;
923  }
924  getState() {
925    return this.component.element.dataset.currentState;
926  }
927  setState(state) {
928    this.component.element.dataset.currentState = state;
929  }
930  updatingExpressStarted() {
931    this.getStateElement().querySelector(".stripe-express-loader-wrapper")?.classList.remove("forceHide");
932    this.getStateElement().querySelector(".stripe-expressCheckout")?.classList.add("elHidden");
933  }
934  updatingExpressEnded() {
935    this.getStateElement().querySelector(".stripe-express-loader-wrapper")?.classList.add("forceHide");
936    this.getStateElement().querySelector(".stripe-expressCheckout")?.classList.remove("elHidden");
937  }
938  getStateElement() {
939    return this.component.element.querySelector(`[data-state="${this.component.element.dataset.currentState}"]`);
940  }
941  unmountElement(name) {
942    if (!this.montedElements[name].element) return;
943    this.montedElements[name].element.unmount();
944    const stripeElement = this.getStateElement().querySelector(`.stripe-${name}`);
945    delete stripeElement?.style.opacity;
946    this.montedElements[name].lastChangeEvent = null;
947    this.montedElements[name].mounted = false;
948  }
949  mountElement(name, options, overrideSelector, overrideMountName) {
950    console.log("[Stripe] mounteElement =>", name, options);
951    const state = this.getState();
952    const selector = overrideSelector ?? `.stripe-${name}`;
953    const hasElement = this.getStateElement().querySelector(selector);
954    if (!hasElement) return;
955    const mountName = overrideMountName ?? name;
956    if (!this.montedElements[mountName].element) {
957      options = options ?? {};
958      this.montedElements[mountName].element = this.stripeElements.create(name, options);
959    }
960    this.montedElements[mountName].element.mount(`[data-state=${state}] ${selector}`);
961    this.montedElements[mountName].mounted = true;
962  }
963  mountLink() {
964    if (this.montedElements.linkAuthentication.mounted) return;
965    const options = {};
966    if (this.checkoutData.contact.email) {
967      options.defaultValues = { email: this.checkoutData.contact.email };
968    }
969    this.mountElement("linkAuthentication", options);
970    this.montedElements.linkAuthentication.element?.on("change", (event) => {
971      this.removeSubmitNotificationStripeElementChange();
972      console.log("[Stripe] linkAuthentication [incoming-event]: ", event);
973      delete this.errors.fields["linkAuthentication"];
974      this.montedElements.linkAuthentication.lastChangeEvent = event;
975      if (!event.complete) return;
976      this.checkoutData.contact.email = event.value.email;
977      this.triggerTrackingForStripeElement({ email: event.value.email });
978      this.updatePaymentElementDefaultValues();
979    });
980    this.montedElements.linkAuthentication.element?.on("ready", () => {
981      this.elementReady("linkAuthentication");
982      this.elementReady("contact-form");
983    });
984    this.montedElements.linkAuthentication.element?.on(
985      "loaderror",
986      (error) => this.handleStripeElementLoadingError(error)
987    );
988  }
989  pushSetupError(code, customMessage, context) {
990    this.setupErrors.push(code);
991    const setupErrorComponent = this.component.getComponent(CheckoutConfigurationErrorV1);
992    const errorMessage = customMessage || getStripeCheckoutErrorMessage(this.setupErrors);
993    setupErrorComponent.setErrors(errorMessage);
994    scrollToFirstVisibleError(setupErrorComponent.element);
995    globalThis.Honeybadger?.notify(`StripeCheckout setup error: ${StripeCheckoutErrorCode[code]}`, {
996      context: {
997        errorCode: `0x${code.toString(16)}`,
998        // The banner shows the OR of all codes pushed so far. Report it too so
999        // a banner screenshot (e.g. "Code: 0x24") can be matched to notices.
1000        errorMask: `0x${this.setupErrors.reduce((acc, val) => acc | val, 0).toString(16)}`,
1001        checkoutState: this.getState(),
1002        hasContactEmail: Boolean(globalThis.sessionData?.contact?.email),
1003        ...context ?? {}
1004      }
1005    });
1006  }
1007  handleStripeElementLoadingError({ elementType, error }) {
1008    const errorEnumName = `STRIPE_${elementType.split(/(?=[A-Z])/).join("_").toUpperCase()}_ELEMENT_INITIALIZATION_ERROR`;
1009    const errorCode = StripeCheckoutErrorCode[errorEnumName];
1010    const errorMessage = error?.message ? `Error loading ${elementType} element: ${error.message}` : getStripeCheckoutErrorMessage([errorCode]);
1011    this.pushSetupError(errorCode, errorMessage, { elementType, stripeError: error });
1012    console.error(`Stripe ${elementType} element initialization error: `, error);
1013  }
1014  getTotalSteps() {
1015    return this.getState() !== "guest" ? 1 : this.component.totalSteps;
1016  }
1017  mountAddress() {
1018    const options = this.addressOptions;
1019    const mode = options.mode;
1020    const state = this.getState();
1021    if (this.montedElements[mode].mounted) return;
1022    if (mode === "billing" && state === "oto" /* OTO */ && !this.paymentDeclined) return;
1023    const stateElement = this.getStateElement();
1024    const otherMode = options.mode == "shipping" ? "billing" : "shipping";
1025    stateElement.querySelector(`.stripe-address-${otherMode}-container`)?.classList.add("forceHide");
1026    this.unmountElement(otherMode);
1027    if (mode === "billing" && !this.component.billingEnabled) {
1028      const contactFormElement = stateElement.querySelector(".stripe-contact-form");
1029      contactFormElement?.classList.remove("forceHide");
1030      return;
1031    }
1032    if (mode === "shipping" && !this.component.billingEnabled && this.component.totalSteps === 1) {
1033      const contactFormElement = stateElement.querySelector(".stripe-contact-form");
1034      contactFormElement?.classList.add("forceHide");
1035    }
1036    const stripeElement = stateElement.querySelector(`.stripe-${mode}`);
1037    stateElement.querySelector('[data-stripe-loading-element="address"]').classList.remove("forceHide");
1038    stripeElement.classList.add("elAbsolute");
1039    delete stripeElement.style.opacity;
1040    stateElement.querySelector(`.stripe-address-${mode}-container`)?.classList.remove("forceHide");
1041    this.mountElement("address", options, `.stripe-${mode}`, mode);
1042    this.montedElements[mode].element?.on("change", (event) => {
1043      this.removeSubmitNotificationStripeElementChange();
1044      this.montedElements[mode].lastChangeEvent = event;
1045      delete this.errors.fields[mode];
1046      const parsedData = this.parsedAddressEventData(event);
1047      console.log("[Stripe] address [incoming-event]: ", event);
1048      this.checkoutData.contact.first_name = parsedData.first_name;
1049      this.checkoutData.contact.last_name = parsedData.last_name;
1050      this.checkoutData.contact.phone_number = parsedData.phone_number;
1051      this.triggerTrackingForStripeElement({
1052        firstName: parsedData.first_name,
1053        lastName: parsedData.last_name,
1054        phone: parsedData.phone_number
1055      });
1056      this.syncInputFields();
1057      this.updatePaymentElementDefaultValues();
1058      this.checkoutData.address = parsedData.address;
1059      if (hasPhysicalProducts(globalThis.Checkout.computed.checkoutCart.get())) {
1060        if (this.hasValidAddress(this.checkoutData.address)) {
1061          this.shippingComponents.setLoading();
1062        } else {
1063          this.shippingComponents.setInvalidAddress();
1064        }
1065      }
1066      this.sendOrderPreview({ throttle: true });
1067    });
1068    this.montedElements[mode].element?.on("ready", () => {
1069      stateElement.querySelector(`.stripe-address-${mode}-container`).classList.remove("forceHide");
1070      this.elementReady(mode);
1071    });
1072    this.montedElements[mode].element?.on("loaderror", (error) => this.handleStripeElementLoadingError(error));
1073  }
1074  parsedAddressEventData(event) {
1075    const data = {};
1076    if (event.value.firstName || event.value.lastName) {
1077      data.first_name = event.value.firstName;
1078      data.last_name = event.value.lastName;
1079    } else {
1080      const [first_name, ...last_name] = (event.value?.name ?? "").split(" ");
1081      data.first_name = first_name;
1082      data.last_name = last_name.join(" ");
1083    }
1084    data.phone_number = event.value.phone;
1085    data.address = convertAddressFromStripe(event.value.address);
1086    return data;
1087  }
1088  get paymentOptions() {
1089    let address = "auto";
1090    if (!this.component.billingEnabled && this.component.billingFields === "if_required") {
1091      address = "if_required";
1092    }
1093    return {
1094      defaultValues: this.generatePaymentDefaultValues(),
1095      fields: {
1096        billingDetails: {
1097          name: "never",
1098          phone: "auto",
1099          address
1100        }
1101      }
1102    };
1103  }
1104  mountPayment() {
1105    if (this.montedElements.payment.mounted) return;
1106    const options = {
1107      terms: { card: "never" },
1108      ...this.paymentOptions
1109    };
1110    this.mountElement("payment", options);
1111    this.montedElements.payment.element?.on("change", (event) => {
1112      this.removeSubmitNotificationStripeElementChange();
1113      delete this.errors.fields["payment"];
1114      console.log("[Stripe] paymentMethods [incoming-event]: ", event);
1115      this.montedElements.payment.lastChangeEvent = event;
1116      this.sendOrderPreview({ throttle: true });
1117    });
1118    this.montedElements.payment.element?.on("ready", () => {
1119      this.elementReady("payment");
1120    });
1121    this.montedElements.payment.element?.on("loaderror", (error) => this.handleStripeElementLoadingError(error));
1122  }
1123  generatePaymentDefaultValues() {
1124    const defaultValues = {};
1125    if (this.checkoutData.contact.first_name || this.checkoutData.contact.last_name) {
1126      defaultValues.billingDetails = defaultValues?.billingDetails ?? {};
1127      defaultValues.billingDetails.name = [
1128        this.checkoutData.contact.first_name ?? "",
1129        this.checkoutData.contact.last_name ?? ""
1130      ].filter(Boolean).join(" ");
1131    }
1132    if (this.checkoutData.contact.email) {
1133      defaultValues.billingDetails = defaultValues?.billingDetails ?? {};
1134      defaultValues.billingDetails.email = this.checkoutData.contact.email;
1135    }
1136    if (this.checkoutData.contact.phone_number && this.hasPhoneNumber()) {
1137      defaultValues.billingDetails = defaultValues?.billingDetails ?? {};
1138      defaultValues.billingDetails.phone = this.checkoutData.contact.phone_number;
1139    }
1140    return defaultValues;
1141  }
1142  updatePaymentElementDefaultValues() {
1143    if (this.getState() !== "guest") return;
1144    this.montedElements.payment.element?.update({
1145      ...this.paymentOptions
1146    });
1147  }
1148  handleOrderPreviewForExpressCheckout(response, resolve) {
1149    const cart = this.store.checkoutCart.get();
1150    this.stripeElements.update({
1151      amount: response.total_amount_cents,
1152      mode: getStripeMode(cart, response.total_amount_cents)
1153    });
1154    const changeResolveDetails = calculateStripeChangeResolveDetails(
1155      response.line_items,
1156      response.shipping_quotes_response?.options,
1157      response.selected_shipping_option,
1158      response.tax_amount_cents,
1159      response.discount_amount_cents
1160    );
1161    resolve(changeResolveDetails);
1162  }
1163  mountExpress() {
1164    if (this.montedElements.expressCheckout.mounted) return;
1165    this.mountElement("expressCheckout", {
1166      paymentMethods: { link: this.component.payWithLinkEnabled ? "auto" : "never" }
1167    });
1168    this.montedElements.expressCheckout.element?.on("confirm", (evt) => {
1169      const shippingOption = this.formatExpressShippingOption(evt.shippingRate?.
1169id);
1170      this.storeShippingDataFromExpress(evt.shippingAddress);
1171      this.handleSubmit(shippingOption, true);
1172    });
1173    this.montedElements.expressCheckout.element?.on("click", ({ resolve }) => {
1174      resolve({
1175        shippingAddressRequired: true,
1176        emailRequired: true,
1177        phoneNumberRequired: this.hasPhoneNumber(),
1178        shippingRates: [{ id: "calculating", amount: 0, displayName: "Calculating..." }],
1179        lineItems: calculateStripeLineItems(this.summaryLineItems)
1180      });
1181    });
1182    const sendExpressCheckoutOrderPreview = async (resolve, reject) => {
1183      const cart = this.store.checkoutCart.get();
1184      const dataToPreview = {
1185        cart,
1186        address: this.digitalPaymentData.address,
1187        integrations_stripe_installation_id: stripeInstallationId
1188      };
1189      const couponState = this.store.coupons.state.get();
1190      let couponCode;
1191      if (couponState == "applying" /* APPLYING */) {
1192        couponCode = this.store.coupons.currentCode.get();
1193      } else {
1194        couponCode = this.store.coupons.appliedCode.get();
1195      }
1196      dataToPreview.coupon_code = couponCode;
1197      dataToPreview.shippingOption = this.formatExpressShippingOption(this.digitalPaymentData.shippingRateId);
1198      await fetchOrderPreview(dataToPreview).then((response) => {
1199        if (isResponseError(response)) {
1200          reject();
1201        } else {
1202          this.handleOrderPreviewForExpressCheckout(response, resolve);
1203        }
1204      });
1205    };
1206    this.montedElements.expressCheckout.element?.on("shippingaddresschange", async ({ address, resolve, reject }) => {
1207      this.digitalPaymentData.address = convertAddressFromStripe(address);
1208      sendExpressCheckoutOrderPreview(resolve, reject);
1209    });
1210    this.montedElements.expressCheckout.element?.on("cancel", () => {
1211      const cart = this.store.checkoutCart.get();
1212      this.stripeElements.update({
1213        amount: this.summaryLineItemSubtotalCents,
1214        mode: getStripeMode(cart, this.summaryLineItemSubtotalCents)
1215      });
1216    });
1217    this.montedElements.expressCheckout.element?.on("shippingratechange", async ({ shippingRate, resolve, reject }) => {
1218      this.digitalPaymentData.shippingRateId = shippingRate.id;
1219      sendExpressCheckoutOrderPreview(resolve, reject);
1220    });
1221    this.montedElements.payment.element?.on("loaderror", (error) => this.handleStripeElementLoadingError(error));
1222  }
1223  formatExpressShippingOption(id) {
1224    if (id && id != STRIPE_SKIP_SHIPPING_ID) {
1225      return JSON.parse(id);
1226    }
1227  }
1228  elementReady(name) {
1229    const stateElement = this.getStateElement();
1230    const loaderElementName = ["shipping", "billing"].includes(name) ? "address" : name;
1231    const loaderElement = stateElement.querySelector(`[data-stripe-loading-element="${loaderElementName}"]`);
1232    const stripeElement = stateElement.querySelector(`.stripe-${name}`);
1233    this.stripeElements.update({ appearance: this.parsedAppearence });
1234    let obeserverTimeout;
1235    const resizeObserver = new ResizeObserver(() => {
1236      clearTimeout(obeserverTimeout);
1237      obeserverTimeout = setTimeout(() => {
1238        resizeObserver.disconnect();
1239        this.stripeElements.update({ appearance: this.parsedAppearence });
1240        loaderElement.classList.add("forceHide");
1241        stripeElement.classList.remove("elAbsolute");
1242        stripeElement.style.opacity = "1";
1243      }, 500);
1244    });
1245    resizeObserver.observe(stripeElement);
1246  }
1247  oneTimeListeners() {
1248    const signOutButtonthis = this.component.element.querySelector(".sign-out-button");
1249    signOutButtonthis.addEventListener("click", () => {
1250      fetch("/contacts/sign_out", {
1251        method: "DELETE",
1252        headers: { "Content-Type": "application/json" },
1253        credentials: "same-origin"
1254      }).then(() => this.ensureStripeSession()).then((session) => {
1255        if (session) {
1256          this.store.checkout.step.set(0);
1257          this.setState("guest");
1258          this.initializeElements(session, this.summaryLineItemSubtotalCents);
1259          setTimeout(() => {
1260            this.updateElementsDisplay();
1261            const cart = this.store.checkoutCart.get();
1262            CheckoutExistingOrders.clearUpdatableOrders(cart.items[0]?.product_id);
1263          }, 1e3);
1264        }
1265      });
1266    });
1267    this.component.getComponents("Input/V1").forEach((inputComponent) => {
1268      const input = inputComponent.element.querySelector("input");
1269      const inputName = input.getAttribute("name");
1270      if (!["first_name", "last_name", "phone_number"].includes(inputName)) return;
1271      if (inputName == "phone_number") {
1272        IntlTel_initPhoneInput(input, { initialCountry: globalThis.cfVisitorData?.country ?? "us" });
1273      }
1274      this.guestInputFields[inputName] = input;
1275      ["input", "focus"].forEach((eventName) => {
1276        input.addEventListener(eventName, () => {
1277          const errorfield = this.errorInputForInput(input);
1278          errorfield.style.height = "0px";
1279          errorfield.previousElementSibling.classList.remove("elInputError");
1280          errorfield.textContent = "";
1281        });
1282      });
1283      input.addEventListener("blur", (event) => {
1284        const input2 = event.target;
1285        let value = input2.value;
1286        if (inputName == "phone_number") {
1287          value = input2.iti.getNumber();
1288        }
1289        this.checkoutData.contact[inputName] = value;
1290        this.updateInputState(inputName, value);
1291        this.updatePaymentElementDefaultValues();
1292      });
1293    });
1294    this.store.checkoutCart.subscribe(() => {
1295      this.updateElementsDisplay();
1296      this.sendOrderPreview();
1297      if (this.submitedOnce) {
1298        this.clearErrors("products");
1299        this.showErrors();
1300      }
1301    });
1302    this.listenAndSurfaceSummaryErrors();
1303  }
1304  // Mirrors Rebilly's `listenAndUpdateCheckoutErrors` (rebilly-checkout.ygg): when an
1305  // order-preview error lands on `summary.error.message`, surface it via the same
1306  // `.checkout-general-errors-wrapper` that submit-time errors use.
1307  listenAndSurfaceSummaryErrors() {
1308    this.store.summary.subscribe((summary) => {
1309      const message = summary?.state === "error" /* ERROR */ && summary?.error?.message ? summary.error.message : null;
1310      if (this.summaryErrorEntry) {
1311        const idx = this.errors.globalErrors.indexOf(this.summaryErrorEntry);
1312        if (idx >= 0) this.errors.globalErrors.splice(idx, 1);
1313        this.summaryErrorEntry = null;
1314      }
1315      if (message) {
1316        this.summaryErrorEntry = { message };
1317        this.errors.globalErrors.push(this.summaryErrorEntry);
1318      }
1319      this.showErrors();
1320    });
1321  }
1322  updateElementsDisplay() {
1323    this.cartAddressUpdates();
1324    this.updatePaymentElement();
1325    this.updateShippingOptionsDisplay();
1326    this.updateSubmitButton();
1327  }
1328  updatePaymentElement() {
1329    if (this.hasPaymentElement()) {
1330      this.mountPayment();
1331      this.mountExpress();
1332      this.mountLink();
1333      this.getStateElement().querySelector(".stripe-payment-container")?.classList.remove("forceHide");
1334      this.getStateElement().querySelector(".stripe-expressCheckout-container")?.classList.remove("forceHide");
1335    } else {
1336      this.unmountElement("linkAuthentication");
1337      this.unmountElement("payment");
1338      this.unmountElement("expressCheckout");
1339      this.getStateElement().querySelector(".stripe-payment-container")?.classList.add("forceHide");
1340      this.getStateElement().querySelector(".stripe-expressCheckout-container")?.classList.add("forceHide");
1341    }
1342  }
1343  cartAddressUpdates() {
1344    const cart = this.store.checkoutCart.get();
1345    const hasPhysical = hasPhysicalProducts(cart);
1346    if (this.oldHasPhysical != hasPhysical) {
1347      this.updateWithShippingAddress(cart);
1348    }
1349    if (this.getState() == "oto") {
1350      if (this.otoRequiresShippingForm() || this.paymentDeclined) {
1351        this.mountAddress();
1352        this.getStateElement().querySelector(".stripe-address")?.classList.remove("forceHide");
1353      } else {
1354        this.getStateElement().querySelector(".stripe-address")?.classList.add("forceHide");
1355      }
1356      if (hasUpgradeDowngradeItems(cart)) {
1357        this.getStateElement().querySelector('[data-page-element="CheckoutProductSelectBump/V2"]')?.classList.add("forceHide");
1358      } else {
1359        this.getStateElement().querySelector('[data-page-element="CheckoutProductSelectBump/V2"]')?.classList.remove("forceHide");
1360      }
1361    } else if (hasUpgradeDowngradeItems(cart)) {
1362      this.getStateElement().querySelector(".stripe-address")?.classList.add("forceHide");
1363    } else {
1364      this.mountAddress();
1365      this.getStateElement().querySelector(".stripe-address")?.classList.remove("forceHide");
1366    }
1367    this.oldHasPhysical = hasPhysical;
1368  }
1369  updateSubmitButton() {
1370    if (this.submitInFlight) return;
1371    const cart = this.store.checkoutCart.get();
1372    if (hasUpgradeDowngradeItems(cart)) {
1373      this.submitButtons.update(this.component.buttonUpgradeDowngrade);
1374    } else {
1375      this.submitButtons.setButtonInitialHTML();
1376    }
1377  }
1378  get addressOptions() {
1379    const hasPhysical = hasPhysicalProducts(this.store.checkoutCart.get());
1380    const options = {
1381      mode: hasPhysical ? "shipping" : "billing",
1382      fields: { phone: this.hasPhoneNumber() ? "always" : "never" },
1383      validation: this.hasPhoneNumber() ? { phone: { required: "always" } } : {},
1384      display: {
1385        name: "split"
1386      }
1387    };
1388    options.autocomplete = { mode: "automatic" };
1389    options.defaultValues = {};
1390    if (Object.keys(this.checkoutData.address).length || this.get
1390State() == "oto") {
1391      options.defaultValues.address = convertToStripeAddress(this.checkoutData.address);
1392    }
1393    const { first_name, last_name, phone_number } = this.checkoutData.contact ?? {};
1394    if (options.display.name == "split") {
1395      if (first_name) options.defaultValues.firstName = first_name;
1396      if (last_name) options.defaultValues.lastName = last_name;
1397    } else {
1398      if (first_name) {
1399        options.defaultValues.name = first_name;
1400        if (last_name) {
1401          options.defaultValues.name += ` ${last_name}`;
1402        }
1403      }
1404    }
1405    if (this.checkoutData.contact.phone_number && this.hasPhoneNumber()) {
1406      options.defaultValues.phone = this.checkoutData.contact.phone_number;
1407    }
1408    if (options.defaultValues.address && first_name && last_name) {
1409      const phoneNumberObj = this.hasPhoneNumber() ? { phone: phone_number } : {};
1410      options.contacts = [
1411        { name: `${first_name} ${last_name}`, address: options.defaultValues.address, ...phoneNumberObj }
1412      ];
1413    }
1414    return options;
1415  }
1416  hasPhoneNumber() {
1417    const showPhoneNumber = this.component.contactFields.includes("phone_number");
1418    return showPhoneNumber;
1419  }
1420  stripeElementHasError(type) {
1421    return !!this.montedElements[type].lastChangeEvent && !this.montedElements[type].lastChangeEvent?.complete;
1422  }
1423  shouldClearFormErrors(type) {
1424    return !this.submitedOnce && this.stripeElementHasError(type);
1425  }
1426  clearStripeElement(type) {
1427    console.log("[Stripe][clearStripeElement] =>", type);
1428    this.montedElements[type].element?.clear();
1429  }
1430  processCheckoutError(errorsByForm) {
1431    for (const [, errors] of Object.entries(errorsByForm)) {
1432      for (const [field, error] of Object.entries(errors?.fields ?? {})) {
1433        if (!error) continue;
1434        this.pushFieldError(field, error.message);
1435      }
1436      if (errors?.globalErrors?.length) {
1437        this.pushGlobalError(errors.globalErrors[0].message);
1438      }
1439    }
1440    return !hasErrors(this.errors);
1441  }
1442  shippingOptionErrors() {
1443    const state = this.component.getComponent(CheckoutShippingProfileSelectV1);
1444    const cart = this.store.checkoutCart.get();
1445    if (hasUpgradeDowngradeItems(cart)) {
1446      return null;
1447    } else if (state) {
1448      const { shippingOptions, shippingOption, loadingShipping } = state;
1449      return shippingOptionErrors(loadingShipping, cart, shippingOptions, shippingOption, true, null);
1450    }
1451  }
1452  tosErrors() {
1453    const state = this.component.getComponent(CheckoutTosV1);
1454    if (state) {
1455      return tosErrors(state.accepted, true, true);
1456    }
1457  }
1458  contactErrors() {
1459    return contactErrors(this.checkoutData.contact, Object.keys(this.guestInputFields));
1460  }
1461  stripeFormErrors(type) {
1462    if (this.shouldValidateStripeElements() && this.stripeElementHasError(type)) {
1463      return { fields: { [type]: { message: "has error" } } };
1464    }
1465  }
1466  formErrorsByFormName(formName) {
1467    switch (formName) {
1468      case "products":
1469        return productErrors(this.store.checkoutCart.get(), true);
1470      case "shippingOption":
1471        return this.shippingOptionErrors();
1472      case "tos":
1473        return this.tosErrors();
1474      case "contact":
1475        return this.contactErrors();
1476    }
1477  }
1478  async validateStep(step) {
1479    this.clearAllErrors();
1480    const formErrors = {};
1481    const curretStepForms = FORM_STRUCTURE_BY_TOTAL_STEPS[this.getTotalSteps()][step];
1482    let hasStripeElementInStep = false;
1483    for (const field of curretStepForms) {
1484      if (stripeElementsForms.includes(field)) {
1485        hasStripeElementInStep = true;
1486        formErrors[field] = this.stripeFormErrors(field);
1487      } else {
1488        formErrors[field] = this.formErrorsByFormName(field);
1489      }
1490    }
1491    const formValid = this.processCheckoutError(formErrors);
1492    if (!formValid && hasStripeElementInStep) {
1493      await this.stripeElements.submit();
1494      if (this.shouldClearFormErrors("billing")) this.clearStripeElement("billing");
1495      if (this.shouldClearFormErrors("shipping")) this.clearStripeElement("shipping");
1496      if (this.shouldClearFormErrors("payment")) this.clearStripeElement("payment");
1497    }
1498    const customFieldsValid = checkValidCustomFields(this.component.element);
1499    const valid = formValid && customFieldsValid;
1500    if (!valid) {
1501      this.showErrors({ shouldScrollToError: true });
1502    }
1503    return valid;
1504  }
1505  updateShippingOptionsDisplay() {
1506    const stateElement = this.getStateElement();
1507    const cart = this.store.checkoutCart.get();
1508    if (hasPhysicalProducts(cart) && !hasUpgradeDowngradeItems(cart)) {
1509      stateElement.querySelector(".shipping-options-container")?.classList.remove("forceHide");
1510      this.shippingComponents.show();
1511    } else {
1512      this.shippingComponents.hide();
1513      stateElement.querySelector(".shipping-options-container")?.classList.add("forceHide");
1514    }
1515  }
1516  selectShippingOption(option) {
1517    this.selectedShippingOption = option;
1518    this.shippingComponents.setOption(option);
1519    this.sendOrderPreview();
1520    if (this.submitedOnce) {
1521      this.clearErrors("shippingOption");
1522      this.showErrors();
1523    }
1524  }
1525  updateShippingOptions(update) {
1526    this.shippingComponents.update(update);
1527  }
1528  async sendOrderPreview(options) {
1529    const { skipUpdatingStripe, throttle, isCouponValidation, skipThrottle, forceOrderPreview } = options ?? {};
1530    if (this.preventOrderPreview && !forceOrderPreview) return;
1531    const { summary } = this.store;
1532    const cart = this.store.checkoutCart.get();
1533    if (!cart.items?.length) {
1534      if (this.store.coupons.appliedCode.get() || this.store.coupons.currentCode.get()) {
1535        this.store.coupons.appliedCode.set("");
1536        this.store.coupons.currentCode.set("");
1537        this.store.coupons.state.set("ready" /* READY */);
1538      }
1539      summary.set({ state: "waiting" /* WAITING */ });
1540      return;
1541    }
1542    const couponStateBeforeApplying = this.store.coupons.state.get();
1543    if (isCouponValidation && couponStateBeforeApplying != "applying" /* APPLYING */) {
1544      this.couponStateBeforeApplying = couponStateBeforeApplying;
1545      this.store.coupons.state.set("applying" /* APPLYING */);
1546    }
1547    const payload = this.hasValidAddress(this.checkoutData.address) ? {
1548      address: this.checkoutData.address,
1549      shippingOption: this.selectedShippingOption,
1550      cart
1551    } : { cart };
1552    payload.integrations_stripe_installation_id = stripeInstallationId;
1553    const couponState = this.store.coupons.state.get();
1554    let couponCode;
1555    if (couponState == "applying" /* APPLYING */) {
1556      couponCode = this.store.coupons.currentCode.get();
1557    } else {
1558      couponCode = this.store.coupons.appliedCode.get();
1559    }
1560    payload.coupon_code = couponCode;
1561    const canUpdateSummary = this.hasValidDataForSummaryUpdate(payload);
1562    const canFetchLineItemSubtotal = hasValidDataForLineItemSubtotal(payload);
1563    if (!canUpdateSummary) {
1564      summary.set({
1565        state: "waiting" /* WAITING */
1566      });
1567    }
1568    if (canUpdateSummary && !canFetchLineItemSubtotal) {
1569      return;
1570    }
1571    this.updatingExpressStarted();
1572    clearTimeout(this.sendOrderPreviewTimer);
1573    const sendOrderPreviewFn = async () => {
1574      const response = await fetchOrderPreview(payload, () => {
1575        if (canUpdateSummary) {
1576          if (hasPhysicalProducts(cart)) {
1577            this.shippingComponents.setLoading();
1578          }
1579          summary.set({
1580            state: "calculating" /* CALCULATING */
1581          });
1582        }
1583      });
1584      if (canFetchLineItemSubtotal && !isResponseError(response)) {
1585        this.summaryLineItems = response.line_items;
1586        this.summaryLineItemSubtotalCents = response.line_item_subtotal_cents;
1587        const currentCode = this.store.coupons.currentCode.get();
1588        const couponCodeApplied = response.discounts?.find(
1589          (discount) => discount.code?.toUpperCase() == currentCode?.toUpperCase()
1590        );
1591        if (couponCodeApplied) {
1592          this.store.coupons.appliedCode.set(currentCode);
1593          this.store.coupons.state.set("applied" /* APPLIED */);
1594        } else {
1595          this.store.coupons.state.set("ready" /* READY */);
1596        }
1597        if (!skipUpdatingStripe) {
1598          this.stripeElements.update({
1599            amount: response.line_item_subtotal_cents,
1600            mode: getStripeMode(cart, response.line_item_subtotal_cents)
1601          });
1602        }
1603      } else if (isBackendError(response)) {
1604        this.updatingExpressEnded();
1605        if (isResponseError(response)) {
1606          this.handleOrderPreviewErrorForExpress(response.error);
1607        }
1608      }
1609      if (canUpdateSummary || couponCode) {
1610        if (isResponseError(response)) {
1611          if (isBackendError(response)) {
1612            this.handleOrderPreviewErrorForSummary(response.error);
1613          }
1614        } else {
1615          const summaryResponse = processOrderPreviewResponseForSummary(response);
1616          const { shipping_quotes_response, selected_shipping_option } = response;
1617          this.selectedShippingOption = selected_shipping_option;
1618          summary.set({
1619            state: "ok" /* OK */,
1620            data: summaryResponse
1621          });
1622          if (hasPhysicalProducts(cart)) {
1623            this.shippingComponents.setShippingOptions(
1624              shipping_quotes_response?.options ?? [],
1625              selected_shipping_option
1626            );
1627          }
1628        }
1629      }
1630    };
1631    if (skipThrottle) {
1632      return await sendOrderPreviewFn();
1633    } else {
1634      this.sendOrderPreviewTimer = setTimeout(
1635        async () => {
1636          await sendOrderPreviewFn();
1637        },
1638        throttle ? 500 : 0
1639      );
1640    }
1641  }
1642  startLoadingState() {
1643    this.submitInFlight = true;
1644    this.loadingComponents.show();
1645    this.submitButtons.setSubmittingText();
1646  }
1647  removeLoadingState() {
1648    this.submitInFlight = false;
1649    this.loadingComponents.hide();
1650    this.submitButtons.setButtonInitialHTML();
1651  }
1652  handleStripeError(error) {
1653    if (!this.hasPaymentElement() && STRIPE_INSTRUMENT_REJECTION_CODES.has(error.code)) {
1654      this.paymentDeclined = true;
1655      this.updateElementsDisplay();
1656    }
1657    return error.message;
1658  }
1659  handleOrderPreviewErrorForExpress(response) {
1660    const errorDetail = response.details?.[0];
1661    if (errorDetail?.type == "InvalidCouponError") {
1662      this.store.coupons.appliedCode.set("");
1663      this.store.coupons.currentCode.set("");
1664      this.store.coupons.errorMessage.set(errorDetail.message);
1665      this.store.coupons.state.set("error" /* ERROR */);
1666    } else {
1667      globalThis.Checkout.store.coupons.state.set(this.couponStateBeforeApplying);
1668    }
1669  }
1670  handleOrderPreviewErrorForSummary(response) {
1671    const errorDetail = response.details?.[0];
1672    if (errorDetail?.type == "InvalidCouponError") {
1673      const summaryResponse = processOrderPreviewResponseForSummary(errorDetail.preview);
1674      this.store.summary.set({
1675        state: "ok" /* OK */,
1676        data: summaryResponse
1677      });
1678    } else if (errorDetail?.message) {
1679      this.store.summary.set({
1680        state: "error" /* ERROR */,
1681        error: { message: errorDetail.message }
1682      });
1683    } else {
1684      this.store.summary.set({
1685        state: "error" /* ERROR */,
1686        error: { message: "There was an error calculating your order total" }
1687      });
1688    }
1689  }
1690  handleError(error, skipRemoveLoadingState = false) {
1691    const GENERIC_PAYMENT_ERROR = "There was a problem processing your payment. Please try again or use a different payment method.";
1692    console.error("Error Submiting Payment:", error);
1693    if (!skipRemoveLoadingState) {
1694      this.removeLoadingState();
1695    }
1696    let displayMessage = "";
1697    let actionable = true;
1698    if (isStripeError(error)) {
1699      displayMessage = this.handleStripeError(error);
1700    } else {
1701      displayMessage = serverCheckoutErrorMessage(error) ?? GENER
1701IC_PAYMENT_ERROR;
1702      actionable = isActionableCheckoutError(error);
1703    }
1704    this.lastSubmitFailure = { message: displayMessage, actionable };
1705    this.setSubmitNotification("Failed Submit", displayMessage);
1706  }
1707  async processStripeResponse(next_url, { error, paymentIntent }) {
1708    if (error) {
1709      this.handleError(error);
1710    } else if (paymentIntent.status === "succeeded") {
1711      fetch(next_url, {
1712        method: "GET",
1713        redirect: "manual"
1714      }).then((response) => {
1715        if (response.status >= 300 && response.status < 400) {
1716          const location = response.headers.get("Location");
1717          window.location.href = location;
1718        } else {
1719          response.text().then((data) => {
1720            const jsonResponse = JSON.parse(data);
1721            this.handleError({
1722              message: jsonResponse.error
1723            });
1724          });
1725        }
1726      });
1727    } else if (paymentIntent.status === "processing") {
1728      setTimeout(async () => {
1729        const result = await this.stripe.retrievePaymentIntent(paymentIntent.client_secret);
1730        this.processStripeResponse(next_url, result);
1731      }, 1e3);
1732    } else {
1733      const voucherNextActions = ["konbini_display_details", "boleto_display_details", "oxxo_display_details", "multibanco_display_details"];
1734      const nextActionType = paymentIntent.next_action?.type;
1735      if (paymentIntent.status === "requires_action" && nextActionType && voucherNextActions.includes(nextActionType)) {
1736        window.location.href = next_url;
1737      } else {
1738        this.removeLoadingState();
1739      }
1740    }
1741  }
1742  async handleServerResponse(response) {
1743    if (isResponseError(response)) {
1744      this.handleError(response.error);
1745    } else {
1746      if (response.payment_intent?.status === "requires_action") {
1747        const result = await this.stripe.handleNextAction({
1748          clientSecret: response.payment_intent.client_secret
1749        });
1750        if (result.error) {
1751          this.handleError(result.error);
1752        } else if ("setupIntent" in result && result.setupIntent) {
1753          if (result.setupIntent.status === "succeeded") {
1754            window.location.href = response.next_url;
1755          } else {
1756            this.removeLoadingState();
1757          }
1758        } else {
1759          await this.processStripeResponse(response.next_url, result);
1760        }
1761      } else if (response.next_url) {
1762        window.location.href = response.next_url;
1763      } else {
1764        this.handleError(response);
1765      }
1766    }
1767  }
1768  shouldIncludeRegistration() {
1769    return document.getElementsByName("registration[calendar_event_id]")?.length > 0;
1770  }
1771  buildRegistrationDetails() {
1772    return {
1773      calendar_event_id: document.getElementsByName("registration[calendar_event_id]")[0].value,
1774      occurs_at: document.getElementsByName("registration[occurs_at]")[0].value
1775    };
1776  }
1777  buildSubmitPayload(shippingOption, idempotencyKey, confirmationToken, redirectOverride) {
1778    const customFields = buildCustomFields();
1779    const cart = this.store.checkoutCart.get();
1780    const coupon = this.store.coupons.appliedCode.get();
1781    const defaultRedirect = this.element.querySelector('[href="#submit-checkout-form"]')?.getAttribute("data-on-submit-go-to");
1782    const redirect_to = redirectOverride || defaultRedirect;
1783    const payload = {
1784      ...customFields ? customFields : {},
1785      payment_processor: "stripe",
1786      integrations_stripe_installation_id: stripeInstallationId,
1787      request_idempotency: idempotencyKey,
1788      skip_optin_track: document.getElementById("cfAR")?.getAttribute("data-leads-collected") === "true",
1789      purchase: {
1790        coupon_codes: [coupon].filter(Boolean),
1791        process_new_order: true,
1792        selected_shipping_option: shippingOption,
1793        order_id: cart.order_id,
1794        product_variants: cart.items.map(({ variant_id, price_id, line_item_id, quantity }) => {
1795          return {
1796            id: variant_id,
1797            quantity,
1798            price_id,
1799            ...line_item_id ? { line_item_id } : {}
1800          };
1801        })
1802      }
1803    };
1804    if (redirect_to) {
1805      payload.redirect_to = redirect_to;
1806    }
1807    if (confirmationToken) {
1808      payload.token = confirmationToken.id;
1809    } else if (hasUpgradeDowngradeItems(cart)) {
1810      payload.contact = {
1811        email: globalThis.sessionData.contact.email,
1812        first_name: globalThis.sessionData.contact.first_name,
1813        last_name: globalThis.sessionData.contact.last_name,
1814        phone_number: globalThis.sessionData.contact.phone_number
1815      };
1816    } else {
1817      payload.contact = {
1818        email: globalThis.sessionData.contact.email,
1819        first_name: this.checkoutData.contact.first_name,
1820        last_name: this.checkoutData.contact.last_name,
1821        phone_number: this.checkoutData.contact.phone_number
1822      };
1823      if (Object.keys(this.checkoutData.address).length) {
1824        payload.contact.shipping_addresses_attributes = [
1825          {
1826            physical_address_attributes: {
1827              address_one: this.checkoutData.address.address_one,
1828              address_two: this.checkoutData.address.address_two,
1829              city: this.checkoutData.address.city,
1830              region_name: this.checkoutData.address.state,
1831              country_id: this.checkoutData.address.country,
1832              postal_code: this.checkoutData.address.postal_code
1833            }
1834          }
1835        ];
1836      }
1837    }
1838    if (this.shouldIncludeRegistration()) payload["registration"] = this.buildRegistrationDetail
1838s();
1839    return payload;
1840  }
1841  otoRequiresShippingForm() {
1842    const hasPhysical = hasPhysicalProducts(this.store.checkoutCart.get());
1843    return hasPhysical && !globalThis.sessionData.contact.shipping_addresses?.[0];
1844  }
1845  hasPaymentElement() {
1846    return !hasUpgradeDowngradeItems(this.store.checkoutCart.get()) && ["guest", "saved"].includes(this.getState()) || this.paymentDeclined;
1847  }
1848  shouldValidateStripeElements() {
1849    return this.hasPaymentElement() || this.otoRequiresShippingForm();
1850  }
1851  hasStripeToken() {
1852    return this.hasPaymentElement();
1853  }
1854  async handleSubmit(shippingOption, isExpress, redirectOverride) {
1855    this.removeSubmitNotification();
1856    this.lastSubmitFailure = null;
1857    this.submitedOnce = true;
1858    if (!isExpress && !await this.validateStep(this.store.checkout.step.get())) {
1859      return false;
1860    }
1861    if (!isExpress && !checkValidCustomFields(this.component.element)) {
1862      return false;
1863    }
1864    if (!isExpress) {
1865      if (this.shouldValidateStripeElements()) {
1866        const submitError = await this.stripeElements.submit();
1867        if (submitError.error) {
1868          console.log("[Stripe] submitError =>", submitError);
1869          return false;
1870        }
1871      }
1872      if (this.store.summary.get().state != "ok" /* OK */) return false;
1873    }
1874    this.startLoadingState();
1875    let confirmationToken;
1876    if (isExpress || this.hasStripeToken()) {
1877      const confirmationTokenResult = await this.stripe.createConfirmationToken({
1878        elements: this.stripeElements,
1879        params: {
1880          payment_method_data: {
1881            billing_details: {
1882              name: this.checkoutData.contact.first_name + " " + this.checkoutData.contact.last_name,
1883              phone: this.checkoutData.contact.phone_number,
1884              email: this.checkoutData.contact.email
1885            }
1886          }
1887        }
1888      });
1889      if (confirmationTokenResult.error) {
1890        this.handleError(confirmationTokenResult.error);
1891        return false;
1892      }
1893      confirmationToken = confirmationTokenResult.confirmationToken;
1894    }
1895    const payload = this.buildSubmitPayload(shippingOption, uuidv4(), confirmationToken, redirectOverride);
1896    const response = await postSubmit(payload);
1897    await this.handleServerResponse(response);
1898    return !this.lastSubmitFailure;
1899  }
1900  hasValidAddress(address) {
1901    let addressErrorsVal;
1902    const cart = this.store.checkoutCart.get();
1903    if (!hasPhysicalProducts(cart) && !this.component.billingEnabled || hasUpgradeDowngradeItems(cart) && !this.hasPaymentElement()) {
1904      addressErrorsVal = null;
1905    } else if (this.getState() == "oto" && !hasPhysicalProducts(cart) && !this.hasPaymentElement()) {
1906      addressErrorsVal = addressErrors(address ?? {}, true, []);
1907    } else {
1908      let requiredFields = ["address_one", "city", "state", "country", "postal_code"];
1909      const stripeAddressFieldExceptions = globalThis.globalResourceData.stripeAddressFieldExceptions;
1910      if (address?.country && stripeAddressFieldExceptions.postalCodeless.includes(address?.country)) {
1911        requiredFields = requiredFields.filter((field) => field !== "postal_code");
1912      }
1913      if (address?.country && stripeAddressFieldExceptions.cityless.includes(address?.country)) {
1914        requiredFields = requiredFields.filter((field) => field !== "city");
1915      }
1916      if (address?.country && stripeAddressFieldExceptions.regionless.includes(address?.country)) {
1917        requiredFields = requiredFields.filter((field) => field !== "state");
1918      }
1919      addressErrorsVal = addressErrors(address ?? {}, true, requiredFields);
1920    }
1921    return !hasErrors(addressErrorsVal);
1922  }
1923  hasValidDataForSummaryUpdate(payload) {
1924    const { cart, address } = payload;
1925    const productSelectErrors = productErrors(cart, true);
1926    const hasValidAddress = this.hasValidAddress(address);
1927    return !hasErrors(productSelectErrors) && hasValidAddress;
1928  }
1929  // NOTE: for OTO this gets triggered after mounted.
1930  // We can enhance it later to only skip after this mounting change event.
1931  // Firstly we need to understand how to verify that
1932  removeSubmitNotificationStripeElementChange() {
1933    if (this.getState() != "oto" /* OTO */) this.removeSubmitNotification();
1934  }
1935};
1936
1937// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/stripe-checkout.ts
1938init_runtime();
1939var StripeCheckout = class extends CF2Component {
1940  constructor(el, runtimeSel) {
1941    super(el, runtimeSel);
1942    __publicField(this, "checkout");
1943    __publicField(this, "_lazyInitPending");
1944  }
1945  _doInitialize() {
1946    this.checkout = createInstance(this);
1947  }
1948  _doMount() {
1949    this.checkout.mount();
1950  }
1951  initialize() {
1952    if (this.lazyLoadCheckout) {
1953      this._lazyInitPending = true;
1954      ensureCheckoutStoreInitialized();
1955      return;
1956    }
1957    this._doInitialize();
1958  }
1959  mount() {
1960    if (this._lazyInitPending) {
1961      return;
1962    }
1963    this._doMount();
1964  }
1965  async _performLazyInit() {
1966    this._lazyInitPending = false;
1967    await ensureStripeScriptLoaded();
1968    this._doInitialize();
1969    this._doMount();
1970  }
1971  getCart() {
1972    return this.checkout.store.checkoutCart.get();
1973  }
1974  async submitOTO(redirectOverride) {
1975    const ok = await this.checkout.submitCheckout(redirectOverride);
1976    const failure = this.checkout.lastSubmitFailure;
1977    return { ok, actionable: failure ? failure.actionable : true, message: failure && failure.message };
1978  }
1979};
1980registerComponent("StripeCheckout", StripeCheckout);
1981window["StripeCheckout"] = StripeCheckout;
1982//# sourceMappingURL=stripe-checkout-4J37BNBN.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.