@economist/web-apple-pay 0.1.3-beta.39 → 0.1.3-beta.40
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 +25 -38
- package/dist/src/apple-pay-button.d.ts +1 -1
- package/dist/src/apple-pay-button.js +25 -38
- package/dist/src/apple-pay-button.stories.js +25 -38
- package/dist/src/apple-pay-modal.stories.js +25 -38
- package/dist/src/clients/payment-checkout/detects.js +1 -1
- package/dist/src/clients/payment-checkout/payment-handler.js +6 -12
- package/dist/src/index.js +25 -38
- package/dist/src/utils/expressCheckoutTracking.d.ts +4 -4
- package/dist/src/utils/expressCheckoutTracking.js +8 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1120,7 +1120,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1120
1120
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1121
1121
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1122
1122
|
};
|
|
1123
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
1123
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1124
1124
|
var isApplePayAvailable = async () => {
|
|
1125
1125
|
if (bypassApplePayChecks()) {
|
|
1126
1126
|
return true;
|
|
@@ -1318,21 +1318,17 @@ var track = (action, extra) => {
|
|
|
1318
1318
|
...extra
|
|
1319
1319
|
});
|
|
1320
1320
|
};
|
|
1321
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }
|
|
1321
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1322
1322
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1323
1323
|
wallet_type: "apple_pay",
|
|
1324
1324
|
entry_point: entryPoint,
|
|
1325
1325
|
sku_id: skuId,
|
|
1326
1326
|
country,
|
|
1327
|
-
device: getDevice()
|
|
1328
|
-
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1327
|
+
device: getDevice()
|
|
1329
1328
|
});
|
|
1330
1329
|
};
|
|
1331
|
-
var trackExpressWalletClick = (skuId
|
|
1332
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1333
|
-
sku_id: skuId,
|
|
1334
|
-
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1335
|
-
});
|
|
1330
|
+
var trackExpressWalletClick = (skuId) => {
|
|
1331
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
|
|
1336
1332
|
};
|
|
1337
1333
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1338
1334
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1340,18 +1336,16 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1340
1336
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1341
1337
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1342
1338
|
};
|
|
1343
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
1339
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1344
1340
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1345
1341
|
sku_id: skuId,
|
|
1346
|
-
basket_id: basketId
|
|
1347
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1342
|
+
basket_id: basketId
|
|
1348
1343
|
});
|
|
1349
1344
|
};
|
|
1350
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
1345
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1351
1346
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1352
1347
|
sku_id: skuId,
|
|
1353
|
-
failure_reason: reason
|
|
1354
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1348
|
+
failure_reason: reason
|
|
1355
1349
|
});
|
|
1356
1350
|
};
|
|
1357
1351
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1613,14 +1607,12 @@ function handleStructuredError(ctx) {
|
|
|
1613
1607
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1614
1608
|
const { skuId, returnUrl, country } = config;
|
|
1615
1609
|
let validatedEmail;
|
|
1616
|
-
let purchaseStartTime;
|
|
1617
1610
|
try {
|
|
1618
1611
|
validatedEmail = validateContacts(
|
|
1619
1612
|
event,
|
|
1620
1613
|
sessionData,
|
|
1621
1614
|
config.supportedBillingCountries
|
|
1622
1615
|
);
|
|
1623
|
-
purchaseStartTime = Date.now();
|
|
1624
1616
|
const result = await performPurchase({
|
|
1625
1617
|
applePayToken: event.payment.token,
|
|
1626
1618
|
skuId: config.skuId,
|
|
@@ -1631,8 +1623,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1631
1623
|
},
|
|
1632
1624
|
recaptchaTokens: config.recaptchaTokens
|
|
1633
1625
|
});
|
|
1634
|
-
|
|
1635
|
-
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1626
|
+
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1636
1627
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1637
1628
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1638
1629
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1650,8 +1641,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1650
1641
|
return;
|
|
1651
1642
|
}
|
|
1652
1643
|
const walletError = parseWalletApiError(err);
|
|
1653
|
-
|
|
1654
|
-
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1644
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1655
1645
|
failApplePaySession(session);
|
|
1656
1646
|
if (!walletError) {
|
|
1657
1647
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1923,7 +1913,6 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1923
1913
|
};
|
|
1924
1914
|
|
|
1925
1915
|
// src/apple-pay-button.ts
|
|
1926
|
-
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1927
1916
|
var TOTAL_LABEL = "The Economist";
|
|
1928
1917
|
var DEFAULT_CURRENCY = "USD";
|
|
1929
1918
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1939,7 +1928,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1939
1928
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1940
1929
|
}
|
|
1941
1930
|
/**
|
|
1942
|
-
* Creates and configures an ApplePayButton if the
|
|
1931
|
+
* Creates and configures an ApplePayButton if the offer is eligible.
|
|
1943
1932
|
*/
|
|
1944
1933
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1945
1934
|
if (!offer) {
|
|
@@ -1948,9 +1937,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1948
1937
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1949
1938
|
return null;
|
|
1950
1939
|
}
|
|
1951
|
-
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1952
|
-
return null;
|
|
1953
|
-
}
|
|
1954
1940
|
_ApplePayButton.define();
|
|
1955
1941
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1956
1942
|
button.offer = offer;
|
|
@@ -1974,7 +1960,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1974
1960
|
#country = "";
|
|
1975
1961
|
#rendering = false;
|
|
1976
1962
|
#readyPromise = null;
|
|
1977
|
-
#loadStartTime = 0;
|
|
1978
1963
|
#sessionData = null;
|
|
1979
1964
|
#paymentOptions = null;
|
|
1980
1965
|
#returnUrl = "";
|
|
@@ -2050,7 +2035,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2050
2035
|
}
|
|
2051
2036
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2052
2037
|
async #run() {
|
|
2053
|
-
this.#loadStartTime = Date.now();
|
|
2054
2038
|
try {
|
|
2055
2039
|
this.#renderTemplate();
|
|
2056
2040
|
if (await this.#checkAvailability()) return;
|
|
@@ -2059,8 +2043,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2059
2043
|
this.#captureReturnUrl();
|
|
2060
2044
|
this.#computeBillingCountries();
|
|
2061
2045
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2046
|
+
console.log("[web-apple-pay] button shown \u2014 reason: all checks passed, Apple Pay is available and offer is eligible");
|
|
2062
2047
|
this.#finishLoading();
|
|
2063
|
-
} catch {
|
|
2048
|
+
} catch (error) {
|
|
2049
|
+
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2064
2050
|
this.style.display = "none";
|
|
2065
2051
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2066
2052
|
} finally {
|
|
@@ -2071,6 +2057,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2071
2057
|
async #checkAvailability() {
|
|
2072
2058
|
const available = await isApplePayAvailable();
|
|
2073
2059
|
if (!available) {
|
|
2060
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2074
2061
|
this.style.display = "none";
|
|
2075
2062
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2076
2063
|
return true;
|
|
@@ -2084,6 +2071,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2084
2071
|
async #checkSession() {
|
|
2085
2072
|
this.#sessionData = await this.#fetchSession();
|
|
2086
2073
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2074
|
+
console.log(`[web-apple-pay] button removed from DOM \u2014 reason: session check failed, userType="${this.#sessionData.userType}"`);
|
|
2087
2075
|
this.style.display = "none";
|
|
2088
2076
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2089
2077
|
return true;
|
|
@@ -2093,6 +2081,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2093
2081
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2094
2082
|
#checkOffer() {
|
|
2095
2083
|
if (!this.#offer) {
|
|
2084
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2096
2085
|
this.style.display = "none";
|
|
2097
2086
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2098
2087
|
return true;
|
|
@@ -2121,6 +2110,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2121
2110
|
async #fetchAndCacheOptions() {
|
|
2122
2111
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2123
2112
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2113
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: payment options BFF reports Apple Pay unavailable for this offer");
|
|
2124
2114
|
this.style.display = "none";
|
|
2125
2115
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2126
2116
|
return true;
|
|
@@ -2129,6 +2119,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2129
2119
|
}
|
|
2130
2120
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2131
2121
|
#renderTemplate() {
|
|
2122
|
+
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2132
2123
|
this.style.removeProperty("display");
|
|
2133
2124
|
ensureApplePayLogoSymbol();
|
|
2134
2125
|
const template = document.createElement("template");
|
|
@@ -2150,12 +2141,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2150
2141
|
button.classList.remove("wap-loading");
|
|
2151
2142
|
this.#updateDisabledState();
|
|
2152
2143
|
this.#scheduleRecaptchaTokens();
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
this.#
|
|
2156
|
-
|
|
2157
|
-
buttonLoadDurationMs
|
|
2158
|
-
);
|
|
2144
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2145
|
+
entryPoint: this.#entryPoint,
|
|
2146
|
+
country: this.#country
|
|
2147
|
+
});
|
|
2159
2148
|
}
|
|
2160
2149
|
}
|
|
2161
2150
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2178,7 +2167,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2178
2167
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2179
2168
|
return;
|
|
2180
2169
|
}
|
|
2181
|
-
|
|
2170
|
+
trackExpressWalletClick(this.#offer.sku_id);
|
|
2182
2171
|
ApplePayModal.define();
|
|
2183
2172
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2184
2173
|
modal.offer = this.#offer;
|
|
@@ -2193,8 +2182,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2193
2182
|
this.#scheduleRecaptchaTokens();
|
|
2194
2183
|
};
|
|
2195
2184
|
modal.open(this.#recaptchaTokensPromise);
|
|
2196
|
-
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2197
|
-
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2198
2185
|
}
|
|
2199
2186
|
/**
|
|
2200
2187
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -6,7 +6,7 @@ export declare class ApplePayButton extends HTMLElement {
|
|
|
6
6
|
static readonly tag = "teg-apple-pay-button";
|
|
7
7
|
static define(): void;
|
|
8
8
|
/**
|
|
9
|
-
* Creates and configures an ApplePayButton if the
|
|
9
|
+
* Creates and configures an ApplePayButton if the offer is eligible.
|
|
10
10
|
*/
|
|
11
11
|
static createIfEnabled(offer: Offer | undefined, country: string, entryPoint?: ApplePayEntryPoint): ApplePayButton | null;
|
|
12
12
|
get offer(): Offer | null;
|
|
@@ -1115,7 +1115,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1115
1115
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1116
1116
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1117
1117
|
};
|
|
1118
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
1118
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1119
1119
|
var isApplePayAvailable = async () => {
|
|
1120
1120
|
if (bypassApplePayChecks()) {
|
|
1121
1121
|
return true;
|
|
@@ -1313,21 +1313,17 @@ var track = (action, extra) => {
|
|
|
1313
1313
|
...extra
|
|
1314
1314
|
});
|
|
1315
1315
|
};
|
|
1316
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }
|
|
1316
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1317
1317
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1318
1318
|
wallet_type: "apple_pay",
|
|
1319
1319
|
entry_point: entryPoint,
|
|
1320
1320
|
sku_id: skuId,
|
|
1321
1321
|
country,
|
|
1322
|
-
device: getDevice()
|
|
1323
|
-
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1322
|
+
device: getDevice()
|
|
1324
1323
|
});
|
|
1325
1324
|
};
|
|
1326
|
-
var trackExpressWalletClick = (skuId
|
|
1327
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1328
|
-
sku_id: skuId,
|
|
1329
|
-
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1330
|
-
});
|
|
1325
|
+
var trackExpressWalletClick = (skuId) => {
|
|
1326
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
|
|
1331
1327
|
};
|
|
1332
1328
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1333
1329
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1335,18 +1331,16 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1335
1331
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1336
1332
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1337
1333
|
};
|
|
1338
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
1334
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1339
1335
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1340
1336
|
sku_id: skuId,
|
|
1341
|
-
basket_id: basketId
|
|
1342
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1337
|
+
basket_id: basketId
|
|
1343
1338
|
});
|
|
1344
1339
|
};
|
|
1345
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
1340
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1346
1341
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1347
1342
|
sku_id: skuId,
|
|
1348
|
-
failure_reason: reason
|
|
1349
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1343
|
+
failure_reason: reason
|
|
1350
1344
|
});
|
|
1351
1345
|
};
|
|
1352
1346
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1608,14 +1602,12 @@ function handleStructuredError(ctx) {
|
|
|
1608
1602
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1609
1603
|
const { skuId, returnUrl, country } = config;
|
|
1610
1604
|
let validatedEmail;
|
|
1611
|
-
let purchaseStartTime;
|
|
1612
1605
|
try {
|
|
1613
1606
|
validatedEmail = validateContacts(
|
|
1614
1607
|
event,
|
|
1615
1608
|
sessionData,
|
|
1616
1609
|
config.supportedBillingCountries
|
|
1617
1610
|
);
|
|
1618
|
-
purchaseStartTime = Date.now();
|
|
1619
1611
|
const result = await performPurchase({
|
|
1620
1612
|
applePayToken: event.payment.token,
|
|
1621
1613
|
skuId: config.skuId,
|
|
@@ -1626,8 +1618,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1626
1618
|
},
|
|
1627
1619
|
recaptchaTokens: config.recaptchaTokens
|
|
1628
1620
|
});
|
|
1629
|
-
|
|
1630
|
-
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1621
|
+
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1631
1622
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1632
1623
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1633
1624
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1645,8 +1636,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1645
1636
|
return;
|
|
1646
1637
|
}
|
|
1647
1638
|
const walletError = parseWalletApiError(err);
|
|
1648
|
-
|
|
1649
|
-
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1639
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1650
1640
|
failApplePaySession(session);
|
|
1651
1641
|
if (!walletError) {
|
|
1652
1642
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1918,7 +1908,6 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1918
1908
|
};
|
|
1919
1909
|
|
|
1920
1910
|
// src/apple-pay-button.ts
|
|
1921
|
-
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1922
1911
|
var TOTAL_LABEL = "The Economist";
|
|
1923
1912
|
var DEFAULT_CURRENCY = "USD";
|
|
1924
1913
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1934,7 +1923,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1934
1923
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1935
1924
|
}
|
|
1936
1925
|
/**
|
|
1937
|
-
* Creates and configures an ApplePayButton if the
|
|
1926
|
+
* Creates and configures an ApplePayButton if the offer is eligible.
|
|
1938
1927
|
*/
|
|
1939
1928
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1940
1929
|
if (!offer) {
|
|
@@ -1943,9 +1932,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1943
1932
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1944
1933
|
return null;
|
|
1945
1934
|
}
|
|
1946
|
-
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1947
|
-
return null;
|
|
1948
|
-
}
|
|
1949
1935
|
_ApplePayButton.define();
|
|
1950
1936
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1951
1937
|
button.offer = offer;
|
|
@@ -1969,7 +1955,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1969
1955
|
#country = "";
|
|
1970
1956
|
#rendering = false;
|
|
1971
1957
|
#readyPromise = null;
|
|
1972
|
-
#loadStartTime = 0;
|
|
1973
1958
|
#sessionData = null;
|
|
1974
1959
|
#paymentOptions = null;
|
|
1975
1960
|
#returnUrl = "";
|
|
@@ -2045,7 +2030,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2045
2030
|
}
|
|
2046
2031
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2047
2032
|
async #run() {
|
|
2048
|
-
this.#loadStartTime = Date.now();
|
|
2049
2033
|
try {
|
|
2050
2034
|
this.#renderTemplate();
|
|
2051
2035
|
if (await this.#checkAvailability()) return;
|
|
@@ -2054,8 +2038,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2054
2038
|
this.#captureReturnUrl();
|
|
2055
2039
|
this.#computeBillingCountries();
|
|
2056
2040
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2041
|
+
console.log("[web-apple-pay] button shown \u2014 reason: all checks passed, Apple Pay is available and offer is eligible");
|
|
2057
2042
|
this.#finishLoading();
|
|
2058
|
-
} catch {
|
|
2043
|
+
} catch (error) {
|
|
2044
|
+
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2059
2045
|
this.style.display = "none";
|
|
2060
2046
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2061
2047
|
} finally {
|
|
@@ -2066,6 +2052,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2066
2052
|
async #checkAvailability() {
|
|
2067
2053
|
const available = await isApplePayAvailable();
|
|
2068
2054
|
if (!available) {
|
|
2055
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2069
2056
|
this.style.display = "none";
|
|
2070
2057
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2071
2058
|
return true;
|
|
@@ -2079,6 +2066,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2079
2066
|
async #checkSession() {
|
|
2080
2067
|
this.#sessionData = await this.#fetchSession();
|
|
2081
2068
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2069
|
+
console.log(`[web-apple-pay] button removed from DOM \u2014 reason: session check failed, userType="${this.#sessionData.userType}"`);
|
|
2082
2070
|
this.style.display = "none";
|
|
2083
2071
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2084
2072
|
return true;
|
|
@@ -2088,6 +2076,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2088
2076
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2089
2077
|
#checkOffer() {
|
|
2090
2078
|
if (!this.#offer) {
|
|
2079
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2091
2080
|
this.style.display = "none";
|
|
2092
2081
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2093
2082
|
return true;
|
|
@@ -2116,6 +2105,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2116
2105
|
async #fetchAndCacheOptions() {
|
|
2117
2106
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2118
2107
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2108
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: payment options BFF reports Apple Pay unavailable for this offer");
|
|
2119
2109
|
this.style.display = "none";
|
|
2120
2110
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2121
2111
|
return true;
|
|
@@ -2124,6 +2114,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2124
2114
|
}
|
|
2125
2115
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2126
2116
|
#renderTemplate() {
|
|
2117
|
+
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2127
2118
|
this.style.removeProperty("display");
|
|
2128
2119
|
ensureApplePayLogoSymbol();
|
|
2129
2120
|
const template = document.createElement("template");
|
|
@@ -2145,12 +2136,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2145
2136
|
button.classList.remove("wap-loading");
|
|
2146
2137
|
this.#updateDisabledState();
|
|
2147
2138
|
this.#scheduleRecaptchaTokens();
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
this.#
|
|
2151
|
-
|
|
2152
|
-
buttonLoadDurationMs
|
|
2153
|
-
);
|
|
2139
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2140
|
+
entryPoint: this.#entryPoint,
|
|
2141
|
+
country: this.#country
|
|
2142
|
+
});
|
|
2154
2143
|
}
|
|
2155
2144
|
}
|
|
2156
2145
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2173,7 +2162,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2173
2162
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2174
2163
|
return;
|
|
2175
2164
|
}
|
|
2176
|
-
|
|
2165
|
+
trackExpressWalletClick(this.#offer.sku_id);
|
|
2177
2166
|
ApplePayModal.define();
|
|
2178
2167
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2179
2168
|
modal.offer = this.#offer;
|
|
@@ -2188,8 +2177,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2188
2177
|
this.#scheduleRecaptchaTokens();
|
|
2189
2178
|
};
|
|
2190
2179
|
modal.open(this.#recaptchaTokensPromise);
|
|
2191
|
-
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2192
|
-
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2193
2180
|
}
|
|
2194
2181
|
/**
|
|
2195
2182
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -1123,7 +1123,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1123
1123
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1124
1124
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1125
1125
|
};
|
|
1126
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
1126
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1127
1127
|
var isApplePayAvailable = async () => {
|
|
1128
1128
|
if (bypassApplePayChecks()) {
|
|
1129
1129
|
return true;
|
|
@@ -1321,21 +1321,17 @@ var track = (action, extra) => {
|
|
|
1321
1321
|
...extra
|
|
1322
1322
|
});
|
|
1323
1323
|
};
|
|
1324
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }
|
|
1324
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1325
1325
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1326
1326
|
wallet_type: "apple_pay",
|
|
1327
1327
|
entry_point: entryPoint,
|
|
1328
1328
|
sku_id: skuId,
|
|
1329
1329
|
country,
|
|
1330
|
-
device: getDevice()
|
|
1331
|
-
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1330
|
+
device: getDevice()
|
|
1332
1331
|
});
|
|
1333
1332
|
};
|
|
1334
|
-
var trackExpressWalletClick = (skuId
|
|
1335
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1336
|
-
sku_id: skuId,
|
|
1337
|
-
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1338
|
-
});
|
|
1333
|
+
var trackExpressWalletClick = (skuId) => {
|
|
1334
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
|
|
1339
1335
|
};
|
|
1340
1336
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1341
1337
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1343,18 +1339,16 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1343
1339
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1344
1340
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1345
1341
|
};
|
|
1346
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
1342
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1347
1343
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1348
1344
|
sku_id: skuId,
|
|
1349
|
-
basket_id: basketId
|
|
1350
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1345
|
+
basket_id: basketId
|
|
1351
1346
|
});
|
|
1352
1347
|
};
|
|
1353
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
1348
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1354
1349
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1355
1350
|
sku_id: skuId,
|
|
1356
|
-
failure_reason: reason
|
|
1357
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1351
|
+
failure_reason: reason
|
|
1358
1352
|
});
|
|
1359
1353
|
};
|
|
1360
1354
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1616,14 +1610,12 @@ function handleStructuredError(ctx) {
|
|
|
1616
1610
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1617
1611
|
const { skuId, returnUrl, country } = config;
|
|
1618
1612
|
let validatedEmail;
|
|
1619
|
-
let purchaseStartTime;
|
|
1620
1613
|
try {
|
|
1621
1614
|
validatedEmail = validateContacts(
|
|
1622
1615
|
event,
|
|
1623
1616
|
sessionData,
|
|
1624
1617
|
config.supportedBillingCountries
|
|
1625
1618
|
);
|
|
1626
|
-
purchaseStartTime = Date.now();
|
|
1627
1619
|
const result = await performPurchase({
|
|
1628
1620
|
applePayToken: event.payment.token,
|
|
1629
1621
|
skuId: config.skuId,
|
|
@@ -1634,8 +1626,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1634
1626
|
},
|
|
1635
1627
|
recaptchaTokens: config.recaptchaTokens
|
|
1636
1628
|
});
|
|
1637
|
-
|
|
1638
|
-
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1629
|
+
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1639
1630
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1640
1631
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1641
1632
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1653,8 +1644,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1653
1644
|
return;
|
|
1654
1645
|
}
|
|
1655
1646
|
const walletError = parseWalletApiError(err);
|
|
1656
|
-
|
|
1657
|
-
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1647
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1658
1648
|
failApplePaySession(session);
|
|
1659
1649
|
if (!walletError) {
|
|
1660
1650
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1926,7 +1916,6 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1926
1916
|
};
|
|
1927
1917
|
|
|
1928
1918
|
// src/apple-pay-button.ts
|
|
1929
|
-
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1930
1919
|
var TOTAL_LABEL = "The Economist";
|
|
1931
1920
|
var DEFAULT_CURRENCY = "USD";
|
|
1932
1921
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1942,7 +1931,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1942
1931
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1943
1932
|
}
|
|
1944
1933
|
/**
|
|
1945
|
-
* Creates and configures an ApplePayButton if the
|
|
1934
|
+
* Creates and configures an ApplePayButton if the offer is eligible.
|
|
1946
1935
|
*/
|
|
1947
1936
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1948
1937
|
if (!offer) {
|
|
@@ -1951,9 +1940,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1951
1940
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1952
1941
|
return null;
|
|
1953
1942
|
}
|
|
1954
|
-
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1955
|
-
return null;
|
|
1956
|
-
}
|
|
1957
1943
|
_ApplePayButton.define();
|
|
1958
1944
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1959
1945
|
button.offer = offer;
|
|
@@ -1977,7 +1963,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1977
1963
|
#country = "";
|
|
1978
1964
|
#rendering = false;
|
|
1979
1965
|
#readyPromise = null;
|
|
1980
|
-
#loadStartTime = 0;
|
|
1981
1966
|
#sessionData = null;
|
|
1982
1967
|
#paymentOptions = null;
|
|
1983
1968
|
#returnUrl = "";
|
|
@@ -2053,7 +2038,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2053
2038
|
}
|
|
2054
2039
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2055
2040
|
async #run() {
|
|
2056
|
-
this.#loadStartTime = Date.now();
|
|
2057
2041
|
try {
|
|
2058
2042
|
this.#renderTemplate();
|
|
2059
2043
|
if (await this.#checkAvailability()) return;
|
|
@@ -2062,8 +2046,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2062
2046
|
this.#captureReturnUrl();
|
|
2063
2047
|
this.#computeBillingCountries();
|
|
2064
2048
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2049
|
+
console.log("[web-apple-pay] button shown \u2014 reason: all checks passed, Apple Pay is available and offer is eligible");
|
|
2065
2050
|
this.#finishLoading();
|
|
2066
|
-
} catch {
|
|
2051
|
+
} catch (error) {
|
|
2052
|
+
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2067
2053
|
this.style.display = "none";
|
|
2068
2054
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2069
2055
|
} finally {
|
|
@@ -2074,6 +2060,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2074
2060
|
async #checkAvailability() {
|
|
2075
2061
|
const available = await isApplePayAvailable();
|
|
2076
2062
|
if (!available) {
|
|
2063
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2077
2064
|
this.style.display = "none";
|
|
2078
2065
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2079
2066
|
return true;
|
|
@@ -2087,6 +2074,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2087
2074
|
async #checkSession() {
|
|
2088
2075
|
this.#sessionData = await this.#fetchSession();
|
|
2089
2076
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2077
|
+
console.log(`[web-apple-pay] button removed from DOM \u2014 reason: session check failed, userType="${this.#sessionData.userType}"`);
|
|
2090
2078
|
this.style.display = "none";
|
|
2091
2079
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2092
2080
|
return true;
|
|
@@ -2096,6 +2084,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2096
2084
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2097
2085
|
#checkOffer() {
|
|
2098
2086
|
if (!this.#offer) {
|
|
2087
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2099
2088
|
this.style.display = "none";
|
|
2100
2089
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2101
2090
|
return true;
|
|
@@ -2124,6 +2113,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2124
2113
|
async #fetchAndCacheOptions() {
|
|
2125
2114
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2126
2115
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2116
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: payment options BFF reports Apple Pay unavailable for this offer");
|
|
2127
2117
|
this.style.display = "none";
|
|
2128
2118
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2129
2119
|
return true;
|
|
@@ -2132,6 +2122,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2132
2122
|
}
|
|
2133
2123
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2134
2124
|
#renderTemplate() {
|
|
2125
|
+
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2135
2126
|
this.style.removeProperty("display");
|
|
2136
2127
|
ensureApplePayLogoSymbol();
|
|
2137
2128
|
const template = document.createElement("template");
|
|
@@ -2153,12 +2144,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2153
2144
|
button.classList.remove("wap-loading");
|
|
2154
2145
|
this.#updateDisabledState();
|
|
2155
2146
|
this.#scheduleRecaptchaTokens();
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
this.#
|
|
2159
|
-
|
|
2160
|
-
buttonLoadDurationMs
|
|
2161
|
-
);
|
|
2147
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2148
|
+
entryPoint: this.#entryPoint,
|
|
2149
|
+
country: this.#country
|
|
2150
|
+
});
|
|
2162
2151
|
}
|
|
2163
2152
|
}
|
|
2164
2153
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2181,7 +2170,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2181
2170
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2182
2171
|
return;
|
|
2183
2172
|
}
|
|
2184
|
-
|
|
2173
|
+
trackExpressWalletClick(this.#offer.sku_id);
|
|
2185
2174
|
ApplePayModal.define();
|
|
2186
2175
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2187
2176
|
modal.offer = this.#offer;
|
|
@@ -2196,8 +2185,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2196
2185
|
this.#scheduleRecaptchaTokens();
|
|
2197
2186
|
};
|
|
2198
2187
|
modal.open(this.#recaptchaTokensPromise);
|
|
2199
|
-
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2200
|
-
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2201
2188
|
}
|
|
2202
2189
|
/**
|
|
2203
2190
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -1115,7 +1115,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1115
1115
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1116
1116
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1117
1117
|
};
|
|
1118
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
1118
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1119
1119
|
var isApplePayAvailable = async () => {
|
|
1120
1120
|
if (bypassApplePayChecks()) {
|
|
1121
1121
|
return true;
|
|
@@ -1313,21 +1313,17 @@ var track = (action, extra) => {
|
|
|
1313
1313
|
...extra
|
|
1314
1314
|
});
|
|
1315
1315
|
};
|
|
1316
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }
|
|
1316
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1317
1317
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1318
1318
|
wallet_type: "apple_pay",
|
|
1319
1319
|
entry_point: entryPoint,
|
|
1320
1320
|
sku_id: skuId,
|
|
1321
1321
|
country,
|
|
1322
|
-
device: getDevice()
|
|
1323
|
-
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1322
|
+
device: getDevice()
|
|
1324
1323
|
});
|
|
1325
1324
|
};
|
|
1326
|
-
var trackExpressWalletClick = (skuId
|
|
1327
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1328
|
-
sku_id: skuId,
|
|
1329
|
-
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1330
|
-
});
|
|
1325
|
+
var trackExpressWalletClick = (skuId) => {
|
|
1326
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
|
|
1331
1327
|
};
|
|
1332
1328
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1333
1329
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1335,18 +1331,16 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1335
1331
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1336
1332
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1337
1333
|
};
|
|
1338
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
1334
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1339
1335
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1340
1336
|
sku_id: skuId,
|
|
1341
|
-
basket_id: basketId
|
|
1342
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1337
|
+
basket_id: basketId
|
|
1343
1338
|
});
|
|
1344
1339
|
};
|
|
1345
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
1340
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1346
1341
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1347
1342
|
sku_id: skuId,
|
|
1348
|
-
failure_reason: reason
|
|
1349
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1343
|
+
failure_reason: reason
|
|
1350
1344
|
});
|
|
1351
1345
|
};
|
|
1352
1346
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1608,14 +1602,12 @@ function handleStructuredError(ctx) {
|
|
|
1608
1602
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1609
1603
|
const { skuId, returnUrl, country } = config;
|
|
1610
1604
|
let validatedEmail;
|
|
1611
|
-
let purchaseStartTime;
|
|
1612
1605
|
try {
|
|
1613
1606
|
validatedEmail = validateContacts(
|
|
1614
1607
|
event,
|
|
1615
1608
|
sessionData,
|
|
1616
1609
|
config.supportedBillingCountries
|
|
1617
1610
|
);
|
|
1618
|
-
purchaseStartTime = Date.now();
|
|
1619
1611
|
const result = await performPurchase({
|
|
1620
1612
|
applePayToken: event.payment.token,
|
|
1621
1613
|
skuId: config.skuId,
|
|
@@ -1626,8 +1618,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1626
1618
|
},
|
|
1627
1619
|
recaptchaTokens: config.recaptchaTokens
|
|
1628
1620
|
});
|
|
1629
|
-
|
|
1630
|
-
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1621
|
+
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1631
1622
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1632
1623
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1633
1624
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1645,8 +1636,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1645
1636
|
return;
|
|
1646
1637
|
}
|
|
1647
1638
|
const walletError = parseWalletApiError(err);
|
|
1648
|
-
|
|
1649
|
-
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1639
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1650
1640
|
failApplePaySession(session);
|
|
1651
1641
|
if (!walletError) {
|
|
1652
1642
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1918,7 +1908,6 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1918
1908
|
};
|
|
1919
1909
|
|
|
1920
1910
|
// src/apple-pay-button.ts
|
|
1921
|
-
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1922
1911
|
var TOTAL_LABEL = "The Economist";
|
|
1923
1912
|
var DEFAULT_CURRENCY = "USD";
|
|
1924
1913
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1934,7 +1923,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1934
1923
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1935
1924
|
}
|
|
1936
1925
|
/**
|
|
1937
|
-
* Creates and configures an ApplePayButton if the
|
|
1926
|
+
* Creates and configures an ApplePayButton if the offer is eligible.
|
|
1938
1927
|
*/
|
|
1939
1928
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1940
1929
|
if (!offer) {
|
|
@@ -1943,9 +1932,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1943
1932
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1944
1933
|
return null;
|
|
1945
1934
|
}
|
|
1946
|
-
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1947
|
-
return null;
|
|
1948
|
-
}
|
|
1949
1935
|
_ApplePayButton.define();
|
|
1950
1936
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1951
1937
|
button.offer = offer;
|
|
@@ -1969,7 +1955,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1969
1955
|
#country = "";
|
|
1970
1956
|
#rendering = false;
|
|
1971
1957
|
#readyPromise = null;
|
|
1972
|
-
#loadStartTime = 0;
|
|
1973
1958
|
#sessionData = null;
|
|
1974
1959
|
#paymentOptions = null;
|
|
1975
1960
|
#returnUrl = "";
|
|
@@ -2045,7 +2030,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2045
2030
|
}
|
|
2046
2031
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2047
2032
|
async #run() {
|
|
2048
|
-
this.#loadStartTime = Date.now();
|
|
2049
2033
|
try {
|
|
2050
2034
|
this.#renderTemplate();
|
|
2051
2035
|
if (await this.#checkAvailability()) return;
|
|
@@ -2054,8 +2038,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2054
2038
|
this.#captureReturnUrl();
|
|
2055
2039
|
this.#computeBillingCountries();
|
|
2056
2040
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2041
|
+
console.log("[web-apple-pay] button shown \u2014 reason: all checks passed, Apple Pay is available and offer is eligible");
|
|
2057
2042
|
this.#finishLoading();
|
|
2058
|
-
} catch {
|
|
2043
|
+
} catch (error) {
|
|
2044
|
+
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2059
2045
|
this.style.display = "none";
|
|
2060
2046
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2061
2047
|
} finally {
|
|
@@ -2066,6 +2052,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2066
2052
|
async #checkAvailability() {
|
|
2067
2053
|
const available = await isApplePayAvailable();
|
|
2068
2054
|
if (!available) {
|
|
2055
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2069
2056
|
this.style.display = "none";
|
|
2070
2057
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2071
2058
|
return true;
|
|
@@ -2079,6 +2066,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2079
2066
|
async #checkSession() {
|
|
2080
2067
|
this.#sessionData = await this.#fetchSession();
|
|
2081
2068
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2069
|
+
console.log(`[web-apple-pay] button removed from DOM \u2014 reason: session check failed, userType="${this.#sessionData.userType}"`);
|
|
2082
2070
|
this.style.display = "none";
|
|
2083
2071
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2084
2072
|
return true;
|
|
@@ -2088,6 +2076,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2088
2076
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2089
2077
|
#checkOffer() {
|
|
2090
2078
|
if (!this.#offer) {
|
|
2079
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2091
2080
|
this.style.display = "none";
|
|
2092
2081
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2093
2082
|
return true;
|
|
@@ -2116,6 +2105,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2116
2105
|
async #fetchAndCacheOptions() {
|
|
2117
2106
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2118
2107
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2108
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: payment options BFF reports Apple Pay unavailable for this offer");
|
|
2119
2109
|
this.style.display = "none";
|
|
2120
2110
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2121
2111
|
return true;
|
|
@@ -2124,6 +2114,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2124
2114
|
}
|
|
2125
2115
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2126
2116
|
#renderTemplate() {
|
|
2117
|
+
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2127
2118
|
this.style.removeProperty("display");
|
|
2128
2119
|
ensureApplePayLogoSymbol();
|
|
2129
2120
|
const template = document.createElement("template");
|
|
@@ -2145,12 +2136,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2145
2136
|
button.classList.remove("wap-loading");
|
|
2146
2137
|
this.#updateDisabledState();
|
|
2147
2138
|
this.#scheduleRecaptchaTokens();
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
this.#
|
|
2151
|
-
|
|
2152
|
-
buttonLoadDurationMs
|
|
2153
|
-
);
|
|
2139
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2140
|
+
entryPoint: this.#entryPoint,
|
|
2141
|
+
country: this.#country
|
|
2142
|
+
});
|
|
2154
2143
|
}
|
|
2155
2144
|
}
|
|
2156
2145
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2173,7 +2162,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2173
2162
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2174
2163
|
return;
|
|
2175
2164
|
}
|
|
2176
|
-
|
|
2165
|
+
trackExpressWalletClick(this.#offer.sku_id);
|
|
2177
2166
|
ApplePayModal.define();
|
|
2178
2167
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2179
2168
|
modal.offer = this.#offer;
|
|
@@ -2188,8 +2177,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2188
2177
|
this.#scheduleRecaptchaTokens();
|
|
2189
2178
|
};
|
|
2190
2179
|
modal.open(this.#recaptchaTokensPromise);
|
|
2191
|
-
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2192
|
-
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2193
2180
|
}
|
|
2194
2181
|
/**
|
|
2195
2182
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -8,7 +8,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
8
8
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
9
9
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
10
10
|
};
|
|
11
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
11
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
12
12
|
var isApplePayAvailable = async () => {
|
|
13
13
|
if (bypassApplePayChecks()) {
|
|
14
14
|
return true;
|
|
@@ -93,18 +93,16 @@ var track = (action, extra) => {
|
|
|
93
93
|
...extra
|
|
94
94
|
});
|
|
95
95
|
};
|
|
96
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
96
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
97
97
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
98
98
|
sku_id: skuId,
|
|
99
|
-
basket_id: basketId
|
|
100
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
99
|
+
basket_id: basketId
|
|
101
100
|
});
|
|
102
101
|
};
|
|
103
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
102
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
104
103
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
105
104
|
sku_id: skuId,
|
|
106
|
-
failure_reason: reason
|
|
107
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
105
|
+
failure_reason: reason
|
|
108
106
|
});
|
|
109
107
|
};
|
|
110
108
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -347,14 +345,12 @@ function handleStructuredError(ctx) {
|
|
|
347
345
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
348
346
|
const { skuId, returnUrl, country } = config;
|
|
349
347
|
let validatedEmail;
|
|
350
|
-
let purchaseStartTime;
|
|
351
348
|
try {
|
|
352
349
|
validatedEmail = validateContacts(
|
|
353
350
|
event,
|
|
354
351
|
sessionData,
|
|
355
352
|
config.supportedBillingCountries
|
|
356
353
|
);
|
|
357
|
-
purchaseStartTime = Date.now();
|
|
358
354
|
const result = await performPurchase({
|
|
359
355
|
applePayToken: event.payment.token,
|
|
360
356
|
skuId: config.skuId,
|
|
@@ -365,8 +361,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
365
361
|
},
|
|
366
362
|
recaptchaTokens: config.recaptchaTokens
|
|
367
363
|
});
|
|
368
|
-
|
|
369
|
-
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
364
|
+
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
370
365
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
371
366
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
372
367
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -384,8 +379,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
384
379
|
return;
|
|
385
380
|
}
|
|
386
381
|
const walletError = parseWalletApiError(err);
|
|
387
|
-
|
|
388
|
-
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
382
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
389
383
|
failApplePaySession(session);
|
|
390
384
|
if (!walletError) {
|
|
391
385
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
package/dist/src/index.js
CHANGED
|
@@ -1120,7 +1120,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
1120
1120
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
1121
1121
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
1122
1122
|
};
|
|
1123
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
1123
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
1124
1124
|
var isApplePayAvailable = async () => {
|
|
1125
1125
|
if (bypassApplePayChecks()) {
|
|
1126
1126
|
return true;
|
|
@@ -1318,21 +1318,17 @@ var track = (action, extra) => {
|
|
|
1318
1318
|
...extra
|
|
1319
1319
|
});
|
|
1320
1320
|
};
|
|
1321
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }
|
|
1321
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
1322
1322
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
1323
1323
|
wallet_type: "apple_pay",
|
|
1324
1324
|
entry_point: entryPoint,
|
|
1325
1325
|
sku_id: skuId,
|
|
1326
1326
|
country,
|
|
1327
|
-
device: getDevice()
|
|
1328
|
-
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
1327
|
+
device: getDevice()
|
|
1329
1328
|
});
|
|
1330
1329
|
};
|
|
1331
|
-
var trackExpressWalletClick = (skuId
|
|
1332
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
1333
|
-
sku_id: skuId,
|
|
1334
|
-
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
1335
|
-
});
|
|
1330
|
+
var trackExpressWalletClick = (skuId) => {
|
|
1331
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
|
|
1336
1332
|
};
|
|
1337
1333
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
1338
1334
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -1340,18 +1336,16 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
1340
1336
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
1341
1337
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
1342
1338
|
};
|
|
1343
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
1339
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
1344
1340
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
1345
1341
|
sku_id: skuId,
|
|
1346
|
-
basket_id: basketId
|
|
1347
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1342
|
+
basket_id: basketId
|
|
1348
1343
|
});
|
|
1349
1344
|
};
|
|
1350
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
1345
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
1351
1346
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
1352
1347
|
sku_id: skuId,
|
|
1353
|
-
failure_reason: reason
|
|
1354
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
1348
|
+
failure_reason: reason
|
|
1355
1349
|
});
|
|
1356
1350
|
};
|
|
1357
1351
|
var trackFallbackCheckout = (skuId) => {
|
|
@@ -1613,14 +1607,12 @@ function handleStructuredError(ctx) {
|
|
|
1613
1607
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1614
1608
|
const { skuId, returnUrl, country } = config;
|
|
1615
1609
|
let validatedEmail;
|
|
1616
|
-
let purchaseStartTime;
|
|
1617
1610
|
try {
|
|
1618
1611
|
validatedEmail = validateContacts(
|
|
1619
1612
|
event,
|
|
1620
1613
|
sessionData,
|
|
1621
1614
|
config.supportedBillingCountries
|
|
1622
1615
|
);
|
|
1623
|
-
purchaseStartTime = Date.now();
|
|
1624
1616
|
const result = await performPurchase({
|
|
1625
1617
|
applePayToken: event.payment.token,
|
|
1626
1618
|
skuId: config.skuId,
|
|
@@ -1631,8 +1623,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1631
1623
|
},
|
|
1632
1624
|
recaptchaTokens: config.recaptchaTokens
|
|
1633
1625
|
});
|
|
1634
|
-
|
|
1635
|
-
trackWalletPaymentSuccess(skuId, result.basketId, purchaseDurationMs);
|
|
1626
|
+
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1636
1627
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1637
1628
|
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1638
1629
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1650,8 +1641,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1650
1641
|
return;
|
|
1651
1642
|
}
|
|
1652
1643
|
const walletError = parseWalletApiError(err);
|
|
1653
|
-
|
|
1654
|
-
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN", purchaseDurationMs);
|
|
1644
|
+
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1655
1645
|
failApplePaySession(session);
|
|
1656
1646
|
if (!walletError) {
|
|
1657
1647
|
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
@@ -1923,7 +1913,6 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1923
1913
|
};
|
|
1924
1914
|
|
|
1925
1915
|
// src/apple-pay-button.ts
|
|
1926
|
-
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1927
1916
|
var TOTAL_LABEL = "The Economist";
|
|
1928
1917
|
var DEFAULT_CURRENCY = "USD";
|
|
1929
1918
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1939,7 +1928,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1939
1928
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1940
1929
|
}
|
|
1941
1930
|
/**
|
|
1942
|
-
* Creates and configures an ApplePayButton if the
|
|
1931
|
+
* Creates and configures an ApplePayButton if the offer is eligible.
|
|
1943
1932
|
*/
|
|
1944
1933
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1945
1934
|
if (!offer) {
|
|
@@ -1948,9 +1937,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1948
1937
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1949
1938
|
return null;
|
|
1950
1939
|
}
|
|
1951
|
-
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1952
|
-
return null;
|
|
1953
|
-
}
|
|
1954
1940
|
_ApplePayButton.define();
|
|
1955
1941
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1956
1942
|
button.offer = offer;
|
|
@@ -1974,7 +1960,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1974
1960
|
#country = "";
|
|
1975
1961
|
#rendering = false;
|
|
1976
1962
|
#readyPromise = null;
|
|
1977
|
-
#loadStartTime = 0;
|
|
1978
1963
|
#sessionData = null;
|
|
1979
1964
|
#paymentOptions = null;
|
|
1980
1965
|
#returnUrl = "";
|
|
@@ -2050,7 +2035,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2050
2035
|
}
|
|
2051
2036
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
2052
2037
|
async #run() {
|
|
2053
|
-
this.#loadStartTime = Date.now();
|
|
2054
2038
|
try {
|
|
2055
2039
|
this.#renderTemplate();
|
|
2056
2040
|
if (await this.#checkAvailability()) return;
|
|
@@ -2059,8 +2043,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2059
2043
|
this.#captureReturnUrl();
|
|
2060
2044
|
this.#computeBillingCountries();
|
|
2061
2045
|
if (await this.#fetchAndCacheOptions()) return;
|
|
2046
|
+
console.log("[web-apple-pay] button shown \u2014 reason: all checks passed, Apple Pay is available and offer is eligible");
|
|
2062
2047
|
this.#finishLoading();
|
|
2063
|
-
} catch {
|
|
2048
|
+
} catch (error) {
|
|
2049
|
+
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2064
2050
|
this.style.display = "none";
|
|
2065
2051
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2066
2052
|
} finally {
|
|
@@ -2071,6 +2057,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2071
2057
|
async #checkAvailability() {
|
|
2072
2058
|
const available = await isApplePayAvailable();
|
|
2073
2059
|
if (!available) {
|
|
2060
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2074
2061
|
this.style.display = "none";
|
|
2075
2062
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2076
2063
|
return true;
|
|
@@ -2084,6 +2071,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2084
2071
|
async #checkSession() {
|
|
2085
2072
|
this.#sessionData = await this.#fetchSession();
|
|
2086
2073
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
2074
|
+
console.log(`[web-apple-pay] button removed from DOM \u2014 reason: session check failed, userType="${this.#sessionData.userType}"`);
|
|
2087
2075
|
this.style.display = "none";
|
|
2088
2076
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2089
2077
|
return true;
|
|
@@ -2093,6 +2081,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2093
2081
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2094
2082
|
#checkOffer() {
|
|
2095
2083
|
if (!this.#offer) {
|
|
2084
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2096
2085
|
this.style.display = "none";
|
|
2097
2086
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2098
2087
|
return true;
|
|
@@ -2121,6 +2110,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2121
2110
|
async #fetchAndCacheOptions() {
|
|
2122
2111
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2123
2112
|
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2113
|
+
console.log("[web-apple-pay] button removed from DOM \u2014 reason: payment options BFF reports Apple Pay unavailable for this offer");
|
|
2124
2114
|
this.style.display = "none";
|
|
2125
2115
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2126
2116
|
return true;
|
|
@@ -2129,6 +2119,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2129
2119
|
}
|
|
2130
2120
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2131
2121
|
#renderTemplate() {
|
|
2122
|
+
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2132
2123
|
this.style.removeProperty("display");
|
|
2133
2124
|
ensureApplePayLogoSymbol();
|
|
2134
2125
|
const template = document.createElement("template");
|
|
@@ -2150,12 +2141,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2150
2141
|
button.classList.remove("wap-loading");
|
|
2151
2142
|
this.#updateDisabledState();
|
|
2152
2143
|
this.#scheduleRecaptchaTokens();
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
this.#
|
|
2156
|
-
|
|
2157
|
-
buttonLoadDurationMs
|
|
2158
|
-
);
|
|
2144
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2145
|
+
entryPoint: this.#entryPoint,
|
|
2146
|
+
country: this.#country
|
|
2147
|
+
});
|
|
2159
2148
|
}
|
|
2160
2149
|
}
|
|
2161
2150
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
@@ -2178,7 +2167,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2178
2167
|
if (document.querySelector(ApplePayModal.tag)) {
|
|
2179
2168
|
return;
|
|
2180
2169
|
}
|
|
2181
|
-
|
|
2170
|
+
trackExpressWalletClick(this.#offer.sku_id);
|
|
2182
2171
|
ApplePayModal.define();
|
|
2183
2172
|
const modal = document.createElement(ApplePayModal.tag);
|
|
2184
2173
|
modal.offer = this.#offer;
|
|
@@ -2193,8 +2182,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2193
2182
|
this.#scheduleRecaptchaTokens();
|
|
2194
2183
|
};
|
|
2195
2184
|
modal.open(this.#recaptchaTokensPromise);
|
|
2196
|
-
const modalRenderDurationMs = Date.now() - modalOpenStart;
|
|
2197
|
-
trackExpressWalletClick(skuId, modalRenderDurationMs);
|
|
2198
2185
|
}
|
|
2199
2186
|
/**
|
|
2200
2187
|
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
@@ -47,17 +47,17 @@ export type ImpressionMetadata = {
|
|
|
47
47
|
country: string;
|
|
48
48
|
};
|
|
49
49
|
/** Wallet button displayed — emits all 5 required analytics dimensions. */
|
|
50
|
-
export declare const trackExpressWalletImpression: (skuId: string, { entryPoint, country }: ImpressionMetadata
|
|
50
|
+
export declare const trackExpressWalletImpression: (skuId: string, { entryPoint, country }: ImpressionMetadata) => void;
|
|
51
51
|
/** Wallet button clicked */
|
|
52
|
-
export declare const trackExpressWalletClick: (skuId: string
|
|
52
|
+
export declare const trackExpressWalletClick: (skuId: string) => void;
|
|
53
53
|
/** Apple Pay sheet opened (session.begin() called) */
|
|
54
54
|
export declare const trackWalletPaymentSheetOpen: (skuId: string) => void;
|
|
55
55
|
/** Payment authorised by the user in the Apple Pay sheet */
|
|
56
56
|
export declare const trackWalletPaymentAuthorised: (skuId: string) => void;
|
|
57
57
|
/** Purchase completed — BFF returned success */
|
|
58
|
-
export declare const trackWalletPaymentSuccess: (skuId: string, basketId: string
|
|
58
|
+
export declare const trackWalletPaymentSuccess: (skuId: string, basketId: string) => void;
|
|
59
59
|
/** Payment failed — BFF returned an error */
|
|
60
|
-
export declare const trackWalletPaymentFailure: (skuId: string, reason: string
|
|
60
|
+
export declare const trackWalletPaymentFailure: (skuId: string, reason: string) => void;
|
|
61
61
|
/** Redirect to standard checkout triggered */
|
|
62
62
|
export declare const trackFallbackCheckout: (skuId: string) => void;
|
|
63
63
|
/** Billing/shipping field failed validation (emitted per-field when Apple Pay sheet stays open) */
|
|
@@ -35,21 +35,17 @@ var track = (action, extra) => {
|
|
|
35
35
|
...extra
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
|
-
var trackExpressWalletImpression = (skuId, { entryPoint, country }
|
|
38
|
+
var trackExpressWalletImpression = (skuId, { entryPoint, country }) => {
|
|
39
39
|
track(EXPRESS_CHECKOUT_EVENTS.IMPRESSION, {
|
|
40
40
|
wallet_type: "apple_pay",
|
|
41
41
|
entry_point: entryPoint,
|
|
42
42
|
sku_id: skuId,
|
|
43
43
|
country,
|
|
44
|
-
device: getDevice()
|
|
45
|
-
...buttonLoadDurationMs !== void 0 && { button_load_duration_ms: buttonLoadDurationMs }
|
|
44
|
+
device: getDevice()
|
|
46
45
|
});
|
|
47
46
|
};
|
|
48
|
-
var trackExpressWalletClick = (skuId
|
|
49
|
-
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, {
|
|
50
|
-
sku_id: skuId,
|
|
51
|
-
...modalRenderDurationMs !== void 0 && { modal_render_duration_ms: modalRenderDurationMs }
|
|
52
|
-
});
|
|
47
|
+
var trackExpressWalletClick = (skuId) => {
|
|
48
|
+
track(EXPRESS_CHECKOUT_EVENTS.BUTTON_CLICK, { sku_id: skuId });
|
|
53
49
|
};
|
|
54
50
|
var trackWalletPaymentSheetOpen = (skuId) => {
|
|
55
51
|
track(EXPRESS_CHECKOUT_EVENTS.SHEET_OPEN, { sku_id: skuId });
|
|
@@ -57,18 +53,16 @@ var trackWalletPaymentSheetOpen = (skuId) => {
|
|
|
57
53
|
var trackWalletPaymentAuthorised = (skuId) => {
|
|
58
54
|
track(EXPRESS_CHECKOUT_EVENTS.AUTHORISED, { sku_id: skuId });
|
|
59
55
|
};
|
|
60
|
-
var trackWalletPaymentSuccess = (skuId, basketId
|
|
56
|
+
var trackWalletPaymentSuccess = (skuId, basketId) => {
|
|
61
57
|
track(EXPRESS_CHECKOUT_EVENTS.SUCCESS, {
|
|
62
58
|
sku_id: skuId,
|
|
63
|
-
basket_id: basketId
|
|
64
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
59
|
+
basket_id: basketId
|
|
65
60
|
});
|
|
66
61
|
};
|
|
67
|
-
var trackWalletPaymentFailure = (skuId, reason
|
|
62
|
+
var trackWalletPaymentFailure = (skuId, reason) => {
|
|
68
63
|
track(EXPRESS_CHECKOUT_EVENTS.FAILURE, {
|
|
69
64
|
sku_id: skuId,
|
|
70
|
-
failure_reason: reason
|
|
71
|
-
...purchaseDurationMs !== void 0 && { purchase_duration_ms: purchaseDurationMs }
|
|
65
|
+
failure_reason: reason
|
|
72
66
|
});
|
|
73
67
|
};
|
|
74
68
|
var trackFallbackCheckout = (skuId) => {
|
package/package.json
CHANGED