@economist/web-apple-pay 1.7.2 → 1.7.4
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 +599 -82
- package/dist/src/apple-pay-button.js +594 -77
- package/dist/src/apple-pay-button.stories.js +620 -85
- package/dist/src/apple-pay-modal.d.ts +16 -1
- package/dist/src/apple-pay-modal.js +556 -10
- package/dist/src/apple-pay-modal.stories.js +594 -77
- package/dist/src/clients/payment-checkout/apple-session.js +4 -2
- package/dist/src/clients/payment-checkout/detects.js +2 -1
- package/dist/src/clients/payment-checkout/payment-handler.d.ts +1 -0
- package/dist/src/clients/payment-checkout/payment-handler.js +1 -0
- package/dist/src/clients/payment-checkout/types.d.ts +1 -0
- package/dist/src/index.js +599 -82
- package/dist/src/stories/utils/story-env.js +18 -0
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -76,7 +76,514 @@ function ensureApplePayLogoSymbol() {
|
|
|
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: none;
|
|
113
|
+
border: none;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
padding: 0;
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
justify-content: center;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.apm__close:focus {
|
|
122
|
+
outline: solid 0.125rem var(--focus-border-color, #121212);
|
|
123
|
+
border-radius: 0.25rem;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.apm__offer-name {
|
|
127
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
128
|
+
font-size: var(--mb-typestyle-title-3-size, 1.25rem);
|
|
129
|
+
font-weight: 500;
|
|
130
|
+
color: var(--mb-colour-greyscale-london-5, #0d0d0d);
|
|
131
|
+
line-height: var(--mb-typestyle-title-3-leading, 1.75rem);
|
|
132
|
+
font-style: normal;
|
|
133
|
+
margin: 0 1.5rem 0.5rem 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.apm__due-today {
|
|
137
|
+
color: #1a1a1a;
|
|
138
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
139
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
140
|
+
font-style: normal;
|
|
141
|
+
font-weight: 400;
|
|
142
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
143
|
+
margin: 0 0 0.75rem 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.apm__rule {
|
|
147
|
+
border: none;
|
|
148
|
+
border-top: 0.0625rem solid #d9d9d9;
|
|
149
|
+
margin: 0 0 1rem 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.apm__terms {
|
|
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 1rem 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.apm__terms-bullets {
|
|
163
|
+
list-style: disc outside;
|
|
164
|
+
padding-left: 1.25rem;
|
|
165
|
+
margin: 0 0 0.75rem 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.apm__terms-bullets li {
|
|
169
|
+
margin-bottom: 0.375rem;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.apm__terms-legal {
|
|
173
|
+
margin: 0;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.apm__passive-terms {
|
|
177
|
+
font-family: var(--wall-type-system-sans);
|
|
178
|
+
font-size: 0.9375rem;
|
|
179
|
+
color: #0d0d0d;
|
|
180
|
+
line-height: 1.4;
|
|
181
|
+
margin: 0 0 8px 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.apm__passive-terms a {
|
|
185
|
+
color: #1a1a1a;
|
|
186
|
+
font-weight: 700;
|
|
187
|
+
text-decoration: underline;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.apm__checkbox-label {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: flex-start;
|
|
193
|
+
gap: var(--mb-spacing-sm, 0.5rem);
|
|
194
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
195
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
196
|
+
color: var(--mb-colour-greyscale-london-20, #1a1a1a);
|
|
197
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
198
|
+
cursor: pointer;
|
|
199
|
+
margin: 0 0 1.5rem 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.apm__checkbox-label--error {
|
|
203
|
+
margin-bottom: 0.25rem;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.apm__checkbox-wrapper {
|
|
207
|
+
position: relative;
|
|
208
|
+
flex-shrink: 0;
|
|
209
|
+
width: 1.25rem;
|
|
210
|
+
height: 1.25rem;
|
|
211
|
+
margin-top: 0.0625rem;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.apm__checkbox-input {
|
|
215
|
+
position: absolute;
|
|
216
|
+
opacity: 0;
|
|
217
|
+
width: 100%;
|
|
218
|
+
height: 100%;
|
|
219
|
+
cursor: pointer;
|
|
220
|
+
margin: 0;
|
|
221
|
+
z-index: 1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.apm__checkbox-custom {
|
|
225
|
+
position: absolute;
|
|
226
|
+
top: 0;
|
|
227
|
+
left: 0;
|
|
228
|
+
width: 1.25rem;
|
|
229
|
+
height: 1.25rem;
|
|
230
|
+
pointer-events: none;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.apm__checkbox-custom svg {
|
|
234
|
+
display: none;
|
|
235
|
+
width: 1.25rem;
|
|
236
|
+
height: 1.25rem;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {
|
|
240
|
+
display: block;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {
|
|
244
|
+
display: block;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.apm__checkbox-label--error
|
|
248
|
+
.apm__checkbox-input:not(:checked)
|
|
249
|
+
~ .apm__checkbox-custom
|
|
250
|
+
.svg-unchecked {
|
|
251
|
+
display: none;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.apm__checkbox-label--error
|
|
255
|
+
.apm__checkbox-input:not(:checked)
|
|
256
|
+
~ .apm__checkbox-custom
|
|
257
|
+
.svg-error {
|
|
258
|
+
display: block;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {
|
|
262
|
+
outline: solid 0.125rem #c91d42;
|
|
263
|
+
outline-offset: 0.125rem;
|
|
264
|
+
border-radius: 0.25rem;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.apm__checkbox-label a {
|
|
268
|
+
color: #1a1a1a;
|
|
269
|
+
font-weight: 700;
|
|
270
|
+
text-decoration: underline;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.apm__error {
|
|
274
|
+
display: none;
|
|
275
|
+
align-items: center;
|
|
276
|
+
gap: 0.75rem;
|
|
277
|
+
color: var(--mb-colour-greyscale-london-5, #0d0d0d);
|
|
278
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
279
|
+
font-size: 1.0625rem;
|
|
280
|
+
font-style: normal;
|
|
281
|
+
font-weight: 500;
|
|
282
|
+
line-height: 1.5rem;
|
|
283
|
+
margin-bottom: 1rem;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.apm__error--visible {
|
|
287
|
+
display: flex;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.apm__cta {
|
|
291
|
+
display: flex;
|
|
292
|
+
width: 100%;
|
|
293
|
+
height: 2.75rem;
|
|
294
|
+
padding: 0.375rem 1rem;
|
|
295
|
+
justify-content: center;
|
|
296
|
+
align-items: center;
|
|
297
|
+
gap: 0.375rem;
|
|
298
|
+
border-radius: 0.25rem;
|
|
299
|
+
background: #000;
|
|
300
|
+
border: none;
|
|
301
|
+
cursor: pointer;
|
|
302
|
+
color: #fff;
|
|
303
|
+
text-align: center;
|
|
304
|
+
font-family: var(
|
|
305
|
+
--mb-typeface-sans,
|
|
306
|
+
var(--wall-type-system-sans, system-ui, sans-serif)
|
|
307
|
+
);
|
|
308
|
+
font-size: 1.25rem;
|
|
309
|
+
font-style: normal;
|
|
310
|
+
font-weight: 500;
|
|
311
|
+
line-height: normal;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.apm__cta:disabled {
|
|
315
|
+
cursor: not-allowed;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.apm__cta[aria-busy="true"] {
|
|
319
|
+
position: relative;
|
|
320
|
+
cursor: not-allowed;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.apm__cta[aria-busy="true"] > * {
|
|
324
|
+
visibility: hidden;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.apm__cta[aria-busy="true"]::after {
|
|
328
|
+
content: '';
|
|
329
|
+
position: absolute;
|
|
330
|
+
left: 50%;
|
|
331
|
+
top: 50%;
|
|
332
|
+
margin-left: -0.625rem;
|
|
333
|
+
margin-top: -0.625rem;
|
|
334
|
+
width: 1.25rem;
|
|
335
|
+
height: 1.25rem;
|
|
336
|
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
337
|
+
border-top-color: #fff;
|
|
338
|
+
border-radius: 50%;
|
|
339
|
+
animation: apm-cta-spinner 0.8s linear infinite;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@keyframes apm-cta-spinner {
|
|
343
|
+
to {
|
|
344
|
+
transform: rotate(360deg);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.apm__cta svg {
|
|
349
|
+
flex-shrink: 0;
|
|
350
|
+
display: block;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
@media (min-width: 22.5rem) and (max-width: 37.5rem) {
|
|
354
|
+
.apm {
|
|
355
|
+
width: 24.375rem;
|
|
356
|
+
max-width: 24.375rem;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@media (min-width: 37.5625rem) {
|
|
361
|
+
.apm {
|
|
362
|
+
border-radius: 0.5rem;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@media (max-width: 22.4375rem) {
|
|
367
|
+
.apm {
|
|
368
|
+
width: 20rem;
|
|
369
|
+
max-width: 20rem;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
@media (max-width: 26.1875rem) {
|
|
374
|
+
.apm__cta {
|
|
375
|
+
font-size: 1.125rem;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
</style>
|
|
379
|
+
|
|
380
|
+
<div class="apm-overlay" id="apple-pay-modal-overlay">
|
|
381
|
+
<div
|
|
382
|
+
class="apm"
|
|
383
|
+
role="dialog"
|
|
384
|
+
aria-modal="true"
|
|
385
|
+
aria-labelledby="apple-pay-modal-offer-name"
|
|
386
|
+
id="apple-pay-modal"
|
|
387
|
+
tabindex="-1"
|
|
388
|
+
>
|
|
389
|
+
<button class="apm__close" id="apple-pay-modal-close" aria-label="Close">
|
|
390
|
+
<svg
|
|
391
|
+
aria-hidden="true"
|
|
392
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
393
|
+
width="24"
|
|
394
|
+
height="24"
|
|
395
|
+
viewBox="0 0 24 24"
|
|
396
|
+
fill="none"
|
|
397
|
+
>
|
|
398
|
+
<g clip-path="url(#clip0_15712_93054)">
|
|
399
|
+
<rect width="24" height="24" fill="white" fill-opacity="0.01" />
|
|
400
|
+
<path
|
|
401
|
+
fill-rule="evenodd"
|
|
402
|
+
clip-rule="evenodd"
|
|
403
|
+
d="M0 0H24V24H0V0Z"
|
|
404
|
+
fill="white"
|
|
405
|
+
fill-opacity="0.01"
|
|
406
|
+
/>
|
|
407
|
+
<path
|
|
408
|
+
fill-rule="evenodd"
|
|
409
|
+
clip-rule="evenodd"
|
|
410
|
+
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"
|
|
411
|
+
fill="#333333"
|
|
412
|
+
/>
|
|
413
|
+
</g>
|
|
414
|
+
<defs>
|
|
415
|
+
<clipPath id="clip0_15712_93054">
|
|
416
|
+
<rect width="24" height="24" fill="white" />
|
|
417
|
+
</clipPath>
|
|
418
|
+
</defs>
|
|
419
|
+
</svg>
|
|
420
|
+
</button>
|
|
421
|
+
<p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>
|
|
422
|
+
<p class="apm__due-today" id="apple-pay-modal-due-today"></p>
|
|
423
|
+
<hr class="apm__rule" />
|
|
424
|
+
<div class="apm__terms" id="apple-pay-modal-terms"></div>
|
|
425
|
+
<p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>
|
|
426
|
+
<label
|
|
427
|
+
class="apm__checkbox-label"
|
|
428
|
+
id="apple-pay-modal-checkbox-label"
|
|
429
|
+
for="apple-pay-modal-checkbox"
|
|
430
|
+
>
|
|
431
|
+
<div class="apm__checkbox-wrapper">
|
|
432
|
+
<input
|
|
433
|
+
class="apm__checkbox-input"
|
|
434
|
+
type="checkbox"
|
|
435
|
+
id="apple-pay-modal-checkbox"
|
|
436
|
+
/>
|
|
437
|
+
<span class="apm__checkbox-custom">
|
|
438
|
+
<svg
|
|
439
|
+
aria-hidden="true"
|
|
440
|
+
class="svg-unchecked"
|
|
441
|
+
width="24"
|
|
442
|
+
height="24"
|
|
443
|
+
viewBox="0 0 24 24"
|
|
444
|
+
fill="none"
|
|
445
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
446
|
+
>
|
|
447
|
+
<path
|
|
448
|
+
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"
|
|
449
|
+
fill="white"
|
|
450
|
+
stroke="#595959"
|
|
451
|
+
/>
|
|
452
|
+
</svg>
|
|
453
|
+
<svg
|
|
454
|
+
aria-hidden="true"
|
|
455
|
+
class="svg-checked"
|
|
456
|
+
width="24"
|
|
457
|
+
height="24"
|
|
458
|
+
viewBox="0 0 24 24"
|
|
459
|
+
fill="none"
|
|
460
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
461
|
+
>
|
|
462
|
+
<g clip-path="url(#clip0_20014_9555)">
|
|
463
|
+
<path
|
|
464
|
+
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"
|
|
465
|
+
fill="#333333"
|
|
466
|
+
/>
|
|
467
|
+
<path
|
|
468
|
+
d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"
|
|
469
|
+
fill="white"
|
|
470
|
+
/>
|
|
471
|
+
</g>
|
|
472
|
+
<defs>
|
|
473
|
+
<clipPath id="clip0_20014_9555">
|
|
474
|
+
<path
|
|
475
|
+
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"
|
|
476
|
+
fill="white"
|
|
477
|
+
/>
|
|
478
|
+
</clipPath>
|
|
479
|
+
</defs>
|
|
480
|
+
</svg>
|
|
481
|
+
<svg
|
|
482
|
+
aria-hidden="true"
|
|
483
|
+
class="svg-error"
|
|
484
|
+
width="24"
|
|
485
|
+
height="24"
|
|
486
|
+
viewBox="0 0 24 24"
|
|
487
|
+
fill="none"
|
|
488
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
489
|
+
>
|
|
490
|
+
<path
|
|
491
|
+
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"
|
|
492
|
+
fill="white"
|
|
493
|
+
stroke="#C91D42"
|
|
494
|
+
stroke-width="2"
|
|
495
|
+
/>
|
|
496
|
+
</svg>
|
|
497
|
+
</span>
|
|
498
|
+
</div>
|
|
499
|
+
<span id="apple-pay-modal-checkbox-text"></span>
|
|
500
|
+
</label>
|
|
501
|
+
<div class="apm__error" id="apple-pay-modal-error" role="alert">
|
|
502
|
+
<svg
|
|
503
|
+
aria-hidden="true"
|
|
504
|
+
width="20"
|
|
505
|
+
height="20"
|
|
506
|
+
viewBox="0 0 20 20"
|
|
507
|
+
fill="none"
|
|
508
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
509
|
+
>
|
|
510
|
+
<path
|
|
511
|
+
fill-rule="evenodd"
|
|
512
|
+
clip-rule="evenodd"
|
|
513
|
+
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"
|
|
514
|
+
fill="#C91D42"
|
|
515
|
+
/>
|
|
516
|
+
</svg>
|
|
517
|
+
Please accept the terms to continue
|
|
518
|
+
</div>
|
|
519
|
+
<button class="apm__cta" id="apple-pay-modal-cta" aria-label="Continue with Apple Pay">
|
|
520
|
+
<span class="apm__cta-content">
|
|
521
|
+
Continue with
|
|
522
|
+
<svg width="51" height="22" aria-hidden="true" role="img">
|
|
523
|
+
<use href="#apple-pay-logo" />
|
|
524
|
+
</svg>
|
|
525
|
+
</span>
|
|
526
|
+
</button>
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
|
|
530
|
+
`;
|
|
531
|
+
|
|
532
|
+
// src/clients/payment-checkout/config.ts
|
|
533
|
+
var runtimeConfig = null;
|
|
534
|
+
var configureApplePay = (config) => {
|
|
535
|
+
runtimeConfig = {
|
|
536
|
+
...config
|
|
537
|
+
};
|
|
538
|
+
};
|
|
539
|
+
var getApplePayConfig = () => runtimeConfig;
|
|
540
|
+
|
|
541
|
+
// src/utils/recaptcha.ts
|
|
542
|
+
var loadRecaptchaScript = (siteKey) => {
|
|
543
|
+
return new Promise((resolve, reject) => {
|
|
544
|
+
if (typeof grecaptcha !== "undefined") return resolve();
|
|
545
|
+
const existingScript = document.querySelector(
|
|
546
|
+
'script[src*="recaptcha/api.js"]'
|
|
547
|
+
);
|
|
548
|
+
if (existingScript) {
|
|
549
|
+
existingScript.addEventListener("load", () => resolve());
|
|
550
|
+
existingScript.addEventListener(
|
|
551
|
+
"error",
|
|
552
|
+
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
553
|
+
);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const script = document.createElement("script");
|
|
557
|
+
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
558
|
+
script.async = true;
|
|
559
|
+
script.defer = true;
|
|
560
|
+
script.onload = () => resolve();
|
|
561
|
+
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
562
|
+
document.head.appendChild(script);
|
|
563
|
+
});
|
|
564
|
+
};
|
|
565
|
+
var getRecaptchaToken = async (action) => {
|
|
566
|
+
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
567
|
+
if (!siteKey) {
|
|
568
|
+
throw new Error(
|
|
569
|
+
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
await loadRecaptchaScript(siteKey);
|
|
573
|
+
return new Promise((resolve, reject) => {
|
|
574
|
+
grecaptcha.ready(() => {
|
|
575
|
+
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
};
|
|
579
|
+
var getPurchaseRecaptchaTokens = async () => {
|
|
580
|
+
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
581
|
+
getRecaptchaToken("checkEligibility"),
|
|
582
|
+
getRecaptchaToken("newBasket"),
|
|
583
|
+
getRecaptchaToken("registerUser")
|
|
584
|
+
]);
|
|
585
|
+
return { checkEligibility, newBasket, registerUser };
|
|
586
|
+
};
|
|
80
587
|
|
|
81
588
|
// src/apple-pay-modal.ts
|
|
82
589
|
function getRenewalDateText(unit, duration) {
|
|
@@ -128,6 +635,7 @@ function getOfferTypeText(offerType) {
|
|
|
128
635
|
}
|
|
129
636
|
var TERMS_LINK = '<a href="https://www.economistgroup.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms and Conditions</a>';
|
|
130
637
|
var PRIVACY_LINK = '<a href="https://www.economistgroup.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>';
|
|
638
|
+
var MSG_RECAPTCHA_LOAD_ERROR = "Something went wrong. Please close and try again.";
|
|
131
639
|
function getCheckboxTermsHtml(isNYT, isLoggedIn, autoRenewal) {
|
|
132
640
|
const autoRenewalClause = autoRenewal ? " and auto-renewal terms above," : "";
|
|
133
641
|
if (isNYT) {
|
|
@@ -297,6 +805,19 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
297
805
|
#country = "";
|
|
298
806
|
#triggerElement = null;
|
|
299
807
|
#keyHandler = null;
|
|
808
|
+
#recaptchaTokens = null;
|
|
809
|
+
#recaptchaTokensPromise = null;
|
|
810
|
+
/**
|
|
811
|
+
* Synchronous callback invoked directly from the CTA click handler once the
|
|
812
|
+
* user confirms. The caller (ApplePayButton) must call startApplePaySession
|
|
813
|
+
* inside this callback to preserve the browser's user-gesture chain — Safari
|
|
814
|
+
* requires new ApplePaySession() to execute within the original click stack.
|
|
815
|
+
*
|
|
816
|
+
* reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
|
|
817
|
+
* until the token pre-fetch resolves, so this callback is never reached
|
|
818
|
+
* without valid tokens.
|
|
819
|
+
*/
|
|
820
|
+
onConfirm = null;
|
|
300
821
|
set offer(value) {
|
|
301
822
|
this.#offer = value;
|
|
302
823
|
}
|
|
@@ -391,27 +912,57 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
391
912
|
}
|
|
392
913
|
});
|
|
393
914
|
}
|
|
915
|
+
if (this.#recaptchaTokensPromise) {
|
|
916
|
+
if (cta) {
|
|
917
|
+
cta.setAttribute("disabled", "");
|
|
918
|
+
cta.setAttribute("aria-disabled", "true");
|
|
919
|
+
cta.setAttribute("aria-busy", "true");
|
|
920
|
+
}
|
|
921
|
+
this.#recaptchaTokensPromise.then((tokens) => {
|
|
922
|
+
this.#recaptchaTokens = tokens;
|
|
923
|
+
if (cta) {
|
|
924
|
+
cta.removeAttribute("disabled");
|
|
925
|
+
cta.removeAttribute("aria-disabled");
|
|
926
|
+
cta.removeAttribute("aria-busy");
|
|
927
|
+
}
|
|
928
|
+
}).catch(() => {
|
|
929
|
+
console.error("[web-apple-pay] apple-pay-modal: failed to pre-fetch reCAPTCHA tokens; CTA remains disabled");
|
|
930
|
+
if (cta) {
|
|
931
|
+
cta.removeAttribute("aria-busy");
|
|
932
|
+
}
|
|
933
|
+
const existingError = this.querySelector("#apple-pay-modal-error");
|
|
934
|
+
if (existingError) {
|
|
935
|
+
const icon = existingError.querySelector("svg");
|
|
936
|
+
existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
937
|
+
if (icon) existingError.prepend(icon);
|
|
938
|
+
existingError.classList.add("apm__error--visible");
|
|
939
|
+
} else {
|
|
940
|
+
const errorNotice = document.createElement("div");
|
|
941
|
+
errorNotice.setAttribute("role", "alert");
|
|
942
|
+
errorNotice.className = "apm__error apm__error--visible";
|
|
943
|
+
errorNotice.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
944
|
+
cta?.insertAdjacentElement("beforebegin", errorNotice);
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
}
|
|
394
948
|
cta?.addEventListener("click", () => {
|
|
395
949
|
if (isUS && checkbox && !checkbox.checked) {
|
|
396
950
|
errorElement?.classList.add("apm__error--visible");
|
|
397
951
|
checkboxLabel?.classList.add("apm__checkbox-label--error");
|
|
398
952
|
return;
|
|
399
953
|
}
|
|
400
|
-
this
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
detail: { skuId: offer.sku_id, country }
|
|
405
|
-
})
|
|
406
|
-
);
|
|
407
|
-
this.close();
|
|
954
|
+
if (this.#recaptchaTokens) {
|
|
955
|
+
this.onConfirm?.(this.#recaptchaTokens);
|
|
956
|
+
this.close();
|
|
957
|
+
}
|
|
408
958
|
});
|
|
409
959
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
410
960
|
"click",
|
|
411
961
|
() => this.close()
|
|
412
962
|
);
|
|
413
963
|
}
|
|
414
|
-
open() {
|
|
964
|
+
open(recaptchaTokensPromise) {
|
|
965
|
+
this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
|
|
415
966
|
this.#triggerElement = document.activeElement;
|
|
416
967
|
document.body.appendChild(this);
|
|
417
968
|
this.#keyHandler = (event) => {
|
|
@@ -524,15 +1075,6 @@ var apple_pay_button_template_default = `<style>
|
|
|
524
1075
|
</div>
|
|
525
1076
|
`;
|
|
526
1077
|
|
|
527
|
-
// src/clients/payment-checkout/config.ts
|
|
528
|
-
var runtimeConfig = null;
|
|
529
|
-
var configureApplePay = (config) => {
|
|
530
|
-
runtimeConfig = {
|
|
531
|
-
...config
|
|
532
|
-
};
|
|
533
|
-
};
|
|
534
|
-
var getApplePayConfig = () => runtimeConfig;
|
|
535
|
-
|
|
536
1078
|
// src/clients/payment-checkout/detects.ts
|
|
537
1079
|
var isAppleDeviceOrSafari = () => {
|
|
538
1080
|
const isIOSOrMacTouchDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.maxTouchPoints > 1 && /Macintosh/.test(navigator.userAgent);
|
|
@@ -565,7 +1107,8 @@ var isApplePayAvailable = async () => {
|
|
|
565
1107
|
);
|
|
566
1108
|
return false;
|
|
567
1109
|
}
|
|
568
|
-
|
|
1110
|
+
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1111
|
+
return hasActiveCard;
|
|
569
1112
|
} catch (error) {
|
|
570
1113
|
console.error("Error checking Apple Pay active card status:", error);
|
|
571
1114
|
return false;
|
|
@@ -694,53 +1237,6 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
694
1237
|
return url.pathname + url.search;
|
|
695
1238
|
};
|
|
696
1239
|
|
|
697
|
-
// src/utils/recaptcha.ts
|
|
698
|
-
var loadRecaptchaScript = (siteKey) => {
|
|
699
|
-
return new Promise((resolve, reject) => {
|
|
700
|
-
if (typeof grecaptcha !== "undefined") return resolve();
|
|
701
|
-
const existingScript = document.querySelector(
|
|
702
|
-
'script[src*="recaptcha/api.js"]'
|
|
703
|
-
);
|
|
704
|
-
if (existingScript) {
|
|
705
|
-
existingScript.addEventListener("load", () => resolve());
|
|
706
|
-
existingScript.addEventListener(
|
|
707
|
-
"error",
|
|
708
|
-
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
709
|
-
);
|
|
710
|
-
return;
|
|
711
|
-
}
|
|
712
|
-
const script = document.createElement("script");
|
|
713
|
-
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
714
|
-
script.async = true;
|
|
715
|
-
script.defer = true;
|
|
716
|
-
script.onload = () => resolve();
|
|
717
|
-
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
718
|
-
document.head.appendChild(script);
|
|
719
|
-
});
|
|
720
|
-
};
|
|
721
|
-
var getRecaptchaToken = async (action) => {
|
|
722
|
-
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
723
|
-
if (!siteKey) {
|
|
724
|
-
throw new Error(
|
|
725
|
-
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
726
|
-
);
|
|
727
|
-
}
|
|
728
|
-
await loadRecaptchaScript(siteKey);
|
|
729
|
-
return new Promise((resolve, reject) => {
|
|
730
|
-
grecaptcha.ready(() => {
|
|
731
|
-
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
732
|
-
});
|
|
733
|
-
});
|
|
734
|
-
};
|
|
735
|
-
var getPurchaseRecaptchaTokens = async () => {
|
|
736
|
-
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
737
|
-
getRecaptchaToken("checkEligibility"),
|
|
738
|
-
getRecaptchaToken("newBasket"),
|
|
739
|
-
getRecaptchaToken("registerUser")
|
|
740
|
-
]);
|
|
741
|
-
return { checkEligibility, newBasket, registerUser };
|
|
742
|
-
};
|
|
743
|
-
|
|
744
1240
|
// src/utils/expressCheckoutTracking.ts
|
|
745
1241
|
var EXPRESS_CHECKOUT_EVENTS = {
|
|
746
1242
|
/** Wallet button displayed */
|
|
@@ -853,7 +1349,8 @@ async function handleMerchantValidation(event, session, config) {
|
|
|
853
1349
|
return;
|
|
854
1350
|
}
|
|
855
1351
|
session.completeMerchantValidation(response.merchantSession);
|
|
856
|
-
} catch {
|
|
1352
|
+
} catch (err) {
|
|
1353
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
857
1354
|
session.abort();
|
|
858
1355
|
redirectToFallbackCheckout(config);
|
|
859
1356
|
}
|
|
@@ -886,7 +1383,8 @@ function startApplePaySession(config) {
|
|
|
886
1383
|
};
|
|
887
1384
|
trackWalletPaymentSheetOpen(config.skuId);
|
|
888
1385
|
session.begin();
|
|
889
|
-
} catch {
|
|
1386
|
+
} catch (err) {
|
|
1387
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create session", err);
|
|
890
1388
|
redirectToFallbackCheckout(config);
|
|
891
1389
|
}
|
|
892
1390
|
}
|
|
@@ -1074,6 +1572,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1074
1572
|
const result = await performPurchase({
|
|
1075
1573
|
applePayToken: event.payment.token,
|
|
1076
1574
|
skuId: config.skuId,
|
|
1575
|
+
currency: config.currency,
|
|
1077
1576
|
billingContact: event.payment.billingContact,
|
|
1078
1577
|
...event.payment.shippingContact && {
|
|
1079
1578
|
shippingContact: event.payment.shippingContact
|
|
@@ -1424,7 +1923,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1424
1923
|
#returnUrl = "";
|
|
1425
1924
|
#supportedBillingCountries = [];
|
|
1426
1925
|
#entryPoint = "";
|
|
1427
|
-
#
|
|
1926
|
+
#recaptchaTokensPromise = null;
|
|
1428
1927
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1429
1928
|
get offer() {
|
|
1430
1929
|
return this.#offer;
|
|
@@ -1489,6 +1988,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1489
1988
|
this.#paymentOptions = null;
|
|
1490
1989
|
this.#returnUrl = "";
|
|
1491
1990
|
this.#supportedBillingCountries = [];
|
|
1991
|
+
this.#recaptchaTokensPromise = null;
|
|
1492
1992
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1493
1993
|
}
|
|
1494
1994
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -1502,7 +2002,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1502
2002
|
this.#computeBillingCountries();
|
|
1503
2003
|
if (await this.#fetchAndCacheOptions()) return;
|
|
1504
2004
|
this.#finishLoading();
|
|
1505
|
-
} catch {
|
|
2005
|
+
} catch (err) {
|
|
2006
|
+
console.error("[web-apple-pay] #run: unexpected error, hiding button", err);
|
|
1506
2007
|
this.style.display = "none";
|
|
1507
2008
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1508
2009
|
} finally {
|
|
@@ -1583,16 +2084,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1583
2084
|
if (button.classList.contains("wap-loading")) return;
|
|
1584
2085
|
this.#openModal();
|
|
1585
2086
|
});
|
|
1586
|
-
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1587
|
-
const { skuId, country } = event.detail;
|
|
1588
|
-
this.#initiateApplePay(skuId, country);
|
|
1589
|
-
}, { once: true });
|
|
1590
2087
|
}
|
|
1591
2088
|
#finishLoading() {
|
|
1592
2089
|
const button = this.querySelector(SEL_BUTTON);
|
|
1593
2090
|
if (button) {
|
|
1594
2091
|
button.classList.remove("wap-loading");
|
|
1595
2092
|
this.#updateDisabledState();
|
|
2093
|
+
this.#scheduleRecaptchaTokens();
|
|
1596
2094
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
1597
2095
|
entryPoint: this.#entryPoint,
|
|
1598
2096
|
country: this.#country
|
|
@@ -1620,10 +2118,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1620
2118
|
return;
|
|
1621
2119
|
}
|
|
1622
2120
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1623
|
-
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1624
|
-
this.#recaptchaTokens = tokens;
|
|
1625
|
-
}).catch(() => {
|
|
1626
|
-
});
|
|
1627
2121
|
ApplePayModal.define();
|
|
1628
2122
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1629
2123
|
modal.offer = this.#offer;
|
|
@@ -1631,7 +2125,30 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1631
2125
|
if (this.#sessionData?.loggedIn) {
|
|
1632
2126
|
modal.dataset.loggedIn = "true";
|
|
1633
2127
|
}
|
|
1634
|
-
|
|
2128
|
+
const skuId = this.#offer.sku_id;
|
|
2129
|
+
const country = this.#country;
|
|
2130
|
+
modal.onConfirm = (recaptchaTokens) => {
|
|
2131
|
+
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2132
|
+
this.#scheduleRecaptchaTokens();
|
|
2133
|
+
};
|
|
2134
|
+
modal.open(this.#recaptchaTokensPromise);
|
|
2135
|
+
}
|
|
2136
|
+
/**
|
|
2137
|
+
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2138
|
+
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2139
|
+
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2140
|
+
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2141
|
+
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2142
|
+
*/
|
|
2143
|
+
#scheduleRecaptchaTokens() {
|
|
2144
|
+
const attempt = getPurchaseRecaptchaTokens();
|
|
2145
|
+
attempt.catch((err) => {
|
|
2146
|
+
console.error("[web-apple-pay] reCAPTCHA token pre-fetch failed; will retry on modal open", err);
|
|
2147
|
+
if (this.#recaptchaTokensPromise === attempt) {
|
|
2148
|
+
this.#recaptchaTokensPromise = null;
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
this.#recaptchaTokensPromise = attempt;
|
|
1635
2152
|
}
|
|
1636
2153
|
async #fetchSession() {
|
|
1637
2154
|
try {
|
|
@@ -1667,6 +2184,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1667
2184
|
onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
|
|
1668
2185
|
skuId,
|
|
1669
2186
|
country,
|
|
2187
|
+
currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
1670
2188
|
returnUrl: this.#returnUrl,
|
|
1671
2189
|
queryString: buildQueryString(),
|
|
1672
2190
|
supportedBillingCountries: this.#supportedBillingCountries,
|
|
@@ -1674,11 +2192,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1674
2192
|
})
|
|
1675
2193
|
};
|
|
1676
2194
|
}
|
|
1677
|
-
|
|
2195
|
+
#initiateApplePay(skuId, country, recaptchaTokens) {
|
|
1678
2196
|
try {
|
|
1679
2197
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1680
2198
|
const paymentOptions = this.#paymentOptions;
|
|
1681
|
-
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1682
2199
|
startApplePaySession(
|
|
1683
2200
|
this.#buildSessionParams(
|
|
1684
2201
|
skuId,
|