@economist/web-apple-pay 0.1.3-beta.41 → 0.1.3-beta.42
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 +11 -44
- package/dist/src/apple-pay-button.d.ts +1 -1
- package/dist/src/apple-pay-button.js +11 -44
- package/dist/src/apple-pay-button.stories.js +11 -44
- package/dist/src/apple-pay-modal.stories.js +11 -44
- package/dist/src/index.js +11 -44
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1913,6 +1913,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1913
1913
|
};
|
|
1914
1914
|
|
|
1915
1915
|
// src/apple-pay-button.ts
|
|
1916
|
+
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1916
1917
|
var TOTAL_LABEL = "The Economist";
|
|
1917
1918
|
var DEFAULT_CURRENCY = "USD";
|
|
1918
1919
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1928,7 +1929,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1928
1929
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1929
1930
|
}
|
|
1930
1931
|
/**
|
|
1931
|
-
* Creates and configures an ApplePayButton if the
|
|
1932
|
+
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1932
1933
|
*/
|
|
1933
1934
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1934
1935
|
if (!offer) {
|
|
@@ -1937,6 +1938,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1937
1938
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1938
1939
|
return null;
|
|
1939
1940
|
}
|
|
1941
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1942
|
+
return null;
|
|
1943
|
+
}
|
|
1940
1944
|
_ApplePayButton.define();
|
|
1941
1945
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1942
1946
|
button.offer = offer;
|
|
@@ -1965,7 +1969,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1965
1969
|
#returnUrl = "";
|
|
1966
1970
|
#supportedBillingCountries = [];
|
|
1967
1971
|
#entryPoint = "";
|
|
1968
|
-
#recaptchaTokensPromise = null;
|
|
1969
1972
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1970
1973
|
get offer() {
|
|
1971
1974
|
return this.#offer;
|
|
@@ -2030,7 +2033,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2030
2033
|
this.#paymentOptions = null;
|
|
2031
2034
|
this.#returnUrl = "";
|
|
2032
2035
|
this.#supportedBillingCountries = [];
|
|
2033
|
-
this.#recaptchaTokensPromise = null;
|
|
2034
2036
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2035
2037
|
}
|
|
2036
2038
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -2043,10 +2045,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2043
2045
|
this.#captureReturnUrl();
|
|
2044
2046
|
this.#computeBillingCountries();
|
|
2045
2047
|
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");
|
|
2047
2048
|
this.#finishLoading();
|
|
2048
|
-
} catch
|
|
2049
|
-
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2049
|
+
} catch {
|
|
2050
2050
|
this.style.display = "none";
|
|
2051
2051
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2052
2052
|
} finally {
|
|
@@ -2057,7 +2057,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2057
2057
|
async #checkAvailability() {
|
|
2058
2058
|
const available = await isApplePayAvailable();
|
|
2059
2059
|
if (!available) {
|
|
2060
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2061
2060
|
this.style.display = "none";
|
|
2062
2061
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2063
2062
|
return true;
|
|
@@ -2071,7 +2070,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2071
2070
|
async #checkSession() {
|
|
2072
2071
|
this.#sessionData = await this.#fetchSession();
|
|
2073
2072
|
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}"`);
|
|
2075
2073
|
this.style.display = "none";
|
|
2076
2074
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2077
2075
|
return true;
|
|
@@ -2081,7 +2079,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2081
2079
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2082
2080
|
#checkOffer() {
|
|
2083
2081
|
if (!this.#offer) {
|
|
2084
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2085
2082
|
this.style.display = "none";
|
|
2086
2083
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2087
2084
|
return true;
|
|
@@ -2109,16 +2106,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2109
2106
|
*/
|
|
2110
2107
|
async #fetchAndCacheOptions() {
|
|
2111
2108
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2112
|
-
if (!this.#paymentOptions) {
|
|
2113
|
-
console.warn("[web-apple-pay] button removed from DOM \u2014 reason: getPaymentOptions threw an error (see previous log for details)");
|
|
2114
|
-
this.style.display = "none";
|
|
2115
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2116
|
-
return true;
|
|
2117
|
-
}
|
|
2118
|
-
if (!this.#paymentOptions.options?.apple_pay) {
|
|
2119
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: BFF responded but apple_pay is absent from payment options", {
|
|
2120
|
-
receivedOptions: this.#paymentOptions.options
|
|
2121
|
-
});
|
|
2109
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2122
2110
|
this.style.display = "none";
|
|
2123
2111
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2124
2112
|
return true;
|
|
@@ -2127,7 +2115,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2127
2115
|
}
|
|
2128
2116
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2129
2117
|
#renderTemplate() {
|
|
2130
|
-
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2131
2118
|
this.style.removeProperty("display");
|
|
2132
2119
|
ensureApplePayLogoSymbol();
|
|
2133
2120
|
const template = document.createElement("template");
|
|
@@ -2148,7 +2135,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2148
2135
|
if (button) {
|
|
2149
2136
|
button.classList.remove("wap-loading");
|
|
2150
2137
|
this.#updateDisabledState();
|
|
2151
|
-
this.#scheduleRecaptchaTokens();
|
|
2152
2138
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2153
2139
|
entryPoint: this.#entryPoint,
|
|
2154
2140
|
country: this.#country
|
|
@@ -2187,25 +2173,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2187
2173
|
const country = this.#country;
|
|
2188
2174
|
modal.onConfirm = (recaptchaTokens) => {
|
|
2189
2175
|
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2190
|
-
this.#scheduleRecaptchaTokens();
|
|
2191
2176
|
};
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
/**
|
|
2195
|
-
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2196
|
-
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2197
|
-
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2198
|
-
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2199
|
-
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2200
|
-
*/
|
|
2201
|
-
#scheduleRecaptchaTokens() {
|
|
2202
|
-
const attempt = getPurchaseRecaptchaTokens();
|
|
2203
|
-
attempt.catch(() => {
|
|
2204
|
-
if (this.#recaptchaTokensPromise === attempt) {
|
|
2205
|
-
this.#recaptchaTokensPromise = null;
|
|
2206
|
-
}
|
|
2207
|
-
});
|
|
2208
|
-
this.#recaptchaTokensPromise = attempt;
|
|
2177
|
+
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
2178
|
+
modal.open(recaptchaTokensPromise);
|
|
2209
2179
|
}
|
|
2210
2180
|
async #fetchSession() {
|
|
2211
2181
|
try {
|
|
@@ -2216,16 +2186,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2216
2186
|
}
|
|
2217
2187
|
async #fetchPaymentOptions() {
|
|
2218
2188
|
try {
|
|
2219
|
-
|
|
2189
|
+
return await getPaymentOptions({
|
|
2220
2190
|
sku: this.#offer.sku_id,
|
|
2221
2191
|
countryCode: this.#country,
|
|
2222
2192
|
currencyCode: this.#offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2223
2193
|
checkoutUrl: this.#returnUrl
|
|
2224
2194
|
});
|
|
2225
|
-
|
|
2226
|
-
return options;
|
|
2227
|
-
} catch (error) {
|
|
2228
|
-
console.warn("[web-apple-pay] getPaymentOptions fetch failed \u2014 returning null", error);
|
|
2195
|
+
} catch {
|
|
2229
2196
|
return null;
|
|
2230
2197
|
}
|
|
2231
2198
|
}
|
|
@@ -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 feature flag is present.
|
|
10
10
|
*/
|
|
11
11
|
static createIfEnabled(offer: Offer | undefined, country: string, entryPoint?: ApplePayEntryPoint): ApplePayButton | null;
|
|
12
12
|
get offer(): Offer | null;
|
|
@@ -1908,6 +1908,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1908
1908
|
};
|
|
1909
1909
|
|
|
1910
1910
|
// src/apple-pay-button.ts
|
|
1911
|
+
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1911
1912
|
var TOTAL_LABEL = "The Economist";
|
|
1912
1913
|
var DEFAULT_CURRENCY = "USD";
|
|
1913
1914
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1923,7 +1924,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1923
1924
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1924
1925
|
}
|
|
1925
1926
|
/**
|
|
1926
|
-
* Creates and configures an ApplePayButton if the
|
|
1927
|
+
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1927
1928
|
*/
|
|
1928
1929
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1929
1930
|
if (!offer) {
|
|
@@ -1932,6 +1933,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1932
1933
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1933
1934
|
return null;
|
|
1934
1935
|
}
|
|
1936
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1937
|
+
return null;
|
|
1938
|
+
}
|
|
1935
1939
|
_ApplePayButton.define();
|
|
1936
1940
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1937
1941
|
button.offer = offer;
|
|
@@ -1960,7 +1964,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1960
1964
|
#returnUrl = "";
|
|
1961
1965
|
#supportedBillingCountries = [];
|
|
1962
1966
|
#entryPoint = "";
|
|
1963
|
-
#recaptchaTokensPromise = null;
|
|
1964
1967
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1965
1968
|
get offer() {
|
|
1966
1969
|
return this.#offer;
|
|
@@ -2025,7 +2028,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2025
2028
|
this.#paymentOptions = null;
|
|
2026
2029
|
this.#returnUrl = "";
|
|
2027
2030
|
this.#supportedBillingCountries = [];
|
|
2028
|
-
this.#recaptchaTokensPromise = null;
|
|
2029
2031
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2030
2032
|
}
|
|
2031
2033
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -2038,10 +2040,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2038
2040
|
this.#captureReturnUrl();
|
|
2039
2041
|
this.#computeBillingCountries();
|
|
2040
2042
|
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");
|
|
2042
2043
|
this.#finishLoading();
|
|
2043
|
-
} catch
|
|
2044
|
-
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2044
|
+
} catch {
|
|
2045
2045
|
this.style.display = "none";
|
|
2046
2046
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2047
2047
|
} finally {
|
|
@@ -2052,7 +2052,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2052
2052
|
async #checkAvailability() {
|
|
2053
2053
|
const available = await isApplePayAvailable();
|
|
2054
2054
|
if (!available) {
|
|
2055
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2056
2055
|
this.style.display = "none";
|
|
2057
2056
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2058
2057
|
return true;
|
|
@@ -2066,7 +2065,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2066
2065
|
async #checkSession() {
|
|
2067
2066
|
this.#sessionData = await this.#fetchSession();
|
|
2068
2067
|
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}"`);
|
|
2070
2068
|
this.style.display = "none";
|
|
2071
2069
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2072
2070
|
return true;
|
|
@@ -2076,7 +2074,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2076
2074
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2077
2075
|
#checkOffer() {
|
|
2078
2076
|
if (!this.#offer) {
|
|
2079
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2080
2077
|
this.style.display = "none";
|
|
2081
2078
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2082
2079
|
return true;
|
|
@@ -2104,16 +2101,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2104
2101
|
*/
|
|
2105
2102
|
async #fetchAndCacheOptions() {
|
|
2106
2103
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2107
|
-
if (!this.#paymentOptions) {
|
|
2108
|
-
console.warn("[web-apple-pay] button removed from DOM \u2014 reason: getPaymentOptions threw an error (see previous log for details)");
|
|
2109
|
-
this.style.display = "none";
|
|
2110
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2111
|
-
return true;
|
|
2112
|
-
}
|
|
2113
|
-
if (!this.#paymentOptions.options?.apple_pay) {
|
|
2114
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: BFF responded but apple_pay is absent from payment options", {
|
|
2115
|
-
receivedOptions: this.#paymentOptions.options
|
|
2116
|
-
});
|
|
2104
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2117
2105
|
this.style.display = "none";
|
|
2118
2106
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2119
2107
|
return true;
|
|
@@ -2122,7 +2110,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2122
2110
|
}
|
|
2123
2111
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2124
2112
|
#renderTemplate() {
|
|
2125
|
-
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2126
2113
|
this.style.removeProperty("display");
|
|
2127
2114
|
ensureApplePayLogoSymbol();
|
|
2128
2115
|
const template = document.createElement("template");
|
|
@@ -2143,7 +2130,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2143
2130
|
if (button) {
|
|
2144
2131
|
button.classList.remove("wap-loading");
|
|
2145
2132
|
this.#updateDisabledState();
|
|
2146
|
-
this.#scheduleRecaptchaTokens();
|
|
2147
2133
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2148
2134
|
entryPoint: this.#entryPoint,
|
|
2149
2135
|
country: this.#country
|
|
@@ -2182,25 +2168,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2182
2168
|
const country = this.#country;
|
|
2183
2169
|
modal.onConfirm = (recaptchaTokens) => {
|
|
2184
2170
|
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2185
|
-
this.#scheduleRecaptchaTokens();
|
|
2186
2171
|
};
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
/**
|
|
2190
|
-
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2191
|
-
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2192
|
-
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2193
|
-
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2194
|
-
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2195
|
-
*/
|
|
2196
|
-
#scheduleRecaptchaTokens() {
|
|
2197
|
-
const attempt = getPurchaseRecaptchaTokens();
|
|
2198
|
-
attempt.catch(() => {
|
|
2199
|
-
if (this.#recaptchaTokensPromise === attempt) {
|
|
2200
|
-
this.#recaptchaTokensPromise = null;
|
|
2201
|
-
}
|
|
2202
|
-
});
|
|
2203
|
-
this.#recaptchaTokensPromise = attempt;
|
|
2172
|
+
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
2173
|
+
modal.open(recaptchaTokensPromise);
|
|
2204
2174
|
}
|
|
2205
2175
|
async #fetchSession() {
|
|
2206
2176
|
try {
|
|
@@ -2211,16 +2181,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2211
2181
|
}
|
|
2212
2182
|
async #fetchPaymentOptions() {
|
|
2213
2183
|
try {
|
|
2214
|
-
|
|
2184
|
+
return await getPaymentOptions({
|
|
2215
2185
|
sku: this.#offer.sku_id,
|
|
2216
2186
|
countryCode: this.#country,
|
|
2217
2187
|
currencyCode: this.#offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2218
2188
|
checkoutUrl: this.#returnUrl
|
|
2219
2189
|
});
|
|
2220
|
-
|
|
2221
|
-
return options;
|
|
2222
|
-
} catch (error) {
|
|
2223
|
-
console.warn("[web-apple-pay] getPaymentOptions fetch failed \u2014 returning null", error);
|
|
2190
|
+
} catch {
|
|
2224
2191
|
return null;
|
|
2225
2192
|
}
|
|
2226
2193
|
}
|
|
@@ -1916,6 +1916,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1916
1916
|
};
|
|
1917
1917
|
|
|
1918
1918
|
// src/apple-pay-button.ts
|
|
1919
|
+
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1919
1920
|
var TOTAL_LABEL = "The Economist";
|
|
1920
1921
|
var DEFAULT_CURRENCY = "USD";
|
|
1921
1922
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1931,7 +1932,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1931
1932
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1932
1933
|
}
|
|
1933
1934
|
/**
|
|
1934
|
-
* Creates and configures an ApplePayButton if the
|
|
1935
|
+
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1935
1936
|
*/
|
|
1936
1937
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1937
1938
|
if (!offer) {
|
|
@@ -1940,6 +1941,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1940
1941
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1941
1942
|
return null;
|
|
1942
1943
|
}
|
|
1944
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1945
|
+
return null;
|
|
1946
|
+
}
|
|
1943
1947
|
_ApplePayButton.define();
|
|
1944
1948
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1945
1949
|
button.offer = offer;
|
|
@@ -1968,7 +1972,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1968
1972
|
#returnUrl = "";
|
|
1969
1973
|
#supportedBillingCountries = [];
|
|
1970
1974
|
#entryPoint = "";
|
|
1971
|
-
#recaptchaTokensPromise = null;
|
|
1972
1975
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1973
1976
|
get offer() {
|
|
1974
1977
|
return this.#offer;
|
|
@@ -2033,7 +2036,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2033
2036
|
this.#paymentOptions = null;
|
|
2034
2037
|
this.#returnUrl = "";
|
|
2035
2038
|
this.#supportedBillingCountries = [];
|
|
2036
|
-
this.#recaptchaTokensPromise = null;
|
|
2037
2039
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2038
2040
|
}
|
|
2039
2041
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -2046,10 +2048,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2046
2048
|
this.#captureReturnUrl();
|
|
2047
2049
|
this.#computeBillingCountries();
|
|
2048
2050
|
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");
|
|
2050
2051
|
this.#finishLoading();
|
|
2051
|
-
} catch
|
|
2052
|
-
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2052
|
+
} catch {
|
|
2053
2053
|
this.style.display = "none";
|
|
2054
2054
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2055
2055
|
} finally {
|
|
@@ -2060,7 +2060,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2060
2060
|
async #checkAvailability() {
|
|
2061
2061
|
const available = await isApplePayAvailable();
|
|
2062
2062
|
if (!available) {
|
|
2063
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2064
2063
|
this.style.display = "none";
|
|
2065
2064
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2066
2065
|
return true;
|
|
@@ -2074,7 +2073,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2074
2073
|
async #checkSession() {
|
|
2075
2074
|
this.#sessionData = await this.#fetchSession();
|
|
2076
2075
|
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}"`);
|
|
2078
2076
|
this.style.display = "none";
|
|
2079
2077
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2080
2078
|
return true;
|
|
@@ -2084,7 +2082,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2084
2082
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2085
2083
|
#checkOffer() {
|
|
2086
2084
|
if (!this.#offer) {
|
|
2087
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2088
2085
|
this.style.display = "none";
|
|
2089
2086
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2090
2087
|
return true;
|
|
@@ -2112,16 +2109,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2112
2109
|
*/
|
|
2113
2110
|
async #fetchAndCacheOptions() {
|
|
2114
2111
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2115
|
-
if (!this.#paymentOptions) {
|
|
2116
|
-
console.warn("[web-apple-pay] button removed from DOM \u2014 reason: getPaymentOptions threw an error (see previous log for details)");
|
|
2117
|
-
this.style.display = "none";
|
|
2118
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2119
|
-
return true;
|
|
2120
|
-
}
|
|
2121
|
-
if (!this.#paymentOptions.options?.apple_pay) {
|
|
2122
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: BFF responded but apple_pay is absent from payment options", {
|
|
2123
|
-
receivedOptions: this.#paymentOptions.options
|
|
2124
|
-
});
|
|
2112
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2125
2113
|
this.style.display = "none";
|
|
2126
2114
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2127
2115
|
return true;
|
|
@@ -2130,7 +2118,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2130
2118
|
}
|
|
2131
2119
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2132
2120
|
#renderTemplate() {
|
|
2133
|
-
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2134
2121
|
this.style.removeProperty("display");
|
|
2135
2122
|
ensureApplePayLogoSymbol();
|
|
2136
2123
|
const template = document.createElement("template");
|
|
@@ -2151,7 +2138,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2151
2138
|
if (button) {
|
|
2152
2139
|
button.classList.remove("wap-loading");
|
|
2153
2140
|
this.#updateDisabledState();
|
|
2154
|
-
this.#scheduleRecaptchaTokens();
|
|
2155
2141
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2156
2142
|
entryPoint: this.#entryPoint,
|
|
2157
2143
|
country: this.#country
|
|
@@ -2190,25 +2176,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2190
2176
|
const country = this.#country;
|
|
2191
2177
|
modal.onConfirm = (recaptchaTokens) => {
|
|
2192
2178
|
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2193
|
-
this.#scheduleRecaptchaTokens();
|
|
2194
2179
|
};
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
/**
|
|
2198
|
-
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2199
|
-
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2200
|
-
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2201
|
-
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2202
|
-
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2203
|
-
*/
|
|
2204
|
-
#scheduleRecaptchaTokens() {
|
|
2205
|
-
const attempt = getPurchaseRecaptchaTokens();
|
|
2206
|
-
attempt.catch(() => {
|
|
2207
|
-
if (this.#recaptchaTokensPromise === attempt) {
|
|
2208
|
-
this.#recaptchaTokensPromise = null;
|
|
2209
|
-
}
|
|
2210
|
-
});
|
|
2211
|
-
this.#recaptchaTokensPromise = attempt;
|
|
2180
|
+
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
2181
|
+
modal.open(recaptchaTokensPromise);
|
|
2212
2182
|
}
|
|
2213
2183
|
async #fetchSession() {
|
|
2214
2184
|
try {
|
|
@@ -2219,16 +2189,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2219
2189
|
}
|
|
2220
2190
|
async #fetchPaymentOptions() {
|
|
2221
2191
|
try {
|
|
2222
|
-
|
|
2192
|
+
return await getPaymentOptions({
|
|
2223
2193
|
sku: this.#offer.sku_id,
|
|
2224
2194
|
countryCode: this.#country,
|
|
2225
2195
|
currencyCode: this.#offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2226
2196
|
checkoutUrl: this.#returnUrl
|
|
2227
2197
|
});
|
|
2228
|
-
|
|
2229
|
-
return options;
|
|
2230
|
-
} catch (error) {
|
|
2231
|
-
console.warn("[web-apple-pay] getPaymentOptions fetch failed \u2014 returning null", error);
|
|
2198
|
+
} catch {
|
|
2232
2199
|
return null;
|
|
2233
2200
|
}
|
|
2234
2201
|
}
|
|
@@ -1908,6 +1908,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1908
1908
|
};
|
|
1909
1909
|
|
|
1910
1910
|
// src/apple-pay-button.ts
|
|
1911
|
+
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1911
1912
|
var TOTAL_LABEL = "The Economist";
|
|
1912
1913
|
var DEFAULT_CURRENCY = "USD";
|
|
1913
1914
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1923,7 +1924,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1923
1924
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1924
1925
|
}
|
|
1925
1926
|
/**
|
|
1926
|
-
* Creates and configures an ApplePayButton if the
|
|
1927
|
+
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1927
1928
|
*/
|
|
1928
1929
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1929
1930
|
if (!offer) {
|
|
@@ -1932,6 +1933,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1932
1933
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1933
1934
|
return null;
|
|
1934
1935
|
}
|
|
1936
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1937
|
+
return null;
|
|
1938
|
+
}
|
|
1935
1939
|
_ApplePayButton.define();
|
|
1936
1940
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1937
1941
|
button.offer = offer;
|
|
@@ -1960,7 +1964,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1960
1964
|
#returnUrl = "";
|
|
1961
1965
|
#supportedBillingCountries = [];
|
|
1962
1966
|
#entryPoint = "";
|
|
1963
|
-
#recaptchaTokensPromise = null;
|
|
1964
1967
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1965
1968
|
get offer() {
|
|
1966
1969
|
return this.#offer;
|
|
@@ -2025,7 +2028,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2025
2028
|
this.#paymentOptions = null;
|
|
2026
2029
|
this.#returnUrl = "";
|
|
2027
2030
|
this.#supportedBillingCountries = [];
|
|
2028
|
-
this.#recaptchaTokensPromise = null;
|
|
2029
2031
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2030
2032
|
}
|
|
2031
2033
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -2038,10 +2040,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2038
2040
|
this.#captureReturnUrl();
|
|
2039
2041
|
this.#computeBillingCountries();
|
|
2040
2042
|
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");
|
|
2042
2043
|
this.#finishLoading();
|
|
2043
|
-
} catch
|
|
2044
|
-
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2044
|
+
} catch {
|
|
2045
2045
|
this.style.display = "none";
|
|
2046
2046
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2047
2047
|
} finally {
|
|
@@ -2052,7 +2052,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2052
2052
|
async #checkAvailability() {
|
|
2053
2053
|
const available = await isApplePayAvailable();
|
|
2054
2054
|
if (!available) {
|
|
2055
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2056
2055
|
this.style.display = "none";
|
|
2057
2056
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2058
2057
|
return true;
|
|
@@ -2066,7 +2065,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2066
2065
|
async #checkSession() {
|
|
2067
2066
|
this.#sessionData = await this.#fetchSession();
|
|
2068
2067
|
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}"`);
|
|
2070
2068
|
this.style.display = "none";
|
|
2071
2069
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2072
2070
|
return true;
|
|
@@ -2076,7 +2074,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2076
2074
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2077
2075
|
#checkOffer() {
|
|
2078
2076
|
if (!this.#offer) {
|
|
2079
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2080
2077
|
this.style.display = "none";
|
|
2081
2078
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2082
2079
|
return true;
|
|
@@ -2104,16 +2101,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2104
2101
|
*/
|
|
2105
2102
|
async #fetchAndCacheOptions() {
|
|
2106
2103
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2107
|
-
if (!this.#paymentOptions) {
|
|
2108
|
-
console.warn("[web-apple-pay] button removed from DOM \u2014 reason: getPaymentOptions threw an error (see previous log for details)");
|
|
2109
|
-
this.style.display = "none";
|
|
2110
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2111
|
-
return true;
|
|
2112
|
-
}
|
|
2113
|
-
if (!this.#paymentOptions.options?.apple_pay) {
|
|
2114
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: BFF responded but apple_pay is absent from payment options", {
|
|
2115
|
-
receivedOptions: this.#paymentOptions.options
|
|
2116
|
-
});
|
|
2104
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2117
2105
|
this.style.display = "none";
|
|
2118
2106
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2119
2107
|
return true;
|
|
@@ -2122,7 +2110,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2122
2110
|
}
|
|
2123
2111
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2124
2112
|
#renderTemplate() {
|
|
2125
|
-
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2126
2113
|
this.style.removeProperty("display");
|
|
2127
2114
|
ensureApplePayLogoSymbol();
|
|
2128
2115
|
const template = document.createElement("template");
|
|
@@ -2143,7 +2130,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2143
2130
|
if (button) {
|
|
2144
2131
|
button.classList.remove("wap-loading");
|
|
2145
2132
|
this.#updateDisabledState();
|
|
2146
|
-
this.#scheduleRecaptchaTokens();
|
|
2147
2133
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2148
2134
|
entryPoint: this.#entryPoint,
|
|
2149
2135
|
country: this.#country
|
|
@@ -2182,25 +2168,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2182
2168
|
const country = this.#country;
|
|
2183
2169
|
modal.onConfirm = (recaptchaTokens) => {
|
|
2184
2170
|
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2185
|
-
this.#scheduleRecaptchaTokens();
|
|
2186
2171
|
};
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
/**
|
|
2190
|
-
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2191
|
-
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2192
|
-
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2193
|
-
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2194
|
-
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2195
|
-
*/
|
|
2196
|
-
#scheduleRecaptchaTokens() {
|
|
2197
|
-
const attempt = getPurchaseRecaptchaTokens();
|
|
2198
|
-
attempt.catch(() => {
|
|
2199
|
-
if (this.#recaptchaTokensPromise === attempt) {
|
|
2200
|
-
this.#recaptchaTokensPromise = null;
|
|
2201
|
-
}
|
|
2202
|
-
});
|
|
2203
|
-
this.#recaptchaTokensPromise = attempt;
|
|
2172
|
+
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
2173
|
+
modal.open(recaptchaTokensPromise);
|
|
2204
2174
|
}
|
|
2205
2175
|
async #fetchSession() {
|
|
2206
2176
|
try {
|
|
@@ -2211,16 +2181,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2211
2181
|
}
|
|
2212
2182
|
async #fetchPaymentOptions() {
|
|
2213
2183
|
try {
|
|
2214
|
-
|
|
2184
|
+
return await getPaymentOptions({
|
|
2215
2185
|
sku: this.#offer.sku_id,
|
|
2216
2186
|
countryCode: this.#country,
|
|
2217
2187
|
currencyCode: this.#offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2218
2188
|
checkoutUrl: this.#returnUrl
|
|
2219
2189
|
});
|
|
2220
|
-
|
|
2221
|
-
return options;
|
|
2222
|
-
} catch (error) {
|
|
2223
|
-
console.warn("[web-apple-pay] getPaymentOptions fetch failed \u2014 returning null", error);
|
|
2190
|
+
} catch {
|
|
2224
2191
|
return null;
|
|
2225
2192
|
}
|
|
2226
2193
|
}
|
package/dist/src/index.js
CHANGED
|
@@ -1913,6 +1913,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1913
1913
|
};
|
|
1914
1914
|
|
|
1915
1915
|
// src/apple-pay-button.ts
|
|
1916
|
+
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1916
1917
|
var TOTAL_LABEL = "The Economist";
|
|
1917
1918
|
var DEFAULT_CURRENCY = "USD";
|
|
1918
1919
|
var DEFAULT_TOTAL = "0.00";
|
|
@@ -1928,7 +1929,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1928
1929
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1929
1930
|
}
|
|
1930
1931
|
/**
|
|
1931
|
-
* Creates and configures an ApplePayButton if the
|
|
1932
|
+
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1932
1933
|
*/
|
|
1933
1934
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1934
1935
|
if (!offer) {
|
|
@@ -1937,6 +1938,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1937
1938
|
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1938
1939
|
return null;
|
|
1939
1940
|
}
|
|
1941
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1942
|
+
return null;
|
|
1943
|
+
}
|
|
1940
1944
|
_ApplePayButton.define();
|
|
1941
1945
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1942
1946
|
button.offer = offer;
|
|
@@ -1965,7 +1969,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1965
1969
|
#returnUrl = "";
|
|
1966
1970
|
#supportedBillingCountries = [];
|
|
1967
1971
|
#entryPoint = "";
|
|
1968
|
-
#recaptchaTokensPromise = null;
|
|
1969
1972
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1970
1973
|
get offer() {
|
|
1971
1974
|
return this.#offer;
|
|
@@ -2030,7 +2033,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2030
2033
|
this.#paymentOptions = null;
|
|
2031
2034
|
this.#returnUrl = "";
|
|
2032
2035
|
this.#supportedBillingCountries = [];
|
|
2033
|
-
this.#recaptchaTokensPromise = null;
|
|
2034
2036
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2035
2037
|
}
|
|
2036
2038
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -2043,10 +2045,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2043
2045
|
this.#captureReturnUrl();
|
|
2044
2046
|
this.#computeBillingCountries();
|
|
2045
2047
|
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");
|
|
2047
2048
|
this.#finishLoading();
|
|
2048
|
-
} catch
|
|
2049
|
-
console.warn("[web-apple-pay] button hidden \u2014 reason: unexpected error in render pipeline", error);
|
|
2049
|
+
} catch {
|
|
2050
2050
|
this.style.display = "none";
|
|
2051
2051
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2052
2052
|
} finally {
|
|
@@ -2057,7 +2057,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2057
2057
|
async #checkAvailability() {
|
|
2058
2058
|
const available = await isApplePayAvailable();
|
|
2059
2059
|
if (!available) {
|
|
2060
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: Apple Pay unavailable on this device/browser");
|
|
2061
2060
|
this.style.display = "none";
|
|
2062
2061
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2063
2062
|
return true;
|
|
@@ -2071,7 +2070,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2071
2070
|
async #checkSession() {
|
|
2072
2071
|
this.#sessionData = await this.#fetchSession();
|
|
2073
2072
|
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}"`);
|
|
2075
2073
|
this.style.display = "none";
|
|
2076
2074
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2077
2075
|
return true;
|
|
@@ -2081,7 +2079,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2081
2079
|
/** Returns `true` (hide) when no offer has been set before mount. */
|
|
2082
2080
|
#checkOffer() {
|
|
2083
2081
|
if (!this.#offer) {
|
|
2084
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: no offer set on element before mount");
|
|
2085
2082
|
this.style.display = "none";
|
|
2086
2083
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2087
2084
|
return true;
|
|
@@ -2109,16 +2106,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2109
2106
|
*/
|
|
2110
2107
|
async #fetchAndCacheOptions() {
|
|
2111
2108
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
2112
|
-
if (!this.#paymentOptions) {
|
|
2113
|
-
console.warn("[web-apple-pay] button removed from DOM \u2014 reason: getPaymentOptions threw an error (see previous log for details)");
|
|
2114
|
-
this.style.display = "none";
|
|
2115
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2116
|
-
return true;
|
|
2117
|
-
}
|
|
2118
|
-
if (!this.#paymentOptions.options?.apple_pay) {
|
|
2119
|
-
console.log("[web-apple-pay] button removed from DOM \u2014 reason: BFF responded but apple_pay is absent from payment options", {
|
|
2120
|
-
receivedOptions: this.#paymentOptions.options
|
|
2121
|
-
});
|
|
2109
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
2122
2110
|
this.style.display = "none";
|
|
2123
2111
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
2124
2112
|
return true;
|
|
@@ -2127,7 +2115,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2127
2115
|
}
|
|
2128
2116
|
/** Injects the button template and wires click and confirm event listeners. */
|
|
2129
2117
|
#renderTemplate() {
|
|
2130
|
-
console.log("[web-apple-pay] button shown \u2014 reason: template injected into DOM (loading state), awaiting pipeline checks");
|
|
2131
2118
|
this.style.removeProperty("display");
|
|
2132
2119
|
ensureApplePayLogoSymbol();
|
|
2133
2120
|
const template = document.createElement("template");
|
|
@@ -2148,7 +2135,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2148
2135
|
if (button) {
|
|
2149
2136
|
button.classList.remove("wap-loading");
|
|
2150
2137
|
this.#updateDisabledState();
|
|
2151
|
-
this.#scheduleRecaptchaTokens();
|
|
2152
2138
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2153
2139
|
entryPoint: this.#entryPoint,
|
|
2154
2140
|
country: this.#country
|
|
@@ -2187,25 +2173,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2187
2173
|
const country = this.#country;
|
|
2188
2174
|
modal.onConfirm = (recaptchaTokens) => {
|
|
2189
2175
|
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2190
|
-
this.#scheduleRecaptchaTokens();
|
|
2191
2176
|
};
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
/**
|
|
2195
|
-
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2196
|
-
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2197
|
-
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2198
|
-
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2199
|
-
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2200
|
-
*/
|
|
2201
|
-
#scheduleRecaptchaTokens() {
|
|
2202
|
-
const attempt = getPurchaseRecaptchaTokens();
|
|
2203
|
-
attempt.catch(() => {
|
|
2204
|
-
if (this.#recaptchaTokensPromise === attempt) {
|
|
2205
|
-
this.#recaptchaTokensPromise = null;
|
|
2206
|
-
}
|
|
2207
|
-
});
|
|
2208
|
-
this.#recaptchaTokensPromise = attempt;
|
|
2177
|
+
const recaptchaTokensPromise = getPurchaseRecaptchaTokens();
|
|
2178
|
+
modal.open(recaptchaTokensPromise);
|
|
2209
2179
|
}
|
|
2210
2180
|
async #fetchSession() {
|
|
2211
2181
|
try {
|
|
@@ -2216,16 +2186,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
2216
2186
|
}
|
|
2217
2187
|
async #fetchPaymentOptions() {
|
|
2218
2188
|
try {
|
|
2219
|
-
|
|
2189
|
+
return await getPaymentOptions({
|
|
2220
2190
|
sku: this.#offer.sku_id,
|
|
2221
2191
|
countryCode: this.#country,
|
|
2222
2192
|
currencyCode: this.#offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2223
2193
|
checkoutUrl: this.#returnUrl
|
|
2224
2194
|
});
|
|
2225
|
-
|
|
2226
|
-
return options;
|
|
2227
|
-
} catch (error) {
|
|
2228
|
-
console.warn("[web-apple-pay] getPaymentOptions fetch failed \u2014 returning null", error);
|
|
2195
|
+
} catch {
|
|
2229
2196
|
return null;
|
|
2230
2197
|
}
|
|
2231
2198
|
}
|
package/package.json
CHANGED