@economist/web-apple-pay 0.1.2-beta.0 → 0.1.3-beta.1

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.js CHANGED
@@ -307,9 +307,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
307
307
  this.#country = value;
308
308
  }
309
309
  connectedCallback() {
310
- console.log("[web-apple-pay] ApplePayModal connectedCallback");
311
310
  if (this.querySelector(".apm-overlay")) {
312
- console.log("[web-apple-pay] ApplePayModal connectedCallback: already rendered, skipping");
313
311
  return;
314
312
  }
315
313
  ensureApplePayLogoSymbol();
@@ -323,7 +321,6 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
323
321
  this.remove();
324
322
  return;
325
323
  }
326
- console.log("[web-apple-pay] ApplePayModal: rendering for offer", { skuId: offer.sku_id, country });
327
324
  const offerNameElement = this.querySelector(
328
325
  "#apple-pay-modal-offer-name"
329
326
  );
@@ -396,14 +393,11 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
396
393
  });
397
394
  }
398
395
  cta?.addEventListener("click", () => {
399
- console.log("[web-apple-pay] ApplePayModal: CTA clicked", { skuId: offer.sku_id, country, isUS });
400
396
  if (isUS && checkbox && !checkbox.checked) {
401
- console.log("[web-apple-pay] ApplePayModal: T&C checkbox not accepted, showing error");
402
397
  errorElement?.classList.add("apm__error--visible");
403
398
  checkboxLabel?.classList.add("apm__checkbox-label--error");
404
399
  return;
405
400
  }
406
- console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed", { skuId: offer.sku_id, country });
407
401
  this.dispatchEvent(
408
402
  new CustomEvent("apple-pay-confirmed", {
409
403
  bubbles: true,
@@ -411,7 +405,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
411
405
  detail: { skuId: offer.sku_id, country }
412
406
  })
413
407
  );
414
- console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
408
+ this.close();
415
409
  });
416
410
  this.querySelector("#apple-pay-modal-close")?.addEventListener(
417
411
  "click",
@@ -419,7 +413,6 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
419
413
  );
420
414
  }
421
415
  open() {
422
- console.log("[web-apple-pay] ApplePayModal: open()");
423
416
  this.#triggerElement = document.activeElement;
424
417
  document.body.appendChild(this);
425
418
  this.#keyHandler = (event) => {
@@ -434,7 +427,6 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
434
427
  this.querySelector("#apple-pay-modal")?.focus();
435
428
  }
436
429
  close() {
437
- console.log("[web-apple-pay] ApplePayModal: close()");
438
430
  if (this.#keyHandler) {
439
431
  document.removeEventListener("keydown", this.#keyHandler, {
440
432
  capture: true
@@ -447,17 +439,95 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
447
439
  };
448
440
 
449
441
  // src/templates/apple-pay-button.template.html
450
- var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n</div>\n';
442
+ var apple_pay_button_template_default = `<style>
443
+ /* Use CSS variables for layout so parent walls can easily override placement and sizing */
444
+ teg-apple-pay-button {
445
+ display: block;
446
+ margin: var(--apple-pay-margin, 0);
447
+ width: 100%;
448
+ height: 100%;
449
+ }
450
+
451
+ teg-apple-pay-button .apple-pay-container {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ width: 100%;
456
+ height: 100%;
457
+ }
458
+
459
+ teg-apple-pay-button .apple-pay-btn {
460
+ display: flex;
461
+ align-items: center;
462
+ justify-content: center;
463
+ gap: 0.375rem;
464
+ width: 100%;
465
+ min-width: 0;
466
+ height: 100%;
467
+ min-height: var(--apple-pay-height, 2.75rem);
468
+ background-color: #000;
469
+ color: #fff;
470
+ border: none;
471
+ border-radius: var(--apple-pay-border-radius, 1.375rem);
472
+ cursor: pointer;
473
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
474
+ font-size: 1.0625rem;
475
+ font-weight: 500;
476
+ }
477
+
478
+ teg-apple-pay-button .apple-pay-btn svg {
479
+ flex-shrink: 0;
480
+ display: block;
481
+ }
482
+
483
+ teg-apple-pay-button .apple-pay-btn.wap-loading {
484
+ position: relative;
485
+ cursor: default;
486
+ }
487
+
488
+ teg-apple-pay-button .apple-pay-btn.wap-loading svg {
489
+ visibility: hidden;
490
+ }
491
+
492
+ teg-apple-pay-button .apple-pay-btn.wap-loading::after {
493
+ content: '';
494
+ position: absolute;
495
+ left: 50%;
496
+ top: 50%;
497
+ margin-left: -0.625rem;
498
+ margin-top: -0.625rem;
499
+ width: 1.25rem;
500
+ height: 1.25rem;
501
+ border: 2px solid rgba(255, 255, 255, 0.2);
502
+ border-top-color: #fff;
503
+ border-radius: 50%;
504
+ animation: wap-button-spinner 0.8s linear infinite;
505
+ }
506
+
507
+ @keyframes wap-button-spinner {
508
+ to {
509
+ transform: rotate(360deg);
510
+ }
511
+ }
512
+ </style>
513
+
514
+ <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
515
+ <button
516
+ class="apple-pay-btn"
517
+ type="button"
518
+ aria-label="Pay with Apple Pay"
519
+ data-analytics="paywall:apple-pay-checkout"
520
+ >
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ `;
451
527
 
452
528
  // src/clients/payment-checkout/config.ts
453
529
  var runtimeConfig = null;
454
530
  var configureApplePay = (config) => {
455
- console.log("[web-apple-pay] configureApplePay called", {
456
- merchantId: config.merchantId,
457
- walletApiBaseUrl: config.walletApiBaseUrl,
458
- debugBypassEnabled: config.debugBypassEnabled,
459
- recaptchaSiteKey: config.recaptchaSiteKey ? "***" : void 0
460
- });
461
531
  runtimeConfig = {
462
532
  ...config
463
533
  };
@@ -472,27 +542,21 @@ var isAppleDeviceOrSafari = () => {
472
542
  };
473
543
  var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
474
544
  var isApplePayAvailable = async () => {
475
- console.log("[web-apple-pay] isApplePayAvailable: checking availability");
476
545
  if (bypassApplePayChecks()) {
477
- console.log("[web-apple-pay] isApplePayAvailable: bypass active \u2192 true");
478
546
  return true;
479
547
  }
480
548
  if (!isAppleDeviceOrSafari()) {
481
- console.log("[web-apple-pay] isApplePayAvailable: not Apple device or Safari \u2192 false");
482
549
  return false;
483
550
  }
484
551
  const applePaySession = window.ApplePaySession;
485
552
  if (!applePaySession) {
486
- console.log("[web-apple-pay] isApplePayAvailable: ApplePaySession not found on window \u2192 false");
487
553
  return false;
488
554
  }
489
555
  try {
490
556
  if (typeof applePaySession.canMakePayments !== "function") {
491
- console.log("[web-apple-pay] isApplePayAvailable: canMakePayments is not a function \u2192 false");
492
557
  return false;
493
558
  }
494
559
  if (!applePaySession.canMakePayments()) {
495
- console.log("[web-apple-pay] isApplePayAvailable: canMakePayments() returned false \u2192 false");
496
560
  return false;
497
561
  }
498
562
  const merchantId = getApplePayConfig()?.merchantId;
@@ -502,10 +566,7 @@ var isApplePayAvailable = async () => {
502
566
  );
503
567
  return false;
504
568
  }
505
- console.log("[web-apple-pay] isApplePayAvailable : calling canMakePaymentsWithActiveCard", { merchantId });
506
- const result = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
507
- console.log("[web-apple-pay] isApplePayAvailable: canMakePaymentsWithActiveCard \u2192", result);
508
- return result;
569
+ return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
509
570
  } catch (error) {
510
571
  console.error("Error checking Apple Pay active card status:", error);
511
572
  return false;
@@ -767,13 +828,6 @@ var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
767
828
 
768
829
  // src/clients/payment-checkout/apple-session.ts
769
830
  function startApplePaySession(config) {
770
- console.log("[web-apple-pay] startApplePaySession", {
771
- skuId: config.skuId,
772
- countryCode: config.countryCode,
773
- currencyCode: config.currencyCode,
774
- totalAmount: config.totalAmount,
775
- userLoggedIn: config.userLoggedIn
776
- });
777
831
  const paymentRequest = {
778
832
  countryCode: config.countryCode,
779
833
  currencyCode: config.currencyCode,
@@ -787,45 +841,26 @@ function startApplePaySession(config) {
787
841
  // Only request email from Apple Pay sheet if user is NOT logged in
788
842
  ...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
789
843
  };
790
- try {
791
- const session = new ApplePaySession(3, paymentRequest);
792
- console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
793
- session.onvalidatemerchant = async (event) => {
794
- console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
795
- try {
796
- const validationHost = new URL(event.validationURL).host;
797
- if (!validationHost.endsWith("apple.com")) {
798
- console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
799
- trackFallbackCheckout(config.skuId);
800
- session.abort();
801
- window.location.href = redirectToCheckoutFallback({
802
- skuId: config.skuId,
803
- returnUrl: config.returnUrl,
804
- inlineError: MSG_PAYMENT_GENERIC_ERROR
805
- });
806
- return;
807
- }
808
- const recaptchaToken = await getRecaptchaToken("verifyMerchant");
809
- console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
810
- const response = await validateAppleMerchant({
811
- validationURL: event.validationURL,
812
- recaptchaToken
844
+ const session = new ApplePaySession(3, paymentRequest);
845
+ session.onvalidatemerchant = async (event) => {
846
+ try {
847
+ const validationHost = new URL(event.validationURL).host;
848
+ if (!validationHost.endsWith("apple.com")) {
849
+ trackFallbackCheckout(config.skuId);
850
+ session.abort();
851
+ window.location.href = redirectToCheckoutFallback({
852
+ skuId: config.skuId,
853
+ returnUrl: config.returnUrl,
854
+ inlineError: MSG_PAYMENT_GENERIC_ERROR
813
855
  });
814
- if (!response?.merchantSession) {
815
- console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
816
- trackFallbackCheckout(config.skuId);
817
- session.abort();
818
- window.location.href = redirectToCheckoutFallback({
819
- skuId: config.skuId,
820
- returnUrl: config.returnUrl,
821
- inlineError: MSG_PAYMENT_GENERIC_ERROR
822
- });
823
- return;
824
- }
825
- console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
826
- session.completeMerchantValidation(response.merchantSession);
827
- } catch (err) {
828
- console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
856
+ return;
857
+ }
858
+ const recaptchaToken = await getRecaptchaToken("verifyMerchant");
859
+ const response = await validateAppleMerchant({
860
+ validationURL: event.validationURL,
861
+ recaptchaToken
862
+ });
863
+ if (!response?.merchantSession) {
829
864
  trackFallbackCheckout(config.skuId);
830
865
  session.abort();
831
866
  window.location.href = redirectToCheckoutFallback({
@@ -833,29 +868,28 @@ function startApplePaySession(config) {
833
868
  returnUrl: config.returnUrl,
834
869
  inlineError: MSG_PAYMENT_GENERIC_ERROR
835
870
  });
871
+ return;
836
872
  }
837
- };
838
- session.onpaymentauthorized = (event) => {
839
- console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
840
- trackWalletPaymentAuthorised(config.skuId);
841
- config.onPaymentAuthorized(event, session);
842
- };
843
- session.oncancel = () => {
844
- console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
845
- config.onCancel?.();
846
- };
847
- console.log("[web-apple-pay] startApplePaySession: beginning session");
848
- trackWalletPaymentSheetOpen(config.skuId);
849
- session.begin();
850
- } catch (err) {
851
- console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
852
- trackFallbackCheckout(config.skuId);
853
- window.location.href = redirectToCheckoutFallback({
854
- skuId: config.skuId,
855
- returnUrl: config.returnUrl,
856
- inlineError: MSG_PAYMENT_GENERIC_ERROR
857
- });
858
- }
873
+ session.completeMerchantValidation(response.merchantSession);
874
+ } catch {
875
+ trackFallbackCheckout(config.skuId);
876
+ session.abort();
877
+ window.location.href = redirectToCheckoutFallback({
878
+ skuId: config.skuId,
879
+ returnUrl: config.returnUrl,
880
+ inlineError: MSG_PAYMENT_GENERIC_ERROR
881
+ });
882
+ }
883
+ };
884
+ session.onpaymentauthorized = (event) => {
885
+ trackWalletPaymentAuthorised(config.skuId);
886
+ config.onPaymentAuthorized(event, session);
887
+ };
888
+ session.oncancel = () => {
889
+ config.onCancel?.();
890
+ };
891
+ trackWalletPaymentSheetOpen(config.skuId);
892
+ session.begin();
859
893
  }
860
894
 
861
895
  // src/clients/payment-checkout/contact-validation.ts
@@ -1032,16 +1066,12 @@ function handleStructuredError(ctx) {
1032
1066
  async function handlePaymentAuthorized(event, session, sessionData, config) {
1033
1067
  const { skuId, returnUrl, queryString } = config;
1034
1068
  let validatedEmail;
1035
- console.log("[web-apple-pay] handlePaymentAuthorized: starting", { skuId, userLoggedIn: sessionData.loggedIn });
1036
1069
  try {
1037
- console.log("[web-apple-pay] handlePaymentAuthorized: step 1 \u2014 validating contacts");
1038
1070
  validatedEmail = validateContacts(
1039
1071
  event,
1040
1072
  sessionData,
1041
1073
  config.supportedBillingCountries
1042
1074
  );
1043
- console.log("[web-apple-pay] handlePaymentAuthorized: contacts valid", { validatedEmail });
1044
- console.log("[web-apple-pay] handlePaymentAuthorized: step 2 \u2014 calling performPurchase", { skuId });
1045
1075
  const result = await performPurchase({
1046
1076
  applePayToken: event.payment.token,
1047
1077
  skuId: config.skuId,
@@ -1051,8 +1081,6 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1051
1081
  },
1052
1082
  recaptchaTokens: config.recaptchaTokens
1053
1083
  });
1054
- console.log("[web-apple-pay] handlePaymentAuthorized: performPurchase succeeded", { basketId: result.basketId });
1055
- console.log("[web-apple-pay] handlePaymentAuthorized: step 3 \u2014 completing payment and redirecting");
1056
1084
  trackWalletPaymentSuccess(skuId, result.basketId);
1057
1085
  session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
1058
1086
  const userStatus = sessionData.loggedIn ? "lex" : "nex";
@@ -1065,25 +1093,17 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1065
1093
  });
1066
1094
  } catch (err) {
1067
1095
  if (err instanceof ContactValidationError) {
1068
- console.warn("[web-apple-pay] handlePaymentAuthorized: contact validation failed", err.errors);
1069
1096
  failApplePaySession(session, err.errors);
1070
1097
  return;
1071
1098
  }
1072
1099
  console.error("[web-apple-pay] onpaymentauthorized error", { skuId, err });
1073
1100
  const walletError = parseWalletApiError(err);
1074
- console.error("[web-apple-pay] handlePaymentAuthorized: BFF/network error", {
1075
- skuId,
1076
- errorType: walletError?.errorType ?? "UNKNOWN",
1077
- message: walletError?.message
1078
- });
1079
1101
  trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
1080
1102
  failApplePaySession(session);
1081
1103
  if (!walletError) {
1082
- console.warn("[web-apple-pay] handlePaymentAuthorized: unstructured error, using generic fallback");
1083
1104
  redirectFallback(skuId, returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
1084
1105
  return;
1085
1106
  }
1086
- console.log("[web-apple-pay] handlePaymentAuthorized: dispatching structured error handler", { errorType: walletError.errorType });
1087
1107
  handleStructuredError({ skuId, returnUrl, validatedEmail, walletError });
1088
1108
  }
1089
1109
  }
@@ -1370,19 +1390,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1370
1390
  * Creates and configures an ApplePayButton if the feature flag is present.
1371
1391
  */
1372
1392
  static createIfEnabled(offer, country, entryPoint) {
1373
- if (!offer) {
1374
- console.log("[web-apple-pay] createIfEnabled: no offer provided \u2192 null");
1393
+ if (!offer) return null;
1394
+ if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant))
1375
1395
  return null;
1376
- }
1377
- if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
1378
- console.log("[web-apple-pay] createIfEnabled: excluded variant \u2192 null", { variant: offer.product?.variant });
1396
+ if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT))
1379
1397
  return null;
1380
- }
1381
- if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
1382
- console.log("[web-apple-pay] createIfEnabled: feature flag absent \u2192 null");
1383
- return null;
1384
- }
1385
- console.log("[web-apple-pay] createIfEnabled: creating button", { skuId: offer.sku_id, country, entryPoint });
1386
1398
  _ApplePayButton.define();
1387
1399
  const button = document.createElement(_ApplePayButton.tag);
1388
1400
  button.offer = offer;
@@ -1450,9 +1462,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1450
1462
  }
1451
1463
  // ─── Lifecycle ──────────────────────────────────────────────────────────────
1452
1464
  async connectedCallback() {
1453
- console.log("[web-apple-pay] connectedCallback: element connected");
1454
1465
  if (this.#rendering || this.querySelector(SEL_CONTAINER)) {
1455
- console.log("[web-apple-pay] connectedCallback: already rendering or rendered, skipping");
1456
1466
  return;
1457
1467
  }
1458
1468
  this.#rendering = true;
@@ -1479,17 +1489,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1479
1489
  }
1480
1490
  // ─── Render pipeline ────────────────────────────────────────────────────────
1481
1491
  async #run() {
1482
- console.log("[web-apple-pay] #run: starting render pipeline");
1483
1492
  try {
1484
1493
  if (await this.#checkAvailability()) return;
1485
- if (await this.#checkSession()) return;
1486
1494
  if (this.#checkOffer()) return;
1495
+ this.#renderTemplate();
1496
+ if (await this.#checkSession()) return;
1487
1497
  this.#captureReturnUrl();
1488
1498
  this.#computeBillingCountries();
1489
1499
  if (await this.#fetchAndCacheOptions()) return;
1490
- this.#renderTemplate();
1500
+ this.#finishLoading();
1491
1501
  } catch {
1492
1502
  this.style.display = "none";
1503
+ this.querySelector(SEL_CONTAINER)?.remove();
1493
1504
  } finally {
1494
1505
  this.#rendering = false;
1495
1506
  }
@@ -1498,11 +1509,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1498
1509
  async #checkAvailability() {
1499
1510
  const available = await isApplePayAvailable();
1500
1511
  if (!available) {
1501
- console.log("[web-apple-pay] #checkAvailability: Apple Pay unavailable \u2192 hiding");
1502
1512
  this.style.display = "none";
1503
1513
  return true;
1504
1514
  }
1505
- console.log("[web-apple-pay] #checkAvailability: Apple Pay available");
1506
1515
  return false;
1507
1516
  }
1508
1517
  /**
@@ -1511,10 +1520,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1511
1520
  */
1512
1521
  async #checkSession() {
1513
1522
  this.#sessionData = await this.#fetchSession();
1514
- console.log("[web-apple-pay] #checkSession: session fetched", { loggedIn: this.#sessionData?.loggedIn, userType: this.#sessionData?.userType });
1515
1523
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1516
- console.log("[web-apple-pay] #checkSession: ineligible user \u2192 hiding", { userType: this.#sessionData.userType });
1517
1524
  this.style.display = "none";
1525
+ this.querySelector(SEL_CONTAINER)?.remove();
1518
1526
  return true;
1519
1527
  }
1520
1528
  return false;
@@ -1522,17 +1530,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1522
1530
  /** Returns `true` (hide) when no offer has been set before mount. */
1523
1531
  #checkOffer() {
1524
1532
  if (!this.#offer) {
1525
- console.log("[web-apple-pay] #checkOffer: no offer set \u2192 hiding");
1526
1533
  this.style.display = "none";
1527
1534
  return true;
1528
1535
  }
1529
- console.log("[web-apple-pay] #checkOffer: offer present", { skuId: this.#offer.sku_id });
1530
1536
  return false;
1531
1537
  }
1532
1538
  /** Captures the current page URL once at mount for reuse across the session lifetime. */
1533
1539
  #captureReturnUrl() {
1534
1540
  this.#returnUrl = captureOriginUrl();
1535
- console.log("[web-apple-pay] #captureReturnUrl:", this.#returnUrl);
1536
1541
  }
1537
1542
  /**
1538
1543
  * Computes supported billing countries once at mount.
@@ -1544,7 +1549,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1544
1549
  this.#country,
1545
1550
  this.#offer.product?.variant ?? ""
1546
1551
  );
1547
- console.log("[web-apple-pay] #computeBillingCountries:", this.#supportedBillingCountries);
1548
1552
  }
1549
1553
  /**
1550
1554
  * Returns `true` (hide) when the wallet BFF reports Apple Pay is unavailable
@@ -1552,36 +1556,44 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1552
1556
  */
1553
1557
  async #fetchAndCacheOptions() {
1554
1558
  this.#paymentOptions = await this.#fetchPaymentOptions();
1555
- console.log("[web-apple-pay] #fetchAndCacheOptions: fetched payment options", { paymentOptions: this.#paymentOptions });
1556
- if (!this.#paymentOptions?.options?.apple_pay) {
1557
- console.log("[web-apple-pay] #fetchAndCacheOptions: apple_pay not in options \u2192 hiding");
1559
+ if (!this.#paymentOptions?.apple_pay) {
1558
1560
  this.style.display = "none";
1561
+ this.querySelector(SEL_CONTAINER)?.remove();
1559
1562
  return true;
1560
1563
  }
1561
1564
  return false;
1562
1565
  }
1563
1566
  /** Injects the button template and wires click and confirm event listeners. */
1564
1567
  #renderTemplate() {
1565
- console.log("[web-apple-pay] #renderTemplate: rendering Apple Pay button", { skuId: this.#offer?.sku_id, country: this.#country });
1566
1568
  this.style.removeProperty("display");
1567
1569
  ensureApplePayLogoSymbol();
1568
1570
  const template = document.createElement("template");
1569
1571
  template.innerHTML = apple_pay_button_template_default;
1570
1572
  this.appendChild(template.content.cloneNode(true));
1571
- this.#updateDisabledState();
1572
- trackExpressWalletImpression(this.#offer.sku_id, {
1573
- entryPoint: this.#entryPoint,
1574
- country: this.#country
1575
- });
1576
1573
  const button = this.querySelector(SEL_BUTTON);
1574
+ button.classList.add("wap-loading");
1575
+ button.setAttribute("disabled", "");
1576
+ button.setAttribute("aria-disabled", "true");
1577
+ button.setAttribute("aria-busy", "true");
1577
1578
  button.addEventListener("click", () => {
1579
+ if (button.classList.contains("wap-loading")) return;
1578
1580
  this.#openModal();
1579
1581
  });
1580
- document.addEventListener("apple-pay-confirmed", (event) => {
1582
+ this.addEventListener("apple-pay-confirmed", (event) => {
1581
1583
  const { skuId, country } = event.detail;
1582
- console.log("[web-apple-pay] apple-pay-confirmed received on document", { skuId, country });
1583
1584
  this.#initiateApplePay(skuId, country);
1584
- }, { once: true });
1585
+ });
1586
+ }
1587
+ #finishLoading() {
1588
+ const button = this.querySelector(SEL_BUTTON);
1589
+ if (button) {
1590
+ button.classList.remove("wap-loading");
1591
+ this.#updateDisabledState();
1592
+ trackExpressWalletImpression(this.#offer.sku_id, {
1593
+ entryPoint: this.#entryPoint,
1594
+ country: this.#country
1595
+ });
1596
+ }
1585
1597
  }
1586
1598
  // ─── Private helpers ────────────────────────────────────────────────────────
1587
1599
  #updateDisabledState() {
@@ -1590,13 +1602,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1590
1602
  if (this.#offer) {
1591
1603
  button.removeAttribute("disabled");
1592
1604
  button.removeAttribute("aria-disabled");
1605
+ button.removeAttribute("aria-busy");
1593
1606
  return;
1594
1607
  }
1595
1608
  button.setAttribute("disabled", "");
1596
1609
  button.setAttribute("aria-disabled", "true");
1597
1610
  }
1598
1611
  #openModal() {
1599
- console.log("[web-apple-pay] #openModal: button clicked", { skuId: this.#offer?.sku_id });
1600
1612
  if (!this.#offer || document.querySelector(ApplePayModal.tag)) return;
1601
1613
  trackExpressWalletClick(this.#offer.sku_id);
1602
1614
  ApplePayModal.define();
@@ -1610,37 +1622,30 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1610
1622
  }
1611
1623
  async #fetchSession() {
1612
1624
  try {
1613
- const session = await getExpressCheckoutSession();
1614
- console.log("[web-apple-pay] #fetchSession: success", { loggedIn: session.loggedIn, userType: session.userType });
1615
- return session;
1616
- } catch (err) {
1617
- console.warn("[web-apple-pay] #fetchSession: failed, falling back to anonymous session", err);
1625
+ return await getExpressCheckoutSession();
1626
+ } catch {
1618
1627
  return null;
1619
1628
  }
1620
1629
  }
1621
1630
  async #fetchPaymentOptions() {
1622
1631
  try {
1623
- const options = await getPaymentOptions({
1632
+ return await getPaymentOptions({
1624
1633
  sku: this.#offer.sku_id,
1625
1634
  countryCode: this.#country,
1626
1635
  currencyCode: this.#offer.price?.currency_code ?? DEFAULT_CURRENCY,
1627
1636
  checkoutUrl: this.#returnUrl
1628
1637
  });
1629
- console.log("[web-apple-pay] #fetchPaymentOptions: success", { hasApplePay: !!options?.options?.apple_pay });
1630
- return options;
1631
- } catch (err) {
1632
- console.warn("[web-apple-pay] #fetchPaymentOptions: failed", err);
1638
+ } catch {
1633
1639
  return null;
1634
1640
  }
1635
1641
  }
1636
1642
  #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokens) {
1637
- console.log("[web-apple-pay] #buildSessionParams", { skuId, country, userLoggedIn: sessionData.loggedIn });
1638
1643
  const offer = this.#offer;
1639
1644
  const totalAmount = offer.price?.purchase ? `${offer.price.purchase}` : DEFAULT_TOTAL;
1640
1645
  return {
1641
1646
  countryCode: country,
1642
1647
  currencyCode: offer.price?.currency_code ?? DEFAULT_CURRENCY,
1643
- supportedNetworks: paymentOptions.options.apple_pay.settings.supported_networks,
1648
+ supportedNetworks: paymentOptions.apple_pay.settings.supported_networks,
1644
1649
  totalAmount,
1645
1650
  totalLabel: TOTAL_LABEL,
1646
1651
  skuId,
@@ -1657,7 +1662,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1657
1662
  };
1658
1663
  }
1659
1664
  async #initiateApplePay(skuId, country) {
1660
- console.log("[web-apple-pay] #initiateApplePay: starting", { skuId, country });
1661
1665
  try {
1662
1666
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
1663
1667
  const paymentOptions = this.#paymentOptions;