@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
|
@@ -76,7 +76,509 @@ 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 getApplePayConfig = () => runtimeConfig;
|
|
535
|
+
|
|
536
|
+
// src/utils/recaptcha.ts
|
|
537
|
+
var loadRecaptchaScript = (siteKey) => {
|
|
538
|
+
return new Promise((resolve, reject) => {
|
|
539
|
+
if (typeof grecaptcha !== "undefined") return resolve();
|
|
540
|
+
const existingScript = document.querySelector(
|
|
541
|
+
'script[src*="recaptcha/api.js"]'
|
|
542
|
+
);
|
|
543
|
+
if (existingScript) {
|
|
544
|
+
existingScript.addEventListener("load", () => resolve());
|
|
545
|
+
existingScript.addEventListener(
|
|
546
|
+
"error",
|
|
547
|
+
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
548
|
+
);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const script = document.createElement("script");
|
|
552
|
+
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
553
|
+
script.async = true;
|
|
554
|
+
script.defer = true;
|
|
555
|
+
script.onload = () => resolve();
|
|
556
|
+
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
557
|
+
document.head.appendChild(script);
|
|
558
|
+
});
|
|
559
|
+
};
|
|
560
|
+
var getRecaptchaToken = async (action) => {
|
|
561
|
+
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
562
|
+
if (!siteKey) {
|
|
563
|
+
throw new Error(
|
|
564
|
+
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
await loadRecaptchaScript(siteKey);
|
|
568
|
+
return new Promise((resolve, reject) => {
|
|
569
|
+
grecaptcha.ready(() => {
|
|
570
|
+
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
};
|
|
574
|
+
var getPurchaseRecaptchaTokens = async () => {
|
|
575
|
+
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
576
|
+
getRecaptchaToken("checkEligibility"),
|
|
577
|
+
getRecaptchaToken("newBasket"),
|
|
578
|
+
getRecaptchaToken("registerUser")
|
|
579
|
+
]);
|
|
580
|
+
return { checkEligibility, newBasket, registerUser };
|
|
581
|
+
};
|
|
80
582
|
|
|
81
583
|
// src/apple-pay-modal.ts
|
|
82
584
|
function getRenewalDateText(unit, duration) {
|
|
@@ -128,6 +630,7 @@ function getOfferTypeText(offerType) {
|
|
|
128
630
|
}
|
|
129
631
|
var TERMS_LINK = '<a href="https://www.economistgroup.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms and Conditions</a>';
|
|
130
632
|
var PRIVACY_LINK = '<a href="https://www.economistgroup.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>';
|
|
633
|
+
var MSG_RECAPTCHA_LOAD_ERROR = "Something went wrong. Please close and try again.";
|
|
131
634
|
function getCheckboxTermsHtml(isNYT, isLoggedIn, autoRenewal) {
|
|
132
635
|
const autoRenewalClause = autoRenewal ? " and auto-renewal terms above," : "";
|
|
133
636
|
if (isNYT) {
|
|
@@ -297,6 +800,19 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
297
800
|
#country = "";
|
|
298
801
|
#triggerElement = null;
|
|
299
802
|
#keyHandler = null;
|
|
803
|
+
#recaptchaTokens = null;
|
|
804
|
+
#recaptchaTokensPromise = null;
|
|
805
|
+
/**
|
|
806
|
+
* Synchronous callback invoked directly from the CTA click handler once the
|
|
807
|
+
* user confirms. The caller (ApplePayButton) must call startApplePaySession
|
|
808
|
+
* inside this callback to preserve the browser's user-gesture chain — Safari
|
|
809
|
+
* requires new ApplePaySession() to execute within the original click stack.
|
|
810
|
+
*
|
|
811
|
+
* reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
|
|
812
|
+
* until the token pre-fetch resolves, so this callback is never reached
|
|
813
|
+
* without valid tokens.
|
|
814
|
+
*/
|
|
815
|
+
onConfirm = null;
|
|
300
816
|
set offer(value) {
|
|
301
817
|
this.#offer = value;
|
|
302
818
|
}
|
|
@@ -391,27 +907,57 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
391
907
|
}
|
|
392
908
|
});
|
|
393
909
|
}
|
|
910
|
+
if (this.#recaptchaTokensPromise) {
|
|
911
|
+
if (cta) {
|
|
912
|
+
cta.setAttribute("disabled", "");
|
|
913
|
+
cta.setAttribute("aria-disabled", "true");
|
|
914
|
+
cta.setAttribute("aria-busy", "true");
|
|
915
|
+
}
|
|
916
|
+
this.#recaptchaTokensPromise.then((tokens) => {
|
|
917
|
+
this.#recaptchaTokens = tokens;
|
|
918
|
+
if (cta) {
|
|
919
|
+
cta.removeAttribute("disabled");
|
|
920
|
+
cta.removeAttribute("aria-disabled");
|
|
921
|
+
cta.removeAttribute("aria-busy");
|
|
922
|
+
}
|
|
923
|
+
}).catch(() => {
|
|
924
|
+
console.error("[web-apple-pay] apple-pay-modal: failed to pre-fetch reCAPTCHA tokens; CTA remains disabled");
|
|
925
|
+
if (cta) {
|
|
926
|
+
cta.removeAttribute("aria-busy");
|
|
927
|
+
}
|
|
928
|
+
const existingError = this.querySelector("#apple-pay-modal-error");
|
|
929
|
+
if (existingError) {
|
|
930
|
+
const icon = existingError.querySelector("svg");
|
|
931
|
+
existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
932
|
+
if (icon) existingError.prepend(icon);
|
|
933
|
+
existingError.classList.add("apm__error--visible");
|
|
934
|
+
} else {
|
|
935
|
+
const errorNotice = document.createElement("div");
|
|
936
|
+
errorNotice.setAttribute("role", "alert");
|
|
937
|
+
errorNotice.className = "apm__error apm__error--visible";
|
|
938
|
+
errorNotice.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
939
|
+
cta?.insertAdjacentElement("beforebegin", errorNotice);
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
}
|
|
394
943
|
cta?.addEventListener("click", () => {
|
|
395
944
|
if (isUS && checkbox && !checkbox.checked) {
|
|
396
945
|
errorElement?.classList.add("apm__error--visible");
|
|
397
946
|
checkboxLabel?.classList.add("apm__checkbox-label--error");
|
|
398
947
|
return;
|
|
399
948
|
}
|
|
400
|
-
this
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
detail: { skuId: offer.sku_id, country }
|
|
405
|
-
})
|
|
406
|
-
);
|
|
407
|
-
this.close();
|
|
949
|
+
if (this.#recaptchaTokens) {
|
|
950
|
+
this.onConfirm?.(this.#recaptchaTokens);
|
|
951
|
+
this.close();
|
|
952
|
+
}
|
|
408
953
|
});
|
|
409
954
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
410
955
|
"click",
|
|
411
956
|
() => this.close()
|
|
412
957
|
);
|
|
413
958
|
}
|
|
414
|
-
open() {
|
|
959
|
+
open(recaptchaTokensPromise) {
|
|
960
|
+
this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
|
|
415
961
|
this.#triggerElement = document.activeElement;
|
|
416
962
|
document.body.appendChild(this);
|
|
417
963
|
this.#keyHandler = (event) => {
|
|
@@ -524,10 +1070,6 @@ var apple_pay_button_template_default = `<style>
|
|
|
524
1070
|
</div>
|
|
525
1071
|
`;
|
|
526
1072
|
|
|
527
|
-
// src/clients/payment-checkout/config.ts
|
|
528
|
-
var runtimeConfig = null;
|
|
529
|
-
var getApplePayConfig = () => runtimeConfig;
|
|
530
|
-
|
|
531
1073
|
// src/clients/payment-checkout/detects.ts
|
|
532
1074
|
var isAppleDeviceOrSafari = () => {
|
|
533
1075
|
const isIOSOrMacTouchDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.maxTouchPoints > 1 && /Macintosh/.test(navigator.userAgent);
|
|
@@ -560,7 +1102,8 @@ var isApplePayAvailable = async () => {
|
|
|
560
1102
|
);
|
|
561
1103
|
return false;
|
|
562
1104
|
}
|
|
563
|
-
|
|
1105
|
+
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1106
|
+
return hasActiveCard;
|
|
564
1107
|
} catch (error) {
|
|
565
1108
|
console.error("Error checking Apple Pay active card status:", error);
|
|
566
1109
|
return false;
|
|
@@ -689,53 +1232,6 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
689
1232
|
return url.pathname + url.search;
|
|
690
1233
|
};
|
|
691
1234
|
|
|
692
|
-
// src/utils/recaptcha.ts
|
|
693
|
-
var loadRecaptchaScript = (siteKey) => {
|
|
694
|
-
return new Promise((resolve, reject) => {
|
|
695
|
-
if (typeof grecaptcha !== "undefined") return resolve();
|
|
696
|
-
const existingScript = document.querySelector(
|
|
697
|
-
'script[src*="recaptcha/api.js"]'
|
|
698
|
-
);
|
|
699
|
-
if (existingScript) {
|
|
700
|
-
existingScript.addEventListener("load", () => resolve());
|
|
701
|
-
existingScript.addEventListener(
|
|
702
|
-
"error",
|
|
703
|
-
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
704
|
-
);
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
const script = document.createElement("script");
|
|
708
|
-
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
709
|
-
script.async = true;
|
|
710
|
-
script.defer = true;
|
|
711
|
-
script.onload = () => resolve();
|
|
712
|
-
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
713
|
-
document.head.appendChild(script);
|
|
714
|
-
});
|
|
715
|
-
};
|
|
716
|
-
var getRecaptchaToken = async (action) => {
|
|
717
|
-
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
718
|
-
if (!siteKey) {
|
|
719
|
-
throw new Error(
|
|
720
|
-
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
721
|
-
);
|
|
722
|
-
}
|
|
723
|
-
await loadRecaptchaScript(siteKey);
|
|
724
|
-
return new Promise((resolve, reject) => {
|
|
725
|
-
grecaptcha.ready(() => {
|
|
726
|
-
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
727
|
-
});
|
|
728
|
-
});
|
|
729
|
-
};
|
|
730
|
-
var getPurchaseRecaptchaTokens = async () => {
|
|
731
|
-
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
732
|
-
getRecaptchaToken("checkEligibility"),
|
|
733
|
-
getRecaptchaToken("newBasket"),
|
|
734
|
-
getRecaptchaToken("registerUser")
|
|
735
|
-
]);
|
|
736
|
-
return { checkEligibility, newBasket, registerUser };
|
|
737
|
-
};
|
|
738
|
-
|
|
739
1235
|
// src/utils/expressCheckoutTracking.ts
|
|
740
1236
|
var EXPRESS_CHECKOUT_EVENTS = {
|
|
741
1237
|
/** Wallet button displayed */
|
|
@@ -848,7 +1344,8 @@ async function handleMerchantValidation(event, session, config) {
|
|
|
848
1344
|
return;
|
|
849
1345
|
}
|
|
850
1346
|
session.completeMerchantValidation(response.merchantSession);
|
|
851
|
-
} catch {
|
|
1347
|
+
} catch (err) {
|
|
1348
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
852
1349
|
session.abort();
|
|
853
1350
|
redirectToFallbackCheckout(config);
|
|
854
1351
|
}
|
|
@@ -881,7 +1378,8 @@ function startApplePaySession(config) {
|
|
|
881
1378
|
};
|
|
882
1379
|
trackWalletPaymentSheetOpen(config.skuId);
|
|
883
1380
|
session.begin();
|
|
884
|
-
} catch {
|
|
1381
|
+
} catch (err) {
|
|
1382
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create session", err);
|
|
885
1383
|
redirectToFallbackCheckout(config);
|
|
886
1384
|
}
|
|
887
1385
|
}
|
|
@@ -1069,6 +1567,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1069
1567
|
const result = await performPurchase({
|
|
1070
1568
|
applePayToken: event.payment.token,
|
|
1071
1569
|
skuId: config.skuId,
|
|
1570
|
+
currency: config.currency,
|
|
1072
1571
|
billingContact: event.payment.billingContact,
|
|
1073
1572
|
...event.payment.shippingContact && {
|
|
1074
1573
|
shippingContact: event.payment.shippingContact
|
|
@@ -1419,7 +1918,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1419
1918
|
#returnUrl = "";
|
|
1420
1919
|
#supportedBillingCountries = [];
|
|
1421
1920
|
#entryPoint = "";
|
|
1422
|
-
#
|
|
1921
|
+
#recaptchaTokensPromise = null;
|
|
1423
1922
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1424
1923
|
get offer() {
|
|
1425
1924
|
return this.#offer;
|
|
@@ -1484,6 +1983,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1484
1983
|
this.#paymentOptions = null;
|
|
1485
1984
|
this.#returnUrl = "";
|
|
1486
1985
|
this.#supportedBillingCountries = [];
|
|
1986
|
+
this.#recaptchaTokensPromise = null;
|
|
1487
1987
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1488
1988
|
}
|
|
1489
1989
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
@@ -1497,7 +1997,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1497
1997
|
this.#computeBillingCountries();
|
|
1498
1998
|
if (await this.#fetchAndCacheOptions()) return;
|
|
1499
1999
|
this.#finishLoading();
|
|
1500
|
-
} catch {
|
|
2000
|
+
} catch (err) {
|
|
2001
|
+
console.error("[web-apple-pay] #run: unexpected error, hiding button", err);
|
|
1501
2002
|
this.style.display = "none";
|
|
1502
2003
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1503
2004
|
} finally {
|
|
@@ -1578,16 +2079,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1578
2079
|
if (button.classList.contains("wap-loading")) return;
|
|
1579
2080
|
this.#openModal();
|
|
1580
2081
|
});
|
|
1581
|
-
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1582
|
-
const { skuId, country } = event.detail;
|
|
1583
|
-
this.#initiateApplePay(skuId, country);
|
|
1584
|
-
}, { once: true });
|
|
1585
2082
|
}
|
|
1586
2083
|
#finishLoading() {
|
|
1587
2084
|
const button = this.querySelector(SEL_BUTTON);
|
|
1588
2085
|
if (button) {
|
|
1589
2086
|
button.classList.remove("wap-loading");
|
|
1590
2087
|
this.#updateDisabledState();
|
|
2088
|
+
this.#scheduleRecaptchaTokens();
|
|
1591
2089
|
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
1592
2090
|
entryPoint: this.#entryPoint,
|
|
1593
2091
|
country: this.#country
|
|
@@ -1615,10 +2113,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1615
2113
|
return;
|
|
1616
2114
|
}
|
|
1617
2115
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1618
|
-
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1619
|
-
this.#recaptchaTokens = tokens;
|
|
1620
|
-
}).catch(() => {
|
|
1621
|
-
});
|
|
1622
2116
|
ApplePayModal.define();
|
|
1623
2117
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1624
2118
|
modal.offer = this.#offer;
|
|
@@ -1626,7 +2120,30 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1626
2120
|
if (this.#sessionData?.loggedIn) {
|
|
1627
2121
|
modal.dataset.loggedIn = "true";
|
|
1628
2122
|
}
|
|
1629
|
-
|
|
2123
|
+
const skuId = this.#offer.sku_id;
|
|
2124
|
+
const country = this.#country;
|
|
2125
|
+
modal.onConfirm = (recaptchaTokens) => {
|
|
2126
|
+
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2127
|
+
this.#scheduleRecaptchaTokens();
|
|
2128
|
+
};
|
|
2129
|
+
modal.open(this.#recaptchaTokensPromise);
|
|
2130
|
+
}
|
|
2131
|
+
/**
|
|
2132
|
+
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2133
|
+
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2134
|
+
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2135
|
+
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2136
|
+
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2137
|
+
*/
|
|
2138
|
+
#scheduleRecaptchaTokens() {
|
|
2139
|
+
const attempt = getPurchaseRecaptchaTokens();
|
|
2140
|
+
attempt.catch((err) => {
|
|
2141
|
+
console.error("[web-apple-pay] reCAPTCHA token pre-fetch failed; will retry on modal open", err);
|
|
2142
|
+
if (this.#recaptchaTokensPromise === attempt) {
|
|
2143
|
+
this.#recaptchaTokensPromise = null;
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
this.#recaptchaTokensPromise = attempt;
|
|
1630
2147
|
}
|
|
1631
2148
|
async #fetchSession() {
|
|
1632
2149
|
try {
|
|
@@ -1662,6 +2179,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1662
2179
|
onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
|
|
1663
2180
|
skuId,
|
|
1664
2181
|
country,
|
|
2182
|
+
currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
1665
2183
|
returnUrl: this.#returnUrl,
|
|
1666
2184
|
queryString: buildQueryString(),
|
|
1667
2185
|
supportedBillingCountries: this.#supportedBillingCountries,
|
|
@@ -1669,11 +2187,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1669
2187
|
})
|
|
1670
2188
|
};
|
|
1671
2189
|
}
|
|
1672
|
-
|
|
2190
|
+
#initiateApplePay(skuId, country, recaptchaTokens) {
|
|
1673
2191
|
try {
|
|
1674
2192
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1675
2193
|
const paymentOptions = this.#paymentOptions;
|
|
1676
|
-
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1677
2194
|
startApplePaySession(
|
|
1678
2195
|
this.#buildSessionParams(
|
|
1679
2196
|
skuId,
|