@economist/web-apple-pay 1.6.2-beta.1 → 1.7.0

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
@@ -439,17 +439,95 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- 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
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
446
530
  var configureApplePay = (config) => {
447
- console.log("[web-apple-pay] configureApplePay called", {
448
- merchantId: config.merchantId,
449
- walletApiBaseUrl: config.walletApiBaseUrl,
450
- debugBypassEnabled: config.debugBypassEnabled,
451
- recaptchaSiteKey: config.recaptchaSiteKey ? "***" : void 0
452
- });
453
531
  runtimeConfig = {
454
532
  ...config
455
533
  };
@@ -464,27 +542,21 @@ var isAppleDeviceOrSafari = () => {
464
542
  };
465
543
  var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
466
544
  var isApplePayAvailable = async () => {
467
- console.log("[web-apple-pay] isApplePayAvailable: checking availability");
468
545
  if (bypassApplePayChecks()) {
469
- console.log("[web-apple-pay] isApplePayAvailable: bypass active \u2192 true");
470
546
  return true;
471
547
  }
472
548
  if (!isAppleDeviceOrSafari()) {
473
- console.log("[web-apple-pay] isApplePayAvailable: not Apple device or Safari \u2192 false");
474
549
  return false;
475
550
  }
476
551
  const applePaySession = window.ApplePaySession;
477
552
  if (!applePaySession) {
478
- console.log("[web-apple-pay] isApplePayAvailable: ApplePaySession not found on window \u2192 false");
479
553
  return false;
480
554
  }
481
555
  try {
482
556
  if (typeof applePaySession.canMakePayments !== "function") {
483
- console.log("[web-apple-pay] isApplePayAvailable: canMakePayments is not a function \u2192 false");
484
557
  return false;
485
558
  }
486
559
  if (!applePaySession.canMakePayments()) {
487
- console.log("[web-apple-pay] isApplePayAvailable: canMakePayments() returned false \u2192 false");
488
560
  return false;
489
561
  }
490
562
  const merchantId = getApplePayConfig()?.merchantId;
@@ -494,10 +566,7 @@ var isApplePayAvailable = async () => {
494
566
  );
495
567
  return false;
496
568
  }
497
- console.log("[web-apple-pay] isApplePayAvailable : calling canMakePaymentsWithActiveCard", { merchantId });
498
- const result = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
499
- console.log("[web-apple-pay] isApplePayAvailable: canMakePaymentsWithActiveCard \u2192", result);
500
- return result;
569
+ return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
501
570
  } catch (error) {
502
571
  console.error("Error checking Apple Pay active card status:", error);
503
572
  return false;
@@ -759,13 +828,6 @@ var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
759
828
 
760
829
  // src/clients/payment-checkout/apple-session.ts
761
830
  function startApplePaySession(config) {
762
- console.log("[web-apple-pay] startApplePaySession", {
763
- skuId: config.skuId,
764
- countryCode: config.countryCode,
765
- currencyCode: config.currencyCode,
766
- totalAmount: config.totalAmount,
767
- userLoggedIn: config.userLoggedIn
768
- });
769
831
  const paymentRequest = {
770
832
  countryCode: config.countryCode,
771
833
  currencyCode: config.currencyCode,
@@ -781,11 +843,9 @@ function startApplePaySession(config) {
781
843
  };
782
844
  const session = new ApplePaySession(3, paymentRequest);
783
845
  session.onvalidatemerchant = async (event) => {
784
- console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
785
846
  try {
786
847
  const validationHost = new URL(event.validationURL).host;
787
848
  if (!validationHost.endsWith("apple.com")) {
788
- console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
789
849
  trackFallbackCheckout(config.skuId);
790
850
  session.abort();
791
851
  window.location.href = redirectToCheckoutFallback({
@@ -796,13 +856,11 @@ function startApplePaySession(config) {
796
856
  return;
797
857
  }
798
858
  const recaptchaToken = await getRecaptchaToken("verifyMerchant");
799
- console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
800
859
  const response = await validateAppleMerchant({
801
860
  validationURL: event.validationURL,
802
861
  recaptchaToken
803
862
  });
804
863
  if (!response?.merchantSession) {
805
- console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
806
864
  trackFallbackCheckout(config.skuId);
807
865
  session.abort();
808
866
  window.location.href = redirectToCheckoutFallback({
@@ -812,10 +870,8 @@ function startApplePaySession(config) {
812
870
  });
813
871
  return;
814
872
  }
815
- console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
816
873
  session.completeMerchantValidation(response.merchantSession);
817
- } catch (err) {
818
- console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
874
+ } catch {
819
875
  trackFallbackCheckout(config.skuId);
820
876
  session.abort();
821
877
  window.location.href = redirectToCheckoutFallback({
@@ -826,15 +882,12 @@ function startApplePaySession(config) {
826
882
  }
827
883
  };
828
884
  session.onpaymentauthorized = (event) => {
829
- console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
830
885
  trackWalletPaymentAuthorised(config.skuId);
831
886
  config.onPaymentAuthorized(event, session);
832
887
  };
833
888
  session.oncancel = () => {
834
- console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
835
889
  config.onCancel?.();
836
890
  };
837
- console.log("[web-apple-pay] startApplePaySession: beginning session");
838
891
  trackWalletPaymentSheetOpen(config.skuId);
839
892
  session.begin();
840
893
  }
@@ -1013,16 +1066,12 @@ function handleStructuredError(ctx) {
1013
1066
  async function handlePaymentAuthorized(event, session, sessionData, config) {
1014
1067
  const { skuId, returnUrl, queryString } = config;
1015
1068
  let validatedEmail;
1016
- console.log("[web-apple-pay] handlePaymentAuthorized: starting", { skuId, userLoggedIn: sessionData.loggedIn });
1017
1069
  try {
1018
- console.log("[web-apple-pay] handlePaymentAuthorized: step 1 \u2014 validating contacts");
1019
1070
  validatedEmail = validateContacts(
1020
1071
  event,
1021
1072
  sessionData,
1022
1073
  config.supportedBillingCountries
1023
1074
  );
1024
- console.log("[web-apple-pay] handlePaymentAuthorized: contacts valid", { validatedEmail });
1025
- console.log("[web-apple-pay] handlePaymentAuthorized: step 2 \u2014 calling performPurchase", { skuId });
1026
1075
  const result = await performPurchase({
1027
1076
  applePayToken: event.payment.token,
1028
1077
  skuId: config.skuId,
@@ -1032,8 +1081,6 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1032
1081
  },
1033
1082
  recaptchaTokens: config.recaptchaTokens
1034
1083
  });
1035
- console.log("[web-apple-pay] handlePaymentAuthorized: performPurchase succeeded", { basketId: result.basketId });
1036
- console.log("[web-apple-pay] handlePaymentAuthorized: step 3 \u2014 completing payment and redirecting");
1037
1084
  trackWalletPaymentSuccess(skuId, result.basketId);
1038
1085
  session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
1039
1086
  const userStatus = sessionData.loggedIn ? "lex" : "nex";
@@ -1046,25 +1093,17 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1046
1093
  });
1047
1094
  } catch (err) {
1048
1095
  if (err instanceof ContactValidationError) {
1049
- console.warn("[web-apple-pay] handlePaymentAuthorized: contact validation failed", err.errors);
1050
1096
  failApplePaySession(session, err.errors);
1051
1097
  return;
1052
1098
  }
1053
1099
  console.error("[web-apple-pay] onpaymentauthorized error", { skuId, err });
1054
1100
  const walletError = parseWalletApiError(err);
1055
- console.error("[web-apple-pay] handlePaymentAuthorized: BFF/network error", {
1056
- skuId,
1057
- errorType: walletError?.errorType ?? "UNKNOWN",
1058
- message: walletError?.message
1059
- });
1060
1101
  trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
1061
1102
  failApplePaySession(session);
1062
1103
  if (!walletError) {
1063
- console.warn("[web-apple-pay] handlePaymentAuthorized: unstructured error, using generic fallback");
1064
1104
  redirectFallback(skuId, returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
1065
1105
  return;
1066
1106
  }
1067
- console.log("[web-apple-pay] handlePaymentAuthorized: dispatching structured error handler", { errorType: walletError.errorType });
1068
1107
  handleStructuredError({ skuId, returnUrl, validatedEmail, walletError });
1069
1108
  }
1070
1109
  }
@@ -1452,14 +1491,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1452
1491
  async #run() {
1453
1492
  try {
1454
1493
  if (await this.#checkAvailability()) return;
1455
- if (await this.#checkSession()) return;
1456
1494
  if (this.#checkOffer()) return;
1495
+ this.#renderTemplate();
1496
+ if (await this.#checkSession()) return;
1457
1497
  this.#captureReturnUrl();
1458
1498
  this.#computeBillingCountries();
1459
1499
  if (await this.#fetchAndCacheOptions()) return;
1460
- this.#renderTemplate();
1500
+ this.#finishLoading();
1461
1501
  } catch {
1462
1502
  this.style.display = "none";
1503
+ this.querySelector(SEL_CONTAINER)?.remove();
1463
1504
  } finally {
1464
1505
  this.#rendering = false;
1465
1506
  }
@@ -1481,6 +1522,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1481
1522
  this.#sessionData = await this.#fetchSession();
1482
1523
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1483
1524
  this.style.display = "none";
1525
+ this.querySelector(SEL_CONTAINER)?.remove();
1484
1526
  return true;
1485
1527
  }
1486
1528
  return false;
@@ -1516,6 +1558,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1516
1558
  this.#paymentOptions = await this.#fetchPaymentOptions();
1517
1559
  if (!this.#paymentOptions?.apple_pay) {
1518
1560
  this.style.display = "none";
1561
+ this.querySelector(SEL_CONTAINER)?.remove();
1519
1562
  return true;
1520
1563
  }
1521
1564
  return false;
@@ -1527,13 +1570,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1527
1570
  const template = document.createElement("template");
1528
1571
  template.innerHTML = apple_pay_button_template_default;
1529
1572
  this.appendChild(template.content.cloneNode(true));
1530
- this.#updateDisabledState();
1531
- trackExpressWalletImpression(this.#offer.sku_id, {
1532
- entryPoint: this.#entryPoint,
1533
- country: this.#country
1534
- });
1535
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");
1536
1578
  button.addEventListener("click", () => {
1579
+ if (button.classList.contains("wap-loading")) return;
1537
1580
  this.#openModal();
1538
1581
  });
1539
1582
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1541,6 +1584,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1541
1584
  this.#initiateApplePay(skuId, country);
1542
1585
  });
1543
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
+ }
1597
+ }
1544
1598
  // ─── Private helpers ────────────────────────────────────────────────────────
1545
1599
  #updateDisabledState() {
1546
1600
  const button = this.querySelector(SEL_BUTTON);
@@ -1548,6 +1602,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1548
1602
  if (this.#offer) {
1549
1603
  button.removeAttribute("disabled");
1550
1604
  button.removeAttribute("aria-disabled");
1605
+ button.removeAttribute("aria-busy");
1551
1606
  return;
1552
1607
  }
1553
1608
  button.setAttribute("disabled", "");
@@ -439,7 +439,91 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- 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
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
@@ -453,27 +537,21 @@ var isAppleDeviceOrSafari = () => {
453
537
  };
454
538
  var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
455
539
  var isApplePayAvailable = async () => {
456
- console.log("[web-apple-pay] isApplePayAvailable: checking availability");
457
540
  if (bypassApplePayChecks()) {
458
- console.log("[web-apple-pay] isApplePayAvailable: bypass active \u2192 true");
459
541
  return true;
460
542
  }
461
543
  if (!isAppleDeviceOrSafari()) {
462
- console.log("[web-apple-pay] isApplePayAvailable: not Apple device or Safari \u2192 false");
463
544
  return false;
464
545
  }
465
546
  const applePaySession = window.ApplePaySession;
466
547
  if (!applePaySession) {
467
- console.log("[web-apple-pay] isApplePayAvailable: ApplePaySession not found on window \u2192 false");
468
548
  return false;
469
549
  }
470
550
  try {
471
551
  if (typeof applePaySession.canMakePayments !== "function") {
472
- console.log("[web-apple-pay] isApplePayAvailable: canMakePayments is not a function \u2192 false");
473
552
  return false;
474
553
  }
475
554
  if (!applePaySession.canMakePayments()) {
476
- console.log("[web-apple-pay] isApplePayAvailable: canMakePayments() returned false \u2192 false");
477
555
  return false;
478
556
  }
479
557
  const merchantId = getApplePayConfig()?.merchantId;
@@ -483,10 +561,7 @@ var isApplePayAvailable = async () => {
483
561
  );
484
562
  return false;
485
563
  }
486
- console.log("[web-apple-pay] isApplePayAvailable : calling canMakePaymentsWithActiveCard", { merchantId });
487
- const result = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
488
- console.log("[web-apple-pay] isApplePayAvailable: canMakePaymentsWithActiveCard \u2192", result);
489
- return result;
564
+ return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
490
565
  } catch (error) {
491
566
  console.error("Error checking Apple Pay active card status:", error);
492
567
  return false;
@@ -748,13 +823,6 @@ var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
748
823
 
749
824
  // src/clients/payment-checkout/apple-session.ts
750
825
  function startApplePaySession(config) {
751
- console.log("[web-apple-pay] startApplePaySession", {
752
- skuId: config.skuId,
753
- countryCode: config.countryCode,
754
- currencyCode: config.currencyCode,
755
- totalAmount: config.totalAmount,
756
- userLoggedIn: config.userLoggedIn
757
- });
758
826
  const paymentRequest = {
759
827
  countryCode: config.countryCode,
760
828
  currencyCode: config.currencyCode,
@@ -770,11 +838,9 @@ function startApplePaySession(config) {
770
838
  };
771
839
  const session = new ApplePaySession(3, paymentRequest);
772
840
  session.onvalidatemerchant = async (event) => {
773
- console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
774
841
  try {
775
842
  const validationHost = new URL(event.validationURL).host;
776
843
  if (!validationHost.endsWith("apple.com")) {
777
- console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
778
844
  trackFallbackCheckout(config.skuId);
779
845
  session.abort();
780
846
  window.location.href = redirectToCheckoutFallback({
@@ -785,13 +851,11 @@ function startApplePaySession(config) {
785
851
  return;
786
852
  }
787
853
  const recaptchaToken = await getRecaptchaToken("verifyMerchant");
788
- console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
789
854
  const response = await validateAppleMerchant({
790
855
  validationURL: event.validationURL,
791
856
  recaptchaToken
792
857
  });
793
858
  if (!response?.merchantSession) {
794
- console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
795
859
  trackFallbackCheckout(config.skuId);
796
860
  session.abort();
797
861
  window.location.href = redirectToCheckoutFallback({
@@ -801,10 +865,8 @@ function startApplePaySession(config) {
801
865
  });
802
866
  return;
803
867
  }
804
- console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
805
868
  session.completeMerchantValidation(response.merchantSession);
806
- } catch (err) {
807
- console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
869
+ } catch {
808
870
  trackFallbackCheckout(config.skuId);
809
871
  session.abort();
810
872
  window.location.href = redirectToCheckoutFallback({
@@ -815,15 +877,12 @@ function startApplePaySession(config) {
815
877
  }
816
878
  };
817
879
  session.onpaymentauthorized = (event) => {
818
- console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
819
880
  trackWalletPaymentAuthorised(config.skuId);
820
881
  config.onPaymentAuthorized(event, session);
821
882
  };
822
883
  session.oncancel = () => {
823
- console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
824
884
  config.onCancel?.();
825
885
  };
826
- console.log("[web-apple-pay] startApplePaySession: beginning session");
827
886
  trackWalletPaymentSheetOpen(config.skuId);
828
887
  session.begin();
829
888
  }
@@ -1002,16 +1061,12 @@ function handleStructuredError(ctx) {
1002
1061
  async function handlePaymentAuthorized(event, session, sessionData, config) {
1003
1062
  const { skuId, returnUrl, queryString } = config;
1004
1063
  let validatedEmail;
1005
- console.log("[web-apple-pay] handlePaymentAuthorized: starting", { skuId, userLoggedIn: sessionData.loggedIn });
1006
1064
  try {
1007
- console.log("[web-apple-pay] handlePaymentAuthorized: step 1 \u2014 validating contacts");
1008
1065
  validatedEmail = validateContacts(
1009
1066
  event,
1010
1067
  sessionData,
1011
1068
  config.supportedBillingCountries
1012
1069
  );
1013
- console.log("[web-apple-pay] handlePaymentAuthorized: contacts valid", { validatedEmail });
1014
- console.log("[web-apple-pay] handlePaymentAuthorized: step 2 \u2014 calling performPurchase", { skuId });
1015
1070
  const result = await performPurchase({
1016
1071
  applePayToken: event.payment.token,
1017
1072
  skuId: config.skuId,
@@ -1021,8 +1076,6 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1021
1076
  },
1022
1077
  recaptchaTokens: config.recaptchaTokens
1023
1078
  });
1024
- console.log("[web-apple-pay] handlePaymentAuthorized: performPurchase succeeded", { basketId: result.basketId });
1025
- console.log("[web-apple-pay] handlePaymentAuthorized: step 3 \u2014 completing payment and redirecting");
1026
1079
  trackWalletPaymentSuccess(skuId, result.basketId);
1027
1080
  session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
1028
1081
  const userStatus = sessionData.loggedIn ? "lex" : "nex";
@@ -1035,25 +1088,17 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1035
1088
  });
1036
1089
  } catch (err) {
1037
1090
  if (err instanceof ContactValidationError) {
1038
- console.warn("[web-apple-pay] handlePaymentAuthorized: contact validation failed", err.errors);
1039
1091
  failApplePaySession(session, err.errors);
1040
1092
  return;
1041
1093
  }
1042
1094
  console.error("[web-apple-pay] onpaymentauthorized error", { skuId, err });
1043
1095
  const walletError = parseWalletApiError(err);
1044
- console.error("[web-apple-pay] handlePaymentAuthorized: BFF/network error", {
1045
- skuId,
1046
- errorType: walletError?.errorType ?? "UNKNOWN",
1047
- message: walletError?.message
1048
- });
1049
1096
  trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
1050
1097
  failApplePaySession(session);
1051
1098
  if (!walletError) {
1052
- console.warn("[web-apple-pay] handlePaymentAuthorized: unstructured error, using generic fallback");
1053
1099
  redirectFallback(skuId, returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
1054
1100
  return;
1055
1101
  }
1056
- console.log("[web-apple-pay] handlePaymentAuthorized: dispatching structured error handler", { errorType: walletError.errorType });
1057
1102
  handleStructuredError({ skuId, returnUrl, validatedEmail, walletError });
1058
1103
  }
1059
1104
  }
@@ -1441,14 +1486,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1441
1486
  async #run() {
1442
1487
  try {
1443
1488
  if (await this.#checkAvailability()) return;
1444
- if (await this.#checkSession()) return;
1445
1489
  if (this.#checkOffer()) return;
1490
+ this.#renderTemplate();
1491
+ if (await this.#checkSession()) return;
1446
1492
  this.#captureReturnUrl();
1447
1493
  this.#computeBillingCountries();
1448
1494
  if (await this.#fetchAndCacheOptions()) return;
1449
- this.#renderTemplate();
1495
+ this.#finishLoading();
1450
1496
  } catch {
1451
1497
  this.style.display = "none";
1498
+ this.querySelector(SEL_CONTAINER)?.remove();
1452
1499
  } finally {
1453
1500
  this.#rendering = false;
1454
1501
  }
@@ -1470,6 +1517,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1470
1517
  this.#sessionData = await this.#fetchSession();
1471
1518
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1472
1519
  this.style.display = "none";
1520
+ this.querySelector(SEL_CONTAINER)?.remove();
1473
1521
  return true;
1474
1522
  }
1475
1523
  return false;
@@ -1505,6 +1553,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1505
1553
  this.#paymentOptions = await this.#fetchPaymentOptions();
1506
1554
  if (!this.#paymentOptions?.apple_pay) {
1507
1555
  this.style.display = "none";
1556
+ this.querySelector(SEL_CONTAINER)?.remove();
1508
1557
  return true;
1509
1558
  }
1510
1559
  return false;
@@ -1516,13 +1565,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1516
1565
  const template = document.createElement("template");
1517
1566
  template.innerHTML = apple_pay_button_template_default;
1518
1567
  this.appendChild(template.content.cloneNode(true));
1519
- this.#updateDisabledState();
1520
- trackExpressWalletImpression(this.#offer.sku_id, {
1521
- entryPoint: this.#entryPoint,
1522
- country: this.#country
1523
- });
1524
1568
  const button = this.querySelector(SEL_BUTTON);
1569
+ button.classList.add("wap-loading");
1570
+ button.setAttribute("disabled", "");
1571
+ button.setAttribute("aria-disabled", "true");
1572
+ button.setAttribute("aria-busy", "true");
1525
1573
  button.addEventListener("click", () => {
1574
+ if (button.classList.contains("wap-loading")) return;
1526
1575
  this.#openModal();
1527
1576
  });
1528
1577
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1530,6 +1579,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1530
1579
  this.#initiateApplePay(skuId, country);
1531
1580
  });
1532
1581
  }
1582
+ #finishLoading() {
1583
+ const button = this.querySelector(SEL_BUTTON);
1584
+ if (button) {
1585
+ button.classList.remove("wap-loading");
1586
+ this.#updateDisabledState();
1587
+ trackExpressWalletImpression(this.#offer.sku_id, {
1588
+ entryPoint: this.#entryPoint,
1589
+ country: this.#country
1590
+ });
1591
+ }
1592
+ }
1533
1593
  // ─── Private helpers ────────────────────────────────────────────────────────
1534
1594
  #updateDisabledState() {
1535
1595
  const button = this.querySelector(SEL_BUTTON);
@@ -1537,6 +1597,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1537
1597
  if (this.#offer) {
1538
1598
  button.removeAttribute("disabled");
1539
1599
  button.removeAttribute("aria-disabled");
1600
+ button.removeAttribute("aria-busy");
1540
1601
  return;
1541
1602
  }
1542
1603
  button.setAttribute("disabled", "");