@economist/web-apple-pay 1.7.9 → 1.7.10

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
@@ -575,10 +575,9 @@ var loadRecaptchaScript = (siteKey) => {
575
575
  );
576
576
  if (existingScript) {
577
577
  existingScript.addEventListener("load", () => resolve());
578
- existingScript.addEventListener(
579
- "error",
580
- () => reject(new Error("Failed to load existing reCAPTCHA script"))
581
- );
578
+ existingScript.addEventListener("error", () => {
579
+ reject(new Error("Failed to load existing reCAPTCHA script"));
580
+ });
582
581
  return;
583
582
  }
584
583
  const script = document.createElement("script");
@@ -586,7 +585,9 @@ var loadRecaptchaScript = (siteKey) => {
586
585
  script.async = true;
587
586
  script.defer = true;
588
587
  script.onload = () => resolve();
589
- script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
588
+ script.onerror = () => {
589
+ reject(new Error("Failed to load reCAPTCHA script"));
590
+ };
590
591
  document.head.appendChild(script);
591
592
  });
592
593
  };
@@ -835,17 +836,14 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
835
836
  #country = "";
836
837
  #triggerElement = null;
837
838
  #keyHandler = null;
838
- #recaptchaTokens = null;
839
- #recaptchaTokensPromise = null;
839
+ #isClosed = false;
840
840
  /**
841
- * Synchronous callback invoked directly from the CTA click handler once the
842
- * user confirms. The caller (ApplePayButton) must call startApplePaySession
843
- * inside this callback to preserve the browser's user-gesture chain — Safari
844
- * requires new ApplePaySession() to execute within the original click stack.
845
- *
846
- * reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
847
- * until the token pre-fetch resolves, so this callback is never reached
848
- * without valid tokens.
841
+ * Callback invoked synchronously from the CTA click handler.
842
+ * Receives a Promise of reCAPTCHA tokens — the promise is already in-flight
843
+ * by the time this is called. The caller (ApplePayButton) must call
844
+ * new ApplePaySession() synchronously inside this callback to stay within
845
+ * Safari's user-gesture window. The token promise resolves before
846
+ * onPaymentAuthorized fires (user still needs to authenticate on the sheet).
849
847
  */
850
848
  onConfirm = null;
851
849
  set offer(value) {
@@ -942,28 +940,32 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
942
940
  }
943
941
  });
944
942
  }
945
- if (this.#recaptchaTokensPromise) {
946
- if (cta) {
947
- cta.setAttribute("disabled", "");
948
- cta.setAttribute("aria-disabled", "true");
949
- cta.setAttribute("aria-busy", "true");
943
+ cta?.addEventListener("click", () => {
944
+ if (cta.disabled) return;
945
+ if (isUS && checkbox && !checkbox.checked) {
946
+ errorElement?.classList.add("apm__error--visible");
947
+ checkboxLabel?.classList.add("apm__checkbox-label--error");
948
+ return;
950
949
  }
951
- this.#recaptchaTokensPromise.then((tokens) => {
952
- this.#recaptchaTokens = tokens;
953
- if (cta) {
954
- cta.removeAttribute("disabled");
955
- cta.removeAttribute("aria-disabled");
956
- cta.removeAttribute("aria-busy");
957
- }
958
- }).catch(() => {
959
- if (cta) {
960
- cta.removeAttribute("aria-busy");
961
- }
950
+ errorElement?.classList.remove("apm__error--visible");
951
+ this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
952
+ cta.disabled = true;
953
+ cta.setAttribute("aria-busy", "true");
954
+ const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
955
+ if (!this.#isClosed && this.onConfirm) {
956
+ this.onConfirm(recaptchaTokensPromise);
957
+ this.close();
958
+ }
959
+ recaptchaTokensPromise.catch(() => {
960
+ if (this.#isClosed) return;
961
+ cta.disabled = false;
962
+ cta.removeAttribute("aria-busy");
962
963
  const existingError = this.querySelector("#apple-pay-modal-error");
963
964
  if (existingError) {
964
965
  const icon = existingError.querySelector("svg");
965
966
  existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
966
967
  if (icon) existingError.prepend(icon);
968
+ existingError.setAttribute("role", "alert");
967
969
  existingError.classList.add("apm__error--visible");
968
970
  } else {
969
971
  const errorNotice = document.createElement("div");
@@ -973,25 +975,14 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
973
975
  cta?.insertAdjacentElement("beforebegin", errorNotice);
974
976
  }
975
977
  });
976
- }
977
- cta?.addEventListener("click", () => {
978
- if (isUS && checkbox && !checkbox.checked) {
979
- errorElement?.classList.add("apm__error--visible");
980
- checkboxLabel?.classList.add("apm__checkbox-label--error");
981
- return;
982
- }
983
- if (this.#recaptchaTokens) {
984
- this.onConfirm?.(this.#recaptchaTokens);
985
- this.close();
986
- }
987
978
  });
988
979
  this.querySelector("#apple-pay-modal-close")?.addEventListener(
989
980
  "click",
990
981
  () => this.close()
991
982
  );
992
983
  }
993
- open(recaptchaTokensPromise) {
994
- this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
984
+ open() {
985
+ this.#isClosed = false;
995
986
  this.#triggerElement = document.activeElement;
996
987
  document.body.appendChild(this);
997
988
  this.#keyHandler = (event) => {
@@ -1006,6 +997,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
1006
997
  this.querySelector("#apple-pay-modal")?.focus();
1007
998
  }
1008
999
  close() {
1000
+ this.#isClosed = true;
1009
1001
  if (this.#keyHandler) {
1010
1002
  document.removeEventListener("keydown", this.#keyHandler, {
1011
1003
  capture: true
@@ -1418,7 +1410,10 @@ function startApplePaySession(config) {
1418
1410
  };
1419
1411
  session.onpaymentauthorized = (event) => {
1420
1412
  trackWalletPaymentAuthorised(config.skuId);
1421
- config.onPaymentAuthorized(event, session);
1413
+ config.onPaymentAuthorized(event, session).catch(() => {
1414
+ session.completePayment({ status: ApplePaySession.STATUS_FAILURE });
1415
+ redirectToFallbackCheckout(config);
1416
+ });
1422
1417
  };
1423
1418
  session.oncancel = () => {
1424
1419
  config.onCancel?.();
@@ -1969,7 +1964,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1969
1964
  #returnUrl = "";
1970
1965
  #supportedBillingCountries = [];
1971
1966
  #entryPoint = "";
1972
- #recaptchaTokensPromise = null;
1973
1967
  // ─── Public API ─────────────────────────────────────────────────────────────
1974
1968
  get offer() {
1975
1969
  return this.#offer;
@@ -2034,7 +2028,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2034
2028
  this.#paymentOptions = null;
2035
2029
  this.#returnUrl = "";
2036
2030
  this.#supportedBillingCountries = [];
2037
- this.#recaptchaTokensPromise = null;
2038
2031
  this.querySelector(SEL_CONTAINER)?.remove();
2039
2032
  }
2040
2033
  // ─── Render pipeline ────────────────────────────────────────────────────────
@@ -2137,7 +2130,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2137
2130
  if (button) {
2138
2131
  button.classList.remove("wap-loading");
2139
2132
  this.#updateDisabledState();
2140
- this.#scheduleRecaptchaTokens();
2141
2133
  trackExpressWalletImpression(this.#offer.sku_id, {
2142
2134
  entryPoint: this.#entryPoint,
2143
2135
  country: this.#country
@@ -2174,27 +2166,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2174
2166
  }
2175
2167
  const skuId = this.#offer.sku_id;
2176
2168
  const country = this.#country;
2177
- modal.onConfirm = (recaptchaTokens) => {
2178
- this.#initiateApplePay(skuId, country, recaptchaTokens);
2179
- this.#scheduleRecaptchaTokens();
2169
+ modal.onConfirm = (recaptchaTokensPromise) => {
2170
+ this.#initiateApplePay(skuId, country, recaptchaTokensPromise);
2180
2171
  };
2181
- modal.open(this.#recaptchaTokensPromise);
2182
- }
2183
- /**
2184
- * Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
2185
- * If the fetch rejects, the field is cleared so the next `modal.open()` call
2186
- * falls back to a new attempt via the modal's own null-fallback path — preventing
2187
- * a single transient failure from permanently disabling the CTA on all retries.
2188
- * The identity guard prevents a late rejection from clobbering a newer attempt.
2189
- */
2190
- #scheduleRecaptchaTokens() {
2191
- const attempt = getPurchaseRecaptchaTokens();
2192
- attempt.catch(() => {
2193
- if (this.#recaptchaTokensPromise === attempt) {
2194
- this.#recaptchaTokensPromise = null;
2195
- }
2196
- });
2197
- this.#recaptchaTokensPromise = attempt;
2172
+ modal.open();
2198
2173
  }
2199
2174
  async #fetchSession() {
2200
2175
  try {
@@ -2215,7 +2190,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2215
2190
  return null;
2216
2191
  }
2217
2192
  }
2218
- #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokens) {
2193
+ #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokensPromise) {
2219
2194
  const offer = this.#offer;
2220
2195
  const totalAmount = offer.price?.purchase ? `${offer.price.purchase}` : DEFAULT_TOTAL;
2221
2196
  return {
@@ -2227,30 +2202,41 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2227
2202
  skuId,
2228
2203
  returnUrl: this.#returnUrl,
2229
2204
  userLoggedIn: sessionData.loggedIn,
2230
- onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
2231
- skuId,
2232
- country,
2233
- currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
2234
- returnUrl: this.#returnUrl,
2235
- supportedBillingCountries: this.#supportedBillingCountries,
2236
- recaptchaTokens
2237
- })
2205
+ onPaymentAuthorized: async (event, session) => {
2206
+ const recaptchaTokens = await recaptchaTokensPromise;
2207
+ return handlePaymentAuthorized(event, session, sessionData, {
2208
+ skuId,
2209
+ country,
2210
+ currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
2211
+ returnUrl: this.#returnUrl,
2212
+ supportedBillingCountries: this.#supportedBillingCountries,
2213
+ recaptchaTokens
2214
+ });
2215
+ }
2238
2216
  };
2239
2217
  }
2240
- #initiateApplePay(skuId, country, recaptchaTokens) {
2218
+ #initiateApplePay(skuId, country, recaptchaTokensPromise) {
2241
2219
  try {
2242
2220
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
2243
2221
  const paymentOptions = this.#paymentOptions;
2222
+ if (!paymentOptions) {
2223
+ return;
2224
+ }
2244
2225
  startApplePaySession(
2245
2226
  this.#buildSessionParams(
2246
2227
  skuId,
2247
2228
  country,
2248
2229
  sessionData,
2249
2230
  paymentOptions,
2250
- recaptchaTokens
2231
+ recaptchaTokensPromise
2251
2232
  )
2252
2233
  );
2253
2234
  } catch {
2235
+ redirectToFallbackCheckout({
2236
+ returnUrl: this.#returnUrl,
2237
+ skuId,
2238
+ countryCode: country
2239
+ });
2254
2240
  }
2255
2241
  }
2256
2242
  };
@@ -570,10 +570,9 @@ var loadRecaptchaScript = (siteKey) => {
570
570
  );
571
571
  if (existingScript) {
572
572
  existingScript.addEventListener("load", () => resolve());
573
- existingScript.addEventListener(
574
- "error",
575
- () => reject(new Error("Failed to load existing reCAPTCHA script"))
576
- );
573
+ existingScript.addEventListener("error", () => {
574
+ reject(new Error("Failed to load existing reCAPTCHA script"));
575
+ });
577
576
  return;
578
577
  }
579
578
  const script = document.createElement("script");
@@ -581,7 +580,9 @@ var loadRecaptchaScript = (siteKey) => {
581
580
  script.async = true;
582
581
  script.defer = true;
583
582
  script.onload = () => resolve();
584
- script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
583
+ script.onerror = () => {
584
+ reject(new Error("Failed to load reCAPTCHA script"));
585
+ };
585
586
  document.head.appendChild(script);
586
587
  });
587
588
  };
@@ -830,17 +831,14 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
830
831
  #country = "";
831
832
  #triggerElement = null;
832
833
  #keyHandler = null;
833
- #recaptchaTokens = null;
834
- #recaptchaTokensPromise = null;
834
+ #isClosed = false;
835
835
  /**
836
- * Synchronous callback invoked directly from the CTA click handler once the
837
- * user confirms. The caller (ApplePayButton) must call startApplePaySession
838
- * inside this callback to preserve the browser's user-gesture chain — Safari
839
- * requires new ApplePaySession() to execute within the original click stack.
840
- *
841
- * reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
842
- * until the token pre-fetch resolves, so this callback is never reached
843
- * without valid tokens.
836
+ * Callback invoked synchronously from the CTA click handler.
837
+ * Receives a Promise of reCAPTCHA tokens — the promise is already in-flight
838
+ * by the time this is called. The caller (ApplePayButton) must call
839
+ * new ApplePaySession() synchronously inside this callback to stay within
840
+ * Safari's user-gesture window. The token promise resolves before
841
+ * onPaymentAuthorized fires (user still needs to authenticate on the sheet).
844
842
  */
845
843
  onConfirm = null;
846
844
  set offer(value) {
@@ -937,28 +935,32 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
937
935
  }
938
936
  });
939
937
  }
940
- if (this.#recaptchaTokensPromise) {
941
- if (cta) {
942
- cta.setAttribute("disabled", "");
943
- cta.setAttribute("aria-disabled", "true");
944
- cta.setAttribute("aria-busy", "true");
938
+ cta?.addEventListener("click", () => {
939
+ if (cta.disabled) return;
940
+ if (isUS && checkbox && !checkbox.checked) {
941
+ errorElement?.classList.add("apm__error--visible");
942
+ checkboxLabel?.classList.add("apm__checkbox-label--error");
943
+ return;
945
944
  }
946
- this.#recaptchaTokensPromise.then((tokens) => {
947
- this.#recaptchaTokens = tokens;
948
- if (cta) {
949
- cta.removeAttribute("disabled");
950
- cta.removeAttribute("aria-disabled");
951
- cta.removeAttribute("aria-busy");
952
- }
953
- }).catch(() => {
954
- if (cta) {
955
- cta.removeAttribute("aria-busy");
956
- }
945
+ errorElement?.classList.remove("apm__error--visible");
946
+ this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
947
+ cta.disabled = true;
948
+ cta.setAttribute("aria-busy", "true");
949
+ const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
950
+ if (!this.#isClosed && this.onConfirm) {
951
+ this.onConfirm(recaptchaTokensPromise);
952
+ this.close();
953
+ }
954
+ recaptchaTokensPromise.catch(() => {
955
+ if (this.#isClosed) return;
956
+ cta.disabled = false;
957
+ cta.removeAttribute("aria-busy");
957
958
  const existingError = this.querySelector("#apple-pay-modal-error");
958
959
  if (existingError) {
959
960
  const icon = existingError.querySelector("svg");
960
961
  existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
961
962
  if (icon) existingError.prepend(icon);
963
+ existingError.setAttribute("role", "alert");
962
964
  existingError.classList.add("apm__error--visible");
963
965
  } else {
964
966
  const errorNotice = document.createElement("div");
@@ -968,25 +970,14 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
968
970
  cta?.insertAdjacentElement("beforebegin", errorNotice);
969
971
  }
970
972
  });
971
- }
972
- cta?.addEventListener("click", () => {
973
- if (isUS && checkbox && !checkbox.checked) {
974
- errorElement?.classList.add("apm__error--visible");
975
- checkboxLabel?.classList.add("apm__checkbox-label--error");
976
- return;
977
- }
978
- if (this.#recaptchaTokens) {
979
- this.onConfirm?.(this.#recaptchaTokens);
980
- this.close();
981
- }
982
973
  });
983
974
  this.querySelector("#apple-pay-modal-close")?.addEventListener(
984
975
  "click",
985
976
  () => this.close()
986
977
  );
987
978
  }
988
- open(recaptchaTokensPromise) {
989
- this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
979
+ open() {
980
+ this.#isClosed = false;
990
981
  this.#triggerElement = document.activeElement;
991
982
  document.body.appendChild(this);
992
983
  this.#keyHandler = (event) => {
@@ -1001,6 +992,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
1001
992
  this.querySelector("#apple-pay-modal")?.focus();
1002
993
  }
1003
994
  close() {
995
+ this.#isClosed = true;
1004
996
  if (this.#keyHandler) {
1005
997
  document.removeEventListener("keydown", this.#keyHandler, {
1006
998
  capture: true
@@ -1413,7 +1405,10 @@ function startApplePaySession(config) {
1413
1405
  };
1414
1406
  session.onpaymentauthorized = (event) => {
1415
1407
  trackWalletPaymentAuthorised(config.skuId);
1416
- config.onPaymentAuthorized(event, session);
1408
+ config.onPaymentAuthorized(event, session).catch(() => {
1409
+ session.completePayment({ status: ApplePaySession.STATUS_FAILURE });
1410
+ redirectToFallbackCheckout(config);
1411
+ });
1417
1412
  };
1418
1413
  session.oncancel = () => {
1419
1414
  config.onCancel?.();
@@ -1964,7 +1959,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1964
1959
  #returnUrl = "";
1965
1960
  #supportedBillingCountries = [];
1966
1961
  #entryPoint = "";
1967
- #recaptchaTokensPromise = null;
1968
1962
  // ─── Public API ─────────────────────────────────────────────────────────────
1969
1963
  get offer() {
1970
1964
  return this.#offer;
@@ -2029,7 +2023,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2029
2023
  this.#paymentOptions = null;
2030
2024
  this.#returnUrl = "";
2031
2025
  this.#supportedBillingCountries = [];
2032
- this.#recaptchaTokensPromise = null;
2033
2026
  this.querySelector(SEL_CONTAINER)?.remove();
2034
2027
  }
2035
2028
  // ─── Render pipeline ────────────────────────────────────────────────────────
@@ -2132,7 +2125,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2132
2125
  if (button) {
2133
2126
  button.classList.remove("wap-loading");
2134
2127
  this.#updateDisabledState();
2135
- this.#scheduleRecaptchaTokens();
2136
2128
  trackExpressWalletImpression(this.#offer.sku_id, {
2137
2129
  entryPoint: this.#entryPoint,
2138
2130
  country: this.#country
@@ -2169,27 +2161,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2169
2161
  }
2170
2162
  const skuId = this.#offer.sku_id;
2171
2163
  const country = this.#country;
2172
- modal.onConfirm = (recaptchaTokens) => {
2173
- this.#initiateApplePay(skuId, country, recaptchaTokens);
2174
- this.#scheduleRecaptchaTokens();
2164
+ modal.onConfirm = (recaptchaTokensPromise) => {
2165
+ this.#initiateApplePay(skuId, country, recaptchaTokensPromise);
2175
2166
  };
2176
- modal.open(this.#recaptchaTokensPromise);
2177
- }
2178
- /**
2179
- * Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
2180
- * If the fetch rejects, the field is cleared so the next `modal.open()` call
2181
- * falls back to a new attempt via the modal's own null-fallback path — preventing
2182
- * a single transient failure from permanently disabling the CTA on all retries.
2183
- * The identity guard prevents a late rejection from clobbering a newer attempt.
2184
- */
2185
- #scheduleRecaptchaTokens() {
2186
- const attempt = getPurchaseRecaptchaTokens();
2187
- attempt.catch(() => {
2188
- if (this.#recaptchaTokensPromise === attempt) {
2189
- this.#recaptchaTokensPromise = null;
2190
- }
2191
- });
2192
- this.#recaptchaTokensPromise = attempt;
2167
+ modal.open();
2193
2168
  }
2194
2169
  async #fetchSession() {
2195
2170
  try {
@@ -2210,7 +2185,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2210
2185
  return null;
2211
2186
  }
2212
2187
  }
2213
- #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokens) {
2188
+ #buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokensPromise) {
2214
2189
  const offer = this.#offer;
2215
2190
  const totalAmount = offer.price?.purchase ? `${offer.price.purchase}` : DEFAULT_TOTAL;
2216
2191
  return {
@@ -2222,30 +2197,41 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
2222
2197
  skuId,
2223
2198
  returnUrl: this.#returnUrl,
2224
2199
  userLoggedIn: sessionData.loggedIn,
2225
- onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
2226
- skuId,
2227
- country,
2228
- currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
2229
- returnUrl: this.#returnUrl,
2230
- supportedBillingCountries: this.#supportedBillingCountries,
2231
- recaptchaTokens
2232
- })
2200
+ onPaymentAuthorized: async (event, session) => {
2201
+ const recaptchaTokens = await recaptchaTokensPromise;
2202
+ return handlePaymentAuthorized(event, session, sessionData, {
2203
+ skuId,
2204
+ country,
2205
+ currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
2206
+ returnUrl: this.#returnUrl,
2207
+ supportedBillingCountries: this.#supportedBillingCountries,
2208
+ recaptchaTokens
2209
+ });
2210
+ }
2233
2211
  };
2234
2212
  }
2235
- #initiateApplePay(skuId, country, recaptchaTokens) {
2213
+ #initiateApplePay(skuId, country, recaptchaTokensPromise) {
2236
2214
  try {
2237
2215
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
2238
2216
  const paymentOptions = this.#paymentOptions;
2217
+ if (!paymentOptions) {
2218
+ return;
2219
+ }
2239
2220
  startApplePaySession(
2240
2221
  this.#buildSessionParams(
2241
2222
  skuId,
2242
2223
  country,
2243
2224
  sessionData,
2244
2225
  paymentOptions,
2245
- recaptchaTokens
2226
+ recaptchaTokensPromise
2246
2227
  )
2247
2228
  );
2248
2229
  } catch {
2230
+ redirectToFallbackCheckout({
2231
+ returnUrl: this.#returnUrl,
2232
+ skuId,
2233
+ countryCode: country
2234
+ });
2249
2235
  }
2250
2236
  }
2251
2237
  };