@economist/web-apple-pay 0.1.3-beta.1 → 0.1.3-beta.11

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 CHANGED
@@ -76,7 +76,512 @@ 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">
520
+ Continue with
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ </div>
527
+
528
+ `;
529
+
530
+ // src/clients/payment-checkout/config.ts
531
+ var runtimeConfig = null;
532
+ var configureApplePay = (config) => {
533
+ runtimeConfig = {
534
+ ...config
535
+ };
536
+ };
537
+ var getApplePayConfig = () => runtimeConfig;
538
+
539
+ // src/utils/recaptcha.ts
540
+ var loadRecaptchaScript = (siteKey) => {
541
+ return new Promise((resolve, reject) => {
542
+ if (typeof grecaptcha !== "undefined") return resolve();
543
+ const existingScript = document.querySelector(
544
+ 'script[src*="recaptcha/api.js"]'
545
+ );
546
+ if (existingScript) {
547
+ existingScript.addEventListener("load", () => resolve());
548
+ existingScript.addEventListener(
549
+ "error",
550
+ () => reject(new Error("Failed to load existing reCAPTCHA script"))
551
+ );
552
+ return;
553
+ }
554
+ const script = document.createElement("script");
555
+ script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
556
+ script.async = true;
557
+ script.defer = true;
558
+ script.onload = () => resolve();
559
+ script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
560
+ document.head.appendChild(script);
561
+ });
562
+ };
563
+ var getRecaptchaToken = async (action) => {
564
+ const siteKey = getApplePayConfig()?.recaptchaSiteKey;
565
+ if (!siteKey) {
566
+ throw new Error(
567
+ "[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
568
+ );
569
+ }
570
+ await loadRecaptchaScript(siteKey);
571
+ return new Promise((resolve, reject) => {
572
+ grecaptcha.ready(() => {
573
+ grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
574
+ });
575
+ });
576
+ };
577
+ var getPurchaseRecaptchaTokens = async () => {
578
+ const [checkEligibility, newBasket, registerUser] = await Promise.all([
579
+ getRecaptchaToken("checkEligibility"),
580
+ getRecaptchaToken("newBasket"),
581
+ getRecaptchaToken("registerUser")
582
+ ]);
583
+ return { checkEligibility, newBasket, registerUser };
584
+ };
80
585
 
81
586
  // src/apple-pay-modal.ts
82
587
  function getRenewalDateText(unit, duration) {
@@ -297,6 +802,19 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
297
802
  #country = "";
298
803
  #triggerElement = null;
299
804
  #keyHandler = null;
805
+ #recaptchaTokens = null;
806
+ #recaptchaTokensPromise = null;
807
+ /**
808
+ * Synchronous callback invoked directly from the CTA click handler once the
809
+ * user confirms. The caller (ApplePayButton) must call startApplePaySession
810
+ * inside this callback to preserve the browser's user-gesture chain — Safari
811
+ * requires new ApplePaySession() to execute within the original click stack.
812
+ *
813
+ * reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
814
+ * until the token pre-fetch resolves, so this callback is never reached
815
+ * without valid tokens.
816
+ */
817
+ onConfirm = null;
300
818
  set offer(value) {
301
819
  this.#offer = value;
302
820
  }
@@ -317,7 +835,6 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
317
835
  const offer = this.#offer;
318
836
  const country = this.#country;
319
837
  if (!offer) {
320
- console.error("ApplePayModal: Missing or invalid offer data");
321
838
  this.remove();
322
839
  return;
323
840
  }
@@ -392,19 +909,32 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
392
909
  }
393
910
  });
394
911
  }
912
+ if (this.#recaptchaTokensPromise) {
913
+ if (cta) {
914
+ cta.setAttribute("disabled", "");
915
+ cta.setAttribute("aria-disabled", "true");
916
+ cta.setAttribute("aria-busy", "true");
917
+ }
918
+ this.#recaptchaTokensPromise.then((tokens) => {
919
+ this.#recaptchaTokens = tokens;
920
+ if (cta) {
921
+ cta.removeAttribute("disabled");
922
+ cta.removeAttribute("aria-disabled");
923
+ cta.removeAttribute("aria-busy");
924
+ }
925
+ }).catch(() => {
926
+ console.error("[web-apple-pay] apple-pay-modal: failed to pre-fetch reCAPTCHA tokens; CTA remains disabled");
927
+ });
928
+ }
395
929
  cta?.addEventListener("click", () => {
396
930
  if (isUS && checkbox && !checkbox.checked) {
397
931
  errorElement?.classList.add("apm__error--visible");
398
932
  checkboxLabel?.classList.add("apm__checkbox-label--error");
399
933
  return;
400
934
  }
401
- this.dispatchEvent(
402
- new CustomEvent("apple-pay-confirmed", {
403
- bubbles: true,
404
- composed: true,
405
- detail: { skuId: offer.sku_id, country }
406
- })
407
- );
935
+ if (this.#recaptchaTokens) {
936
+ this.onConfirm?.(this.#recaptchaTokens);
937
+ }
408
938
  this.close();
409
939
  });
410
940
  this.querySelector("#apple-pay-modal-close")?.addEventListener(
@@ -412,7 +942,8 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
412
942
  () => this.close()
413
943
  );
414
944
  }
415
- open() {
945
+ open(recaptchaTokensPromise) {
946
+ this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
416
947
  this.#triggerElement = document.activeElement;
417
948
  document.body.appendChild(this);
418
949
  this.#keyHandler = (event) => {
@@ -525,15 +1056,6 @@ var apple_pay_button_template_default = `<style>
525
1056
  </div>
526
1057
  `;
527
1058
 
528
- // src/clients/payment-checkout/config.ts
529
- var runtimeConfig = null;
530
- var configureApplePay = (config) => {
531
- runtimeConfig = {
532
- ...config
533
- };
534
- };
535
- var getApplePayConfig = () => runtimeConfig;
536
-
537
1059
  // src/clients/payment-checkout/detects.ts
538
1060
  var isAppleDeviceOrSafari = () => {
539
1061
  const isIOSOrMacTouchDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.maxTouchPoints > 1 && /Macintosh/.test(navigator.userAgent);
@@ -543,20 +1065,25 @@ var isAppleDeviceOrSafari = () => {
543
1065
  var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
544
1066
  var isApplePayAvailable = async () => {
545
1067
  if (bypassApplePayChecks()) {
1068
+ console.debug("[web-apple-pay] isApplePayAvailable: bypass enabled, returning true");
546
1069
  return true;
547
1070
  }
548
1071
  if (!isAppleDeviceOrSafari()) {
1072
+ console.debug("[web-apple-pay] isApplePayAvailable: not an Apple device or Safari", { userAgent: navigator.userAgent });
549
1073
  return false;
550
1074
  }
551
1075
  const applePaySession = window.ApplePaySession;
552
1076
  if (!applePaySession) {
1077
+ console.debug("[web-apple-pay] isApplePayAvailable: ApplePaySession not present on window");
553
1078
  return false;
554
1079
  }
555
1080
  try {
556
1081
  if (typeof applePaySession.canMakePayments !== "function") {
1082
+ console.debug("[web-apple-pay] isApplePayAvailable: canMakePayments is not a function");
557
1083
  return false;
558
1084
  }
559
1085
  if (!applePaySession.canMakePayments()) {
1086
+ console.debug("[web-apple-pay] isApplePayAvailable: canMakePayments() returned false");
560
1087
  return false;
561
1088
  }
562
1089
  const merchantId = getApplePayConfig()?.merchantId;
@@ -566,7 +1093,9 @@ var isApplePayAvailable = async () => {
566
1093
  );
567
1094
  return false;
568
1095
  }
569
- return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
1096
+ const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
1097
+ console.debug("[web-apple-pay] isApplePayAvailable: canMakePaymentsWithActiveCard =", hasActiveCard, { merchantId });
1098
+ return hasActiveCard;
570
1099
  } catch (error) {
571
1100
  console.error("Error checking Apple Pay active card status:", error);
572
1101
  return false;
@@ -640,6 +1169,7 @@ var validateAppleMerchant = (data) => {
640
1169
  });
641
1170
  };
642
1171
  var performPurchase = (data) => {
1172
+ console.log("[web-apple-pay] performPurchase request", JSON.stringify(data, null, 2));
643
1173
  return apiFetch("/v1/wallet/purchase", {
644
1174
  method: "POST",
645
1175
  body: JSON.stringify(data),
@@ -695,53 +1225,6 @@ var redirectToCheckoutFallback = (params) => {
695
1225
  return url.pathname + url.search;
696
1226
  };
697
1227
 
698
- // src/utils/recaptcha.ts
699
- var loadRecaptchaScript = (siteKey) => {
700
- return new Promise((resolve, reject) => {
701
- if (typeof grecaptcha !== "undefined") return resolve();
702
- const existingScript = document.querySelector(
703
- 'script[src*="recaptcha/api.js"]'
704
- );
705
- if (existingScript) {
706
- existingScript.addEventListener("load", () => resolve());
707
- existingScript.addEventListener(
708
- "error",
709
- () => reject(new Error("Failed to load existing reCAPTCHA script"))
710
- );
711
- return;
712
- }
713
- const script = document.createElement("script");
714
- script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
715
- script.async = true;
716
- script.defer = true;
717
- script.onload = () => resolve();
718
- script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
719
- document.head.appendChild(script);
720
- });
721
- };
722
- var getRecaptchaToken = async (action) => {
723
- const siteKey = getApplePayConfig()?.recaptchaSiteKey;
724
- if (!siteKey) {
725
- throw new Error(
726
- "[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
727
- );
728
- }
729
- await loadRecaptchaScript(siteKey);
730
- return new Promise((resolve, reject) => {
731
- grecaptcha.ready(() => {
732
- grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
733
- });
734
- });
735
- };
736
- var getPurchaseRecaptchaTokens = async () => {
737
- const [checkEligibility, newBasket, registerUser] = await Promise.all([
738
- getRecaptchaToken("checkEligibility"),
739
- getRecaptchaToken("newBasket"),
740
- getRecaptchaToken("registerUser")
741
- ]);
742
- return { checkEligibility, newBasket, registerUser };
743
- };
744
-
745
1228
  // src/utils/expressCheckoutTracking.ts
746
1229
  var EXPRESS_CHECKOUT_EVENTS = {
747
1230
  /** Wallet button displayed */
@@ -827,7 +1310,52 @@ var MSG_EMAIL_COLLISION = "This email address is already linked to an account. P
827
1310
  var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
828
1311
 
829
1312
  // src/clients/payment-checkout/apple-session.ts
1313
+ function redirectToFallbackCheckout(config) {
1314
+ trackFallbackCheckout(config.skuId);
1315
+ window.location.href = redirectToCheckoutFallback({
1316
+ skuId: config.skuId,
1317
+ returnUrl: config.returnUrl,
1318
+ inlineError: MSG_PAYMENT_GENERIC_ERROR
1319
+ });
1320
+ }
1321
+ async function handleMerchantValidation(event, session, config) {
1322
+ console.debug("[web-apple-pay] onvalidatemerchant: validating", { validationURL: event.validationURL });
1323
+ try {
1324
+ const validationHost = new URL(event.validationURL).host;
1325
+ if (!validationHost.endsWith("apple.com")) {
1326
+ console.debug("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
1327
+ session.abort();
1328
+ redirectToFallbackCheckout(config);
1329
+ return;
1330
+ }
1331
+ const recaptchaToken = await getRecaptchaToken("verifyMerchant");
1332
+ const response = await validateAppleMerchant({
1333
+ validationURL: event.validationURL,
1334
+ recaptchaToken
1335
+ });
1336
+ if (!response?.merchantSession) {
1337
+ console.debug("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
1338
+ session.abort();
1339
+ redirectToFallbackCheckout(config);
1340
+ return;
1341
+ }
1342
+ console.debug("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
1343
+ session.completeMerchantValidation(response.merchantSession);
1344
+ } catch (err) {
1345
+ console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
1346
+ session.abort();
1347
+ redirectToFallbackCheckout(config);
1348
+ }
1349
+ }
830
1350
  function startApplePaySession(config) {
1351
+ console.debug("[web-apple-pay] startApplePaySession: starting session", {
1352
+ skuId: config.skuId,
1353
+ countryCode: config.countryCode,
1354
+ currencyCode: config.currencyCode,
1355
+ supportedNetworks: config.supportedNetworks,
1356
+ totalAmount: config.totalAmount,
1357
+ userLoggedIn: config.userLoggedIn
1358
+ });
831
1359
  const paymentRequest = {
832
1360
  countryCode: config.countryCode,
833
1361
  currencyCode: config.currencyCode,
@@ -841,55 +1369,27 @@ function startApplePaySession(config) {
841
1369
  // Only request email from Apple Pay sheet if user is NOT logged in
842
1370
  ...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
843
1371
  };
844
- const session = new ApplePaySession(3, paymentRequest);
845
- session.onvalidatemerchant = async (event) => {
846
- try {
847
- const validationHost = new URL(event.validationURL).host;
848
- if (!validationHost.endsWith("apple.com")) {
849
- trackFallbackCheckout(config.skuId);
850
- session.abort();
851
- window.location.href = redirectToCheckoutFallback({
852
- skuId: config.skuId,
853
- returnUrl: config.returnUrl,
854
- inlineError: MSG_PAYMENT_GENERIC_ERROR
855
- });
856
- return;
857
- }
858
- const recaptchaToken = await getRecaptchaToken("verifyMerchant");
859
- const response = await validateAppleMerchant({
860
- validationURL: event.validationURL,
861
- recaptchaToken
862
- });
863
- if (!response?.merchantSession) {
864
- trackFallbackCheckout(config.skuId);
865
- session.abort();
866
- window.location.href = redirectToCheckoutFallback({
867
- skuId: config.skuId,
868
- returnUrl: config.returnUrl,
869
- inlineError: MSG_PAYMENT_GENERIC_ERROR
870
- });
871
- return;
872
- }
873
- session.completeMerchantValidation(response.merchantSession);
874
- } catch {
875
- trackFallbackCheckout(config.skuId);
876
- session.abort();
877
- window.location.href = redirectToCheckoutFallback({
878
- skuId: config.skuId,
879
- returnUrl: config.returnUrl,
880
- inlineError: MSG_PAYMENT_GENERIC_ERROR
881
- });
882
- }
883
- };
884
- session.onpaymentauthorized = (event) => {
885
- trackWalletPaymentAuthorised(config.skuId);
886
- config.onPaymentAuthorized(event, session);
887
- };
888
- session.oncancel = () => {
889
- config.onCancel?.();
890
- };
891
- trackWalletPaymentSheetOpen(config.skuId);
892
- session.begin();
1372
+ try {
1373
+ const session = new ApplePaySession(3, paymentRequest);
1374
+ session.onvalidatemerchant = async (event) => {
1375
+ await handleMerchantValidation(event, session, config);
1376
+ };
1377
+ session.onpaymentauthorized = (event) => {
1378
+ console.debug("[web-apple-pay] onpaymentauthorized: payment authorised");
1379
+ trackWalletPaymentAuthorised(config.skuId);
1380
+ config.onPaymentAuthorized(event, session);
1381
+ };
1382
+ session.oncancel = () => {
1383
+ console.debug("[web-apple-pay] oncancel: user cancelled Apple Pay sheet");
1384
+ config.onCancel?.();
1385
+ };
1386
+ console.debug("[web-apple-pay] startApplePaySession: session.begin()");
1387
+ trackWalletPaymentSheetOpen(config.skuId);
1388
+ session.begin();
1389
+ } catch (err) {
1390
+ console.error("[web-apple-pay] startApplePaySession: failed to create session", err);
1391
+ redirectToFallbackCheckout(config);
1392
+ }
893
1393
  }
894
1394
 
895
1395
  // src/clients/payment-checkout/contact-validation.ts
@@ -1072,9 +1572,11 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1072
1572
  sessionData,
1073
1573
  config.supportedBillingCountries
1074
1574
  );
1575
+ console.log("[web-apple-pay] performPurchase currency", { skuId, currency: config.currency });
1075
1576
  const result = await performPurchase({
1076
1577
  applePayToken: event.payment.token,
1077
1578
  skuId: config.skuId,
1579
+ currency: config.currency,
1078
1580
  billingContact: event.payment.billingContact,
1079
1581
  ...event.payment.shippingContact && {
1080
1582
  shippingContact: event.payment.shippingContact
@@ -1390,11 +1892,15 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1390
1892
  * Creates and configures an ApplePayButton if the feature flag is present.
1391
1893
  */
1392
1894
  static createIfEnabled(offer, country, entryPoint) {
1393
- if (!offer) return null;
1394
- if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant))
1895
+ if (!offer) {
1896
+ return null;
1897
+ }
1898
+ if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
1395
1899
  return null;
1396
- if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT))
1900
+ }
1901
+ if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
1397
1902
  return null;
1903
+ }
1398
1904
  _ApplePayButton.define();
1399
1905
  const button = document.createElement(_ApplePayButton.tag);
1400
1906
  button.offer = offer;
@@ -1421,6 +1927,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1421
1927
  #returnUrl = "";
1422
1928
  #supportedBillingCountries = [];
1423
1929
  #entryPoint = "";
1930
+ #recaptchaTokensPromise = null;
1424
1931
  // ─── Public API ─────────────────────────────────────────────────────────────
1425
1932
  get offer() {
1426
1933
  return this.#offer;
@@ -1485,10 +1992,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1485
1992
  this.#paymentOptions = null;
1486
1993
  this.#returnUrl = "";
1487
1994
  this.#supportedBillingCountries = [];
1995
+ this.#recaptchaTokensPromise = null;
1488
1996
  this.querySelector(SEL_CONTAINER)?.remove();
1489
1997
  }
1490
1998
  // ─── Render pipeline ────────────────────────────────────────────────────────
1491
1999
  async #run() {
2000
+ console.debug("[web-apple-pay] #run: start");
1492
2001
  try {
1493
2002
  if (await this.#checkAvailability()) return;
1494
2003
  if (this.#checkOffer()) return;
@@ -1498,7 +2007,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1498
2007
  this.#computeBillingCountries();
1499
2008
  if (await this.#fetchAndCacheOptions()) return;
1500
2009
  this.#finishLoading();
1501
- } catch {
2010
+ } catch (err) {
2011
+ console.error("[web-apple-pay] #run: unexpected error, hiding button", err);
1502
2012
  this.style.display = "none";
1503
2013
  this.querySelector(SEL_CONTAINER)?.remove();
1504
2014
  } finally {
@@ -1509,9 +2019,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1509
2019
  async #checkAvailability() {
1510
2020
  const available = await isApplePayAvailable();
1511
2021
  if (!available) {
2022
+ console.debug("[web-apple-pay] #checkAvailability: not available on this device/browser");
1512
2023
  this.style.display = "none";
1513
2024
  return true;
1514
2025
  }
2026
+ console.debug("[web-apple-pay] #checkAvailability: ok");
1515
2027
  return false;
1516
2028
  }
1517
2029
  /**
@@ -1520,19 +2032,24 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1520
2032
  */
1521
2033
  async #checkSession() {
1522
2034
  this.#sessionData = await this.#fetchSession();
2035
+ console.debug("[web-apple-pay] #checkSession: session data", { loggedIn: this.#sessionData?.loggedIn, userType: this.#sessionData?.userType });
1523
2036
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
2037
+ console.debug("[web-apple-pay] #checkSession: ineligible user, hiding button", { userType: this.#sessionData.userType });
1524
2038
  this.style.display = "none";
1525
2039
  this.querySelector(SEL_CONTAINER)?.remove();
1526
2040
  return true;
1527
2041
  }
2042
+ console.debug("[web-apple-pay] #checkSession: ok");
1528
2043
  return false;
1529
2044
  }
1530
2045
  /** Returns `true` (hide) when no offer has been set before mount. */
1531
2046
  #checkOffer() {
1532
2047
  if (!this.#offer) {
2048
+ console.debug("[web-apple-pay] #checkOffer: no offer set, hiding button");
1533
2049
  this.style.display = "none";
1534
2050
  return true;
1535
2051
  }
2052
+ console.debug("[web-apple-pay] #checkOffer: ok", { skuId: this.#offer.sku_id });
1536
2053
  return false;
1537
2054
  }
1538
2055
  /** Captures the current page URL once at mount for reuse across the session lifetime. */
@@ -1556,15 +2073,19 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1556
2073
  */
1557
2074
  async #fetchAndCacheOptions() {
1558
2075
  this.#paymentOptions = await this.#fetchPaymentOptions();
1559
- if (!this.#paymentOptions?.apple_pay) {
2076
+ console.debug("[web-apple-pay] #fetchAndCacheOptions: payment options", this.#paymentOptions);
2077
+ if (!this.#paymentOptions?.options?.apple_pay) {
2078
+ console.debug("[web-apple-pay] #fetchAndCacheOptions: apple_pay absent in options, hiding button");
1560
2079
  this.style.display = "none";
1561
2080
  this.querySelector(SEL_CONTAINER)?.remove();
1562
2081
  return true;
1563
2082
  }
2083
+ console.debug("[web-apple-pay] #fetchAndCacheOptions: ok", this.#paymentOptions.options.apple_pay);
1564
2084
  return false;
1565
2085
  }
1566
2086
  /** Injects the button template and wires click and confirm event listeners. */
1567
2087
  #renderTemplate() {
2088
+ console.debug("[web-apple-pay] #renderTemplate: injecting button template");
1568
2089
  this.style.removeProperty("display");
1569
2090
  ensureApplePayLogoSymbol();
1570
2091
  const template = document.createElement("template");
@@ -1579,16 +2100,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1579
2100
  if (button.classList.contains("wap-loading")) return;
1580
2101
  this.#openModal();
1581
2102
  });
1582
- this.addEventListener("apple-pay-confirmed", (event) => {
1583
- const { skuId, country } = event.detail;
1584
- this.#initiateApplePay(skuId, country);
1585
- });
1586
2103
  }
1587
2104
  #finishLoading() {
2105
+ console.debug("[web-apple-pay] #finishLoading: all checks passed, enabling button");
1588
2106
  const button = this.querySelector(SEL_BUTTON);
1589
2107
  if (button) {
1590
2108
  button.classList.remove("wap-loading");
1591
2109
  this.#updateDisabledState();
2110
+ this.#recaptchaTokensPromise = getPurchaseRecaptchaTokens();
1592
2111
  trackExpressWalletImpression(this.#offer.sku_id, {
1593
2112
  entryPoint: this.#entryPoint,
1594
2113
  country: this.#country
@@ -1609,7 +2128,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1609
2128
  button.setAttribute("aria-disabled", "true");
1610
2129
  }
1611
2130
  #openModal() {
1612
- if (!this.#offer || document.querySelector(ApplePayModal.tag)) return;
2131
+ if (!this.#offer) {
2132
+ return;
2133
+ }
2134
+ if (document.querySelector(ApplePayModal.tag)) {
2135
+ return;
2136
+ }
1613
2137
  trackExpressWalletClick(this.#offer.sku_id);
1614
2138
  ApplePayModal.define();
1615
2139
  const modal = document.createElement(ApplePayModal.tag);
@@ -1618,7 +2142,12 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1618
2142
  if (this.#sessionData?.loggedIn) {
1619
2143
  modal.dataset.loggedIn = "true";
1620
2144
  }
1621
- modal.open();
2145
+ const { skuId, country } = { skuId: this.#offer.sku_id, country: this.#country };
2146
+ modal.onConfirm = (recaptchaTokens) => {
2147
+ this.#initiateApplePay(skuId, country, recaptchaTokens);
2148
+ };
2149
+ modal.open(this.#recaptchaTokensPromise ?? void 0);
2150
+ this.#recaptchaTokensPromise = getPurchaseRecaptchaTokens();
1622
2151
  }
1623
2152
  async #fetchSession() {
1624
2153
  try {
@@ -1645,7 +2174,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1645
2174
  return {
1646
2175
  countryCode: country,
1647
2176
  currencyCode: offer.price?.currency_code ?? DEFAULT_CURRENCY,
1648
- supportedNetworks: paymentOptions.apple_pay.settings.supported_networks,
2177
+ supportedNetworks: paymentOptions.options.apple_pay.settings.supported_networks,
1649
2178
  totalAmount,
1650
2179
  totalLabel: TOTAL_LABEL,
1651
2180
  skuId,
@@ -1654,6 +2183,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1654
2183
  onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
1655
2184
  skuId,
1656
2185
  country,
2186
+ currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
1657
2187
  returnUrl: this.#returnUrl,
1658
2188
  queryString: buildQueryString(),
1659
2189
  supportedBillingCountries: this.#supportedBillingCountries,
@@ -1661,11 +2191,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1661
2191
  })
1662
2192
  };
1663
2193
  }
1664
- async #initiateApplePay(skuId, country) {
2194
+ #initiateApplePay(skuId, country, recaptchaTokens) {
1665
2195
  try {
1666
2196
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
1667
2197
  const paymentOptions = this.#paymentOptions;
1668
- const recaptchaTokens = await getPurchaseRecaptchaTokens();
1669
2198
  startApplePaySession(
1670
2199
  this.#buildSessionParams(
1671
2200
  skuId,