@economist/web-apple-pay 1.1.0 → 1.3.0
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 +27 -2
- package/dist/index.js +76 -0
- package/dist/src/apple-pay-button.js +76 -0
- package/dist/src/apple-pay-button.stories.js +1276 -0
- package/dist/src/apple-pay-modal.stories.js +1118 -0
- package/dist/src/clients/payment-checkout/config.d.ts +1 -0
- package/dist/src/clients/payment-checkout/detects.js +3 -0
- package/dist/src/clients/payment-checkout/index.d.ts +1 -0
- package/dist/src/clients/payment-checkout/index.js +59 -0
- package/dist/src/clients/payment-checkout/session.d.ts +2 -0
- package/dist/src/clients/payment-checkout/session.js +67 -0
- package/dist/src/clients/payment-checkout/types.d.ts +14 -0
- package/dist/src/clients/payment-checkout/types.js +14 -0
- package/dist/src/index.js +76 -0
- package/dist/src/stories/fixtures/offer.d.ts +2 -0
- package/dist/src/stories/fixtures/offer.js +28 -0
- package/dist/src/stories/utils/story-env.d.ts +11 -0
- package/dist/src/stories/utils/story-env.js +141 -0
- package/dist/src/types/offer.types.d.ts +0 -10
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -32,6 +32,8 @@ import { configureApplePay, defineApplePayElements } from '@economist/web-apple-
|
|
|
32
32
|
configureApplePay({
|
|
33
33
|
merchantId: 'merchant.com.economist.your-app',
|
|
34
34
|
debugBypassEnabled: false,
|
|
35
|
+
// required: wallet API base URL for session and checkout calls
|
|
36
|
+
walletApiBaseUrl: 'https://bff-test.economist.com',
|
|
35
37
|
});
|
|
36
38
|
|
|
37
39
|
defineApplePayElements();
|
|
@@ -57,11 +59,13 @@ When clicked, the button creates and opens `teg-apple-pay-modal` automatically.
|
|
|
57
59
|
### `configureApplePay(config)`
|
|
58
60
|
|
|
59
61
|
Sets package-level runtime configuration used by Apple Pay availability checks.
|
|
62
|
+
Call this once during app startup.
|
|
60
63
|
|
|
61
64
|
`config` shape:
|
|
62
65
|
|
|
63
66
|
- `merchantId` (`string`, required): Apple Pay merchant identifier used for active-card checks.
|
|
64
67
|
- `debugBypassEnabled` (`boolean`, optional): allows `?BYPASS_APPLE_PAY_CHECKS=1` query param to bypass capability checks in non-production-style debugging flows.
|
|
68
|
+
- `walletApiBaseUrl` (`string`, required): base URL for wallet API requests.
|
|
65
69
|
|
|
66
70
|
If `merchantId` is not configured, Apple Pay availability checks return `false` and the button hides itself.
|
|
67
71
|
|
|
@@ -94,7 +98,7 @@ Consumers should listen for this event and continue payment orchestration.
|
|
|
94
98
|
## Public API
|
|
95
99
|
|
|
96
100
|
- `defineApplePayElements()`: registers both custom elements.
|
|
97
|
-
- `configureApplePay(config)`: sets required runtime config (merchant ID and optional debug bypass).
|
|
101
|
+
- `configureApplePay(config)`: sets required runtime config (merchant ID and wallet API base URL, with optional debug bypass).
|
|
98
102
|
- `ApplePayButton`: button component class.
|
|
99
103
|
- `ApplePayModal`: modal component class.
|
|
100
104
|
- `ensureApplePayLogoSymbol()`: logo symbol injection helper.
|
|
@@ -106,7 +110,7 @@ Consumers should listen for this event and continue payment orchestration.
|
|
|
106
110
|
|
|
107
111
|
Check:
|
|
108
112
|
|
|
109
|
-
- `configureApplePay(...)` was called before rendering (with a valid `merchantId`)
|
|
113
|
+
- `configureApplePay(...)` was called before rendering (with a valid `merchantId` and `walletApiBaseUrl`)
|
|
110
114
|
- device/browser supports Apple Pay checks (Safari/Apple device logic)
|
|
111
115
|
- query string/feature flag gating for your page is satisfied
|
|
112
116
|
- offer variant is not excluded (`bundle`, `insider_print`)
|
|
@@ -138,3 +142,24 @@ Then in a consuming app:
|
|
|
138
142
|
```sh
|
|
139
143
|
yalc add @economist/web-apple-pay
|
|
140
144
|
```
|
|
145
|
+
|
|
146
|
+
## Storybook
|
|
147
|
+
|
|
148
|
+
Run Storybook locally:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
npm run storybook --workspace @economist/web-apple-pay
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Build static Storybook output:
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
npm run build-storybook --workspace @economist/web-apple-pay
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Story coverage matrix:
|
|
161
|
+
|
|
162
|
+
- `ApplePayButton` docs page shows the stable default example.
|
|
163
|
+
- `ApplePayButton` behavior and state variants are available as individual canvas stories in Storybook.
|
|
164
|
+
- `ApplePayModal` docs page shows the stable default example.
|
|
165
|
+
- `ApplePayModal` behavior and state variants are available as individual canvas stories in Storybook.
|
package/dist/index.js
CHANGED
|
@@ -775,6 +775,9 @@ var isApplePayAvailable = async () => {
|
|
|
775
775
|
}
|
|
776
776
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
777
777
|
if (!merchantId) {
|
|
778
|
+
console.warn(
|
|
779
|
+
"[web-apple-pay] Missing merchantId. Call configureApplePay({ merchantId, ... }) before rendering Apple Pay components."
|
|
780
|
+
);
|
|
778
781
|
return false;
|
|
779
782
|
}
|
|
780
783
|
return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
@@ -784,6 +787,67 @@ var isApplePayAvailable = async () => {
|
|
|
784
787
|
}
|
|
785
788
|
};
|
|
786
789
|
|
|
790
|
+
// src/clients/payment-checkout/types.ts
|
|
791
|
+
var ApiError = class extends Error {
|
|
792
|
+
status;
|
|
793
|
+
body;
|
|
794
|
+
constructor(status, body) {
|
|
795
|
+
super(`API request failed with status ${status}`);
|
|
796
|
+
this.name = "ApiError";
|
|
797
|
+
this.status = status;
|
|
798
|
+
this.body = body;
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
// src/clients/payment-checkout/index.ts
|
|
803
|
+
var getWalletApiBaseUrl = () => {
|
|
804
|
+
const config = getApplePayConfig();
|
|
805
|
+
if (!config?.walletApiBaseUrl) {
|
|
806
|
+
throw new Error(
|
|
807
|
+
"[web-apple-pay] Missing walletApiBaseUrl. Call configureApplePay({ merchantId, walletApiBaseUrl, ... }) before making wallet API requests."
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
return config.walletApiBaseUrl;
|
|
811
|
+
};
|
|
812
|
+
var apiFetch = async (path, options = {}) => {
|
|
813
|
+
const baseUrl = getWalletApiBaseUrl();
|
|
814
|
+
const method = (options.method ?? "GET").toUpperCase();
|
|
815
|
+
const hasBody = options.body !== void 0 && options.body !== null;
|
|
816
|
+
const headers = new Headers(options.headers);
|
|
817
|
+
if (!headers.has("Accept")) {
|
|
818
|
+
headers.set("Accept", "application/json");
|
|
819
|
+
}
|
|
820
|
+
if (!headers.has("Content-Type")) {
|
|
821
|
+
if (hasBody || method !== "GET" && method !== "HEAD") {
|
|
822
|
+
headers.set("Content-Type", "application/json");
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
826
|
+
...options,
|
|
827
|
+
headers
|
|
828
|
+
});
|
|
829
|
+
if (!response.ok) {
|
|
830
|
+
const contentType = response.headers.get("content-type") || "";
|
|
831
|
+
if (contentType.includes("application/json")) {
|
|
832
|
+
const errorBody = await response.json();
|
|
833
|
+
throw new ApiError(response.status, errorBody);
|
|
834
|
+
}
|
|
835
|
+
const errorText = await response.text();
|
|
836
|
+
throw new Error(
|
|
837
|
+
`API request failed: ${response.status} ${response.statusText} - ${errorText}`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
return response.json();
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
// src/clients/payment-checkout/session.ts
|
|
844
|
+
var getExpressCheckoutSession = () => {
|
|
845
|
+
return apiFetch("/v1/wallet/session", {
|
|
846
|
+
method: "GET",
|
|
847
|
+
credentials: "include"
|
|
848
|
+
});
|
|
849
|
+
};
|
|
850
|
+
|
|
787
851
|
// src/apple-pay-button.ts
|
|
788
852
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
789
853
|
var APPLE_PAY_EXCLUDED_VARIANTS = ["bundle", "insider_print"];
|
|
@@ -841,6 +905,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
841
905
|
this.style.display = "none";
|
|
842
906
|
return;
|
|
843
907
|
}
|
|
908
|
+
const sessionData = await this.#fetchSession();
|
|
909
|
+
if (sessionData?.loggedIn && (sessionData.userType === "active-subscription" || sessionData.userType === "b2b-user")) {
|
|
910
|
+
this.style.display = "none";
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
844
913
|
this.style.removeProperty("display");
|
|
845
914
|
ensureApplePayLogoSymbol();
|
|
846
915
|
const template = document.createElement("template");
|
|
@@ -883,6 +952,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
883
952
|
button.setAttribute("disabled", "");
|
|
884
953
|
button.setAttribute("aria-disabled", "true");
|
|
885
954
|
}
|
|
955
|
+
async #fetchSession() {
|
|
956
|
+
try {
|
|
957
|
+
return await getExpressCheckoutSession();
|
|
958
|
+
} catch {
|
|
959
|
+
return null;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
886
962
|
};
|
|
887
963
|
|
|
888
964
|
// src/index.ts
|
|
@@ -770,6 +770,9 @@ var isApplePayAvailable = async () => {
|
|
|
770
770
|
}
|
|
771
771
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
772
772
|
if (!merchantId) {
|
|
773
|
+
console.warn(
|
|
774
|
+
"[web-apple-pay] Missing merchantId. Call configureApplePay({ merchantId, ... }) before rendering Apple Pay components."
|
|
775
|
+
);
|
|
773
776
|
return false;
|
|
774
777
|
}
|
|
775
778
|
return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
@@ -779,6 +782,67 @@ var isApplePayAvailable = async () => {
|
|
|
779
782
|
}
|
|
780
783
|
};
|
|
781
784
|
|
|
785
|
+
// src/clients/payment-checkout/types.ts
|
|
786
|
+
var ApiError = class extends Error {
|
|
787
|
+
status;
|
|
788
|
+
body;
|
|
789
|
+
constructor(status, body) {
|
|
790
|
+
super(`API request failed with status ${status}`);
|
|
791
|
+
this.name = "ApiError";
|
|
792
|
+
this.status = status;
|
|
793
|
+
this.body = body;
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
// src/clients/payment-checkout/index.ts
|
|
798
|
+
var getWalletApiBaseUrl = () => {
|
|
799
|
+
const config = getApplePayConfig();
|
|
800
|
+
if (!config?.walletApiBaseUrl) {
|
|
801
|
+
throw new Error(
|
|
802
|
+
"[web-apple-pay] Missing walletApiBaseUrl. Call configureApplePay({ merchantId, walletApiBaseUrl, ... }) before making wallet API requests."
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
return config.walletApiBaseUrl;
|
|
806
|
+
};
|
|
807
|
+
var apiFetch = async (path, options = {}) => {
|
|
808
|
+
const baseUrl = getWalletApiBaseUrl();
|
|
809
|
+
const method = (options.method ?? "GET").toUpperCase();
|
|
810
|
+
const hasBody = options.body !== void 0 && options.body !== null;
|
|
811
|
+
const headers = new Headers(options.headers);
|
|
812
|
+
if (!headers.has("Accept")) {
|
|
813
|
+
headers.set("Accept", "application/json");
|
|
814
|
+
}
|
|
815
|
+
if (!headers.has("Content-Type")) {
|
|
816
|
+
if (hasBody || method !== "GET" && method !== "HEAD") {
|
|
817
|
+
headers.set("Content-Type", "application/json");
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
821
|
+
...options,
|
|
822
|
+
headers
|
|
823
|
+
});
|
|
824
|
+
if (!response.ok) {
|
|
825
|
+
const contentType = response.headers.get("content-type") || "";
|
|
826
|
+
if (contentType.includes("application/json")) {
|
|
827
|
+
const errorBody = await response.json();
|
|
828
|
+
throw new ApiError(response.status, errorBody);
|
|
829
|
+
}
|
|
830
|
+
const errorText = await response.text();
|
|
831
|
+
throw new Error(
|
|
832
|
+
`API request failed: ${response.status} ${response.statusText} - ${errorText}`
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
return response.json();
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
// src/clients/payment-checkout/session.ts
|
|
839
|
+
var getExpressCheckoutSession = () => {
|
|
840
|
+
return apiFetch("/v1/wallet/session", {
|
|
841
|
+
method: "GET",
|
|
842
|
+
credentials: "include"
|
|
843
|
+
});
|
|
844
|
+
};
|
|
845
|
+
|
|
782
846
|
// src/apple-pay-button.ts
|
|
783
847
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
784
848
|
var APPLE_PAY_EXCLUDED_VARIANTS = ["bundle", "insider_print"];
|
|
@@ -836,6 +900,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
836
900
|
this.style.display = "none";
|
|
837
901
|
return;
|
|
838
902
|
}
|
|
903
|
+
const sessionData = await this.#fetchSession();
|
|
904
|
+
if (sessionData?.loggedIn && (sessionData.userType === "active-subscription" || sessionData.userType === "b2b-user")) {
|
|
905
|
+
this.style.display = "none";
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
839
908
|
this.style.removeProperty("display");
|
|
840
909
|
ensureApplePayLogoSymbol();
|
|
841
910
|
const template = document.createElement("template");
|
|
@@ -878,6 +947,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
878
947
|
button.setAttribute("disabled", "");
|
|
879
948
|
button.setAttribute("aria-disabled", "true");
|
|
880
949
|
}
|
|
950
|
+
async #fetchSession() {
|
|
951
|
+
try {
|
|
952
|
+
return await getExpressCheckoutSession();
|
|
953
|
+
} catch {
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
881
957
|
};
|
|
882
958
|
export {
|
|
883
959
|
ApplePayButton
|