@economist/web-apple-pay 0.1.3-beta.5 → 0.1.3-beta.50
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 +956 -210
- package/dist/src/apple-pay-button.d.ts +21 -4
- package/dist/src/apple-pay-button.js +944 -205
- package/dist/src/apple-pay-button.stories.js +970 -213
- package/dist/src/apple-pay-logo.js +1 -1
- package/dist/src/apple-pay-modal.d.ts +9 -0
- package/dist/src/apple-pay-modal.js +586 -25
- package/dist/src/apple-pay-modal.stories.js +944 -205
- package/dist/src/clients/payment-checkout/apple-session.d.ts +1 -0
- package/dist/src/clients/payment-checkout/apple-session.js +86 -55
- package/dist/src/clients/payment-checkout/detects.js +4 -7
- package/dist/src/clients/payment-checkout/index.js +0 -1
- package/dist/src/clients/payment-checkout/messages.d.ts +27 -14
- package/dist/src/clients/payment-checkout/messages.js +14 -5
- package/dist/src/clients/payment-checkout/payment-handler.d.ts +1 -13
- package/dist/src/clients/payment-checkout/payment-handler.js +71 -33
- package/dist/src/clients/payment-checkout/types.d.ts +8 -10
- package/dist/src/constants.d.ts +25 -0
- package/dist/src/constants.js +17 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +956 -210
- package/dist/src/stories/utils/story-env.js +18 -0
- package/dist/src/types/experiment-integration.d.js +0 -0
- package/dist/src/utils/expressCheckoutRedirect.d.ts +33 -7
- package/dist/src/utils/expressCheckoutRedirect.js +24 -8
- package/dist/src/utils/recaptcha.d.ts +6 -6
- package/dist/src/utils/recaptcha.js +9 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -71,12 +71,543 @@ function ensureApplePayLogoSymbol() {
|
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
const tmp = document.createElement("div");
|
|
74
|
-
tmp.innerHTML = `<svg aria-hidden="true" style="display:none" id="${LOGO_DEFS_ID}"><defs><symbol id="apple-pay-logo" viewBox="0 0 51 22"><path d="${LOGO_PATH}" fill="
|
|
74
|
+
tmp.innerHTML = `<svg aria-hidden="true" style="display:none" id="${LOGO_DEFS_ID}"><defs><symbol id="apple-pay-logo" viewBox="0 0 51 22"><path d="${LOGO_PATH}" fill="currentColor"/></symbol></defs></svg>`;
|
|
75
75
|
document.body.prepend(tmp.firstElementChild);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// src/templates/apple-pay-modal.template.html
|
|
79
|
-
var apple_pay_modal_template_default = '<style>\n .apm-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 97;\n background: rgba(13, 13, 13, 0.7);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--wall-gutter, 2rem);\n box-sizing: border-box;\n }\n\n .apm {\n position: relative;\n background: #fff;\n border-radius: 0.5rem 0.5rem 0 0;\n border: 0.0625rem solid #d9d9d9;\n padding: var(--mb-spacing-lg, 1.5rem);\n width: 25rem;\n max-width: 25rem;\n box-sizing: border-box;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n box-shadow: 0 0.25rem 1rem 0 rgba(13, 13, 13, 0.15);\n }\n\n .apm__close {\n position: absolute;\n top: 1.5rem;\n right: 1.3125rem;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .apm__close:focus {\n outline: solid 0.125rem var(--focus-border-color, #121212);\n border-radius: 0.25rem;\n }\n\n .apm__offer-name {\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-title-3-size, 1.25rem);\n font-weight: 500;\n color: var(--mb-colour-greyscale-london-5, #0d0d0d);\n line-height: var(--mb-typestyle-title-3-leading, 1.75rem);\n font-style: normal;\n margin: 0 1.5rem 0.5rem 0;\n }\n\n .apm__due-today {\n color: #1a1a1a;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n font-style: normal;\n font-weight: 400;\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n margin: 0 0 0.75rem 0;\n }\n\n .apm__rule {\n border: none;\n border-top: 0.0625rem solid #d9d9d9;\n margin: 0 0 1rem 0;\n }\n\n .apm__terms {\n color: #1a1a1a;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n font-style: normal;\n font-weight: 400;\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n margin: 0 0 1rem 0;\n }\n\n .apm__terms-bullets {\n list-style: disc outside;\n padding-left: 1.25rem;\n margin: 0 0 0.75rem 0;\n }\n\n .apm__terms-bullets li {\n margin-bottom: 0.375rem;\n }\n\n .apm__terms-legal {\n margin: 0;\n }\n\n .apm__passive-terms {\n font-family: var(--wall-type-system-sans);\n font-size: 0.9375rem;\n color: #0d0d0d;\n line-height: 1.4;\n margin: 0 0 8px 0;\n }\n\n .apm__passive-terms a {\n color: #1a1a1a;\n font-weight: 700;\n text-decoration: underline;\n }\n\n .apm__checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: var(--mb-spacing-sm, 0.5rem);\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n color: var(--mb-colour-greyscale-london-20, #1a1a1a);\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n cursor: pointer;\n margin: 0 0 1.5rem 0;\n }\n\n .apm__checkbox-label--error {\n margin-bottom: 0.25rem;\n }\n\n .apm__checkbox-wrapper {\n position: relative;\n flex-shrink: 0;\n width: 1.25rem;\n height: 1.25rem;\n margin-top: 0.0625rem;\n }\n\n .apm__checkbox-input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n z-index: 1;\n }\n\n .apm__checkbox-custom {\n position: absolute;\n top: 0;\n left: 0;\n width: 1.25rem;\n height: 1.25rem;\n pointer-events: none;\n }\n\n .apm__checkbox-custom svg {\n display: none;\n width: 1.25rem;\n height: 1.25rem;\n }\n\n .apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {\n display: block;\n }\n\n .apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {\n display: block;\n }\n\n .apm__checkbox-label--error\n .apm__checkbox-input:not(:checked)\n ~ .apm__checkbox-custom\n .svg-unchecked {\n display: none;\n }\n\n .apm__checkbox-label--error\n .apm__checkbox-input:not(:checked)\n ~ .apm__checkbox-custom\n .svg-error {\n display: block;\n }\n\n .apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {\n outline: solid 0.125rem #c91d42;\n outline-offset: 0.125rem;\n border-radius: 0.25rem;\n }\n\n .apm__checkbox-label a {\n color: #1a1a1a;\n font-weight: 700;\n text-decoration: underline;\n }\n\n .apm__error {\n display: none;\n align-items: center;\n gap: 0.75rem;\n color: var(--mb-colour-greyscale-london-5, #0d0d0d);\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-style: normal;\n font-weight: 500;\n line-height: 1.5rem;\n margin-bottom: 1rem;\n }\n\n .apm__error--visible {\n display: flex;\n }\n\n .apm__cta {\n display: flex;\n width: 100%;\n height: 2.75rem;\n padding: 0.375rem 1rem;\n justify-content: center;\n align-items: center;\n gap: 0.375rem;\n border-radius: 0.25rem;\n background: #000;\n border: none;\n cursor: pointer;\n color: #fff;\n text-align: center;\n font-family: var(\n --mb-typeface-sans,\n var(--wall-type-system-sans, system-ui, sans-serif)\n );\n font-size: 1.25rem;\n font-style: normal;\n font-weight: 500;\n line-height: normal;\n }\n\n .apm__cta svg {\n flex-shrink: 0;\n display: block;\n }\n\n @media (min-width: 22.5rem) and (max-width: 37.5rem) {\n .apm {\n width: 24.375rem;\n max-width: 24.375rem;\n }\n }\n\n @media (min-width: 37.5625rem) {\n .apm {\n border-radius: 0.5rem;\n }\n }\n\n @media (max-width: 22.4375rem) {\n .apm {\n width: 20rem;\n max-width: 20rem;\n }\n }\n\n @media (max-width: 26.1875rem) {\n .apm__cta {\n font-size: 1.125rem;\n }\n }\n</style>\n\n<div class="apm-overlay" id="apple-pay-modal-overlay">\n <div\n class="apm"\n role="dialog"\n aria-modal="true"\n aria-labelledby="apple-pay-modal-offer-name"\n id="apple-pay-modal"\n tabindex="-1"\n >\n <button class="apm__close" id="apple-pay-modal-close" aria-label="Close">\n <svg\n aria-hidden="true"\n xmlns="http://www.w3.org/2000/svg"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n >\n <g clip-path="url(#clip0_15712_93054)">\n <rect width="24" height="24" fill="white" fill-opacity="0.01" />\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M0 0H24V24H0V0Z"\n fill="white"\n fill-opacity="0.01"\n />\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M18.75 6.60964L17.3904 5.25L12 10.6404L6.60964 5.25L5.25 6.60964L10.6404 12L5.25 17.3904L6.60964 18.75L12 13.3596L17.3904 18.75L18.75 17.3904L13.3596 12L18.75 6.60964Z"\n fill="#333333"\n />\n </g>\n <defs>\n <clipPath id="clip0_15712_93054">\n <rect width="24" height="24" fill="white" />\n </clipPath>\n </defs>\n </svg>\n </button>\n <p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>\n <p class="apm__due-today" id="apple-pay-modal-due-today"></p>\n <hr class="apm__rule" />\n <div class="apm__terms" id="apple-pay-modal-terms"></div>\n <p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>\n <label\n class="apm__checkbox-label"\n id="apple-pay-modal-checkbox-label"\n for="apple-pay-modal-checkbox"\n >\n <div class="apm__checkbox-wrapper">\n <input\n class="apm__checkbox-input"\n type="checkbox"\n id="apple-pay-modal-checkbox"\n />\n <span class="apm__checkbox-custom">\n <svg\n aria-hidden="true"\n class="svg-unchecked"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"\n fill="white"\n stroke="#595959"\n />\n </svg>\n <svg\n aria-hidden="true"\n class="svg-checked"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <g clip-path="url(#clip0_20014_9555)">\n <path\n d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"\n fill="#333333"\n />\n <path\n d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"\n fill="white"\n />\n </g>\n <defs>\n <clipPath id="clip0_20014_9555">\n <path\n d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"\n fill="white"\n />\n </clipPath>\n </defs>\n </svg>\n <svg\n aria-hidden="true"\n class="svg-error"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"\n fill="white"\n stroke="#C91D42"\n stroke-width="2"\n />\n </svg>\n </span>\n </div>\n <span id="apple-pay-modal-checkbox-text"></span>\n </label>\n <div class="apm__error" id="apple-pay-modal-error" role="alert">\n <svg\n aria-hidden="true"\n width="20"\n height="20"\n viewBox="0 0 20 20"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2ZM0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM11 13C11 13.5523 10.5523 14 10 14C9.44772 14 9 13.5523 9 13C9 12.4477 9.44772 12 10 12C10.5523 12 11 12.4477 11 13ZM10 6C10.5523 6 11 6.44772 11 7V10C11 10.5523 10.5523 11 10 11C9.44772 11 9 10.5523 9 10V7C9 6.44772 9.44772 6 10 6Z"\n fill="#C91D42"\n />\n </svg>\n Please accept the terms to continue\n </div>\n <button class="apm__cta" id="apple-pay-modal-cta">\n Continue with\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n </div>\n</div>\n\n';
|
|
79
|
+
var apple_pay_modal_template_default = `<style>
|
|
80
|
+
.apm-overlay {
|
|
81
|
+
position: fixed;
|
|
82
|
+
top: 0;
|
|
83
|
+
left: 0;
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
z-index: 97;
|
|
87
|
+
background: rgba(13, 13, 13, 0.7);
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
justify-content: center;
|
|
91
|
+
padding: var(--wall-gutter, 2rem);
|
|
92
|
+
box-sizing: border-box;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.apm {
|
|
96
|
+
position: relative;
|
|
97
|
+
background: #fff;
|
|
98
|
+
border-radius: 0.5rem 0.5rem 0 0;
|
|
99
|
+
border: 0.0625rem solid #d9d9d9;
|
|
100
|
+
padding: var(--mb-spacing-lg, 1.5rem);
|
|
101
|
+
width: 25rem;
|
|
102
|
+
max-width: 25rem;
|
|
103
|
+
box-sizing: border-box;
|
|
104
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
105
|
+
box-shadow: 0 0.25rem 1rem 0 rgba(13, 13, 13, 0.15);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.apm__close {
|
|
109
|
+
position: absolute;
|
|
110
|
+
top: 1.5rem;
|
|
111
|
+
right: 1.3125rem;
|
|
112
|
+
background: transparent;
|
|
113
|
+
border: none;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
padding: 0;
|
|
116
|
+
width: 1.5rem;
|
|
117
|
+
height: 1.5rem;
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
justify-content: center;
|
|
121
|
+
color: var(--mb-colour-greyscale-london-20, #1a1a1a);
|
|
122
|
+
transition:
|
|
123
|
+
background-color ease-in-out 0.2s,
|
|
124
|
+
color ease-in-out 0.2s;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.apm__close:hover {
|
|
128
|
+
color: var(--mb-colour-base-chicago-30, #333333);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.apm__close:active {
|
|
132
|
+
background-color: var(--mb-colour-base-chicago-90, #e6e6e6);
|
|
133
|
+
color: var(--mb-colour-base-chicago-30, #333333);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.apm__close:focus {
|
|
137
|
+
background-color: var(--mb-colour-base-chicago-90, #e6e6e6);
|
|
138
|
+
outline: solid 0.125rem var(--focus-border-color, #121212);
|
|
139
|
+
border-radius: 0.25rem;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.apm__offer-name {
|
|
143
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
144
|
+
font-size: var(--mb-typestyle-title-3-size, 1.25rem);
|
|
145
|
+
font-weight: 500;
|
|
146
|
+
color: var(--mb-colour-greyscale-london-5, #0d0d0d);
|
|
147
|
+
line-height: var(--mb-typestyle-title-3-leading, 1.75rem);
|
|
148
|
+
font-style: normal;
|
|
149
|
+
margin: 0 1.5rem 0.5rem 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.apm__due-today {
|
|
153
|
+
color: #1a1a1a;
|
|
154
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
155
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
156
|
+
font-style: normal;
|
|
157
|
+
font-weight: 400;
|
|
158
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
159
|
+
margin: 0 0 0.75rem 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.apm__rule {
|
|
163
|
+
border: none;
|
|
164
|
+
border-top: 0.0625rem solid #d9d9d9;
|
|
165
|
+
margin: 0 0 1rem 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.apm__terms {
|
|
169
|
+
color: #1a1a1a;
|
|
170
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
171
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
172
|
+
font-style: normal;
|
|
173
|
+
font-weight: 400;
|
|
174
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
175
|
+
margin: 0 0 1rem 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.apm__terms-bullets {
|
|
179
|
+
list-style: disc outside;
|
|
180
|
+
padding-left: 1.25rem;
|
|
181
|
+
margin: 0 0 0.75rem 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.apm__terms-bullets li {
|
|
185
|
+
margin-bottom: 0.375rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.apm__terms-legal {
|
|
189
|
+
margin: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.apm__passive-terms {
|
|
193
|
+
font-family: var(--wall-type-system-sans);
|
|
194
|
+
font-size: 0.9375rem;
|
|
195
|
+
color: #0d0d0d;
|
|
196
|
+
line-height: 1.4;
|
|
197
|
+
margin: 0 0 8px 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.apm__passive-terms a {
|
|
201
|
+
color: #1a1a1a;
|
|
202
|
+
font-weight: 700;
|
|
203
|
+
text-decoration: underline;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.apm__checkbox-label {
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: flex-start;
|
|
209
|
+
gap: var(--mb-spacing-sm, 0.5rem);
|
|
210
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
211
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
212
|
+
color: var(--mb-colour-greyscale-london-20, #1a1a1a);
|
|
213
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
margin: 0 0 1.5rem 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.apm__checkbox-label--error {
|
|
219
|
+
margin-bottom: 0.25rem;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.apm__checkbox-wrapper {
|
|
223
|
+
position: relative;
|
|
224
|
+
flex-shrink: 0;
|
|
225
|
+
width: 1.25rem;
|
|
226
|
+
height: 1.25rem;
|
|
227
|
+
margin-top: 0.0625rem;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.apm__checkbox-input {
|
|
231
|
+
position: absolute;
|
|
232
|
+
opacity: 0;
|
|
233
|
+
width: 100%;
|
|
234
|
+
height: 100%;
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
margin: 0;
|
|
237
|
+
z-index: 1;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.apm__checkbox-custom {
|
|
241
|
+
position: absolute;
|
|
242
|
+
top: 0;
|
|
243
|
+
left: 0;
|
|
244
|
+
width: 1.25rem;
|
|
245
|
+
height: 1.25rem;
|
|
246
|
+
pointer-events: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.apm__checkbox-custom svg {
|
|
250
|
+
display: none;
|
|
251
|
+
width: 1.25rem;
|
|
252
|
+
height: 1.25rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {
|
|
256
|
+
display: block;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {
|
|
260
|
+
display: block;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.apm__checkbox-label--error
|
|
264
|
+
.apm__checkbox-input:not(:checked)
|
|
265
|
+
~ .apm__checkbox-custom
|
|
266
|
+
.svg-unchecked {
|
|
267
|
+
display: none;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.apm__checkbox-label--error
|
|
271
|
+
.apm__checkbox-input:not(:checked)
|
|
272
|
+
~ .apm__checkbox-custom
|
|
273
|
+
.svg-error {
|
|
274
|
+
display: block;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {
|
|
278
|
+
outline: solid 0.125rem #c91d42;
|
|
279
|
+
outline-offset: 0.125rem;
|
|
280
|
+
border-radius: 0.25rem;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.apm__checkbox-label a {
|
|
284
|
+
color: #1a1a1a;
|
|
285
|
+
font-weight: 700;
|
|
286
|
+
text-decoration: underline;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.apm__error {
|
|
290
|
+
display: none;
|
|
291
|
+
align-items: center;
|
|
292
|
+
gap: 0.75rem;
|
|
293
|
+
color: var(--mb-colour-greyscale-london-5, #0d0d0d);
|
|
294
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
295
|
+
font-size: 1.0625rem;
|
|
296
|
+
font-style: normal;
|
|
297
|
+
font-weight: 500;
|
|
298
|
+
line-height: 1.5rem;
|
|
299
|
+
margin-bottom: 1rem;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.apm__error--visible {
|
|
303
|
+
display: flex;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.apm__cta {
|
|
307
|
+
display: flex;
|
|
308
|
+
width: 100%;
|
|
309
|
+
height: 2.75rem;
|
|
310
|
+
padding: 0.375rem 1rem;
|
|
311
|
+
justify-content: center;
|
|
312
|
+
align-items: center;
|
|
313
|
+
gap: 0.375rem;
|
|
314
|
+
border-radius: 0.25rem;
|
|
315
|
+
background: #000;
|
|
316
|
+
border: none;
|
|
317
|
+
cursor: pointer;
|
|
318
|
+
color: #fff;
|
|
319
|
+
text-align: center;
|
|
320
|
+
font-size: 1.25rem;
|
|
321
|
+
font-style: normal;
|
|
322
|
+
font-weight: 500;
|
|
323
|
+
line-height: normal;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.apm__cta:disabled {
|
|
327
|
+
cursor: not-allowed;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.apm__cta[aria-busy="true"] {
|
|
331
|
+
position: relative;
|
|
332
|
+
cursor: not-allowed;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.apm__cta-content {
|
|
336
|
+
display: flex;
|
|
337
|
+
align-items: center;
|
|
338
|
+
gap: 0.375rem;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.apm__cta-label {
|
|
342
|
+
display: inline-flex;
|
|
343
|
+
align-items: center;
|
|
344
|
+
gap: 0.375rem;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.apm__cta-loading {
|
|
348
|
+
display: none;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.apm__cta[aria-busy="true"]::before {
|
|
352
|
+
content: '';
|
|
353
|
+
position: absolute;
|
|
354
|
+
top: 50%;
|
|
355
|
+
left: 50%;
|
|
356
|
+
width: 1.25rem;
|
|
357
|
+
height: 1.25rem;
|
|
358
|
+
border: 2px solid rgba(255, 255, 255, 0.25);
|
|
359
|
+
border-top-color: #fff;
|
|
360
|
+
border-radius: 50%;
|
|
361
|
+
animation: apm-cta-spinner 0.8s linear infinite;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
@keyframes apm-cta-spinner {
|
|
365
|
+
from {
|
|
366
|
+
transform: translate(-50%, -50%) rotate(0deg);
|
|
367
|
+
}
|
|
368
|
+
to {
|
|
369
|
+
transform: translate(-50%, -50%) rotate(360deg);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.apm__cta svg {
|
|
374
|
+
flex-shrink: 0;
|
|
375
|
+
display: block;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
@media (min-width: 22.5rem) and (max-width: 37.5rem) {
|
|
379
|
+
.apm {
|
|
380
|
+
width: 24.375rem;
|
|
381
|
+
max-width: 24.375rem;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@media (min-width: 37.5625rem) {
|
|
386
|
+
.apm {
|
|
387
|
+
border-radius: 0.5rem;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
@media (max-width: 22.4375rem) {
|
|
392
|
+
.apm {
|
|
393
|
+
width: 20rem;
|
|
394
|
+
max-width: 20rem;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
@media (max-width: 26.1875rem) {
|
|
399
|
+
.apm__cta {
|
|
400
|
+
font-size: 1.125rem;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
</style>
|
|
404
|
+
|
|
405
|
+
<div class="apm-overlay" id="apple-pay-modal-overlay">
|
|
406
|
+
<div
|
|
407
|
+
class="apm"
|
|
408
|
+
role="dialog"
|
|
409
|
+
aria-modal="true"
|
|
410
|
+
aria-labelledby="apple-pay-modal-offer-name"
|
|
411
|
+
id="apple-pay-modal"
|
|
412
|
+
tabindex="-1"
|
|
413
|
+
>
|
|
414
|
+
<button class="apm__close" id="apple-pay-modal-close" aria-label="Close">
|
|
415
|
+
<svg
|
|
416
|
+
aria-hidden="true"
|
|
417
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
418
|
+
width="24"
|
|
419
|
+
height="24"
|
|
420
|
+
viewBox="0 0 24 24"
|
|
421
|
+
fill="none"
|
|
422
|
+
>
|
|
423
|
+
<g clip-path="url(#clip0_15712_93054)">
|
|
424
|
+
<rect width="24" height="24" fill="white" fill-opacity="0.01" />
|
|
425
|
+
<path
|
|
426
|
+
fill-rule="evenodd"
|
|
427
|
+
clip-rule="evenodd"
|
|
428
|
+
d="M0 0H24V24H0V0Z"
|
|
429
|
+
fill="white"
|
|
430
|
+
fill-opacity="0.01"
|
|
431
|
+
/>
|
|
432
|
+
<path
|
|
433
|
+
fill-rule="evenodd"
|
|
434
|
+
clip-rule="evenodd"
|
|
435
|
+
d="M18.75 6.60964L17.3904 5.25L12 10.6404L6.60964 5.25L5.25 6.60964L10.6404 12L5.25 17.3904L6.60964 18.75L12 13.3596L17.3904 18.75L18.75 17.3904L13.3596 12L18.75 6.60964Z"
|
|
436
|
+
fill="currentColor"
|
|
437
|
+
/>
|
|
438
|
+
</g>
|
|
439
|
+
<defs>
|
|
440
|
+
<clipPath id="clip0_15712_93054">
|
|
441
|
+
<rect width="24" height="24" fill="white" />
|
|
442
|
+
</clipPath>
|
|
443
|
+
</defs>
|
|
444
|
+
</svg>
|
|
445
|
+
</button>
|
|
446
|
+
<p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>
|
|
447
|
+
<p class="apm__due-today" id="apple-pay-modal-due-today"></p>
|
|
448
|
+
<hr class="apm__rule" />
|
|
449
|
+
<div class="apm__terms" id="apple-pay-modal-terms"></div>
|
|
450
|
+
<p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>
|
|
451
|
+
<label
|
|
452
|
+
class="apm__checkbox-label"
|
|
453
|
+
id="apple-pay-modal-checkbox-label"
|
|
454
|
+
for="apple-pay-modal-checkbox"
|
|
455
|
+
>
|
|
456
|
+
<div class="apm__checkbox-wrapper">
|
|
457
|
+
<input
|
|
458
|
+
class="apm__checkbox-input"
|
|
459
|
+
type="checkbox"
|
|
460
|
+
id="apple-pay-modal-checkbox"
|
|
461
|
+
/>
|
|
462
|
+
<span class="apm__checkbox-custom">
|
|
463
|
+
<svg
|
|
464
|
+
aria-hidden="true"
|
|
465
|
+
class="svg-unchecked"
|
|
466
|
+
width="24"
|
|
467
|
+
height="24"
|
|
468
|
+
viewBox="0 0 24 24"
|
|
469
|
+
fill="none"
|
|
470
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
471
|
+
>
|
|
472
|
+
<path
|
|
473
|
+
d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"
|
|
474
|
+
fill="white"
|
|
475
|
+
stroke="#595959"
|
|
476
|
+
/>
|
|
477
|
+
</svg>
|
|
478
|
+
<svg
|
|
479
|
+
aria-hidden="true"
|
|
480
|
+
class="svg-checked"
|
|
481
|
+
width="24"
|
|
482
|
+
height="24"
|
|
483
|
+
viewBox="0 0 24 24"
|
|
484
|
+
fill="none"
|
|
485
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
486
|
+
>
|
|
487
|
+
<g clip-path="url(#clip0_20014_9555)">
|
|
488
|
+
<path
|
|
489
|
+
d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"
|
|
490
|
+
fill="#333333"
|
|
491
|
+
/>
|
|
492
|
+
<path
|
|
493
|
+
d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"
|
|
494
|
+
fill="white"
|
|
495
|
+
/>
|
|
496
|
+
</g>
|
|
497
|
+
<defs>
|
|
498
|
+
<clipPath id="clip0_20014_9555">
|
|
499
|
+
<path
|
|
500
|
+
d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"
|
|
501
|
+
fill="white"
|
|
502
|
+
/>
|
|
503
|
+
</clipPath>
|
|
504
|
+
</defs>
|
|
505
|
+
</svg>
|
|
506
|
+
<svg
|
|
507
|
+
aria-hidden="true"
|
|
508
|
+
class="svg-error"
|
|
509
|
+
width="24"
|
|
510
|
+
height="24"
|
|
511
|
+
viewBox="0 0 24 24"
|
|
512
|
+
fill="none"
|
|
513
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
514
|
+
>
|
|
515
|
+
<path
|
|
516
|
+
d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"
|
|
517
|
+
fill="white"
|
|
518
|
+
stroke="#C91D42"
|
|
519
|
+
stroke-width="2"
|
|
520
|
+
/>
|
|
521
|
+
</svg>
|
|
522
|
+
</span>
|
|
523
|
+
</div>
|
|
524
|
+
<span id="apple-pay-modal-checkbox-text"></span>
|
|
525
|
+
</label>
|
|
526
|
+
<div class="apm__error" id="apple-pay-modal-error" role="alert">
|
|
527
|
+
<svg
|
|
528
|
+
aria-hidden="true"
|
|
529
|
+
width="20"
|
|
530
|
+
height="20"
|
|
531
|
+
viewBox="0 0 20 20"
|
|
532
|
+
fill="none"
|
|
533
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
534
|
+
>
|
|
535
|
+
<path
|
|
536
|
+
fill-rule="evenodd"
|
|
537
|
+
clip-rule="evenodd"
|
|
538
|
+
d="M10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2ZM0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM11 13C11 13.5523 10.5523 14 10 14C9.44772 14 9 13.5523 9 13C9 12.4477 9.44772 12 10 12C10.5523 12 11 12.4477 11 13ZM10 6C10.5523 6 11 6.44772 11 7V10C11 10.5523 10.5523 11 10 11C9.44772 11 9 10.5523 9 10V7C9 6.44772 9.44772 6 10 6Z"
|
|
539
|
+
fill="#C91D42"
|
|
540
|
+
/>
|
|
541
|
+
</svg>
|
|
542
|
+
Please accept the terms to continue
|
|
543
|
+
</div>
|
|
544
|
+
<button class="apm__cta" id="apple-pay-modal-cta" aria-label="Continue with Apple Pay">
|
|
545
|
+
<span class="apm__cta-content">
|
|
546
|
+
<span class="apm__cta-label">
|
|
547
|
+
Continue with
|
|
548
|
+
<svg width="51" height="22" aria-hidden="true" role="img">
|
|
549
|
+
<use href="#apple-pay-logo" />
|
|
550
|
+
</svg>
|
|
551
|
+
</span>
|
|
552
|
+
</span>
|
|
553
|
+
<span class="apm__cta-loading" aria-hidden="true">Loading...</span>
|
|
554
|
+
</button>
|
|
555
|
+
</div>
|
|
556
|
+
</div>
|
|
557
|
+
|
|
558
|
+
`;
|
|
559
|
+
|
|
560
|
+
// src/clients/payment-checkout/config.ts
|
|
561
|
+
var runtimeConfig = null;
|
|
562
|
+
var configureApplePay = (config) => {
|
|
563
|
+
runtimeConfig = {
|
|
564
|
+
...config
|
|
565
|
+
};
|
|
566
|
+
};
|
|
567
|
+
var getApplePayConfig = () => runtimeConfig;
|
|
568
|
+
|
|
569
|
+
// src/utils/recaptcha.ts
|
|
570
|
+
var loadRecaptchaScript = (siteKey) => {
|
|
571
|
+
return new Promise((resolve, reject) => {
|
|
572
|
+
if (typeof grecaptcha !== "undefined") return resolve();
|
|
573
|
+
const existingScript = document.querySelector(
|
|
574
|
+
'script[src*="recaptcha/api.js"]'
|
|
575
|
+
);
|
|
576
|
+
if (existingScript) {
|
|
577
|
+
existingScript.addEventListener("load", () => resolve());
|
|
578
|
+
existingScript.addEventListener("error", () => {
|
|
579
|
+
reject(new Error("Failed to load existing reCAPTCHA script"));
|
|
580
|
+
});
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
const script = document.createElement("script");
|
|
584
|
+
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
585
|
+
script.async = true;
|
|
586
|
+
script.defer = true;
|
|
587
|
+
script.onload = () => resolve();
|
|
588
|
+
script.onerror = () => {
|
|
589
|
+
reject(new Error("Failed to load reCAPTCHA script"));
|
|
590
|
+
};
|
|
591
|
+
document.head.appendChild(script);
|
|
592
|
+
});
|
|
593
|
+
};
|
|
594
|
+
var getRecaptchaToken = async (action) => {
|
|
595
|
+
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
596
|
+
if (!siteKey) {
|
|
597
|
+
throw new Error(
|
|
598
|
+
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
await loadRecaptchaScript(siteKey);
|
|
602
|
+
return new Promise((resolve, reject) => {
|
|
603
|
+
grecaptcha.ready(() => {
|
|
604
|
+
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
};
|
|
608
|
+
var getPurchaseRecaptchaToken = () => {
|
|
609
|
+
return getRecaptchaToken("walletPurchase");
|
|
610
|
+
};
|
|
80
611
|
|
|
81
612
|
// src/apple-pay-modal.ts
|
|
82
613
|
function getRenewalDateText(unit, duration) {
|
|
@@ -128,6 +659,7 @@ function getOfferTypeText(offerType) {
|
|
|
128
659
|
}
|
|
129
660
|
var TERMS_LINK = '<a href="https://www.economistgroup.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms and Conditions</a>';
|
|
130
661
|
var PRIVACY_LINK = '<a href="https://www.economistgroup.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>';
|
|
662
|
+
var MSG_RECAPTCHA_LOAD_ERROR = "Something went wrong. Please close and try again.";
|
|
131
663
|
function getCheckboxTermsHtml(isNYT, isLoggedIn, autoRenewal) {
|
|
132
664
|
const autoRenewalClause = autoRenewal ? " and auto-renewal terms above," : "";
|
|
133
665
|
if (isNYT) {
|
|
@@ -160,6 +692,8 @@ function renewalPeriodText(unit, duration) {
|
|
|
160
692
|
return "";
|
|
161
693
|
}
|
|
162
694
|
}
|
|
695
|
+
var LI_SEPARATOR = "\0LI_SEP\0";
|
|
696
|
+
var P_SEPARATOR = "\0P_SEP\0";
|
|
163
697
|
function buildTermsContext(offer, country) {
|
|
164
698
|
const isUS = country === "US";
|
|
165
699
|
const isCA = country === "CA";
|
|
@@ -196,19 +730,19 @@ function freeTrialTerms(offer, ctx) {
|
|
|
196
730
|
const trialDuration = offer.subscription_options?.trial_period?.duration ?? 1;
|
|
197
731
|
const trialDateStr = `on ${getRenewalDateText(trialUnit, trialDuration)}${ctx.verificationText}`;
|
|
198
732
|
if (ctx.isUS) {
|
|
199
|
-
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled{
|
|
733
|
+
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal until cancelled. ${ctx.usCancelNote}${ctx.taxFootnote}`;
|
|
200
734
|
}
|
|
201
|
-
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled{
|
|
735
|
+
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}`;
|
|
202
736
|
}
|
|
203
737
|
function nytTerms(ctx) {
|
|
204
738
|
const nytAccessText = "Your complimentary access to The New York Times is for one year only and does not auto-renew. We will send your instructions on how to redeem access to The New York Times by email.";
|
|
205
739
|
if (ctx.isUS) {
|
|
206
|
-
return `Your subscription to <em>The Economist</em> auto-renews ${ctx.periodText} until cancelled{
|
|
740
|
+
return `Your subscription to <em>The Economist</em> auto-renews ${ctx.periodText} until cancelled${LI_SEPARATOR}Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.renewalDateStr}${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal until cancelled. ${ctx.usCancelNote}${ctx.taxFootnote}${P_SEPARATOR}${nytAccessText}`;
|
|
207
741
|
}
|
|
208
742
|
if (ctx.isCA) {
|
|
209
|
-
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled
|
|
743
|
+
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled.${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}${P_SEPARATOR}${nytAccessText}`;
|
|
210
744
|
}
|
|
211
|
-
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled{
|
|
745
|
+
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime} ${nytAccessText}`;
|
|
212
746
|
}
|
|
213
747
|
function minTermContractTerms(offer, ctx) {
|
|
214
748
|
const duePrice = formatPrice(offer.price.purchase, offer.price.currency_code);
|
|
@@ -218,28 +752,28 @@ function minTermContractTerms(offer, ctx) {
|
|
|
218
752
|
const contractLength = mtDuration && mtUnit ? `${mtDuration} ${mtUnit}` : "";
|
|
219
753
|
const initialContractText = contractLength ? `your initial ${contractLength} contract` : "your initial contract";
|
|
220
754
|
const mtRenewalDateText = mtUnit && mtDuration ? getRenewalDateText(mtUnit, Number(mtDuration)) : ctx.renewalDateText;
|
|
221
|
-
return `You\u2019ll be charged ${duePrice} a month for the duration of ${initialContractText}{
|
|
755
|
+
return `You\u2019ll be charged ${duePrice} a month for the duration of ${initialContractText}${LI_SEPARATOR}Your subscription auto-renews annually at ${ctx.renewalPriceText} a month on ${mtRenewalDateText} until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}`;
|
|
222
756
|
}
|
|
223
757
|
function paidTrialTerms(offer, ctx) {
|
|
224
758
|
const trialUnit = offer.subscription_options?.trial_period?.unit ?? ctx.unit;
|
|
225
759
|
const trialDuration = offer.subscription_options?.trial_period?.duration ?? ctx.duration;
|
|
226
760
|
const trialDateText = getRenewalDateText(trialUnit, trialDuration);
|
|
227
761
|
if (ctx.isUS) {
|
|
228
|
-
return `Your subscription auto-renews ${ctx.periodText} until cancelled{
|
|
762
|
+
return `Your subscription auto-renews ${ctx.periodText} until cancelled${LI_SEPARATOR}Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} on ${trialDateText} when your paid trial ends${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.usCancelNote}${ctx.taxFootnote}`;
|
|
229
763
|
}
|
|
230
|
-
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} on ${trialDateText} when your paid trial ends, until cancelled{
|
|
764
|
+
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} on ${trialDateText} when your paid trial ends, until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}`;
|
|
231
765
|
}
|
|
232
766
|
function autoRenewalTerms(ctx) {
|
|
233
767
|
if (ctx.isUS) {
|
|
234
|
-
return `Your subscription auto-renews ${ctx.periodText} until cancelled{
|
|
768
|
+
return `Your subscription auto-renews ${ctx.periodText} until cancelled${LI_SEPARATOR}Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.renewalDateStr}${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal until cancelled. ${ctx.usCancelNote}${ctx.taxFootnote}`;
|
|
235
769
|
}
|
|
236
|
-
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled{
|
|
770
|
+
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}`;
|
|
237
771
|
}
|
|
238
772
|
function noAutoRenewalTerms(ctx) {
|
|
239
773
|
if (ctx.isUS || ctx.isCA) {
|
|
240
|
-
return `Your subscription does not renew automatically${ctx.taxFootnote}{
|
|
774
|
+
return `Your subscription does not renew automatically${ctx.taxFootnote}${LI_SEPARATOR}`;
|
|
241
775
|
}
|
|
242
|
-
return `Your subscription does not renew automatically{
|
|
776
|
+
return `Your subscription does not renew automatically${LI_SEPARATOR}`;
|
|
243
777
|
}
|
|
244
778
|
function generateApplePayModalTerms(offer, country) {
|
|
245
779
|
const ctx = buildTermsContext(offer, country);
|
|
@@ -262,9 +796,9 @@ function generateApplePayModalTerms(offer, country) {
|
|
|
262
796
|
return noAutoRenewalTerms(ctx);
|
|
263
797
|
}
|
|
264
798
|
function renderTermsHtml(termsText) {
|
|
265
|
-
const renewalTextLists = termsText.split(
|
|
799
|
+
const renewalTextLists = termsText.split(LI_SEPARATOR);
|
|
266
800
|
const lastPart = renewalTextLists.pop() || "";
|
|
267
|
-
const renewalTextParagraphs = lastPart.split(
|
|
801
|
+
const renewalTextParagraphs = lastPart.split(P_SEPARATOR);
|
|
268
802
|
const ulHtml = `<ul class="apm__terms-bullets">${renewalTextLists.map((value) => `<li>${value}</li>`).join("")}</ul>`;
|
|
269
803
|
const paragraphHtml = renewalTextParagraphs.filter(Boolean).map((value) => `<p class="apm__terms-legal">${value}</p>`).join("");
|
|
270
804
|
return ulHtml + paragraphHtml;
|
|
@@ -297,6 +831,16 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
297
831
|
#country = "";
|
|
298
832
|
#triggerElement = null;
|
|
299
833
|
#keyHandler = null;
|
|
834
|
+
#isClosed = false;
|
|
835
|
+
/**
|
|
836
|
+
* Callback invoked synchronously from the CTA click handler.
|
|
837
|
+
* Receives a Promise of a reCAPTCHA token — the promise is already in-flight
|
|
838
|
+
* by the time this is called. The caller (ApplePayButton) must call
|
|
839
|
+
* new ApplePaySession() synchronously inside this callback to stay within
|
|
840
|
+
* Safari's user-gesture window. The token promise resolves before
|
|
841
|
+
* onPaymentAuthorized fires (user still needs to authenticate on the sheet).
|
|
842
|
+
*/
|
|
843
|
+
onConfirm = null;
|
|
300
844
|
set offer(value) {
|
|
301
845
|
this.#offer = value;
|
|
302
846
|
}
|
|
@@ -317,7 +861,6 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
317
861
|
const offer = this.#offer;
|
|
318
862
|
const country = this.#country;
|
|
319
863
|
if (!offer) {
|
|
320
|
-
console.error("ApplePayModal: Missing or invalid offer data");
|
|
321
864
|
this.remove();
|
|
322
865
|
return;
|
|
323
866
|
}
|
|
@@ -393,19 +936,40 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
393
936
|
});
|
|
394
937
|
}
|
|
395
938
|
cta?.addEventListener("click", () => {
|
|
939
|
+
if (cta.disabled) return;
|
|
396
940
|
if (isUS && checkbox && !checkbox.checked) {
|
|
397
941
|
errorElement?.classList.add("apm__error--visible");
|
|
398
942
|
checkboxLabel?.classList.add("apm__checkbox-label--error");
|
|
399
943
|
return;
|
|
400
944
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
945
|
+
errorElement?.classList.remove("apm__error--visible");
|
|
946
|
+
this.querySelector('[role="alert"]:not(#apple-pay-modal-error)')?.remove();
|
|
947
|
+
cta.disabled = true;
|
|
948
|
+
cta.setAttribute("aria-busy", "true");
|
|
949
|
+
const recaptchaTokenPromise = getPurchaseRecaptchaToken();
|
|
950
|
+
if (!this.#isClosed && this.onConfirm) {
|
|
951
|
+
this.onConfirm(recaptchaTokenPromise);
|
|
952
|
+
this.close();
|
|
953
|
+
}
|
|
954
|
+
recaptchaTokenPromise.catch(() => {
|
|
955
|
+
if (this.#isClosed) return;
|
|
956
|
+
cta.disabled = false;
|
|
957
|
+
cta.removeAttribute("aria-busy");
|
|
958
|
+
const existingError = this.querySelector("#apple-pay-modal-error");
|
|
959
|
+
if (existingError) {
|
|
960
|
+
const icon = existingError.querySelector("svg");
|
|
961
|
+
existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
962
|
+
if (icon) existingError.prepend(icon);
|
|
963
|
+
existingError.setAttribute("role", "alert");
|
|
964
|
+
existingError.classList.add("apm__error--visible");
|
|
965
|
+
} else {
|
|
966
|
+
const errorNotice = document.createElement("div");
|
|
967
|
+
errorNotice.setAttribute("role", "alert");
|
|
968
|
+
errorNotice.className = "apm__error apm__error--visible";
|
|
969
|
+
errorNotice.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
970
|
+
cta?.insertAdjacentElement("beforebegin", errorNotice);
|
|
971
|
+
}
|
|
972
|
+
});
|
|
409
973
|
});
|
|
410
974
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
411
975
|
"click",
|
|
@@ -413,6 +977,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
413
977
|
);
|
|
414
978
|
}
|
|
415
979
|
open() {
|
|
980
|
+
this.#isClosed = false;
|
|
416
981
|
this.#triggerElement = document.activeElement;
|
|
417
982
|
document.body.appendChild(this);
|
|
418
983
|
this.#keyHandler = (event) => {
|
|
@@ -427,6 +992,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
427
992
|
this.querySelector("#apple-pay-modal")?.focus();
|
|
428
993
|
}
|
|
429
994
|
close() {
|
|
995
|
+
this.#isClosed = true;
|
|
430
996
|
if (this.#keyHandler) {
|
|
431
997
|
document.removeEventListener("keydown", this.#keyHandler, {
|
|
432
998
|
capture: true
|
|
@@ -439,16 +1005,136 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
439
1005
|
};
|
|
440
1006
|
|
|
441
1007
|
// src/templates/apple-pay-button.template.html
|
|
442
|
-
var apple_pay_button_template_default =
|
|
1008
|
+
var apple_pay_button_template_default = `<style>
|
|
1009
|
+
/*
|
|
1010
|
+
* Entry CTA: \u201CSubscribe with\u201D + Apple Pay wordmark (Figma 1118:14088).
|
|
1011
|
+
* \u201CSubscribe with\u201D matches Continue to checkout typography (EconomistSans Regular / 17 / 24 / 400).
|
|
1012
|
+
*/
|
|
1013
|
+
teg-apple-pay-button {
|
|
1014
|
+
display: block;
|
|
1015
|
+
margin: var(--apple-pay-margin, 0);
|
|
1016
|
+
width: 100%;
|
|
1017
|
+
height: 100%;
|
|
1018
|
+
}
|
|
443
1019
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
|
|
1020
|
+
teg-apple-pay-button .apple-pay-container {
|
|
1021
|
+
display: flex;
|
|
1022
|
+
flex-direction: column;
|
|
1023
|
+
align-items: stretch;
|
|
1024
|
+
width: 100%;
|
|
1025
|
+
height: 100%;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
teg-apple-pay-button .apple-pay-btn {
|
|
1029
|
+
display: flex;
|
|
1030
|
+
align-items: center;
|
|
1031
|
+
justify-content: center;
|
|
1032
|
+
width: 100%;
|
|
1033
|
+
min-width: 0;
|
|
1034
|
+
height: 100%;
|
|
1035
|
+
min-height: var(--apple-pay-height, 2.5rem);
|
|
1036
|
+
padding: 0;
|
|
1037
|
+
box-sizing: border-box;
|
|
1038
|
+
background-color: var(--apple-pay-background-color, #1a1a1a);
|
|
1039
|
+
color: var(--apple-pay-foreground-color, #fff);
|
|
1040
|
+
border: none;
|
|
1041
|
+
border-radius: var(--apple-pay-border-radius, 0.25rem);
|
|
1042
|
+
cursor: pointer;
|
|
1043
|
+
/* Same as wall Continue to checkout / Marber button large */
|
|
1044
|
+
font-family: var(
|
|
1045
|
+
--mb-typeface-sans,
|
|
1046
|
+
var(--wall-type-system-sans, 'EconomistSans', system-ui, sans-serif)
|
|
1047
|
+
);
|
|
1048
|
+
font-size: var(--mb-button-font-size, 1.0625rem);
|
|
1049
|
+
font-weight: var(--mb-font-weight-regular, 400);
|
|
1050
|
+
line-height: 1;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
teg-apple-pay-button .apple-pay-btn__label {
|
|
1054
|
+
display: inline-flex;
|
|
1055
|
+
align-items: center;
|
|
1056
|
+
/* No flex gap \u2014 spacing after \u201Cwith\u201D uses the same word-space as \u201CSubscribe with\u201D */
|
|
1057
|
+
gap: 0;
|
|
1058
|
+
white-space: nowrap;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
teg-apple-pay-button .apple-pay-btn__caption {
|
|
1062
|
+
/* One typographic word space after \u201Cwith\u201D, matching Subscribe\u2194with */
|
|
1063
|
+
padding-right: 0.25em;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
teg-apple-pay-button .apple-pay-btn__logo {
|
|
1067
|
+
flex-shrink: 0;
|
|
1068
|
+
display: block;
|
|
1069
|
+
/* Match caption font-size so mark aligns with text metrics */
|
|
1070
|
+
height: 1.05em;
|
|
1071
|
+
width: auto;
|
|
1072
|
+
aspect-ratio: 51 / 22;
|
|
1073
|
+
color: currentColor;
|
|
1074
|
+
/* Optical nudge \u2014 SVG viewBox sits slightly high vs EconomistSans caps */
|
|
1075
|
+
transform: translateY(0.06em);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
teg-apple-pay-button .apple-pay-btn.wap-loading {
|
|
1079
|
+
position: relative;
|
|
1080
|
+
cursor: default;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
teg-apple-pay-button .apple-pay-btn.wap-loading .apple-pay-btn__label {
|
|
1084
|
+
visibility: hidden;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
teg-apple-pay-button .apple-pay-btn.wap-loading::before {
|
|
1088
|
+
content: '';
|
|
1089
|
+
position: absolute;
|
|
1090
|
+
top: 50%;
|
|
1091
|
+
left: 50%;
|
|
1092
|
+
width: 1.25rem;
|
|
1093
|
+
height: 1.25rem;
|
|
1094
|
+
border: 2px solid var(--apple-pay-spinner-track-color, rgba(255, 255, 255, 0.25));
|
|
1095
|
+
border-top-color: var(--apple-pay-spinner-head-color, currentColor);
|
|
1096
|
+
border-radius: 50%;
|
|
1097
|
+
animation: wap-button-spinner 0.8s linear infinite;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
teg-apple-pay-button .apple-pay-btn__loading {
|
|
1101
|
+
display: none;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
@keyframes wap-button-spinner {
|
|
1105
|
+
from {
|
|
1106
|
+
transform: translate(-50%, -50%) rotate(0deg);
|
|
1107
|
+
}
|
|
1108
|
+
to {
|
|
1109
|
+
transform: translate(-50%, -50%) rotate(360deg);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
</style>
|
|
1113
|
+
|
|
1114
|
+
<div class="apple-pay-container" aria-label="Subscribe with Apple Pay">
|
|
1115
|
+
<button
|
|
1116
|
+
class="apple-pay-btn"
|
|
1117
|
+
type="button"
|
|
1118
|
+
aria-label="Subscribe with Apple Pay"
|
|
1119
|
+
data-analytics="paywall:apple-pay-checkout"
|
|
1120
|
+
>
|
|
1121
|
+
<span class="apple-pay-btn__label"
|
|
1122
|
+
><span class="apple-pay-btn__caption">Subscribe with</span
|
|
1123
|
+
><svg
|
|
1124
|
+
class="apple-pay-btn__logo"
|
|
1125
|
+
width="42"
|
|
1126
|
+
height="18"
|
|
1127
|
+
viewBox="0 0 51 22"
|
|
1128
|
+
aria-hidden="true"
|
|
1129
|
+
role="img"
|
|
1130
|
+
>
|
|
1131
|
+
<use href="#apple-pay-logo" />
|
|
1132
|
+
</svg
|
|
1133
|
+
></span>
|
|
1134
|
+
<span class="apple-pay-btn__loading" aria-hidden="true">Loading...</span>
|
|
1135
|
+
</button>
|
|
1136
|
+
</div>
|
|
1137
|
+
`;
|
|
452
1138
|
|
|
453
1139
|
// src/clients/payment-checkout/detects.ts
|
|
454
1140
|
var isAppleDeviceOrSafari = () => {
|
|
@@ -456,7 +1142,7 @@ var isAppleDeviceOrSafari = () => {
|
|
|
456
1142
|
const isSafariBrowser = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1;
|
|
457
1143
|
return isIOSOrMacTouchDevice || isSafariBrowser;
|
|
458
1144
|
};
|
|
459
|
-
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null
|
|
1145
|
+
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null;
|
|
460
1146
|
var isApplePayAvailable = async () => {
|
|
461
1147
|
if (bypassApplePayChecks()) {
|
|
462
1148
|
return true;
|
|
@@ -477,14 +1163,11 @@ var isApplePayAvailable = async () => {
|
|
|
477
1163
|
}
|
|
478
1164
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
479
1165
|
if (!merchantId) {
|
|
480
|
-
console.warn(
|
|
481
|
-
"[web-apple-pay] Missing merchantId. Call configureApplePay({ merchantId, ... }) before rendering Apple Pay components."
|
|
482
|
-
);
|
|
483
1166
|
return false;
|
|
484
1167
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
1168
|
+
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1169
|
+
return hasActiveCard;
|
|
1170
|
+
} catch {
|
|
488
1171
|
return false;
|
|
489
1172
|
}
|
|
490
1173
|
};
|
|
@@ -556,7 +1239,6 @@ var validateAppleMerchant = (data) => {
|
|
|
556
1239
|
});
|
|
557
1240
|
};
|
|
558
1241
|
var performPurchase = (data) => {
|
|
559
|
-
console.log("[web-apple-pay] performPurchase request", JSON.stringify(data, null, 2));
|
|
560
1242
|
return apiFetch("/v1/wallet/purchase", {
|
|
561
1243
|
method: "POST",
|
|
562
1244
|
body: JSON.stringify(data),
|
|
@@ -573,13 +1255,25 @@ var getExpressCheckoutSession = () => {
|
|
|
573
1255
|
};
|
|
574
1256
|
|
|
575
1257
|
// src/utils/expressCheckoutRedirect.ts
|
|
576
|
-
var
|
|
577
|
-
var
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
1258
|
+
var CHECKOUT_REDIRECT_KEY = "checkout-redirect";
|
|
1259
|
+
var ALLOWED_REDIRECT_HOSTNAME = "economist.com";
|
|
1260
|
+
function isAllowedRedirectUrl(url) {
|
|
1261
|
+
if (url.startsWith("/")) return !url.startsWith("//");
|
|
1262
|
+
try {
|
|
1263
|
+
const { hostname } = new URL(url);
|
|
1264
|
+
return hostname === ALLOWED_REDIRECT_HOSTNAME || hostname.endsWith(`.${ALLOWED_REDIRECT_HOSTNAME}`);
|
|
1265
|
+
} catch {
|
|
1266
|
+
return false;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
var writeCheckoutRedirect = (originUrl) => {
|
|
1270
|
+
if (!isAllowedRedirectUrl(originUrl)) return;
|
|
1271
|
+
try {
|
|
1272
|
+
localStorage.setItem(CHECKOUT_REDIRECT_KEY, originUrl);
|
|
1273
|
+
} catch {
|
|
1274
|
+
}
|
|
582
1275
|
};
|
|
1276
|
+
var captureOriginUrl = () => window.location.href;
|
|
583
1277
|
var decodeSku = (sku) => {
|
|
584
1278
|
try {
|
|
585
1279
|
return atob(sku.substring(sku.indexOf("-") + 1));
|
|
@@ -590,75 +1284,25 @@ var decodeSku = (sku) => {
|
|
|
590
1284
|
var redirectToCheckoutComplete = (params) => {
|
|
591
1285
|
const url = new URL("/checkout/complete", window.location.origin);
|
|
592
1286
|
url.searchParams.set("basketId", params.basketId);
|
|
593
|
-
if (params.queryString) {
|
|
594
|
-
const qs = params.queryString.startsWith("?") ? params.queryString.slice(1) : params.queryString;
|
|
595
|
-
new URLSearchParams(qs).forEach((v, k) => url.searchParams.set(k, v));
|
|
596
|
-
}
|
|
597
1287
|
url.searchParams.set("lmo_offer", params.skuId);
|
|
598
1288
|
url.searchParams.set("status", params.status);
|
|
599
1289
|
url.searchParams.set("redirectToCheckout", "true");
|
|
600
|
-
url.searchParams.set("
|
|
1290
|
+
if (params.email) url.searchParams.set("email", params.email);
|
|
1291
|
+
if (params.country) url.searchParams.set("country", params.country);
|
|
601
1292
|
return url.pathname + url.search;
|
|
602
1293
|
};
|
|
603
1294
|
var redirectToCheckoutFallback = (params) => {
|
|
604
1295
|
const url = new URL(window.location.href);
|
|
605
1296
|
url.pathname = "/checkout";
|
|
606
|
-
url.searchParams.set("lmo_offer", params.skuId);
|
|
1297
|
+
url.searchParams.set("lmo_offer", decodeSku(params.skuId));
|
|
607
1298
|
if (params.inlineError)
|
|
608
1299
|
url.searchParams.set("inlineError", params.inlineError);
|
|
609
1300
|
if (params.email) url.searchParams.set("email", params.email);
|
|
610
1301
|
if (params.emailError) url.searchParams.set("emailError", params.emailError);
|
|
611
|
-
url.searchParams.set("
|
|
1302
|
+
if (params.country) url.searchParams.set("country", params.country);
|
|
612
1303
|
return url.pathname + url.search;
|
|
613
1304
|
};
|
|
614
1305
|
|
|
615
|
-
// src/utils/recaptcha.ts
|
|
616
|
-
var loadRecaptchaScript = (siteKey) => {
|
|
617
|
-
return new Promise((resolve, reject) => {
|
|
618
|
-
if (typeof grecaptcha !== "undefined") return resolve();
|
|
619
|
-
const existingScript = document.querySelector(
|
|
620
|
-
'script[src*="recaptcha/api.js"]'
|
|
621
|
-
);
|
|
622
|
-
if (existingScript) {
|
|
623
|
-
existingScript.addEventListener("load", () => resolve());
|
|
624
|
-
existingScript.addEventListener(
|
|
625
|
-
"error",
|
|
626
|
-
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
627
|
-
);
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
const script = document.createElement("script");
|
|
631
|
-
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
632
|
-
script.async = true;
|
|
633
|
-
script.defer = true;
|
|
634
|
-
script.onload = () => resolve();
|
|
635
|
-
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
636
|
-
document.head.appendChild(script);
|
|
637
|
-
});
|
|
638
|
-
};
|
|
639
|
-
var getRecaptchaToken = async (action) => {
|
|
640
|
-
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
641
|
-
if (!siteKey) {
|
|
642
|
-
throw new Error(
|
|
643
|
-
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
644
|
-
);
|
|
645
|
-
}
|
|
646
|
-
await loadRecaptchaScript(siteKey);
|
|
647
|
-
return new Promise((resolve, reject) => {
|
|
648
|
-
grecaptcha.ready(() => {
|
|
649
|
-
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
650
|
-
});
|
|
651
|
-
});
|
|
652
|
-
};
|
|
653
|
-
var getPurchaseRecaptchaTokens = async () => {
|
|
654
|
-
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
655
|
-
getRecaptchaToken("checkEligibility"),
|
|
656
|
-
getRecaptchaToken("newBasket"),
|
|
657
|
-
getRecaptchaToken("registerUser")
|
|
658
|
-
]);
|
|
659
|
-
return { checkEligibility, newBasket, registerUser };
|
|
660
|
-
};
|
|
661
|
-
|
|
662
1306
|
// src/utils/expressCheckoutTracking.ts
|
|
663
1307
|
var EXPRESS_CHECKOUT_EVENTS = {
|
|
664
1308
|
/** Wallet button displayed */
|
|
@@ -738,12 +1382,54 @@ var MSG_MISSING_REQUIRED_FIELD = "Missing required field";
|
|
|
738
1382
|
var MSG_EMAIL_WRONG_FORMAT = "That email doesn\u2019t look right. Please enter a valid email address.";
|
|
739
1383
|
var MSG_EMAIL_TOO_LONG = "This field must be 80 characters or less.";
|
|
740
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 buildCountryMismatchMessage = (countryCode) => {
|
|
1387
|
+
if (!countryCode) return BILLING_COUNTRY_MISMATCH_FALLBACK;
|
|
1388
|
+
try {
|
|
1389
|
+
const regionNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
1390
|
+
const countryName = regionNames.of(countryCode.toUpperCase());
|
|
1391
|
+
return countryName ? `${countryName} address required` : BILLING_COUNTRY_MISMATCH_FALLBACK;
|
|
1392
|
+
} catch {
|
|
1393
|
+
return BILLING_COUNTRY_MISMATCH_FALLBACK;
|
|
1394
|
+
}
|
|
1395
|
+
};
|
|
741
1396
|
var MSG_PAYMENT_GENERIC_ERROR = "Something went wrong. Please check your payment and billing details and try again or contact us.";
|
|
742
|
-
var MSG_RECAPTCHA_VALIDATION_FAILED = "Security check failed. Please try again.";
|
|
743
|
-
var MSG_EMAIL_COLLISION = "This email address is already linked to an account. Please log in, or try a different email address.";
|
|
744
1397
|
var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
|
|
745
1398
|
|
|
746
1399
|
// src/clients/payment-checkout/apple-session.ts
|
|
1400
|
+
function redirectToFallbackCheckout(config) {
|
|
1401
|
+
writeCheckoutRedirect(config.returnUrl);
|
|
1402
|
+
trackFallbackCheckout(config.skuId);
|
|
1403
|
+
window.location.href = redirectToCheckoutFallback({
|
|
1404
|
+
skuId: config.skuId,
|
|
1405
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR,
|
|
1406
|
+
country: config.countryCode
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
async function handleMerchantValidation(event, session, config) {
|
|
1410
|
+
try {
|
|
1411
|
+
const validationHost = new URL(event.validationURL).host;
|
|
1412
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
1413
|
+
session.abort();
|
|
1414
|
+
redirectToFallbackCheckout(config);
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
1418
|
+
const response = await validateAppleMerchant({
|
|
1419
|
+
validationURL: event.validationURL,
|
|
1420
|
+
recaptchaToken
|
|
1421
|
+
});
|
|
1422
|
+
if (!response?.merchantSession) {
|
|
1423
|
+
session.abort();
|
|
1424
|
+
redirectToFallbackCheckout(config);
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
1428
|
+
} catch {
|
|
1429
|
+
session.abort();
|
|
1430
|
+
redirectToFallbackCheckout(config);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
747
1433
|
function startApplePaySession(config) {
|
|
748
1434
|
const paymentRequest = {
|
|
749
1435
|
countryCode: config.countryCode,
|
|
@@ -758,55 +1444,26 @@ function startApplePaySession(config) {
|
|
|
758
1444
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
759
1445
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
760
1446
|
};
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
772
|
-
});
|
|
773
|
-
return;
|
|
774
|
-
}
|
|
775
|
-
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
776
|
-
const response = await validateAppleMerchant({
|
|
777
|
-
validationURL: event.validationURL,
|
|
778
|
-
recaptchaToken
|
|
779
|
-
});
|
|
780
|
-
if (!response?.merchantSession) {
|
|
781
|
-
trackFallbackCheckout(config.skuId);
|
|
782
|
-
session.abort();
|
|
783
|
-
window.location.href = redirectToCheckoutFallback({
|
|
784
|
-
skuId: config.skuId,
|
|
785
|
-
returnUrl: config.returnUrl,
|
|
786
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
787
|
-
});
|
|
788
|
-
return;
|
|
789
|
-
}
|
|
790
|
-
session.completeMerchantValidation(response.merchantSession);
|
|
791
|
-
} catch {
|
|
792
|
-
trackFallbackCheckout(config.skuId);
|
|
793
|
-
session.abort();
|
|
794
|
-
window.location.href = redirectToCheckoutFallback({
|
|
795
|
-
skuId: config.skuId,
|
|
796
|
-
returnUrl: config.returnUrl,
|
|
797
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
1447
|
+
try {
|
|
1448
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
1449
|
+
session.onvalidatemerchant = async (event) => {
|
|
1450
|
+
await handleMerchantValidation(event, session, config);
|
|
1451
|
+
};
|
|
1452
|
+
session.onpaymentauthorized = (event) => {
|
|
1453
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
1454
|
+
config.onPaymentAuthorized(event, session).catch(() => {
|
|
1455
|
+
session.completePayment({ status: ApplePaySession.STATUS_FAILURE });
|
|
1456
|
+
redirectToFallbackCheckout(config);
|
|
798
1457
|
});
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
config.
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
config
|
|
807
|
-
}
|
|
808
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
809
|
-
session.begin();
|
|
1458
|
+
};
|
|
1459
|
+
session.oncancel = () => {
|
|
1460
|
+
config.onCancel?.();
|
|
1461
|
+
};
|
|
1462
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
1463
|
+
session.begin();
|
|
1464
|
+
} catch {
|
|
1465
|
+
redirectToFallbackCheckout(config);
|
|
1466
|
+
}
|
|
810
1467
|
}
|
|
811
1468
|
|
|
812
1469
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -926,8 +1583,6 @@ var shippingContactDetails = (shippingContact) => {
|
|
|
926
1583
|
};
|
|
927
1584
|
|
|
928
1585
|
// src/clients/payment-checkout/payment-handler.ts
|
|
929
|
-
var MSG_ELIGIBILITY = "Something went wrong, please try again";
|
|
930
|
-
var MSG_REGISTRATION = "We couldn't create your account. Please enter your email or try a different login method.";
|
|
931
1586
|
var failApplePaySession = (session, errors = []) => {
|
|
932
1587
|
session.completePayment({
|
|
933
1588
|
status: ApplePaySession.STATUS_FAILURE,
|
|
@@ -951,37 +1606,42 @@ function validateContacts(event, sessionData, supportedBillingCountries) {
|
|
|
951
1606
|
}
|
|
952
1607
|
return void 0;
|
|
953
1608
|
}
|
|
954
|
-
function redirectFallback(skuId, returnUrl, options) {
|
|
1609
|
+
function redirectFallback(skuId, returnUrl, country, options) {
|
|
1610
|
+
writeCheckoutRedirect(returnUrl);
|
|
955
1611
|
trackFallbackCheckout(skuId);
|
|
956
1612
|
window.location.href = redirectToCheckoutFallback({
|
|
957
1613
|
skuId,
|
|
958
|
-
|
|
1614
|
+
country,
|
|
959
1615
|
...options
|
|
960
1616
|
});
|
|
961
1617
|
}
|
|
962
1618
|
var ERROR_HANDLERS = {
|
|
963
|
-
|
|
964
|
-
|
|
1619
|
+
// emailError flows as an inline field error on the email input.
|
|
1620
|
+
// email pre-populates the input so the user doesn't have to retype it.
|
|
1621
|
+
EMAIL_COLLISION: ({ skuId, returnUrl, country, validatedEmail, walletError }) => redirectFallback(skuId, returnUrl, country, {
|
|
1622
|
+
emailError: walletError.message,
|
|
1623
|
+
email: validatedEmail
|
|
1624
|
+
}),
|
|
1625
|
+
PAYMENT_DECLINED: ({ skuId, returnUrl, country, walletError }) => redirectFallback(skuId, returnUrl, country, { inlineError: walletError.message }),
|
|
1626
|
+
ELIGIBILITY_REJECTED: ({ skuId, returnUrl, country, walletError }) => redirectFallback(skuId, returnUrl, country, { inlineError: walletError.message }),
|
|
1627
|
+
REGISTRATION_FAILED: ({ skuId, returnUrl, country, walletError }) => redirectFallback(skuId, returnUrl, country, { inlineError: walletError.message }),
|
|
1628
|
+
ACCOUNT_CREATION_FAILED: ({ skuId, returnUrl, country, validatedEmail, walletError }) => redirectFallback(skuId, returnUrl, country, {
|
|
1629
|
+
emailError: walletError.message,
|
|
965
1630
|
email: validatedEmail
|
|
966
1631
|
}),
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
redirectFallback(skuId, returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR })
|
|
970
|
-
),
|
|
971
|
-
ELIGIBILITY_REJECTED: ({ skuId, returnUrl }) => redirectFallback(skuId, returnUrl, { inlineError: MSG_ELIGIBILITY }),
|
|
972
|
-
REGISTRATION_FAILED: ({ skuId, returnUrl }) => redirectFallback(skuId, returnUrl, { inlineError: MSG_REGISTRATION }),
|
|
973
|
-
VALIDATION_ERROR: ({ skuId, returnUrl }) => redirectFallback(skuId, returnUrl, { inlineError: MSG_RECAPTCHA_VALIDATION_FAILED })
|
|
1632
|
+
VALIDATION_ERROR: ({ skuId, returnUrl, country, walletError }) => redirectFallback(skuId, returnUrl, country, { inlineError: walletError.message }),
|
|
1633
|
+
RECAPTCHA_FAILED: ({ skuId, returnUrl, country, walletError }) => redirectFallback(skuId, returnUrl, country, { inlineError: walletError.message })
|
|
974
1634
|
};
|
|
975
1635
|
function handleStructuredError(ctx) {
|
|
976
1636
|
const handler = ERROR_HANDLERS[ctx.walletError.errorType];
|
|
977
1637
|
if (handler) {
|
|
978
1638
|
handler(ctx);
|
|
979
1639
|
} else {
|
|
980
|
-
redirectFallback(ctx.skuId, ctx.returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
1640
|
+
redirectFallback(ctx.skuId, ctx.returnUrl, ctx.country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
981
1641
|
}
|
|
982
1642
|
}
|
|
983
1643
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
984
|
-
const { skuId, returnUrl,
|
|
1644
|
+
const { skuId, returnUrl, country } = config;
|
|
985
1645
|
let validatedEmail;
|
|
986
1646
|
try {
|
|
987
1647
|
validatedEmail = validateContacts(
|
|
@@ -989,7 +1649,6 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
989
1649
|
sessionData,
|
|
990
1650
|
config.supportedBillingCountries
|
|
991
1651
|
);
|
|
992
|
-
console.log("[web-apple-pay] performPurchase currency", { skuId, currency: config.currency });
|
|
993
1652
|
const result = await performPurchase({
|
|
994
1653
|
applePayToken: event.payment.token,
|
|
995
1654
|
skuId: config.skuId,
|
|
@@ -998,32 +1657,45 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
998
1657
|
...event.payment.shippingContact && {
|
|
999
1658
|
shippingContact: event.payment.shippingContact
|
|
1000
1659
|
},
|
|
1001
|
-
|
|
1660
|
+
recaptchaToken: config.recaptchaToken
|
|
1002
1661
|
});
|
|
1003
1662
|
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1004
1663
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1664
|
+
const successEmail = sessionData.loggedIn ? sessionData.emailAddress : validatedEmail;
|
|
1005
1665
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
1666
|
+
writeCheckoutRedirect(returnUrl);
|
|
1006
1667
|
window.location.href = redirectToCheckoutComplete({
|
|
1007
1668
|
basketId: result.basketId,
|
|
1008
1669
|
status: userStatus,
|
|
1009
1670
|
skuId: decodeSku(skuId),
|
|
1010
|
-
|
|
1011
|
-
|
|
1671
|
+
email: successEmail,
|
|
1672
|
+
country
|
|
1012
1673
|
});
|
|
1013
1674
|
} catch (err) {
|
|
1014
1675
|
if (err instanceof ContactValidationError) {
|
|
1015
|
-
|
|
1676
|
+
const isBillingCountryMismatch = err.errors.some(
|
|
1677
|
+
(e) => e.message === MSG_UNSUPPORTED_BILLING_COUNTRY
|
|
1678
|
+
);
|
|
1679
|
+
if (isBillingCountryMismatch) {
|
|
1680
|
+
const countryCode = event.payment.billingContact?.countryCode;
|
|
1681
|
+
const userMessage = buildCountryMismatchMessage(countryCode);
|
|
1682
|
+
failApplePaySession(session, [
|
|
1683
|
+
new ApplePayError("billingContactInvalid", "countryCode", userMessage)
|
|
1684
|
+
]);
|
|
1685
|
+
redirectFallback(skuId, returnUrl, country, { inlineError: userMessage });
|
|
1686
|
+
} else {
|
|
1687
|
+
failApplePaySession(session, err.errors);
|
|
1688
|
+
}
|
|
1016
1689
|
return;
|
|
1017
1690
|
}
|
|
1018
|
-
console.error("[web-apple-pay] onpaymentauthorized error", { skuId, err });
|
|
1019
1691
|
const walletError = parseWalletApiError(err);
|
|
1020
1692
|
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1021
1693
|
failApplePaySession(session);
|
|
1022
1694
|
if (!walletError) {
|
|
1023
|
-
redirectFallback(skuId, returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
1695
|
+
redirectFallback(skuId, returnUrl, country, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
1024
1696
|
return;
|
|
1025
1697
|
}
|
|
1026
|
-
handleStructuredError({ skuId, returnUrl, validatedEmail, walletError });
|
|
1698
|
+
handleStructuredError({ skuId, returnUrl, country, validatedEmail, walletError });
|
|
1027
1699
|
}
|
|
1028
1700
|
}
|
|
1029
1701
|
|
|
@@ -1288,12 +1960,24 @@ var getSupportedBillingCountries = (offerCountry, offerVariant) => {
|
|
|
1288
1960
|
return [...zoneCountries];
|
|
1289
1961
|
};
|
|
1290
1962
|
|
|
1963
|
+
// src/constants.ts
|
|
1964
|
+
var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint3) => {
|
|
1965
|
+
ApplePayEntryPoint3["PAYWALL"] = "article_paywall";
|
|
1966
|
+
ApplePayEntryPoint3["REGWALL"] = "article_regwall";
|
|
1967
|
+
ApplePayEntryPoint3["DUAL_OFFER_BANNER"] = "dual_offer_banner";
|
|
1968
|
+
return ApplePayEntryPoint3;
|
|
1969
|
+
})(ApplePayEntryPoint || {});
|
|
1970
|
+
var APPLE_PAY_EXPRESS_EXPERIMENT_KEY = "apple-pay-express-feature-flag-placeholder";
|
|
1971
|
+
var APPLE_PAY_EXPRESS_VARIANTS = {
|
|
1972
|
+
CONTROL: "control",
|
|
1973
|
+
TREATMENT: "treatment"
|
|
1974
|
+
};
|
|
1975
|
+
|
|
1291
1976
|
// src/apple-pay-button.ts
|
|
1292
1977
|
var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
1293
1978
|
var TOTAL_LABEL = "The Economist";
|
|
1294
1979
|
var DEFAULT_CURRENCY = "USD";
|
|
1295
1980
|
var DEFAULT_TOTAL = "0.00";
|
|
1296
|
-
var ERROR_INITIATE = "Failed to initiate Apple Pay session:";
|
|
1297
1981
|
var SEL_CONTAINER = ".apple-pay-container";
|
|
1298
1982
|
var SEL_BUTTON = ".apple-pay-btn";
|
|
1299
1983
|
var APPLE_PAY_EXCLUDED_VARIANTS = [
|
|
@@ -1306,19 +1990,48 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1306
1990
|
define(_ApplePayButton.tag, _ApplePayButton);
|
|
1307
1991
|
}
|
|
1308
1992
|
/**
|
|
1309
|
-
* Creates and configures an ApplePayButton
|
|
1993
|
+
* Creates and configures an ApplePayButton when the Amplitude experiment is enabled.
|
|
1994
|
+
*
|
|
1995
|
+
* Reads the experiment variant from `window.experimentIntegration.getVariant` using
|
|
1996
|
+
* {@link APPLE_PAY_EXPRESS_EXPERIMENT_KEY}. The host page is responsible
|
|
1997
|
+
* for setting up `window.experimentIntegration` before calling this method.
|
|
1998
|
+
*
|
|
1999
|
+
* - `treatment` → button created and returned
|
|
2000
|
+
* - `control` / missing / anything else → returns null (button suppressed)
|
|
2001
|
+
*
|
|
2002
|
+
* **Transition period:** the legacy `FEATURE_APPLE_PAY_EXPRESS_CHECKOUT` URL param
|
|
2003
|
+
* gate is also evaluated as a fallback until all host apps have integrated
|
|
2004
|
+
* `window.experimentIntegration`. Once all consumers are migrated, the URL param
|
|
2005
|
+
* fallback will be removed.
|
|
2006
|
+
*
|
|
2007
|
+
* @param offer - The offer to display in the Apple Pay flow.
|
|
2008
|
+
* @param country - The user's country code.
|
|
2009
|
+
* @param entryPoint - Where the button is being rendered (e.g. paywall, banner).
|
|
1310
2010
|
*/
|
|
1311
2011
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1312
|
-
if (!offer)
|
|
1313
|
-
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant))
|
|
2012
|
+
if (!offer) {
|
|
1314
2013
|
return null;
|
|
1315
|
-
|
|
2014
|
+
}
|
|
2015
|
+
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
2016
|
+
return null;
|
|
2017
|
+
}
|
|
2018
|
+
const experimentValue = window.experimentIntegration?.getVariant?.(
|
|
2019
|
+
APPLE_PAY_EXPRESS_EXPERIMENT_KEY
|
|
2020
|
+
);
|
|
2021
|
+
const isTreatment = experimentValue === APPLE_PAY_EXPRESS_VARIANTS.TREATMENT;
|
|
2022
|
+
const hasUrlParamFlag = new URLSearchParams(window.location.search).has(
|
|
2023
|
+
FEATURE_APPLE_PAY_EXPRESS_CHECKOUT
|
|
2024
|
+
);
|
|
2025
|
+
if (!isTreatment && !hasUrlParamFlag) {
|
|
1316
2026
|
return null;
|
|
2027
|
+
}
|
|
1317
2028
|
_ApplePayButton.define();
|
|
1318
2029
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1319
2030
|
button.offer = offer;
|
|
1320
2031
|
button.country = country;
|
|
1321
|
-
|
|
2032
|
+
if (entryPoint) {
|
|
2033
|
+
button.entryPoint = entryPoint;
|
|
2034
|
+
}
|
|
1322
2035
|
return button;
|
|
1323
2036
|
}
|
|
1324
2037
|
/**
|
|
@@ -1409,15 +2122,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1409
2122
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
1410
2123
|
async #run() {
|
|
1411
2124
|
try {
|
|
2125
|
+
this.#renderTemplate();
|
|
1412
2126
|
if (await this.#checkAvailability()) return;
|
|
1413
|
-
if (await this.#checkSession()) return;
|
|
1414
2127
|
if (this.#checkOffer()) return;
|
|
2128
|
+
if (await this.#checkSession()) return;
|
|
1415
2129
|
this.#captureReturnUrl();
|
|
1416
2130
|
this.#computeBillingCountries();
|
|
1417
2131
|
if (await this.#fetchAndCacheOptions()) return;
|
|
1418
|
-
this.#
|
|
2132
|
+
this.#finishLoading();
|
|
1419
2133
|
} catch {
|
|
1420
2134
|
this.style.display = "none";
|
|
2135
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1421
2136
|
} finally {
|
|
1422
2137
|
this.#rendering = false;
|
|
1423
2138
|
}
|
|
@@ -1427,6 +2142,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1427
2142
|
const available = await isApplePayAvailable();
|
|
1428
2143
|
if (!available) {
|
|
1429
2144
|
this.style.display = "none";
|
|
2145
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1430
2146
|
return true;
|
|
1431
2147
|
}
|
|
1432
2148
|
return false;
|
|
@@ -1439,6 +2155,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1439
2155
|
this.#sessionData = await this.#fetchSession();
|
|
1440
2156
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
1441
2157
|
this.style.display = "none";
|
|
2158
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1442
2159
|
return true;
|
|
1443
2160
|
}
|
|
1444
2161
|
return false;
|
|
@@ -1447,6 +2164,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1447
2164
|
#checkOffer() {
|
|
1448
2165
|
if (!this.#offer) {
|
|
1449
2166
|
this.style.display = "none";
|
|
2167
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1450
2168
|
return true;
|
|
1451
2169
|
}
|
|
1452
2170
|
return false;
|
|
@@ -1472,8 +2190,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1472
2190
|
*/
|
|
1473
2191
|
async #fetchAndCacheOptions() {
|
|
1474
2192
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
1475
|
-
if (!this.#paymentOptions?.apple_pay) {
|
|
2193
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
1476
2194
|
this.style.display = "none";
|
|
2195
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1477
2196
|
return true;
|
|
1478
2197
|
}
|
|
1479
2198
|
return false;
|
|
@@ -1485,19 +2204,26 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1485
2204
|
const template = document.createElement("template");
|
|
1486
2205
|
template.innerHTML = apple_pay_button_template_default;
|
|
1487
2206
|
this.appendChild(template.content.cloneNode(true));
|
|
1488
|
-
this.#updateDisabledState();
|
|
1489
|
-
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
1490
|
-
entryPoint: this.#entryPoint,
|
|
1491
|
-
country: this.#country
|
|
1492
|
-
});
|
|
1493
2207
|
const button = this.querySelector(SEL_BUTTON);
|
|
2208
|
+
button.classList.add("wap-loading");
|
|
2209
|
+
button.setAttribute("disabled", "");
|
|
2210
|
+
button.setAttribute("aria-disabled", "true");
|
|
2211
|
+
button.setAttribute("aria-busy", "true");
|
|
1494
2212
|
button.addEventListener("click", () => {
|
|
2213
|
+
if (button.classList.contains("wap-loading")) return;
|
|
1495
2214
|
this.#openModal();
|
|
1496
2215
|
});
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
2216
|
+
}
|
|
2217
|
+
#finishLoading() {
|
|
2218
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2219
|
+
if (button) {
|
|
2220
|
+
button.classList.remove("wap-loading");
|
|
2221
|
+
this.#updateDisabledState();
|
|
2222
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2223
|
+
entryPoint: this.#entryPoint,
|
|
2224
|
+
country: this.#country
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
1501
2227
|
}
|
|
1502
2228
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1503
2229
|
#updateDisabledState() {
|
|
@@ -1506,13 +2232,19 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1506
2232
|
if (this.#offer) {
|
|
1507
2233
|
button.removeAttribute("disabled");
|
|
1508
2234
|
button.removeAttribute("aria-disabled");
|
|
2235
|
+
button.removeAttribute("aria-busy");
|
|
1509
2236
|
return;
|
|
1510
2237
|
}
|
|
1511
2238
|
button.setAttribute("disabled", "");
|
|
1512
2239
|
button.setAttribute("aria-disabled", "true");
|
|
1513
2240
|
}
|
|
1514
2241
|
#openModal() {
|
|
1515
|
-
if (!this.#offer
|
|
2242
|
+
if (!this.#offer) {
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2245
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
1516
2248
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1517
2249
|
ApplePayModal.define();
|
|
1518
2250
|
const modal = document.createElement(ApplePayModal.tag);
|
|
@@ -1521,6 +2253,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1521
2253
|
if (this.#sessionData?.loggedIn) {
|
|
1522
2254
|
modal.dataset.loggedIn = "true";
|
|
1523
2255
|
}
|
|
2256
|
+
const skuId = this.#offer.sku_id;
|
|
2257
|
+
const country = this.#country;
|
|
2258
|
+
modal.onConfirm = (recaptchaTokenPromise) => {
|
|
2259
|
+
this.#initiateApplePay(skuId, country, recaptchaTokenPromise);
|
|
2260
|
+
};
|
|
1524
2261
|
modal.open();
|
|
1525
2262
|
}
|
|
1526
2263
|
async #fetchSession() {
|
|
@@ -1542,45 +2279,53 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1542
2279
|
return null;
|
|
1543
2280
|
}
|
|
1544
2281
|
}
|
|
1545
|
-
#buildSessionParams(skuId, country, sessionData, paymentOptions,
|
|
2282
|
+
#buildSessionParams(skuId, country, sessionData, paymentOptions, recaptchaTokenPromise) {
|
|
1546
2283
|
const offer = this.#offer;
|
|
1547
2284
|
const totalAmount = offer.price?.purchase ? `${offer.price.purchase}` : DEFAULT_TOTAL;
|
|
1548
2285
|
return {
|
|
1549
2286
|
countryCode: country,
|
|
1550
2287
|
currencyCode: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
1551
|
-
supportedNetworks: paymentOptions.apple_pay.settings.supported_networks,
|
|
2288
|
+
supportedNetworks: paymentOptions.options.apple_pay.settings.supported_networks,
|
|
1552
2289
|
totalAmount,
|
|
1553
2290
|
totalLabel: TOTAL_LABEL,
|
|
1554
2291
|
skuId,
|
|
1555
2292
|
returnUrl: this.#returnUrl,
|
|
1556
2293
|
userLoggedIn: sessionData.loggedIn,
|
|
1557
|
-
onPaymentAuthorized: (event, session) =>
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
2294
|
+
onPaymentAuthorized: async (event, session) => {
|
|
2295
|
+
const recaptchaToken = await recaptchaTokenPromise;
|
|
2296
|
+
return handlePaymentAuthorized(event, session, sessionData, {
|
|
2297
|
+
skuId,
|
|
2298
|
+
country,
|
|
2299
|
+
currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
2300
|
+
returnUrl: this.#returnUrl,
|
|
2301
|
+
supportedBillingCountries: this.#supportedBillingCountries,
|
|
2302
|
+
recaptchaToken
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
1566
2305
|
};
|
|
1567
2306
|
}
|
|
1568
|
-
|
|
2307
|
+
#initiateApplePay(skuId, country, recaptchaTokenPromise) {
|
|
1569
2308
|
try {
|
|
1570
2309
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1571
2310
|
const paymentOptions = this.#paymentOptions;
|
|
1572
|
-
|
|
2311
|
+
if (!paymentOptions) {
|
|
2312
|
+
return;
|
|
2313
|
+
}
|
|
1573
2314
|
startApplePaySession(
|
|
1574
2315
|
this.#buildSessionParams(
|
|
1575
2316
|
skuId,
|
|
1576
2317
|
country,
|
|
1577
2318
|
sessionData,
|
|
1578
2319
|
paymentOptions,
|
|
1579
|
-
|
|
2320
|
+
recaptchaTokenPromise
|
|
1580
2321
|
)
|
|
1581
2322
|
);
|
|
1582
|
-
} catch
|
|
1583
|
-
|
|
2323
|
+
} catch {
|
|
2324
|
+
redirectToFallbackCheckout({
|
|
2325
|
+
returnUrl: this.#returnUrl,
|
|
2326
|
+
skuId,
|
|
2327
|
+
countryCode: country
|
|
2328
|
+
});
|
|
1584
2329
|
}
|
|
1585
2330
|
}
|
|
1586
2331
|
};
|
|
@@ -1593,6 +2338,7 @@ function defineApplePayElements() {
|
|
|
1593
2338
|
export {
|
|
1594
2339
|
APPLE_PAY_EXCLUDED_VARIANTS,
|
|
1595
2340
|
ApplePayButton,
|
|
2341
|
+
ApplePayEntryPoint,
|
|
1596
2342
|
ApplePayModal,
|
|
1597
2343
|
configureApplePay,
|
|
1598
2344
|
defineApplePayElements,
|