@economist/web-apple-pay 0.1.3-beta.46 → 0.1.3-beta.47
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 +18 -72
- package/dist/src/apple-pay-button.js +18 -72
- package/dist/src/apple-pay-button.stories.js +18 -72
- package/dist/src/apple-pay-modal.d.ts +1 -5
- package/dist/src/apple-pay-modal.js +6 -24
- package/dist/src/apple-pay-modal.stories.js +18 -72
- package/dist/src/clients/payment-checkout/apple-session.d.ts +1 -0
- package/dist/src/clients/payment-checkout/apple-session.js +6 -19
- package/dist/src/clients/payment-checkout/payment-handler.d.ts +1 -5
- package/dist/src/clients/payment-checkout/payment-handler.js +1 -21
- package/dist/src/clients/payment-checkout/types.d.ts +1 -5
- package/dist/src/index.js +18 -72
- package/dist/src/utils/recaptcha.d.ts +8 -6
- package/dist/src/utils/recaptcha.js +4 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -576,9 +576,7 @@ var loadRecaptchaScript = (siteKey) => {
|
|
|
576
576
|
if (existingScript) {
|
|
577
577
|
existingScript.addEventListener("load", () => resolve());
|
|
578
578
|
existingScript.addEventListener("error", () => {
|
|
579
|
-
|
|
580
|
-
console.error("[web-apple-pay] reCAPTCHA script load failed (existing script)", error);
|
|
581
|
-
reject(error);
|
|
579
|
+
reject(new Error("Failed to load existing reCAPTCHA script"));
|
|
582
580
|
});
|
|
583
581
|
return;
|
|
584
582
|
}
|
|
@@ -588,9 +586,7 @@ var loadRecaptchaScript = (siteKey) => {
|
|
|
588
586
|
script.defer = true;
|
|
589
587
|
script.onload = () => resolve();
|
|
590
588
|
script.onerror = () => {
|
|
591
|
-
|
|
592
|
-
console.error("[web-apple-pay] reCAPTCHA script load failed (new script)", error);
|
|
593
|
-
reject(error);
|
|
589
|
+
reject(new Error("Failed to load reCAPTCHA script"));
|
|
594
590
|
};
|
|
595
591
|
document.head.appendChild(script);
|
|
596
592
|
});
|
|
@@ -609,20 +605,8 @@ var getRecaptchaToken = async (action) => {
|
|
|
609
605
|
});
|
|
610
606
|
});
|
|
611
607
|
};
|
|
612
|
-
var getPurchaseRecaptchaTokens =
|
|
613
|
-
|
|
614
|
-
try {
|
|
615
|
-
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
616
|
-
getRecaptchaToken("checkEligibility"),
|
|
617
|
-
getRecaptchaToken("newBasket"),
|
|
618
|
-
getRecaptchaToken("registerUser")
|
|
619
|
-
]);
|
|
620
|
-
console.info("[web-apple-pay] All reCAPTCHA tokens acquired successfully");
|
|
621
|
-
return { checkEligibility, newBasket, registerUser };
|
|
622
|
-
} catch (error) {
|
|
623
|
-
console.error("[web-apple-pay] Failed to acquire one or more reCAPTCHA tokens", error);
|
|
624
|
-
throw error;
|
|
625
|
-
}
|
|
608
|
+
var getPurchaseRecaptchaTokens = () => {
|
|
609
|
+
return getRecaptchaToken("walletPurchase");
|
|
626
610
|
};
|
|
627
611
|
|
|
628
612
|
// src/apple-pay-modal.ts
|
|
@@ -962,15 +946,12 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
962
946
|
this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
|
|
963
947
|
cta.disabled = true;
|
|
964
948
|
cta.setAttribute("aria-busy", "true");
|
|
965
|
-
console.info("[web-apple-pay] CTA clicked \u2014 fetching reCAPTCHA tokens");
|
|
966
949
|
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
967
950
|
if (!this.#isClosed && this.onConfirm) {
|
|
968
|
-
console.info("[web-apple-pay] Calling onConfirm synchronously to initiate Apple Pay session");
|
|
969
951
|
this.onConfirm(recaptchaTokensPromise);
|
|
970
952
|
this.close();
|
|
971
953
|
}
|
|
972
|
-
recaptchaTokensPromise.catch((
|
|
973
|
-
console.error("[web-apple-pay] reCAPTCHA token fetch failed", error);
|
|
954
|
+
recaptchaTokensPromise.catch(() => {
|
|
974
955
|
if (this.#isClosed) return;
|
|
975
956
|
cta.disabled = false;
|
|
976
957
|
cta.removeAttribute("aria-busy");
|
|
@@ -996,6 +977,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
996
977
|
);
|
|
997
978
|
}
|
|
998
979
|
open() {
|
|
980
|
+
this.#isClosed = false;
|
|
999
981
|
this.#triggerElement = document.activeElement;
|
|
1000
982
|
document.body.appendChild(this);
|
|
1001
983
|
this.#keyHandler = (event) => {
|
|
@@ -1382,28 +1364,22 @@ async function handleMerchantValidation(event, session, config) {
|
|
|
1382
1364
|
try {
|
|
1383
1365
|
const validationHost = new URL(event.validationURL).host;
|
|
1384
1366
|
if (!validationHost.endsWith("apple.com")) {
|
|
1385
|
-
console.error("[web-apple-pay] Merchant validation URL is not from apple.com \u2014 aborting session", { validationURL: event.validationURL });
|
|
1386
1367
|
session.abort();
|
|
1387
1368
|
redirectToFallbackCheckout(config);
|
|
1388
1369
|
return;
|
|
1389
1370
|
}
|
|
1390
|
-
console.info("[web-apple-pay] Merchant validation started", { validationHost });
|
|
1391
1371
|
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
1392
|
-
console.info("[web-apple-pay] verifyMerchant reCAPTCHA token acquired \u2014 calling validateAppleMerchant");
|
|
1393
1372
|
const response = await validateAppleMerchant({
|
|
1394
1373
|
validationURL: event.validationURL,
|
|
1395
1374
|
recaptchaToken
|
|
1396
1375
|
});
|
|
1397
1376
|
if (!response?.merchantSession) {
|
|
1398
|
-
console.error("[web-apple-pay] Merchant validation response missing merchantSession \u2014 aborting session", { response });
|
|
1399
1377
|
session.abort();
|
|
1400
1378
|
redirectToFallbackCheckout(config);
|
|
1401
1379
|
return;
|
|
1402
1380
|
}
|
|
1403
|
-
console.info("[web-apple-pay] Merchant validation succeeded \u2014 completing merchant validation");
|
|
1404
1381
|
session.completeMerchantValidation(response.merchantSession);
|
|
1405
|
-
} catch
|
|
1406
|
-
console.error("[web-apple-pay] Merchant validation threw an error \u2014 aborting session", error);
|
|
1382
|
+
} catch {
|
|
1407
1383
|
session.abort();
|
|
1408
1384
|
redirectToFallbackCheckout(config);
|
|
1409
1385
|
}
|
|
@@ -1424,14 +1400,12 @@ function startApplePaySession(config) {
|
|
|
1424
1400
|
};
|
|
1425
1401
|
try {
|
|
1426
1402
|
const session = new ApplePaySession(3, paymentRequest);
|
|
1427
|
-
console.info("[web-apple-pay] ApplePaySession created successfully");
|
|
1428
1403
|
session.onvalidatemerchant = async (event) => {
|
|
1429
1404
|
await handleMerchantValidation(event, session, config);
|
|
1430
1405
|
};
|
|
1431
1406
|
session.onpaymentauthorized = (event) => {
|
|
1432
1407
|
trackWalletPaymentAuthorised(config.skuId);
|
|
1433
|
-
config.onPaymentAuthorized(event, session).catch((
|
|
1434
|
-
console.error("[web-apple-pay] onPaymentAuthorized threw an unhandled error \u2014 aborting session", err);
|
|
1408
|
+
config.onPaymentAuthorized(event, session).catch(() => {
|
|
1435
1409
|
session.completePayment({ status: ApplePaySession.STATUS_FAILURE });
|
|
1436
1410
|
redirectToFallbackCheckout(config);
|
|
1437
1411
|
});
|
|
@@ -1441,9 +1415,7 @@ function startApplePaySession(config) {
|
|
|
1441
1415
|
};
|
|
1442
1416
|
trackWalletPaymentSheetOpen(config.skuId);
|
|
1443
1417
|
session.begin();
|
|
1444
|
-
|
|
1445
|
-
} catch (error) {
|
|
1446
|
-
console.error("[web-apple-pay] ApplePaySession creation or begin() threw \u2014 redirecting to fallback checkout", error);
|
|
1418
|
+
} catch {
|
|
1447
1419
|
redirectToFallbackCheckout(config);
|
|
1448
1420
|
}
|
|
1449
1421
|
}
|
|
@@ -1625,24 +1597,12 @@ function handleStructuredError(ctx) {
|
|
|
1625
1597
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1626
1598
|
const { skuId, returnUrl, country } = config;
|
|
1627
1599
|
let validatedEmail;
|
|
1628
|
-
console.info("[web-apple-pay] Payment authorised \u2014 starting purchase flow", {
|
|
1629
|
-
skuId,
|
|
1630
|
-
country,
|
|
1631
|
-
loggedIn: sessionData.loggedIn,
|
|
1632
|
-
userType: sessionData.userType,
|
|
1633
|
-
recaptchaTokensPresent: {
|
|
1634
|
-
checkEligibility: !!config.recaptchaTokens.checkEligibility,
|
|
1635
|
-
newBasket: !!config.recaptchaTokens.newBasket,
|
|
1636
|
-
registerUser: !!config.recaptchaTokens.registerUser
|
|
1637
|
-
}
|
|
1638
|
-
});
|
|
1639
1600
|
try {
|
|
1640
1601
|
validatedEmail = validateContacts(
|
|
1641
1602
|
event,
|
|
1642
1603
|
sessionData,
|
|
1643
1604
|
config.supportedBillingCountries
|
|
1644
1605
|
);
|
|
1645
|
-
console.info("[web-apple-pay] Contact validation passed \u2014 calling purchase API");
|
|
1646
1606
|
const result = await performPurchase({
|
|
1647
1607
|
applePayToken: event.payment.token,
|
|
1648
1608
|
skuId: config.skuId,
|
|
@@ -1651,9 +1611,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1651
1611
|
...event.payment.shippingContact && {
|
|
1652
1612
|
shippingContact: event.payment.shippingContact
|
|
1653
1613
|
},
|
|
1654
|
-
|
|
1614
|
+
recaptchaToken: config.recaptchaToken
|
|
1655
1615
|
});
|
|
1656
|
-
console.info("[web-apple-pay] Purchase API succeeded", { skuId, basketId: result.basketId });
|
|
1657
1616
|
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1658
1617
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1659
1618
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
@@ -1668,17 +1627,10 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1668
1627
|
});
|
|
1669
1628
|
} catch (err) {
|
|
1670
1629
|
if (err instanceof ContactValidationError) {
|
|
1671
|
-
console.warn("[web-apple-pay] Contact validation failed \u2014 keeping Apple Pay sheet open", err);
|
|
1672
1630
|
failApplePaySession(session, err.errors);
|
|
1673
1631
|
return;
|
|
1674
1632
|
}
|
|
1675
1633
|
const walletError = parseWalletApiError(err);
|
|
1676
|
-
console.error("[web-apple-pay] Purchase API failed", {
|
|
1677
|
-
skuId,
|
|
1678
|
-
errorType: walletError?.errorType ?? "UNKNOWN",
|
|
1679
|
-
message: walletError?.message,
|
|
1680
|
-
err
|
|
1681
|
-
});
|
|
1682
1634
|
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1683
1635
|
failApplePaySession(session);
|
|
1684
1636
|
if (!walletError) {
|
|
@@ -2210,10 +2162,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2210
2162
|
const skuId = this.#offer.sku_id;
|
|
2211
2163
|
const country = this.#country;
|
|
2212
2164
|
modal.onConfirm = (recaptchaTokensPromise) => {
|
|
2213
|
-
console.info("[web-apple-pay] onConfirm received from modal \u2014 initiating Apple Pay session", { skuId, country });
|
|
2214
2165
|
this.#initiateApplePay(skuId, country, recaptchaTokensPromise);
|
|
2215
2166
|
};
|
|
2216
|
-
console.info("[web-apple-pay] Opening Apple Pay modal", { skuId, country });
|
|
2217
2167
|
modal.open();
|
|
2218
2168
|
}
|
|
2219
2169
|
async #fetchSession() {
|
|
@@ -2248,14 +2198,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2248
2198
|
returnUrl: this.#returnUrl,
|
|
2249
2199
|
userLoggedIn: sessionData.loggedIn,
|
|
2250
2200
|
onPaymentAuthorized: async (event, session) => {
|
|
2251
|
-
const
|
|
2201
|
+
const recaptchaToken = await recaptchaTokensPromise;
|
|
2252
2202
|
return handlePaymentAuthorized(event, session, sessionData, {
|
|
2253
2203
|
skuId,
|
|
2254
2204
|
country,
|
|
2255
2205
|
currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2256
2206
|
returnUrl: this.#returnUrl,
|
|
2257
2207
|
supportedBillingCountries: this.#supportedBillingCountries,
|
|
2258
|
-
|
|
2208
|
+
recaptchaToken
|
|
2259
2209
|
});
|
|
2260
2210
|
}
|
|
2261
2211
|
};
|
|
@@ -2265,16 +2215,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2265
2215
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
2266
2216
|
const paymentOptions = this.#paymentOptions;
|
|
2267
2217
|
if (!paymentOptions) {
|
|
2268
|
-
console.error("[web-apple-pay] #initiateApplePay called before payment options were fetched");
|
|
2269
2218
|
return;
|
|
2270
2219
|
}
|
|
2271
|
-
console.info("[web-apple-pay] Starting Apple Pay session", {
|
|
2272
|
-
skuId,
|
|
2273
|
-
country,
|
|
2274
|
-
loggedIn: sessionData.loggedIn,
|
|
2275
|
-
userType: sessionData.userType,
|
|
2276
|
-
hasPaymentOptions: true
|
|
2277
|
-
});
|
|
2278
2220
|
startApplePaySession(
|
|
2279
2221
|
this.#buildSessionParams(
|
|
2280
2222
|
skuId,
|
|
@@ -2284,8 +2226,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2284
2226
|
recaptchaTokensPromise
|
|
2285
2227
|
)
|
|
2286
2228
|
);
|
|
2287
|
-
} catch
|
|
2288
|
-
|
|
2229
|
+
} catch {
|
|
2230
|
+
redirectToFallbackCheckout({
|
|
2231
|
+
returnUrl: this.#returnUrl,
|
|
2232
|
+
skuId,
|
|
2233
|
+
countryCode: country
|
|
2234
|
+
});
|
|
2289
2235
|
}
|
|
2290
2236
|
}
|
|
2291
2237
|
};
|
|
@@ -571,9 +571,7 @@ var loadRecaptchaScript = (siteKey) => {
|
|
|
571
571
|
if (existingScript) {
|
|
572
572
|
existingScript.addEventListener("load", () => resolve());
|
|
573
573
|
existingScript.addEventListener("error", () => {
|
|
574
|
-
|
|
575
|
-
console.error("[web-apple-pay] reCAPTCHA script load failed (existing script)", error);
|
|
576
|
-
reject(error);
|
|
574
|
+
reject(new Error("Failed to load existing reCAPTCHA script"));
|
|
577
575
|
});
|
|
578
576
|
return;
|
|
579
577
|
}
|
|
@@ -583,9 +581,7 @@ var loadRecaptchaScript = (siteKey) => {
|
|
|
583
581
|
script.defer = true;
|
|
584
582
|
script.onload = () => resolve();
|
|
585
583
|
script.onerror = () => {
|
|
586
|
-
|
|
587
|
-
console.error("[web-apple-pay] reCAPTCHA script load failed (new script)", error);
|
|
588
|
-
reject(error);
|
|
584
|
+
reject(new Error("Failed to load reCAPTCHA script"));
|
|
589
585
|
};
|
|
590
586
|
document.head.appendChild(script);
|
|
591
587
|
});
|
|
@@ -604,20 +600,8 @@ var getRecaptchaToken = async (action) => {
|
|
|
604
600
|
});
|
|
605
601
|
});
|
|
606
602
|
};
|
|
607
|
-
var getPurchaseRecaptchaTokens =
|
|
608
|
-
|
|
609
|
-
try {
|
|
610
|
-
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
611
|
-
getRecaptchaToken("checkEligibility"),
|
|
612
|
-
getRecaptchaToken("newBasket"),
|
|
613
|
-
getRecaptchaToken("registerUser")
|
|
614
|
-
]);
|
|
615
|
-
console.info("[web-apple-pay] All reCAPTCHA tokens acquired successfully");
|
|
616
|
-
return { checkEligibility, newBasket, registerUser };
|
|
617
|
-
} catch (error) {
|
|
618
|
-
console.error("[web-apple-pay] Failed to acquire one or more reCAPTCHA tokens", error);
|
|
619
|
-
throw error;
|
|
620
|
-
}
|
|
603
|
+
var getPurchaseRecaptchaTokens = () => {
|
|
604
|
+
return getRecaptchaToken("walletPurchase");
|
|
621
605
|
};
|
|
622
606
|
|
|
623
607
|
// src/apple-pay-modal.ts
|
|
@@ -957,15 +941,12 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
957
941
|
this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
|
|
958
942
|
cta.disabled = true;
|
|
959
943
|
cta.setAttribute("aria-busy", "true");
|
|
960
|
-
console.info("[web-apple-pay] CTA clicked \u2014 fetching reCAPTCHA tokens");
|
|
961
944
|
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
962
945
|
if (!this.#isClosed && this.onConfirm) {
|
|
963
|
-
console.info("[web-apple-pay] Calling onConfirm synchronously to initiate Apple Pay session");
|
|
964
946
|
this.onConfirm(recaptchaTokensPromise);
|
|
965
947
|
this.close();
|
|
966
948
|
}
|
|
967
|
-
recaptchaTokensPromise.catch((
|
|
968
|
-
console.error("[web-apple-pay] reCAPTCHA token fetch failed", error);
|
|
949
|
+
recaptchaTokensPromise.catch(() => {
|
|
969
950
|
if (this.#isClosed) return;
|
|
970
951
|
cta.disabled = false;
|
|
971
952
|
cta.removeAttribute("aria-busy");
|
|
@@ -991,6 +972,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
991
972
|
);
|
|
992
973
|
}
|
|
993
974
|
open() {
|
|
975
|
+
this.#isClosed = false;
|
|
994
976
|
this.#triggerElement = document.activeElement;
|
|
995
977
|
document.body.appendChild(this);
|
|
996
978
|
this.#keyHandler = (event) => {
|
|
@@ -1377,28 +1359,22 @@ async function handleMerchantValidation(event, session, config) {
|
|
|
1377
1359
|
try {
|
|
1378
1360
|
const validationHost = new URL(event.validationURL).host;
|
|
1379
1361
|
if (!validationHost.endsWith("apple.com")) {
|
|
1380
|
-
console.error("[web-apple-pay] Merchant validation URL is not from apple.com \u2014 aborting session", { validationURL: event.validationURL });
|
|
1381
1362
|
session.abort();
|
|
1382
1363
|
redirectToFallbackCheckout(config);
|
|
1383
1364
|
return;
|
|
1384
1365
|
}
|
|
1385
|
-
console.info("[web-apple-pay] Merchant validation started", { validationHost });
|
|
1386
1366
|
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
1387
|
-
console.info("[web-apple-pay] verifyMerchant reCAPTCHA token acquired \u2014 calling validateAppleMerchant");
|
|
1388
1367
|
const response = await validateAppleMerchant({
|
|
1389
1368
|
validationURL: event.validationURL,
|
|
1390
1369
|
recaptchaToken
|
|
1391
1370
|
});
|
|
1392
1371
|
if (!response?.merchantSession) {
|
|
1393
|
-
console.error("[web-apple-pay] Merchant validation response missing merchantSession \u2014 aborting session", { response });
|
|
1394
1372
|
session.abort();
|
|
1395
1373
|
redirectToFallbackCheckout(config);
|
|
1396
1374
|
return;
|
|
1397
1375
|
}
|
|
1398
|
-
console.info("[web-apple-pay] Merchant validation succeeded \u2014 completing merchant validation");
|
|
1399
1376
|
session.completeMerchantValidation(response.merchantSession);
|
|
1400
|
-
} catch
|
|
1401
|
-
console.error("[web-apple-pay] Merchant validation threw an error \u2014 aborting session", error);
|
|
1377
|
+
} catch {
|
|
1402
1378
|
session.abort();
|
|
1403
1379
|
redirectToFallbackCheckout(config);
|
|
1404
1380
|
}
|
|
@@ -1419,14 +1395,12 @@ function startApplePaySession(config) {
|
|
|
1419
1395
|
};
|
|
1420
1396
|
try {
|
|
1421
1397
|
const session = new ApplePaySession(3, paymentRequest);
|
|
1422
|
-
console.info("[web-apple-pay] ApplePaySession created successfully");
|
|
1423
1398
|
session.onvalidatemerchant = async (event) => {
|
|
1424
1399
|
await handleMerchantValidation(event, session, config);
|
|
1425
1400
|
};
|
|
1426
1401
|
session.onpaymentauthorized = (event) => {
|
|
1427
1402
|
trackWalletPaymentAuthorised(config.skuId);
|
|
1428
|
-
config.onPaymentAuthorized(event, session).catch((
|
|
1429
|
-
console.error("[web-apple-pay] onPaymentAuthorized threw an unhandled error \u2014 aborting session", err);
|
|
1403
|
+
config.onPaymentAuthorized(event, session).catch(() => {
|
|
1430
1404
|
session.completePayment({ status: ApplePaySession.STATUS_FAILURE });
|
|
1431
1405
|
redirectToFallbackCheckout(config);
|
|
1432
1406
|
});
|
|
@@ -1436,9 +1410,7 @@ function startApplePaySession(config) {
|
|
|
1436
1410
|
};
|
|
1437
1411
|
trackWalletPaymentSheetOpen(config.skuId);
|
|
1438
1412
|
session.begin();
|
|
1439
|
-
|
|
1440
|
-
} catch (error) {
|
|
1441
|
-
console.error("[web-apple-pay] ApplePaySession creation or begin() threw \u2014 redirecting to fallback checkout", error);
|
|
1413
|
+
} catch {
|
|
1442
1414
|
redirectToFallbackCheckout(config);
|
|
1443
1415
|
}
|
|
1444
1416
|
}
|
|
@@ -1620,24 +1592,12 @@ function handleStructuredError(ctx) {
|
|
|
1620
1592
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1621
1593
|
const { skuId, returnUrl, country } = config;
|
|
1622
1594
|
let validatedEmail;
|
|
1623
|
-
console.info("[web-apple-pay] Payment authorised \u2014 starting purchase flow", {
|
|
1624
|
-
skuId,
|
|
1625
|
-
country,
|
|
1626
|
-
loggedIn: sessionData.loggedIn,
|
|
1627
|
-
userType: sessionData.userType,
|
|
1628
|
-
recaptchaTokensPresent: {
|
|
1629
|
-
checkEligibility: !!config.recaptchaTokens.checkEligibility,
|
|
1630
|
-
newBasket: !!config.recaptchaTokens.newBasket,
|
|
1631
|
-
registerUser: !!config.recaptchaTokens.registerUser
|
|
1632
|
-
}
|
|
1633
|
-
});
|
|
1634
1595
|
try {
|
|
1635
1596
|
validatedEmail = validateContacts(
|
|
1636
1597
|
event,
|
|
1637
1598
|
sessionData,
|
|
1638
1599
|
config.supportedBillingCountries
|
|
1639
1600
|
);
|
|
1640
|
-
console.info("[web-apple-pay] Contact validation passed \u2014 calling purchase API");
|
|
1641
1601
|
const result = await performPurchase({
|
|
1642
1602
|
applePayToken: event.payment.token,
|
|
1643
1603
|
skuId: config.skuId,
|
|
@@ -1646,9 +1606,8 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1646
1606
|
...event.payment.shippingContact && {
|
|
1647
1607
|
shippingContact: event.payment.shippingContact
|
|
1648
1608
|
},
|
|
1649
|
-
|
|
1609
|
+
recaptchaToken: config.recaptchaToken
|
|
1650
1610
|
});
|
|
1651
|
-
console.info("[web-apple-pay] Purchase API succeeded", { skuId, basketId: result.basketId });
|
|
1652
1611
|
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1653
1612
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1654
1613
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
@@ -1663,17 +1622,10 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1663
1622
|
});
|
|
1664
1623
|
} catch (err) {
|
|
1665
1624
|
if (err instanceof ContactValidationError) {
|
|
1666
|
-
console.warn("[web-apple-pay] Contact validation failed \u2014 keeping Apple Pay sheet open", err);
|
|
1667
1625
|
failApplePaySession(session, err.errors);
|
|
1668
1626
|
return;
|
|
1669
1627
|
}
|
|
1670
1628
|
const walletError = parseWalletApiError(err);
|
|
1671
|
-
console.error("[web-apple-pay] Purchase API failed", {
|
|
1672
|
-
skuId,
|
|
1673
|
-
errorType: walletError?.errorType ?? "UNKNOWN",
|
|
1674
|
-
message: walletError?.message,
|
|
1675
|
-
err
|
|
1676
|
-
});
|
|
1677
1629
|
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1678
1630
|
failApplePaySession(session);
|
|
1679
1631
|
if (!walletError) {
|
|
@@ -2205,10 +2157,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2205
2157
|
const skuId = this.#offer.sku_id;
|
|
2206
2158
|
const country = this.#country;
|
|
2207
2159
|
modal.onConfirm = (recaptchaTokensPromise) => {
|
|
2208
|
-
console.info("[web-apple-pay] onConfirm received from modal \u2014 initiating Apple Pay session", { skuId, country });
|
|
2209
2160
|
this.#initiateApplePay(skuId, country, recaptchaTokensPromise);
|
|
2210
2161
|
};
|
|
2211
|
-
console.info("[web-apple-pay] Opening Apple Pay modal", { skuId, country });
|
|
2212
2162
|
modal.open();
|
|
2213
2163
|
}
|
|
2214
2164
|
async #fetchSession() {
|
|
@@ -2243,14 +2193,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2243
2193
|
returnUrl: this.#returnUrl,
|
|
2244
2194
|
userLoggedIn: sessionData.loggedIn,
|
|
2245
2195
|
onPaymentAuthorized: async (event, session) => {
|
|
2246
|
-
const
|
|
2196
|
+
const recaptchaToken = await recaptchaTokensPromise;
|
|
2247
2197
|
return handlePaymentAuthorized(event, session, sessionData, {
|
|
2248
2198
|
skuId,
|
|
2249
2199
|
country,
|
|
2250
2200
|
currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2251
2201
|
returnUrl: this.#returnUrl,
|
|
2252
2202
|
supportedBillingCountries: this.#supportedBillingCountries,
|
|
2253
|
-
|
|
2203
|
+
recaptchaToken
|
|
2254
2204
|
});
|
|
2255
2205
|
}
|
|
2256
2206
|
};
|
|
@@ -2260,16 +2210,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2260
2210
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
2261
2211
|
const paymentOptions = this.#paymentOptions;
|
|
2262
2212
|
if (!paymentOptions) {
|
|
2263
|
-
console.error("[web-apple-pay] #initiateApplePay called before payment options were fetched");
|
|
2264
2213
|
return;
|
|
2265
2214
|
}
|
|
2266
|
-
console.info("[web-apple-pay] Starting Apple Pay session", {
|
|
2267
|
-
skuId,
|
|
2268
|
-
country,
|
|
2269
|
-
loggedIn: sessionData.loggedIn,
|
|
2270
|
-
userType: sessionData.userType,
|
|
2271
|
-
hasPaymentOptions: true
|
|
2272
|
-
});
|
|
2273
2215
|
startApplePaySession(
|
|
2274
2216
|
this.#buildSessionParams(
|
|
2275
2217
|
skuId,
|
|
@@ -2279,8 +2221,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2279
2221
|
recaptchaTokensPromise
|
|
2280
2222
|
)
|
|
2281
2223
|
);
|
|
2282
|
-
} catch
|
|
2283
|
-
|
|
2224
|
+
} catch {
|
|
2225
|
+
redirectToFallbackCheckout({
|
|
2226
|
+
returnUrl: this.#returnUrl,
|
|
2227
|
+
skuId,
|
|
2228
|
+
countryCode: country
|
|
2229
|
+
});
|
|
2284
2230
|
}
|
|
2285
2231
|
}
|
|
2286
2232
|
};
|