@economist/web-apple-pay 1.9.0 → 1.9.2

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/README.md CHANGED
@@ -132,7 +132,7 @@ Consumers should listen for this event and continue payment orchestration.
132
132
  Check:
133
133
 
134
134
  - `configureApplePay(...)` was called before rendering (with a valid `merchantId` and `walletApiBaseUrl`)
135
- - device/browser supports Apple Pay checks (Safari/Apple device logic)
135
+ - device/browser supports Apple Pay (Safari on Apple device required)
136
136
  - query string/feature flag gating for your page is satisfied
137
137
  - offer variant is not excluded (`bundle`, `insider_print`)
138
138
 
package/dist/index.js CHANGED
@@ -1382,6 +1382,20 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
1382
1382
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
1383
1383
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
1384
1384
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
1385
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
1386
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
1387
+ var buildCountryMismatchMessage = (countryCode) => {
1388
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
1389
+ try {
1390
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
1391
+ const upper = countryCode.toUpperCase();
1392
+ const countryName = regionNames.of(upper);
1393
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
1394
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
1395
+ } catch {
1396
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
1397
+ }
1398
+ };
1385
1399
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
1386
1400
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
1387
1401
 
@@ -1662,7 +1676,19 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1662
1676
  });
1663
1677
  } catch (err) {
1664
1678
  if (err instanceof ContactValidationError) {
1665
- failApplePaySession(session, err.errors);
1679
+ const isBillingCountryMismatch = err.errors.some(
1680
+ (e) => e.contactField === "countryCode"
1681
+ );
1682
+ if (isBillingCountryMismatch) {
1683
+ const countryCode = event.payment.billingContact?.countryCode;
1684
+ const userMessage = buildCountryMismatchMessage(countryCode);
1685
+ failApplePaySession(session, [
1686
+ new ApplePayError("billingContactInvalid", "countryCode", userMessage)
1687
+ ]);
1688
+ redirectFallback(skuId, returnUrl, country, { inlineError: MSG_BILLING_COUNTRY_MISMATCH_REDIRECT });
1689
+ } else {
1690
+ failApplePaySession(session, err.errors);
1691
+ }
1666
1692
  return;
1667
1693
  }
1668
1694
  const walletError = parseWalletApiError(err);
@@ -1944,7 +1970,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint3) => {
1944
1970
  ApplePayEntryPoint3["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1945
1971
  return ApplePayEntryPoint3;
1946
1972
  })(ApplePayEntryPoint || {});
1947
- var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
1973
+ var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
1948
1974
  var APPLE_PAY_EXPRESS_VARIANTS = {
1949
1975
  CONTROL: "control",
1950
1976
  TREATMENT: "treatment"
@@ -1377,6 +1377,20 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
1377
1377
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
1378
1378
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
1379
1379
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
1380
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
1381
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
1382
+ var buildCountryMismatchMessage = (countryCode) => {
1383
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
1384
+ try {
1385
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
1386
+ const upper = countryCode.toUpperCase();
1387
+ const countryName = regionNames.of(upper);
1388
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
1389
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
1390
+ } catch {
1391
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
1392
+ }
1393
+ };
1380
1394
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
1381
1395
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
1382
1396
 
@@ -1657,7 +1671,19 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1657
1671
  });
1658
1672
  } catch (err) {
1659
1673
  if (err instanceof ContactValidationError) {
1660
- failApplePaySession(session, err.errors);
1674
+ const isBillingCountryMismatch = err.errors.some(
1675
+ (e) => e.contactField === "countryCode"
1676
+ );
1677
+ if (isBillingCountryMismatch) {
1678
+ const countryCode = event.payment.billingContact?.countryCode;
1679
+ const userMessage = buildCountryMismatchMessage(countryCode);
1680
+ failApplePaySession(session, [
1681
+ new ApplePayError("billingContactInvalid", "countryCode", userMessage)
1682
+ ]);
1683
+ redirectFallback(skuId, returnUrl, country, { inlineError: MSG_BILLING_COUNTRY_MISMATCH_REDIRECT });
1684
+ } else {
1685
+ failApplePaySession(session, err.errors);
1686
+ }
1661
1687
  return;
1662
1688
  }
1663
1689
  const walletError = parseWalletApiError(err);
@@ -1933,7 +1959,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
1933
1959
  };
1934
1960
 
1935
1961
  // src/constants.ts
1936
- var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
1962
+ var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
1937
1963
  var APPLE_PAY_EXPRESS_VARIANTS = {
1938
1964
  CONTROL: "control",
1939
1965
  TREATMENT: "treatment"
@@ -1385,6 +1385,20 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
1385
1385
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
1386
1386
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
1387
1387
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
1388
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
1389
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
1390
+ var buildCountryMismatchMessage = (countryCode) => {
1391
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
1392
+ try {
1393
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
1394
+ const upper = countryCode.toUpperCase();
1395
+ const countryName = regionNames.of(upper);
1396
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
1397
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
1398
+ } catch {
1399
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
1400
+ }
1401
+ };
1388
1402
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
1389
1403
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
1390
1404
 
@@ -1665,7 +1679,19 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1665
1679
  });
1666
1680
  } catch (err) {
1667
1681
  if (err instanceof ContactValidationError) {
1668
- failApplePaySession(session, err.errors);
1682
+ const isBillingCountryMismatch = err.errors.some(
1683
+ (e) => e.contactField === "countryCode"
1684
+ );
1685
+ if (isBillingCountryMismatch) {
1686
+ const countryCode = event.payment.billingContact?.countryCode;
1687
+ const userMessage = buildCountryMismatchMessage(countryCode);
1688
+ failApplePaySession(session, [
1689
+ new ApplePayError("billingContactInvalid", "countryCode", userMessage)
1690
+ ]);
1691
+ redirectFallback(skuId, returnUrl, country, { inlineError: MSG_BILLING_COUNTRY_MISMATCH_REDIRECT });
1692
+ } else {
1693
+ failApplePaySession(session, err.errors);
1694
+ }
1669
1695
  return;
1670
1696
  }
1671
1697
  const walletError = parseWalletApiError(err);
@@ -1941,7 +1967,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
1941
1967
  };
1942
1968
 
1943
1969
  // src/constants.ts
1944
- var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
1970
+ var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
1945
1971
  var APPLE_PAY_EXPRESS_VARIANTS = {
1946
1972
  CONTROL: "control",
1947
1973
  TREATMENT: "treatment"
@@ -1377,6 +1377,20 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
1377
1377
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
1378
1378
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
1379
1379
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
1380
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
1381
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
1382
+ var buildCountryMismatchMessage = (countryCode) => {
1383
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
1384
+ try {
1385
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
1386
+ const upper = countryCode.toUpperCase();
1387
+ const countryName = regionNames.of(upper);
1388
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
1389
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
1390
+ } catch {
1391
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
1392
+ }
1393
+ };
1380
1394
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
1381
1395
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
1382
1396
 
@@ -1657,7 +1671,19 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1657
1671
  });
1658
1672
  } catch (err) {
1659
1673
  if (err instanceof ContactValidationError) {
1660
- failApplePaySession(session, err.errors);
1674
+ const isBillingCountryMismatch = err.errors.some(
1675
+ (e) => e.contactField === "countryCode"
1676
+ );
1677
+ if (isBillingCountryMismatch) {
1678
+ const countryCode = event.payment.billingContact?.countryCode;
1679
+ const userMessage = buildCountryMismatchMessage(countryCode);
1680
+ failApplePaySession(session, [
1681
+ new ApplePayError("billingContactInvalid", "countryCode", userMessage)
1682
+ ]);
1683
+ redirectFallback(skuId, returnUrl, country, { inlineError: MSG_BILLING_COUNTRY_MISMATCH_REDIRECT });
1684
+ } else {
1685
+ failApplePaySession(session, err.errors);
1686
+ }
1661
1687
  return;
1662
1688
  }
1663
1689
  const walletError = parseWalletApiError(err);
@@ -1933,7 +1959,7 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
1933
1959
  };
1934
1960
 
1935
1961
  // src/constants.ts
1936
- var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
1962
+ var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
1937
1963
  var APPLE_PAY_EXPRESS_VARIANTS = {
1938
1964
  CONTROL: "control",
1939
1965
  TREATMENT: "treatment"
@@ -22,6 +22,25 @@ export declare const MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look righ
22
22
  export declare const MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
23
23
  /** Shown when the billing country is not in the supported list for the offer. */
24
24
  export declare const MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
25
+ /**
26
+ * Fallback user-facing message for billing country mismatch when the country
27
+ * name cannot be resolved from the country code.
28
+ */
29
+ export declare const BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
30
+ /**
31
+ * User-facing message shown as an inlineError on the checkout redirect page
32
+ * when the billing country does not match the offer price zone.
33
+ */
34
+ export declare const MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
35
+ /**
36
+ * Builds a short, user-facing message for a billing country mismatch, suitable
37
+ * for Apple's native payment sheet (~50 char limit).
38
+ *
39
+ * Returns `"[Country] address required"` (e.g. "Taiwan address required") when
40
+ * the country code resolves to a name, otherwise falls back to
41
+ * BILLING_COUNTRY_MISMATCH_FALLBACK.
42
+ */
43
+ export declare const buildCountryMismatchMessage: (countryCode: string | undefined) => string;
25
44
  /**
26
45
  * Generic fallback error shown to the user when merchant validation or the
27
46
  * purchase call fails. Redirected as an inlineError on the checkout fallback page.
@@ -3,13 +3,30 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
3
3
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
4
4
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
5
5
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
6
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
7
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
8
+ var buildCountryMismatchMessage = (countryCode) => {
9
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
10
+ try {
11
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
12
+ const upper = countryCode.toUpperCase();
13
+ const countryName = regionNames.of(upper);
14
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
15
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
16
+ } catch {
17
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
18
+ }
19
+ };
6
20
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
7
21
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
8
22
  export {
23
+ BILLING_COUNTRY_MISMATCH_FALLBACK,
24
+ MSG_BILLING_COUNTRY_MISMATCH_REDIRECT,
9
25
  MSG_CONTACT_VALIDATION_INTERNAL,
10
26
  MSG_EMAIL_TOO_LONG,
11
27
  MSG_EMAIL_WRONG_FORMAT,
12
28
  MSG_MISSING_REQUIRED_FIELD,
13
29
  MSG_PAYMENT_GENERIC_ERROR,
14
- MSG_UNSUPPORTED_BILLING_COUNTRY
30
+ MSG_UNSUPPORTED_BILLING_COUNTRY,
31
+ buildCountryMismatchMessage
15
32
  };
@@ -117,6 +117,20 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
117
117
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
118
118
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
119
119
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
120
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
121
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
122
+ var buildCountryMismatchMessage = (countryCode) => {
123
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
124
+ try {
125
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
126
+ const upper = countryCode.toUpperCase();
127
+ const countryName = regionNames.of(upper);
128
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
129
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
130
+ } catch {
131
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
132
+ }
133
+ };
120
134
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
121
135
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
122
136
 
@@ -375,7 +389,19 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
375
389
  });
376
390
  } catch (err) {
377
391
  if (err instanceof ContactValidationError) {
378
- failApplePaySession(session, err.errors);
392
+ const isBillingCountryMismatch = err.errors.some(
393
+ (e) => e.contactField === "countryCode"
394
+ );
395
+ if (isBillingCountryMismatch) {
396
+ const countryCode = event.payment.billingContact?.countryCode;
397
+ const userMessage = buildCountryMismatchMessage(countryCode);
398
+ failApplePaySession(session, [
399
+ new ApplePayError("billingContactInvalid", "countryCode", userMessage)
400
+ ]);
401
+ redirectFallback(skuId, returnUrl, country, { inlineError: MSG_BILLING_COUNTRY_MISMATCH_REDIRECT });
402
+ } else {
403
+ failApplePaySession(session, err.errors);
404
+ }
379
405
  return;
380
406
  }
381
407
  const walletError = parseWalletApiError(err);
@@ -4,16 +4,18 @@ export declare enum ApplePayEntryPoint {
4
4
  DUAL_OFFER_BANNER = "dual_offer_banner"
5
5
  }
6
6
  /**
7
- * Amplitude experiment key for Apple Pay Express Checkout.
7
+ * Amplitude experiment key for Apple Pay Express Checkout on banners.
8
8
  * This package reads the variant for this key internally via
9
9
  * `window.experimentIntegration.getVariant()` — set up by the host page
10
10
  * before `createIfEnabled` is called. Gates all entry points (paywall, regwall, banner).
11
11
  *
12
- * TODO: Replace with the confirmed Amplitude experiment key once available.
13
- * The current value is a placeholder and must be verified against the
14
- * Amplitude experiment dashboard before going to production.
12
+ * Fail-closed: missing integration, missing key, `control`, or Amplitude fetch
13
+ * failure on the host → button is hidden (unless QA URL param is present).
14
+ *
15
+ * Must match the Feature experiment key in Amplitude and host app constants
16
+ * (Engagement / Insider / Podcasts).
15
17
  */
16
- export declare const APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
18
+ export declare const APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
17
19
  /**
18
20
  * Amplitude variant values for the Apple Pay Express Checkout experiment.
19
21
  * CONTROL → button hidden (baseline)
@@ -5,7 +5,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
5
5
  ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
6
6
  return ApplePayEntryPoint2;
7
7
  })(ApplePayEntryPoint || {});
8
- var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
8
+ var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
9
9
  var APPLE_PAY_EXPRESS_VARIANTS = {
10
10
  CONTROL: "control",
11
11
  TREATMENT: "treatment"
package/dist/src/index.js CHANGED
@@ -1382,6 +1382,20 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
1382
1382
  var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
1383
1383
  var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
1384
1384
  var MSG_UNSUPPORTED_BILLING_COUNTRY = "Billing country does not match offer price zone";
1385
+ var BILLING_COUNTRY_MISMATCH_FALLBACK = "Country not supported for this purchase";
1386
+ var MSG_BILLING_COUNTRY_MISMATCH_REDIRECT = "This country isn\u2019t supported for this purchase. Try updating your billing address.";
1387
+ var buildCountryMismatchMessage = (countryCode) => {
1388
+ if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
1389
+ try {
1390
+ const regionNames = new Intl.DisplayNames(["en"], { type: "region", fallback: "none" });
1391
+ const upper = countryCode.toUpperCase();
1392
+ const countryName = regionNames.of(upper);
1393
+ const isResolved = countryName && countryName !== upper && countryName !== "Unknown Region";
1394
+ return isResolved ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
1395
+ } catch {
1396
+ return BILLING_COUNTRY_MISMATCH_FALLBACK;
1397
+ }
1398
+ };
1385
1399
  var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
1386
1400
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
1387
1401
 
@@ -1662,7 +1676,19 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1662
1676
  });
1663
1677
  } catch (err) {
1664
1678
  if (err instanceof ContactValidationError) {
1665
- failApplePaySession(session, err.errors);
1679
+ const isBillingCountryMismatch = err.errors.some(
1680
+ (e) => e.contactField === "countryCode"
1681
+ );
1682
+ if (isBillingCountryMismatch) {
1683
+ const countryCode = event.payment.billingContact?.countryCode;
1684
+ const userMessage = buildCountryMismatchMessage(countryCode);
1685
+ failApplePaySession(session, [
1686
+ new ApplePayError("billingContactInvalid", "countryCode", userMessage)
1687
+ ]);
1688
+ redirectFallback(skuId, returnUrl, country, { inlineError: MSG_BILLING_COUNTRY_MISMATCH_REDIRECT });
1689
+ } else {
1690
+ failApplePaySession(session, err.errors);
1691
+ }
1666
1692
  return;
1667
1693
  }
1668
1694
  const walletError = parseWalletApiError(err);
@@ -1944,7 +1970,7 @@ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint3) => {
1944
1970
  ApplePayEntryPoint3["DUAL_OFFER_BANNER"] = "dual_offer_banner";
1945
1971
  return ApplePayEntryPoint3;
1946
1972
  })(ApplePayEntryPoint || {});
1947
- var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
1973
+ var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-checkout-on-banners";
1948
1974
  var APPLE_PAY_EXPRESS_VARIANTS = {
1949
1975
  CONTROL: "control",
1950
1976
  TREATMENT: "treatment"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@economist/web-apple-pay",
3
3
  "description": "Web component package for Apple Pay checkout UI",
4
- "version": "1.9.0",
4
+ "version": "1.9.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",