@economist/web-apple-pay 0.1.3-beta.3 → 0.1.3-beta.30
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 +829 -162
- package/dist/src/apple-pay-button.d.ts +4 -3
- package/dist/src/apple-pay-button.js +815 -157
- package/dist/src/apple-pay-button.stories.js +841 -165
- package/dist/src/apple-pay-logo.js +1 -1
- package/dist/src/apple-pay-modal.d.ts +16 -1
- package/dist/src/apple-pay-modal.js +600 -26
- package/dist/src/apple-pay-modal.stories.js +815 -157
- package/dist/src/clients/payment-checkout/apple-session.js +57 -50
- package/dist/src/clients/payment-checkout/detects.js +2 -5
- package/dist/src/clients/payment-checkout/payment-handler.js +1 -2
- package/dist/src/clients/payment-checkout/types.d.ts +6 -4
- package/dist/src/constants.d.ts +5 -0
- package/dist/src/constants.js +10 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +829 -162
- package/dist/src/stories/utils/story-env.js +18 -0
- package/dist/src/utils/expressCheckoutRedirect.d.ts +5 -1
- package/dist/src/utils/expressCheckoutRedirect.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -71,12 +71,547 @@ function ensureApplePayLogoSymbol() {
|
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
const tmp = document.createElement("div");
|
|
74
|
-
tmp.innerHTML = `<svg aria-hidden="true" style="display:none" id="${LOGO_DEFS_ID}"><defs><symbol id="apple-pay-logo" viewBox="0 0 51 22"><path d="${LOGO_PATH}" fill="
|
|
74
|
+
tmp.innerHTML = `<svg aria-hidden="true" style="display:none" id="${LOGO_DEFS_ID}"><defs><symbol id="apple-pay-logo" viewBox="0 0 51 22"><path d="${LOGO_PATH}" fill="currentColor"/></symbol></defs></svg>`;
|
|
75
75
|
document.body.prepend(tmp.firstElementChild);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// src/templates/apple-pay-modal.template.html
|
|
79
|
-
var apple_pay_modal_template_default = '<style>\n .apm-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 97;\n background: rgba(13, 13, 13, 0.7);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--wall-gutter, 2rem);\n box-sizing: border-box;\n }\n\n .apm {\n position: relative;\n background: #fff;\n border-radius: 0.5rem 0.5rem 0 0;\n border: 0.0625rem solid #d9d9d9;\n padding: var(--mb-spacing-lg, 1.5rem);\n width: 25rem;\n max-width: 25rem;\n box-sizing: border-box;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n box-shadow: 0 0.25rem 1rem 0 rgba(13, 13, 13, 0.15);\n }\n\n .apm__close {\n position: absolute;\n top: 1.5rem;\n right: 1.3125rem;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .apm__close:focus {\n outline: solid 0.125rem var(--focus-border-color, #121212);\n border-radius: 0.25rem;\n }\n\n .apm__offer-name {\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-title-3-size, 1.25rem);\n font-weight: 500;\n color: var(--mb-colour-greyscale-london-5, #0d0d0d);\n line-height: var(--mb-typestyle-title-3-leading, 1.75rem);\n font-style: normal;\n margin: 0 1.5rem 0.5rem 0;\n }\n\n .apm__due-today {\n color: #1a1a1a;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n font-style: normal;\n font-weight: 400;\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n margin: 0 0 0.75rem 0;\n }\n\n .apm__rule {\n border: none;\n border-top: 0.0625rem solid #d9d9d9;\n margin: 0 0 1rem 0;\n }\n\n .apm__terms {\n color: #1a1a1a;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n font-style: normal;\n font-weight: 400;\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n margin: 0 0 1rem 0;\n }\n\n .apm__terms-bullets {\n list-style: disc outside;\n padding-left: 1.25rem;\n margin: 0 0 0.75rem 0;\n }\n\n .apm__terms-bullets li {\n margin-bottom: 0.375rem;\n }\n\n .apm__terms-legal {\n margin: 0;\n }\n\n .apm__passive-terms {\n font-family: var(--wall-type-system-sans);\n font-size: 0.9375rem;\n color: #0d0d0d;\n line-height: 1.4;\n margin: 0 0 8px 0;\n }\n\n .apm__passive-terms a {\n color: #1a1a1a;\n font-weight: 700;\n text-decoration: underline;\n }\n\n .apm__checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: var(--mb-spacing-sm, 0.5rem);\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n color: var(--mb-colour-greyscale-london-20, #1a1a1a);\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n cursor: pointer;\n margin: 0 0 1.5rem 0;\n }\n\n .apm__checkbox-label--error {\n margin-bottom: 0.25rem;\n }\n\n .apm__checkbox-wrapper {\n position: relative;\n flex-shrink: 0;\n width: 1.25rem;\n height: 1.25rem;\n margin-top: 0.0625rem;\n }\n\n .apm__checkbox-input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n z-index: 1;\n }\n\n .apm__checkbox-custom {\n position: absolute;\n top: 0;\n left: 0;\n width: 1.25rem;\n height: 1.25rem;\n pointer-events: none;\n }\n\n .apm__checkbox-custom svg {\n display: none;\n width: 1.25rem;\n height: 1.25rem;\n }\n\n .apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {\n display: block;\n }\n\n .apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {\n display: block;\n }\n\n .apm__checkbox-label--error\n .apm__checkbox-input:not(:checked)\n ~ .apm__checkbox-custom\n .svg-unchecked {\n display: none;\n }\n\n .apm__checkbox-label--error\n .apm__checkbox-input:not(:checked)\n ~ .apm__checkbox-custom\n .svg-error {\n display: block;\n }\n\n .apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {\n outline: solid 0.125rem #c91d42;\n outline-offset: 0.125rem;\n border-radius: 0.25rem;\n }\n\n .apm__checkbox-label a {\n color: #1a1a1a;\n font-weight: 700;\n text-decoration: underline;\n }\n\n .apm__error {\n display: none;\n align-items: center;\n gap: 0.75rem;\n color: var(--mb-colour-greyscale-london-5, #0d0d0d);\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-style: normal;\n font-weight: 500;\n line-height: 1.5rem;\n margin-bottom: 1rem;\n }\n\n .apm__error--visible {\n display: flex;\n }\n\n .apm__cta {\n display: flex;\n width: 100%;\n height: 2.75rem;\n padding: 0.375rem 1rem;\n justify-content: center;\n align-items: center;\n gap: 0.375rem;\n border-radius: 0.25rem;\n background: #000;\n border: none;\n cursor: pointer;\n color: #fff;\n text-align: center;\n font-family: var(\n --mb-typeface-sans,\n var(--wall-type-system-sans, system-ui, sans-serif)\n );\n font-size: 1.25rem;\n font-style: normal;\n font-weight: 500;\n line-height: normal;\n }\n\n .apm__cta svg {\n flex-shrink: 0;\n display: block;\n }\n\n @media (min-width: 22.5rem) and (max-width: 37.5rem) {\n .apm {\n width: 24.375rem;\n max-width: 24.375rem;\n }\n }\n\n @media (min-width: 37.5625rem) {\n .apm {\n border-radius: 0.5rem;\n }\n }\n\n @media (max-width: 22.4375rem) {\n .apm {\n width: 20rem;\n max-width: 20rem;\n }\n }\n\n @media (max-width: 26.1875rem) {\n .apm__cta {\n font-size: 1.125rem;\n }\n }\n</style>\n\n<div class="apm-overlay" id="apple-pay-modal-overlay">\n <div\n class="apm"\n role="dialog"\n aria-modal="true"\n aria-labelledby="apple-pay-modal-offer-name"\n id="apple-pay-modal"\n tabindex="-1"\n >\n <button class="apm__close" id="apple-pay-modal-close" aria-label="Close">\n <svg\n aria-hidden="true"\n xmlns="http://www.w3.org/2000/svg"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n >\n <g clip-path="url(#clip0_15712_93054)">\n <rect width="24" height="24" fill="white" fill-opacity="0.01" />\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M0 0H24V24H0V0Z"\n fill="white"\n fill-opacity="0.01"\n />\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M18.75 6.60964L17.3904 5.25L12 10.6404L6.60964 5.25L5.25 6.60964L10.6404 12L5.25 17.3904L6.60964 18.75L12 13.3596L17.3904 18.75L18.75 17.3904L13.3596 12L18.75 6.60964Z"\n fill="#333333"\n />\n </g>\n <defs>\n <clipPath id="clip0_15712_93054">\n <rect width="24" height="24" fill="white" />\n </clipPath>\n </defs>\n </svg>\n </button>\n <p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>\n <p class="apm__due-today" id="apple-pay-modal-due-today"></p>\n <hr class="apm__rule" />\n <div class="apm__terms" id="apple-pay-modal-terms"></div>\n <p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>\n <label\n class="apm__checkbox-label"\n id="apple-pay-modal-checkbox-label"\n for="apple-pay-modal-checkbox"\n >\n <div class="apm__checkbox-wrapper">\n <input\n class="apm__checkbox-input"\n type="checkbox"\n id="apple-pay-modal-checkbox"\n />\n <span class="apm__checkbox-custom">\n <svg\n aria-hidden="true"\n class="svg-unchecked"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"\n fill="white"\n stroke="#595959"\n />\n </svg>\n <svg\n aria-hidden="true"\n class="svg-checked"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <g clip-path="url(#clip0_20014_9555)">\n <path\n d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"\n fill="#333333"\n />\n <path\n d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"\n fill="white"\n />\n </g>\n <defs>\n <clipPath id="clip0_20014_9555">\n <path\n d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"\n fill="white"\n />\n </clipPath>\n </defs>\n </svg>\n <svg\n aria-hidden="true"\n class="svg-error"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"\n fill="white"\n stroke="#C91D42"\n stroke-width="2"\n />\n </svg>\n </span>\n </div>\n <span id="apple-pay-modal-checkbox-text"></span>\n </label>\n <div class="apm__error" id="apple-pay-modal-error" role="alert">\n <svg\n aria-hidden="true"\n width="20"\n height="20"\n viewBox="0 0 20 20"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2ZM0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM11 13C11 13.5523 10.5523 14 10 14C9.44772 14 9 13.5523 9 13C9 12.4477 9.44772 12 10 12C10.5523 12 11 12.4477 11 13ZM10 6C10.5523 6 11 6.44772 11 7V10C11 10.5523 10.5523 11 10 11C9.44772 11 9 10.5523 9 10V7C9 6.44772 9.44772 6 10 6Z"\n fill="#C91D42"\n />\n </svg>\n Please accept the terms to continue\n </div>\n <button class="apm__cta" id="apple-pay-modal-cta">\n Continue with\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n </div>\n</div>\n\n';
|
|
79
|
+
var apple_pay_modal_template_default = `<style>
|
|
80
|
+
.apm-overlay {
|
|
81
|
+
position: fixed;
|
|
82
|
+
top: 0;
|
|
83
|
+
left: 0;
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
z-index: 97;
|
|
87
|
+
background: rgba(13, 13, 13, 0.7);
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
justify-content: center;
|
|
91
|
+
padding: var(--wall-gutter, 2rem);
|
|
92
|
+
box-sizing: border-box;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.apm {
|
|
96
|
+
position: relative;
|
|
97
|
+
background: #fff;
|
|
98
|
+
border-radius: 0.5rem 0.5rem 0 0;
|
|
99
|
+
border: 0.0625rem solid #d9d9d9;
|
|
100
|
+
padding: var(--mb-spacing-lg, 1.5rem);
|
|
101
|
+
width: 25rem;
|
|
102
|
+
max-width: 25rem;
|
|
103
|
+
box-sizing: border-box;
|
|
104
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
105
|
+
box-shadow: 0 0.25rem 1rem 0 rgba(13, 13, 13, 0.15);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.apm__close {
|
|
109
|
+
position: absolute;
|
|
110
|
+
top: 1.5rem;
|
|
111
|
+
right: 1.3125rem;
|
|
112
|
+
background: transparent;
|
|
113
|
+
border: none;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
padding: 0;
|
|
116
|
+
width: 1.5rem;
|
|
117
|
+
height: 1.5rem;
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
justify-content: center;
|
|
121
|
+
color: var(--mb-colour-greyscale-london-20, #1a1a1a);
|
|
122
|
+
transition:
|
|
123
|
+
background-color ease-in-out 0.2s,
|
|
124
|
+
color ease-in-out 0.2s;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.apm__close:hover {
|
|
128
|
+
color: var(--mb-colour-base-chicago-30, #333333);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.apm__close:active {
|
|
132
|
+
background-color: var(--mb-colour-base-chicago-90, #e6e6e6);
|
|
133
|
+
color: var(--mb-colour-base-chicago-30, #333333);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.apm__close:focus {
|
|
137
|
+
background-color: var(--mb-colour-base-chicago-90, #e6e6e6);
|
|
138
|
+
outline: solid 0.125rem var(--focus-border-color, #121212);
|
|
139
|
+
border-radius: 0.25rem;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.apm__offer-name {
|
|
143
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
144
|
+
font-size: var(--mb-typestyle-title-3-size, 1.25rem);
|
|
145
|
+
font-weight: 500;
|
|
146
|
+
color: var(--mb-colour-greyscale-london-5, #0d0d0d);
|
|
147
|
+
line-height: var(--mb-typestyle-title-3-leading, 1.75rem);
|
|
148
|
+
font-style: normal;
|
|
149
|
+
margin: 0 1.5rem 0.5rem 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.apm__due-today {
|
|
153
|
+
color: #1a1a1a;
|
|
154
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
155
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
156
|
+
font-style: normal;
|
|
157
|
+
font-weight: 400;
|
|
158
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
159
|
+
margin: 0 0 0.75rem 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.apm__rule {
|
|
163
|
+
border: none;
|
|
164
|
+
border-top: 0.0625rem solid #d9d9d9;
|
|
165
|
+
margin: 0 0 1rem 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.apm__terms {
|
|
169
|
+
color: #1a1a1a;
|
|
170
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
171
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
172
|
+
font-style: normal;
|
|
173
|
+
font-weight: 400;
|
|
174
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
175
|
+
margin: 0 0 1rem 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.apm__terms-bullets {
|
|
179
|
+
list-style: disc outside;
|
|
180
|
+
padding-left: 1.25rem;
|
|
181
|
+
margin: 0 0 0.75rem 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.apm__terms-bullets li {
|
|
185
|
+
margin-bottom: 0.375rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.apm__terms-legal {
|
|
189
|
+
margin: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.apm__passive-terms {
|
|
193
|
+
font-family: var(--wall-type-system-sans);
|
|
194
|
+
font-size: 0.9375rem;
|
|
195
|
+
color: #0d0d0d;
|
|
196
|
+
line-height: 1.4;
|
|
197
|
+
margin: 0 0 8px 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.apm__passive-terms a {
|
|
201
|
+
color: #1a1a1a;
|
|
202
|
+
font-weight: 700;
|
|
203
|
+
text-decoration: underline;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.apm__checkbox-label {
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: flex-start;
|
|
209
|
+
gap: var(--mb-spacing-sm, 0.5rem);
|
|
210
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
211
|
+
font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
|
|
212
|
+
color: var(--mb-colour-greyscale-london-20, #1a1a1a);
|
|
213
|
+
line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
margin: 0 0 1.5rem 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.apm__checkbox-label--error {
|
|
219
|
+
margin-bottom: 0.25rem;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.apm__checkbox-wrapper {
|
|
223
|
+
position: relative;
|
|
224
|
+
flex-shrink: 0;
|
|
225
|
+
width: 1.25rem;
|
|
226
|
+
height: 1.25rem;
|
|
227
|
+
margin-top: 0.0625rem;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.apm__checkbox-input {
|
|
231
|
+
position: absolute;
|
|
232
|
+
opacity: 0;
|
|
233
|
+
width: 100%;
|
|
234
|
+
height: 100%;
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
margin: 0;
|
|
237
|
+
z-index: 1;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.apm__checkbox-custom {
|
|
241
|
+
position: absolute;
|
|
242
|
+
top: 0;
|
|
243
|
+
left: 0;
|
|
244
|
+
width: 1.25rem;
|
|
245
|
+
height: 1.25rem;
|
|
246
|
+
pointer-events: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.apm__checkbox-custom svg {
|
|
250
|
+
display: none;
|
|
251
|
+
width: 1.25rem;
|
|
252
|
+
height: 1.25rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {
|
|
256
|
+
display: block;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {
|
|
260
|
+
display: block;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.apm__checkbox-label--error
|
|
264
|
+
.apm__checkbox-input:not(:checked)
|
|
265
|
+
~ .apm__checkbox-custom
|
|
266
|
+
.svg-unchecked {
|
|
267
|
+
display: none;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.apm__checkbox-label--error
|
|
271
|
+
.apm__checkbox-input:not(:checked)
|
|
272
|
+
~ .apm__checkbox-custom
|
|
273
|
+
.svg-error {
|
|
274
|
+
display: block;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {
|
|
278
|
+
outline: solid 0.125rem #c91d42;
|
|
279
|
+
outline-offset: 0.125rem;
|
|
280
|
+
border-radius: 0.25rem;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.apm__checkbox-label a {
|
|
284
|
+
color: #1a1a1a;
|
|
285
|
+
font-weight: 700;
|
|
286
|
+
text-decoration: underline;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.apm__error {
|
|
290
|
+
display: none;
|
|
291
|
+
align-items: center;
|
|
292
|
+
gap: 0.75rem;
|
|
293
|
+
color: var(--mb-colour-greyscale-london-5, #0d0d0d);
|
|
294
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
295
|
+
font-size: 1.0625rem;
|
|
296
|
+
font-style: normal;
|
|
297
|
+
font-weight: 500;
|
|
298
|
+
line-height: 1.5rem;
|
|
299
|
+
margin-bottom: 1rem;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.apm__error--visible {
|
|
303
|
+
display: flex;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.apm__cta {
|
|
307
|
+
display: flex;
|
|
308
|
+
width: 100%;
|
|
309
|
+
height: 2.75rem;
|
|
310
|
+
padding: 0.375rem 1rem;
|
|
311
|
+
justify-content: center;
|
|
312
|
+
align-items: center;
|
|
313
|
+
gap: 0.375rem;
|
|
314
|
+
border-radius: 0.25rem;
|
|
315
|
+
background: #000;
|
|
316
|
+
border: none;
|
|
317
|
+
cursor: pointer;
|
|
318
|
+
color: #fff;
|
|
319
|
+
text-align: center;
|
|
320
|
+
font-size: 1.25rem;
|
|
321
|
+
font-style: normal;
|
|
322
|
+
font-weight: 500;
|
|
323
|
+
line-height: normal;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.apm__cta:disabled {
|
|
327
|
+
cursor: not-allowed;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.apm__cta[aria-busy="true"] {
|
|
331
|
+
position: relative;
|
|
332
|
+
cursor: not-allowed;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.apm__cta-content {
|
|
336
|
+
display: flex;
|
|
337
|
+
align-items: center;
|
|
338
|
+
gap: 0.375rem;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.apm__cta-label {
|
|
342
|
+
display: inline-flex;
|
|
343
|
+
align-items: center;
|
|
344
|
+
gap: 0.375rem;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.apm__cta-loading {
|
|
348
|
+
display: none;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.apm__cta[aria-busy="true"]::before {
|
|
352
|
+
content: '';
|
|
353
|
+
position: absolute;
|
|
354
|
+
top: 50%;
|
|
355
|
+
left: 50%;
|
|
356
|
+
width: 1.25rem;
|
|
357
|
+
height: 1.25rem;
|
|
358
|
+
border: 2px solid rgba(255, 255, 255, 0.25);
|
|
359
|
+
border-top-color: #fff;
|
|
360
|
+
border-radius: 50%;
|
|
361
|
+
animation: apm-cta-spinner 0.8s linear infinite;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
@keyframes apm-cta-spinner {
|
|
365
|
+
from {
|
|
366
|
+
transform: translate(-50%, -50%) rotate(0deg);
|
|
367
|
+
}
|
|
368
|
+
to {
|
|
369
|
+
transform: translate(-50%, -50%) rotate(360deg);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.apm__cta svg {
|
|
374
|
+
flex-shrink: 0;
|
|
375
|
+
display: block;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
@media (min-width: 22.5rem) and (max-width: 37.5rem) {
|
|
379
|
+
.apm {
|
|
380
|
+
width: 24.375rem;
|
|
381
|
+
max-width: 24.375rem;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@media (min-width: 37.5625rem) {
|
|
386
|
+
.apm {
|
|
387
|
+
border-radius: 0.5rem;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
@media (max-width: 22.4375rem) {
|
|
392
|
+
.apm {
|
|
393
|
+
width: 20rem;
|
|
394
|
+
max-width: 20rem;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
@media (max-width: 26.1875rem) {
|
|
399
|
+
.apm__cta {
|
|
400
|
+
font-size: 1.125rem;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
</style>
|
|
404
|
+
|
|
405
|
+
<div class="apm-overlay" id="apple-pay-modal-overlay">
|
|
406
|
+
<div
|
|
407
|
+
class="apm"
|
|
408
|
+
role="dialog"
|
|
409
|
+
aria-modal="true"
|
|
410
|
+
aria-labelledby="apple-pay-modal-offer-name"
|
|
411
|
+
id="apple-pay-modal"
|
|
412
|
+
tabindex="-1"
|
|
413
|
+
>
|
|
414
|
+
<button class="apm__close" id="apple-pay-modal-close" aria-label="Close">
|
|
415
|
+
<svg
|
|
416
|
+
aria-hidden="true"
|
|
417
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
418
|
+
width="24"
|
|
419
|
+
height="24"
|
|
420
|
+
viewBox="0 0 24 24"
|
|
421
|
+
fill="none"
|
|
422
|
+
>
|
|
423
|
+
<g clip-path="url(#clip0_15712_93054)">
|
|
424
|
+
<rect width="24" height="24" fill="white" fill-opacity="0.01" />
|
|
425
|
+
<path
|
|
426
|
+
fill-rule="evenodd"
|
|
427
|
+
clip-rule="evenodd"
|
|
428
|
+
d="M0 0H24V24H0V0Z"
|
|
429
|
+
fill="white"
|
|
430
|
+
fill-opacity="0.01"
|
|
431
|
+
/>
|
|
432
|
+
<path
|
|
433
|
+
fill-rule="evenodd"
|
|
434
|
+
clip-rule="evenodd"
|
|
435
|
+
d="M18.75 6.60964L17.3904 5.25L12 10.6404L6.60964 5.25L5.25 6.60964L10.6404 12L5.25 17.3904L6.60964 18.75L12 13.3596L17.3904 18.75L18.75 17.3904L13.3596 12L18.75 6.60964Z"
|
|
436
|
+
fill="currentColor"
|
|
437
|
+
/>
|
|
438
|
+
</g>
|
|
439
|
+
<defs>
|
|
440
|
+
<clipPath id="clip0_15712_93054">
|
|
441
|
+
<rect width="24" height="24" fill="white" />
|
|
442
|
+
</clipPath>
|
|
443
|
+
</defs>
|
|
444
|
+
</svg>
|
|
445
|
+
</button>
|
|
446
|
+
<p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>
|
|
447
|
+
<p class="apm__due-today" id="apple-pay-modal-due-today"></p>
|
|
448
|
+
<hr class="apm__rule" />
|
|
449
|
+
<div class="apm__terms" id="apple-pay-modal-terms"></div>
|
|
450
|
+
<p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>
|
|
451
|
+
<label
|
|
452
|
+
class="apm__checkbox-label"
|
|
453
|
+
id="apple-pay-modal-checkbox-label"
|
|
454
|
+
for="apple-pay-modal-checkbox"
|
|
455
|
+
>
|
|
456
|
+
<div class="apm__checkbox-wrapper">
|
|
457
|
+
<input
|
|
458
|
+
class="apm__checkbox-input"
|
|
459
|
+
type="checkbox"
|
|
460
|
+
id="apple-pay-modal-checkbox"
|
|
461
|
+
/>
|
|
462
|
+
<span class="apm__checkbox-custom">
|
|
463
|
+
<svg
|
|
464
|
+
aria-hidden="true"
|
|
465
|
+
class="svg-unchecked"
|
|
466
|
+
width="24"
|
|
467
|
+
height="24"
|
|
468
|
+
viewBox="0 0 24 24"
|
|
469
|
+
fill="none"
|
|
470
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
471
|
+
>
|
|
472
|
+
<path
|
|
473
|
+
d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"
|
|
474
|
+
fill="white"
|
|
475
|
+
stroke="#595959"
|
|
476
|
+
/>
|
|
477
|
+
</svg>
|
|
478
|
+
<svg
|
|
479
|
+
aria-hidden="true"
|
|
480
|
+
class="svg-checked"
|
|
481
|
+
width="24"
|
|
482
|
+
height="24"
|
|
483
|
+
viewBox="0 0 24 24"
|
|
484
|
+
fill="none"
|
|
485
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
486
|
+
>
|
|
487
|
+
<g clip-path="url(#clip0_20014_9555)">
|
|
488
|
+
<path
|
|
489
|
+
d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"
|
|
490
|
+
fill="#333333"
|
|
491
|
+
/>
|
|
492
|
+
<path
|
|
493
|
+
d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"
|
|
494
|
+
fill="white"
|
|
495
|
+
/>
|
|
496
|
+
</g>
|
|
497
|
+
<defs>
|
|
498
|
+
<clipPath id="clip0_20014_9555">
|
|
499
|
+
<path
|
|
500
|
+
d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"
|
|
501
|
+
fill="white"
|
|
502
|
+
/>
|
|
503
|
+
</clipPath>
|
|
504
|
+
</defs>
|
|
505
|
+
</svg>
|
|
506
|
+
<svg
|
|
507
|
+
aria-hidden="true"
|
|
508
|
+
class="svg-error"
|
|
509
|
+
width="24"
|
|
510
|
+
height="24"
|
|
511
|
+
viewBox="0 0 24 24"
|
|
512
|
+
fill="none"
|
|
513
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
514
|
+
>
|
|
515
|
+
<path
|
|
516
|
+
d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"
|
|
517
|
+
fill="white"
|
|
518
|
+
stroke="#C91D42"
|
|
519
|
+
stroke-width="2"
|
|
520
|
+
/>
|
|
521
|
+
</svg>
|
|
522
|
+
</span>
|
|
523
|
+
</div>
|
|
524
|
+
<span id="apple-pay-modal-checkbox-text"></span>
|
|
525
|
+
</label>
|
|
526
|
+
<div class="apm__error" id="apple-pay-modal-error" role="alert">
|
|
527
|
+
<svg
|
|
528
|
+
aria-hidden="true"
|
|
529
|
+
width="20"
|
|
530
|
+
height="20"
|
|
531
|
+
viewBox="0 0 20 20"
|
|
532
|
+
fill="none"
|
|
533
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
534
|
+
>
|
|
535
|
+
<path
|
|
536
|
+
fill-rule="evenodd"
|
|
537
|
+
clip-rule="evenodd"
|
|
538
|
+
d="M10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2ZM0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM11 13C11 13.5523 10.5523 14 10 14C9.44772 14 9 13.5523 9 13C9 12.4477 9.44772 12 10 12C10.5523 12 11 12.4477 11 13ZM10 6C10.5523 6 11 6.44772 11 7V10C11 10.5523 10.5523 11 10 11C9.44772 11 9 10.5523 9 10V7C9 6.44772 9.44772 6 10 6Z"
|
|
539
|
+
fill="#C91D42"
|
|
540
|
+
/>
|
|
541
|
+
</svg>
|
|
542
|
+
Please accept the terms to continue
|
|
543
|
+
</div>
|
|
544
|
+
<button class="apm__cta" id="apple-pay-modal-cta" aria-label="Continue with Apple Pay">
|
|
545
|
+
<span class="apm__cta-content">
|
|
546
|
+
<span class="apm__cta-label">
|
|
547
|
+
Continue with
|
|
548
|
+
<svg width="51" height="22" aria-hidden="true" role="img">
|
|
549
|
+
<use href="#apple-pay-logo" />
|
|
550
|
+
</svg>
|
|
551
|
+
</span>
|
|
552
|
+
</span>
|
|
553
|
+
<span class="apm__cta-loading" aria-hidden="true">Loading...</span>
|
|
554
|
+
</button>
|
|
555
|
+
</div>
|
|
556
|
+
</div>
|
|
557
|
+
|
|
558
|
+
`;
|
|
559
|
+
|
|
560
|
+
// src/clients/payment-checkout/config.ts
|
|
561
|
+
var runtimeConfig = null;
|
|
562
|
+
var configureApplePay = (config) => {
|
|
563
|
+
runtimeConfig = {
|
|
564
|
+
...config
|
|
565
|
+
};
|
|
566
|
+
};
|
|
567
|
+
var getApplePayConfig = () => runtimeConfig;
|
|
568
|
+
|
|
569
|
+
// src/utils/recaptcha.ts
|
|
570
|
+
var loadRecaptchaScript = (siteKey) => {
|
|
571
|
+
return new Promise((resolve, reject) => {
|
|
572
|
+
if (typeof grecaptcha !== "undefined") return resolve();
|
|
573
|
+
const existingScript = document.querySelector(
|
|
574
|
+
'script[src*="recaptcha/api.js"]'
|
|
575
|
+
);
|
|
576
|
+
if (existingScript) {
|
|
577
|
+
existingScript.addEventListener("load", () => resolve());
|
|
578
|
+
existingScript.addEventListener(
|
|
579
|
+
"error",
|
|
580
|
+
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
581
|
+
);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const script = document.createElement("script");
|
|
585
|
+
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
586
|
+
script.async = true;
|
|
587
|
+
script.defer = true;
|
|
588
|
+
script.onload = () => resolve();
|
|
589
|
+
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
590
|
+
document.head.appendChild(script);
|
|
591
|
+
});
|
|
592
|
+
};
|
|
593
|
+
var getRecaptchaToken = async (action) => {
|
|
594
|
+
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
595
|
+
if (!siteKey) {
|
|
596
|
+
throw new Error(
|
|
597
|
+
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
await loadRecaptchaScript(siteKey);
|
|
601
|
+
return new Promise((resolve, reject) => {
|
|
602
|
+
grecaptcha.ready(() => {
|
|
603
|
+
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
604
|
+
});
|
|
605
|
+
});
|
|
606
|
+
};
|
|
607
|
+
var getPurchaseRecaptchaTokens = async () => {
|
|
608
|
+
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
609
|
+
getRecaptchaToken("checkEligibility"),
|
|
610
|
+
getRecaptchaToken("newBasket"),
|
|
611
|
+
getRecaptchaToken("registerUser")
|
|
612
|
+
]);
|
|
613
|
+
return { checkEligibility, newBasket, registerUser };
|
|
614
|
+
};
|
|
80
615
|
|
|
81
616
|
// src/apple-pay-modal.ts
|
|
82
617
|
function getRenewalDateText(unit, duration) {
|
|
@@ -128,6 +663,7 @@ function getOfferTypeText(offerType) {
|
|
|
128
663
|
}
|
|
129
664
|
var TERMS_LINK = '<a href="https://www.economistgroup.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms and Conditions</a>';
|
|
130
665
|
var PRIVACY_LINK = '<a href="https://www.economistgroup.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>';
|
|
666
|
+
var MSG_RECAPTCHA_LOAD_ERROR = "Something went wrong. Please close and try again.";
|
|
131
667
|
function getCheckboxTermsHtml(isNYT, isLoggedIn, autoRenewal) {
|
|
132
668
|
const autoRenewalClause = autoRenewal ? " and auto-renewal terms above," : "";
|
|
133
669
|
if (isNYT) {
|
|
@@ -160,6 +696,8 @@ function renewalPeriodText(unit, duration) {
|
|
|
160
696
|
return "";
|
|
161
697
|
}
|
|
162
698
|
}
|
|
699
|
+
var LI_SEPARATOR = "\0LI_SEP\0";
|
|
700
|
+
var P_SEPARATOR = "\0P_SEP\0";
|
|
163
701
|
function buildTermsContext(offer, country) {
|
|
164
702
|
const isUS = country === "US";
|
|
165
703
|
const isCA = country === "CA";
|
|
@@ -196,19 +734,19 @@ function freeTrialTerms(offer, ctx) {
|
|
|
196
734
|
const trialDuration = offer.subscription_options?.trial_period?.duration ?? 1;
|
|
197
735
|
const trialDateStr = `on ${getRenewalDateText(trialUnit, trialDuration)}${ctx.verificationText}`;
|
|
198
736
|
if (ctx.isUS) {
|
|
199
|
-
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled{
|
|
737
|
+
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal until cancelled. ${ctx.usCancelNote}${ctx.taxFootnote}`;
|
|
200
738
|
}
|
|
201
|
-
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled{
|
|
739
|
+
return `Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${trialDateStr} when your free trial ends, until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}`;
|
|
202
740
|
}
|
|
203
741
|
function nytTerms(ctx) {
|
|
204
742
|
const nytAccessText = "Your complimentary access to The New York Times is for one year only and does not auto-renew. We will send your instructions on how to redeem access to The New York Times by email.";
|
|
205
743
|
if (ctx.isUS) {
|
|
206
|
-
return `Your subscription to <em>The Economist</em> auto-renews ${ctx.periodText} until cancelled{
|
|
744
|
+
return `Your subscription to <em>The Economist</em> auto-renews ${ctx.periodText} until cancelled${LI_SEPARATOR}Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.renewalDateStr}${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal until cancelled. ${ctx.usCancelNote}${ctx.taxFootnote}${P_SEPARATOR}${nytAccessText}`;
|
|
207
745
|
}
|
|
208
746
|
if (ctx.isCA) {
|
|
209
|
-
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled
|
|
747
|
+
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled.${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}${P_SEPARATOR}${nytAccessText}`;
|
|
210
748
|
}
|
|
211
|
-
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled{
|
|
749
|
+
return `Your subscription to <em>The Economist</em> auto-renews at ${ctx.renewalPriceText} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime} ${nytAccessText}`;
|
|
212
750
|
}
|
|
213
751
|
function minTermContractTerms(offer, ctx) {
|
|
214
752
|
const duePrice = formatPrice(offer.price.purchase, offer.price.currency_code);
|
|
@@ -218,28 +756,28 @@ function minTermContractTerms(offer, ctx) {
|
|
|
218
756
|
const contractLength = mtDuration && mtUnit ? `${mtDuration} ${mtUnit}` : "";
|
|
219
757
|
const initialContractText = contractLength ? `your initial ${contractLength} contract` : "your initial contract";
|
|
220
758
|
const mtRenewalDateText = mtUnit && mtDuration ? getRenewalDateText(mtUnit, Number(mtDuration)) : ctx.renewalDateText;
|
|
221
|
-
return `You\u2019ll be charged ${duePrice} a month for the duration of ${initialContractText}{
|
|
759
|
+
return `You\u2019ll be charged ${duePrice} a month for the duration of ${initialContractText}${LI_SEPARATOR}Your subscription auto-renews annually at ${ctx.renewalPriceText} a month on ${mtRenewalDateText} until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}`;
|
|
222
760
|
}
|
|
223
761
|
function paidTrialTerms(offer, ctx) {
|
|
224
762
|
const trialUnit = offer.subscription_options?.trial_period?.unit ?? ctx.unit;
|
|
225
763
|
const trialDuration = offer.subscription_options?.trial_period?.duration ?? ctx.duration;
|
|
226
764
|
const trialDateText = getRenewalDateText(trialUnit, trialDuration);
|
|
227
765
|
if (ctx.isUS) {
|
|
228
|
-
return `Your subscription auto-renews ${ctx.periodText} until cancelled{
|
|
766
|
+
return `Your subscription auto-renews ${ctx.periodText} until cancelled${LI_SEPARATOR}Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} on ${trialDateText} when your paid trial ends${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.usCancelNote}${ctx.taxFootnote}`;
|
|
229
767
|
}
|
|
230
|
-
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} on ${trialDateText} when your paid trial ends, until cancelled{
|
|
768
|
+
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} on ${trialDateText} when your paid trial ends, until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}`;
|
|
231
769
|
}
|
|
232
770
|
function autoRenewalTerms(ctx) {
|
|
233
771
|
if (ctx.isUS) {
|
|
234
|
-
return `Your subscription auto-renews ${ctx.periodText} until cancelled{
|
|
772
|
+
return `Your subscription auto-renews ${ctx.periodText} until cancelled${LI_SEPARATOR}Your subscription renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.renewalDateStr}${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal until cancelled. ${ctx.usCancelNote}${ctx.taxFootnote}`;
|
|
235
773
|
}
|
|
236
|
-
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled{
|
|
774
|
+
return `Your subscription auto-renews at ${ctx.renewalPriceText}${ctx.taxSuffix} ${ctx.periodText} ${ctx.renewalDateStr} until cancelled${LI_SEPARATOR}You\u2019ll be charged the rate in effect at each renewal. ${ctx.cancelAnytime}${ctx.taxFootnote}`;
|
|
237
775
|
}
|
|
238
776
|
function noAutoRenewalTerms(ctx) {
|
|
239
777
|
if (ctx.isUS || ctx.isCA) {
|
|
240
|
-
return `Your subscription does not renew automatically${ctx.taxFootnote}{
|
|
778
|
+
return `Your subscription does not renew automatically${ctx.taxFootnote}${LI_SEPARATOR}`;
|
|
241
779
|
}
|
|
242
|
-
return `Your subscription does not renew automatically{
|
|
780
|
+
return `Your subscription does not renew automatically${LI_SEPARATOR}`;
|
|
243
781
|
}
|
|
244
782
|
function generateApplePayModalTerms(offer, country) {
|
|
245
783
|
const ctx = buildTermsContext(offer, country);
|
|
@@ -262,9 +800,9 @@ function generateApplePayModalTerms(offer, country) {
|
|
|
262
800
|
return noAutoRenewalTerms(ctx);
|
|
263
801
|
}
|
|
264
802
|
function renderTermsHtml(termsText) {
|
|
265
|
-
const renewalTextLists = termsText.split(
|
|
803
|
+
const renewalTextLists = termsText.split(LI_SEPARATOR);
|
|
266
804
|
const lastPart = renewalTextLists.pop() || "";
|
|
267
|
-
const renewalTextParagraphs = lastPart.split(
|
|
805
|
+
const renewalTextParagraphs = lastPart.split(P_SEPARATOR);
|
|
268
806
|
const ulHtml = `<ul class="apm__terms-bullets">${renewalTextLists.map((value) => `<li>${value}</li>`).join("")}</ul>`;
|
|
269
807
|
const paragraphHtml = renewalTextParagraphs.filter(Boolean).map((value) => `<p class="apm__terms-legal">${value}</p>`).join("");
|
|
270
808
|
return ulHtml + paragraphHtml;
|
|
@@ -297,6 +835,19 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
297
835
|
#country = "";
|
|
298
836
|
#triggerElement = null;
|
|
299
837
|
#keyHandler = null;
|
|
838
|
+
#recaptchaTokens = null;
|
|
839
|
+
#recaptchaTokensPromise = null;
|
|
840
|
+
/**
|
|
841
|
+
* Synchronous callback invoked directly from the CTA click handler once the
|
|
842
|
+
* user confirms. The caller (ApplePayButton) must call startApplePaySession
|
|
843
|
+
* inside this callback to preserve the browser's user-gesture chain — Safari
|
|
844
|
+
* requires new ApplePaySession() to execute within the original click stack.
|
|
845
|
+
*
|
|
846
|
+
* reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
|
|
847
|
+
* until the token pre-fetch resolves, so this callback is never reached
|
|
848
|
+
* without valid tokens.
|
|
849
|
+
*/
|
|
850
|
+
onConfirm = null;
|
|
300
851
|
set offer(value) {
|
|
301
852
|
this.#offer = value;
|
|
302
853
|
}
|
|
@@ -317,7 +868,6 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
317
868
|
const offer = this.#offer;
|
|
318
869
|
const country = this.#country;
|
|
319
870
|
if (!offer) {
|
|
320
|
-
console.error("ApplePayModal: Missing or invalid offer data");
|
|
321
871
|
this.remove();
|
|
322
872
|
return;
|
|
323
873
|
}
|
|
@@ -392,27 +942,56 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
392
942
|
}
|
|
393
943
|
});
|
|
394
944
|
}
|
|
945
|
+
if (this.#recaptchaTokensPromise) {
|
|
946
|
+
if (cta) {
|
|
947
|
+
cta.setAttribute("disabled", "");
|
|
948
|
+
cta.setAttribute("aria-disabled", "true");
|
|
949
|
+
cta.setAttribute("aria-busy", "true");
|
|
950
|
+
}
|
|
951
|
+
this.#recaptchaTokensPromise.then((tokens) => {
|
|
952
|
+
this.#recaptchaTokens = tokens;
|
|
953
|
+
if (cta) {
|
|
954
|
+
cta.removeAttribute("disabled");
|
|
955
|
+
cta.removeAttribute("aria-disabled");
|
|
956
|
+
cta.removeAttribute("aria-busy");
|
|
957
|
+
}
|
|
958
|
+
}).catch(() => {
|
|
959
|
+
if (cta) {
|
|
960
|
+
cta.removeAttribute("aria-busy");
|
|
961
|
+
}
|
|
962
|
+
const existingError = this.querySelector("#apple-pay-modal-error");
|
|
963
|
+
if (existingError) {
|
|
964
|
+
const icon = existingError.querySelector("svg");
|
|
965
|
+
existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
966
|
+
if (icon) existingError.prepend(icon);
|
|
967
|
+
existingError.classList.add("apm__error--visible");
|
|
968
|
+
} else {
|
|
969
|
+
const errorNotice = document.createElement("div");
|
|
970
|
+
errorNotice.setAttribute("role", "alert");
|
|
971
|
+
errorNotice.className = "apm__error apm__error--visible";
|
|
972
|
+
errorNotice.textContent = MSG_RECAPTCHA_LOAD_ERROR;
|
|
973
|
+
cta?.insertAdjacentElement("beforebegin", errorNotice);
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
}
|
|
395
977
|
cta?.addEventListener("click", () => {
|
|
396
978
|
if (isUS && checkbox && !checkbox.checked) {
|
|
397
979
|
errorElement?.classList.add("apm__error--visible");
|
|
398
980
|
checkboxLabel?.classList.add("apm__checkbox-label--error");
|
|
399
981
|
return;
|
|
400
982
|
}
|
|
401
|
-
this
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
detail: { skuId: offer.sku_id, country }
|
|
406
|
-
})
|
|
407
|
-
);
|
|
408
|
-
this.close();
|
|
983
|
+
if (this.#recaptchaTokens) {
|
|
984
|
+
this.onConfirm?.(this.#recaptchaTokens);
|
|
985
|
+
this.close();
|
|
986
|
+
}
|
|
409
987
|
});
|
|
410
988
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
411
989
|
"click",
|
|
412
990
|
() => this.close()
|
|
413
991
|
);
|
|
414
992
|
}
|
|
415
|
-
open() {
|
|
993
|
+
open(recaptchaTokensPromise) {
|
|
994
|
+
this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
|
|
416
995
|
this.#triggerElement = document.activeElement;
|
|
417
996
|
document.body.appendChild(this);
|
|
418
997
|
this.#keyHandler = (event) => {
|
|
@@ -439,16 +1018,101 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
439
1018
|
};
|
|
440
1019
|
|
|
441
1020
|
// src/templates/apple-pay-button.template.html
|
|
442
|
-
var apple_pay_button_template_default =
|
|
1021
|
+
var apple_pay_button_template_default = `<style>
|
|
1022
|
+
/* Use CSS variables for layout so parent walls can easily override placement and sizing */
|
|
1023
|
+
teg-apple-pay-button {
|
|
1024
|
+
display: block;
|
|
1025
|
+
margin: var(--apple-pay-margin, 0);
|
|
1026
|
+
width: 100%;
|
|
1027
|
+
height: 100%;
|
|
1028
|
+
}
|
|
443
1029
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
|
|
1030
|
+
teg-apple-pay-button .apple-pay-container {
|
|
1031
|
+
display: flex;
|
|
1032
|
+
flex-direction: column;
|
|
1033
|
+
align-items: stretch;
|
|
1034
|
+
width: 100%;
|
|
1035
|
+
height: 100%;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
teg-apple-pay-button .apple-pay-btn {
|
|
1039
|
+
display: flex;
|
|
1040
|
+
align-items: center;
|
|
1041
|
+
justify-content: center;
|
|
1042
|
+
gap: 0.375rem;
|
|
1043
|
+
width: 100%;
|
|
1044
|
+
min-width: 0;
|
|
1045
|
+
height: 100%;
|
|
1046
|
+
min-height: var(--apple-pay-height, 2.75rem);
|
|
1047
|
+
background-color: var(--apple-pay-background-color, #000);
|
|
1048
|
+
color: var(--apple-pay-foreground-color, #fff);
|
|
1049
|
+
border: none;
|
|
1050
|
+
border-radius: var(--apple-pay-border-radius, 1.375rem);
|
|
1051
|
+
cursor: pointer;
|
|
1052
|
+
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
1053
|
+
font-size: 1.0625rem;
|
|
1054
|
+
font-weight: 500;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
teg-apple-pay-button .apple-pay-btn svg {
|
|
1058
|
+
flex-shrink: 0;
|
|
1059
|
+
display: block;
|
|
1060
|
+
color: currentColor;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
teg-apple-pay-button .apple-pay-btn.wap-loading {
|
|
1064
|
+
position: relative;
|
|
1065
|
+
cursor: default;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
teg-apple-pay-button .apple-pay-btn.wap-loading::before {
|
|
1069
|
+
content: '';
|
|
1070
|
+
position: absolute;
|
|
1071
|
+
top: 50%;
|
|
1072
|
+
left: 50%;
|
|
1073
|
+
width: 1.25rem;
|
|
1074
|
+
height: 1.25rem;
|
|
1075
|
+
border: 2px solid var(--apple-pay-spinner-track-color, rgba(255, 255, 255, 0.25));
|
|
1076
|
+
border-top-color: var(--apple-pay-spinner-head-color, currentColor);
|
|
1077
|
+
border-radius: 50%;
|
|
1078
|
+
animation: wap-button-spinner 0.8s linear infinite;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
teg-apple-pay-button .apple-pay-btn__logo {
|
|
1082
|
+
display: inline-flex;
|
|
1083
|
+
align-items: center;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
teg-apple-pay-button .apple-pay-btn__loading {
|
|
1087
|
+
display: none;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
@keyframes wap-button-spinner {
|
|
1091
|
+
from {
|
|
1092
|
+
transform: translate(-50%, -50%) rotate(0deg);
|
|
1093
|
+
}
|
|
1094
|
+
to {
|
|
1095
|
+
transform: translate(-50%, -50%) rotate(360deg);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
</style>
|
|
1099
|
+
|
|
1100
|
+
<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
|
|
1101
|
+
<button
|
|
1102
|
+
class="apple-pay-btn"
|
|
1103
|
+
type="button"
|
|
1104
|
+
aria-label="Pay with Apple Pay"
|
|
1105
|
+
data-analytics="paywall:apple-pay-checkout"
|
|
1106
|
+
>
|
|
1107
|
+
<span class="apple-pay-btn__logo">
|
|
1108
|
+
<svg width="51" height="22" aria-label="Apple Pay" role="img">
|
|
1109
|
+
<use href="#apple-pay-logo" />
|
|
1110
|
+
</svg>
|
|
1111
|
+
</span>
|
|
1112
|
+
<span class="apple-pay-btn__loading" aria-hidden="true">Loading...</span>
|
|
1113
|
+
</button>
|
|
1114
|
+
</div>
|
|
1115
|
+
`;
|
|
452
1116
|
|
|
453
1117
|
// src/clients/payment-checkout/detects.ts
|
|
454
1118
|
var isAppleDeviceOrSafari = () => {
|
|
@@ -477,14 +1141,11 @@ var isApplePayAvailable = async () => {
|
|
|
477
1141
|
}
|
|
478
1142
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
479
1143
|
if (!merchantId) {
|
|
480
|
-
console.warn(
|
|
481
|
-
"[web-apple-pay] Missing merchantId. Call configureApplePay({ merchantId, ... }) before rendering Apple Pay components."
|
|
482
|
-
);
|
|
483
1144
|
return false;
|
|
484
1145
|
}
|
|
485
|
-
|
|
1146
|
+
const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
1147
|
+
return hasActiveCard;
|
|
486
1148
|
} catch (error) {
|
|
487
|
-
console.error("Error checking Apple Pay active card status:", error);
|
|
488
1149
|
return false;
|
|
489
1150
|
}
|
|
490
1151
|
};
|
|
@@ -602,7 +1263,7 @@ var redirectToCheckoutComplete = (params) => {
|
|
|
602
1263
|
var redirectToCheckoutFallback = (params) => {
|
|
603
1264
|
const url = new URL(window.location.href);
|
|
604
1265
|
url.pathname = "/checkout";
|
|
605
|
-
url.searchParams.set("lmo_offer", params.skuId);
|
|
1266
|
+
url.searchParams.set("lmo_offer", decodeSku(params.skuId));
|
|
606
1267
|
if (params.inlineError)
|
|
607
1268
|
url.searchParams.set("inlineError", params.inlineError);
|
|
608
1269
|
if (params.email) url.searchParams.set("email", params.email);
|
|
@@ -611,53 +1272,6 @@ var redirectToCheckoutFallback = (params) => {
|
|
|
611
1272
|
return url.pathname + url.search;
|
|
612
1273
|
};
|
|
613
1274
|
|
|
614
|
-
// src/utils/recaptcha.ts
|
|
615
|
-
var loadRecaptchaScript = (siteKey) => {
|
|
616
|
-
return new Promise((resolve, reject) => {
|
|
617
|
-
if (typeof grecaptcha !== "undefined") return resolve();
|
|
618
|
-
const existingScript = document.querySelector(
|
|
619
|
-
'script[src*="recaptcha/api.js"]'
|
|
620
|
-
);
|
|
621
|
-
if (existingScript) {
|
|
622
|
-
existingScript.addEventListener("load", () => resolve());
|
|
623
|
-
existingScript.addEventListener(
|
|
624
|
-
"error",
|
|
625
|
-
() => reject(new Error("Failed to load existing reCAPTCHA script"))
|
|
626
|
-
);
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
const script = document.createElement("script");
|
|
630
|
-
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
|
|
631
|
-
script.async = true;
|
|
632
|
-
script.defer = true;
|
|
633
|
-
script.onload = () => resolve();
|
|
634
|
-
script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
|
|
635
|
-
document.head.appendChild(script);
|
|
636
|
-
});
|
|
637
|
-
};
|
|
638
|
-
var getRecaptchaToken = async (action) => {
|
|
639
|
-
const siteKey = getApplePayConfig()?.recaptchaSiteKey;
|
|
640
|
-
if (!siteKey) {
|
|
641
|
-
throw new Error(
|
|
642
|
-
"[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
await loadRecaptchaScript(siteKey);
|
|
646
|
-
return new Promise((resolve, reject) => {
|
|
647
|
-
grecaptcha.ready(() => {
|
|
648
|
-
grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
649
|
-
});
|
|
650
|
-
});
|
|
651
|
-
};
|
|
652
|
-
var getPurchaseRecaptchaTokens = async () => {
|
|
653
|
-
const [checkEligibility, newBasket, registerUser] = await Promise.all([
|
|
654
|
-
getRecaptchaToken("checkEligibility"),
|
|
655
|
-
getRecaptchaToken("newBasket"),
|
|
656
|
-
getRecaptchaToken("registerUser")
|
|
657
|
-
]);
|
|
658
|
-
return { checkEligibility, newBasket, registerUser };
|
|
659
|
-
};
|
|
660
|
-
|
|
661
1275
|
// src/utils/expressCheckoutTracking.ts
|
|
662
1276
|
var EXPRESS_CHECKOUT_EVENTS = {
|
|
663
1277
|
/** Wallet button displayed */
|
|
@@ -743,6 +1357,38 @@ var MSG_EMAIL_COLLISION = "This email address is already linked to an account. P
|
|
|
743
1357
|
var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
|
|
744
1358
|
|
|
745
1359
|
// src/clients/payment-checkout/apple-session.ts
|
|
1360
|
+
function redirectToFallbackCheckout(config) {
|
|
1361
|
+
trackFallbackCheckout(config.skuId);
|
|
1362
|
+
window.location.href = redirectToCheckoutFallback({
|
|
1363
|
+
skuId: config.skuId,
|
|
1364
|
+
returnUrl: config.returnUrl,
|
|
1365
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
async function handleMerchantValidation(event, session, config) {
|
|
1369
|
+
try {
|
|
1370
|
+
const validationHost = new URL(event.validationURL).host;
|
|
1371
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
1372
|
+
session.abort();
|
|
1373
|
+
redirectToFallbackCheckout(config);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
1377
|
+
const response = await validateAppleMerchant({
|
|
1378
|
+
validationURL: event.validationURL,
|
|
1379
|
+
recaptchaToken
|
|
1380
|
+
});
|
|
1381
|
+
if (!response?.merchantSession) {
|
|
1382
|
+
session.abort();
|
|
1383
|
+
redirectToFallbackCheckout(config);
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
1387
|
+
} catch (err) {
|
|
1388
|
+
session.abort();
|
|
1389
|
+
redirectToFallbackCheckout(config);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
746
1392
|
function startApplePaySession(config) {
|
|
747
1393
|
const paymentRequest = {
|
|
748
1394
|
countryCode: config.countryCode,
|
|
@@ -757,55 +1403,23 @@ function startApplePaySession(config) {
|
|
|
757
1403
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
758
1404
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
759
1405
|
};
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
recaptchaToken
|
|
778
|
-
});
|
|
779
|
-
if (!response?.merchantSession) {
|
|
780
|
-
trackFallbackCheckout(config.skuId);
|
|
781
|
-
session.abort();
|
|
782
|
-
window.location.href = redirectToCheckoutFallback({
|
|
783
|
-
skuId: config.skuId,
|
|
784
|
-
returnUrl: config.returnUrl,
|
|
785
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
786
|
-
});
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
session.completeMerchantValidation(response.merchantSession);
|
|
790
|
-
} catch {
|
|
791
|
-
trackFallbackCheckout(config.skuId);
|
|
792
|
-
session.abort();
|
|
793
|
-
window.location.href = redirectToCheckoutFallback({
|
|
794
|
-
skuId: config.skuId,
|
|
795
|
-
returnUrl: config.returnUrl,
|
|
796
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
};
|
|
800
|
-
session.onpaymentauthorized = (event) => {
|
|
801
|
-
trackWalletPaymentAuthorised(config.skuId);
|
|
802
|
-
config.onPaymentAuthorized(event, session);
|
|
803
|
-
};
|
|
804
|
-
session.oncancel = () => {
|
|
805
|
-
config.onCancel?.();
|
|
806
|
-
};
|
|
807
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
808
|
-
session.begin();
|
|
1406
|
+
try {
|
|
1407
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
1408
|
+
session.onvalidatemerchant = async (event) => {
|
|
1409
|
+
await handleMerchantValidation(event, session, config);
|
|
1410
|
+
};
|
|
1411
|
+
session.onpaymentauthorized = (event) => {
|
|
1412
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
1413
|
+
config.onPaymentAuthorized(event, session);
|
|
1414
|
+
};
|
|
1415
|
+
session.oncancel = () => {
|
|
1416
|
+
config.onCancel?.();
|
|
1417
|
+
};
|
|
1418
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
1419
|
+
session.begin();
|
|
1420
|
+
} catch (err) {
|
|
1421
|
+
redirectToFallbackCheckout(config);
|
|
1422
|
+
}
|
|
809
1423
|
}
|
|
810
1424
|
|
|
811
1425
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1013,7 +1627,6 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1013
1627
|
failApplePaySession(session, err.errors);
|
|
1014
1628
|
return;
|
|
1015
1629
|
}
|
|
1016
|
-
console.error("[web-apple-pay] onpaymentauthorized error", { skuId, err });
|
|
1017
1630
|
const walletError = parseWalletApiError(err);
|
|
1018
1631
|
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1019
1632
|
failApplePaySession(session);
|
|
@@ -1291,7 +1904,6 @@ var FEATURE_APPLE_PAY_EXPRESS_CHECKOUT = "FEATURE_APPLE_PAY_EXPRESS_CHECKOUT";
|
|
|
1291
1904
|
var TOTAL_LABEL = "The Economist";
|
|
1292
1905
|
var DEFAULT_CURRENCY = "USD";
|
|
1293
1906
|
var DEFAULT_TOTAL = "0.00";
|
|
1294
|
-
var ERROR_INITIATE = "Failed to initiate Apple Pay session:";
|
|
1295
1907
|
var SEL_CONTAINER = ".apple-pay-container";
|
|
1296
1908
|
var SEL_BUTTON = ".apple-pay-btn";
|
|
1297
1909
|
var APPLE_PAY_EXCLUDED_VARIANTS = [
|
|
@@ -1307,16 +1919,22 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1307
1919
|
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1308
1920
|
*/
|
|
1309
1921
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1310
|
-
if (!offer)
|
|
1311
|
-
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant))
|
|
1922
|
+
if (!offer) {
|
|
1312
1923
|
return null;
|
|
1313
|
-
|
|
1924
|
+
}
|
|
1925
|
+
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1926
|
+
return null;
|
|
1927
|
+
}
|
|
1928
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1314
1929
|
return null;
|
|
1930
|
+
}
|
|
1315
1931
|
_ApplePayButton.define();
|
|
1316
1932
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1317
1933
|
button.offer = offer;
|
|
1318
1934
|
button.country = country;
|
|
1319
|
-
|
|
1935
|
+
if (entryPoint) {
|
|
1936
|
+
button.entryPoint = entryPoint;
|
|
1937
|
+
}
|
|
1320
1938
|
return button;
|
|
1321
1939
|
}
|
|
1322
1940
|
/**
|
|
@@ -1338,6 +1956,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1338
1956
|
#returnUrl = "";
|
|
1339
1957
|
#supportedBillingCountries = [];
|
|
1340
1958
|
#entryPoint = "";
|
|
1959
|
+
#recaptchaTokensPromise = null;
|
|
1341
1960
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1342
1961
|
get offer() {
|
|
1343
1962
|
return this.#offer;
|
|
@@ -1402,20 +2021,23 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1402
2021
|
this.#paymentOptions = null;
|
|
1403
2022
|
this.#returnUrl = "";
|
|
1404
2023
|
this.#supportedBillingCountries = [];
|
|
2024
|
+
this.#recaptchaTokensPromise = null;
|
|
1405
2025
|
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1406
2026
|
}
|
|
1407
2027
|
// ─── Render pipeline ────────────────────────────────────────────────────────
|
|
1408
2028
|
async #run() {
|
|
1409
2029
|
try {
|
|
1410
2030
|
if (await this.#checkAvailability()) return;
|
|
1411
|
-
if (await this.#checkSession()) return;
|
|
1412
2031
|
if (this.#checkOffer()) return;
|
|
2032
|
+
this.#renderTemplate();
|
|
2033
|
+
if (await this.#checkSession()) return;
|
|
1413
2034
|
this.#captureReturnUrl();
|
|
1414
2035
|
this.#computeBillingCountries();
|
|
1415
2036
|
if (await this.#fetchAndCacheOptions()) return;
|
|
1416
|
-
this.#
|
|
1417
|
-
} catch {
|
|
2037
|
+
this.#finishLoading();
|
|
2038
|
+
} catch (err) {
|
|
1418
2039
|
this.style.display = "none";
|
|
2040
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1419
2041
|
} finally {
|
|
1420
2042
|
this.#rendering = false;
|
|
1421
2043
|
}
|
|
@@ -1437,6 +2059,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1437
2059
|
this.#sessionData = await this.#fetchSession();
|
|
1438
2060
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
1439
2061
|
this.style.display = "none";
|
|
2062
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1440
2063
|
return true;
|
|
1441
2064
|
}
|
|
1442
2065
|
return false;
|
|
@@ -1470,8 +2093,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1470
2093
|
*/
|
|
1471
2094
|
async #fetchAndCacheOptions() {
|
|
1472
2095
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
1473
|
-
if (!this.#paymentOptions?.apple_pay) {
|
|
2096
|
+
if (!this.#paymentOptions?.options?.apple_pay) {
|
|
1474
2097
|
this.style.display = "none";
|
|
2098
|
+
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1475
2099
|
return true;
|
|
1476
2100
|
}
|
|
1477
2101
|
return false;
|
|
@@ -1483,19 +2107,27 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1483
2107
|
const template = document.createElement("template");
|
|
1484
2108
|
template.innerHTML = apple_pay_button_template_default;
|
|
1485
2109
|
this.appendChild(template.content.cloneNode(true));
|
|
1486
|
-
this.#updateDisabledState();
|
|
1487
|
-
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
1488
|
-
entryPoint: this.#entryPoint,
|
|
1489
|
-
country: this.#country
|
|
1490
|
-
});
|
|
1491
2110
|
const button = this.querySelector(SEL_BUTTON);
|
|
2111
|
+
button.classList.add("wap-loading");
|
|
2112
|
+
button.setAttribute("disabled", "");
|
|
2113
|
+
button.setAttribute("aria-disabled", "true");
|
|
2114
|
+
button.setAttribute("aria-busy", "true");
|
|
1492
2115
|
button.addEventListener("click", () => {
|
|
2116
|
+
if (button.classList.contains("wap-loading")) return;
|
|
1493
2117
|
this.#openModal();
|
|
1494
2118
|
});
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
2119
|
+
}
|
|
2120
|
+
#finishLoading() {
|
|
2121
|
+
const button = this.querySelector(SEL_BUTTON);
|
|
2122
|
+
if (button) {
|
|
2123
|
+
button.classList.remove("wap-loading");
|
|
2124
|
+
this.#updateDisabledState();
|
|
2125
|
+
this.#scheduleRecaptchaTokens();
|
|
2126
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
2127
|
+
entryPoint: this.#entryPoint,
|
|
2128
|
+
country: this.#country
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
1499
2131
|
}
|
|
1500
2132
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1501
2133
|
#updateDisabledState() {
|
|
@@ -1504,13 +2136,19 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1504
2136
|
if (this.#offer) {
|
|
1505
2137
|
button.removeAttribute("disabled");
|
|
1506
2138
|
button.removeAttribute("aria-disabled");
|
|
2139
|
+
button.removeAttribute("aria-busy");
|
|
1507
2140
|
return;
|
|
1508
2141
|
}
|
|
1509
2142
|
button.setAttribute("disabled", "");
|
|
1510
2143
|
button.setAttribute("aria-disabled", "true");
|
|
1511
2144
|
}
|
|
1512
2145
|
#openModal() {
|
|
1513
|
-
if (!this.#offer
|
|
2146
|
+
if (!this.#offer) {
|
|
2147
|
+
return;
|
|
2148
|
+
}
|
|
2149
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
1514
2152
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1515
2153
|
ApplePayModal.define();
|
|
1516
2154
|
const modal = document.createElement(ApplePayModal.tag);
|
|
@@ -1519,7 +2157,29 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1519
2157
|
if (this.#sessionData?.loggedIn) {
|
|
1520
2158
|
modal.dataset.loggedIn = "true";
|
|
1521
2159
|
}
|
|
1522
|
-
|
|
2160
|
+
const skuId = this.#offer.sku_id;
|
|
2161
|
+
const country = this.#country;
|
|
2162
|
+
modal.onConfirm = (recaptchaTokens) => {
|
|
2163
|
+
this.#initiateApplePay(skuId, country, recaptchaTokens);
|
|
2164
|
+
this.#scheduleRecaptchaTokens();
|
|
2165
|
+
};
|
|
2166
|
+
modal.open(this.#recaptchaTokensPromise);
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
|
|
2170
|
+
* If the fetch rejects, the field is cleared so the next `modal.open()` call
|
|
2171
|
+
* falls back to a new attempt via the modal's own null-fallback path — preventing
|
|
2172
|
+
* a single transient failure from permanently disabling the CTA on all retries.
|
|
2173
|
+
* The identity guard prevents a late rejection from clobbering a newer attempt.
|
|
2174
|
+
*/
|
|
2175
|
+
#scheduleRecaptchaTokens() {
|
|
2176
|
+
const attempt = getPurchaseRecaptchaTokens();
|
|
2177
|
+
attempt.catch((err) => {
|
|
2178
|
+
if (this.#recaptchaTokensPromise === attempt) {
|
|
2179
|
+
this.#recaptchaTokensPromise = null;
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
this.#recaptchaTokensPromise = attempt;
|
|
1523
2183
|
}
|
|
1524
2184
|
async #fetchSession() {
|
|
1525
2185
|
try {
|
|
@@ -1546,7 +2206,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1546
2206
|
return {
|
|
1547
2207
|
countryCode: country,
|
|
1548
2208
|
currencyCode: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
1549
|
-
supportedNetworks: paymentOptions.apple_pay.settings.supported_networks,
|
|
2209
|
+
supportedNetworks: paymentOptions.options.apple_pay.settings.supported_networks,
|
|
1550
2210
|
totalAmount,
|
|
1551
2211
|
totalLabel: TOTAL_LABEL,
|
|
1552
2212
|
skuId,
|
|
@@ -1563,11 +2223,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1563
2223
|
})
|
|
1564
2224
|
};
|
|
1565
2225
|
}
|
|
1566
|
-
|
|
2226
|
+
#initiateApplePay(skuId, country, recaptchaTokens) {
|
|
1567
2227
|
try {
|
|
1568
2228
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1569
2229
|
const paymentOptions = this.#paymentOptions;
|
|
1570
|
-
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1571
2230
|
startApplePaySession(
|
|
1572
2231
|
this.#buildSessionParams(
|
|
1573
2232
|
skuId,
|
|
@@ -1578,11 +2237,18 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1578
2237
|
)
|
|
1579
2238
|
);
|
|
1580
2239
|
} catch (error) {
|
|
1581
|
-
console.error(ERROR_INITIATE, error);
|
|
1582
2240
|
}
|
|
1583
2241
|
}
|
|
1584
2242
|
};
|
|
1585
2243
|
|
|
2244
|
+
// src/constants.ts
|
|
2245
|
+
var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
|
|
2246
|
+
ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
|
|
2247
|
+
ApplePayEntryPoint2["REGWALL"] = "article_regwall";
|
|
2248
|
+
ApplePayEntryPoint2["DUAL_OFFER_BANNER"] = "dual_offer_banner";
|
|
2249
|
+
return ApplePayEntryPoint2;
|
|
2250
|
+
})(ApplePayEntryPoint || {});
|
|
2251
|
+
|
|
1586
2252
|
// src/index.ts
|
|
1587
2253
|
function defineApplePayElements() {
|
|
1588
2254
|
ApplePayButton.define();
|
|
@@ -1591,6 +2257,7 @@ function defineApplePayElements() {
|
|
|
1591
2257
|
export {
|
|
1592
2258
|
APPLE_PAY_EXCLUDED_VARIANTS,
|
|
1593
2259
|
ApplePayButton,
|
|
2260
|
+
ApplePayEntryPoint,
|
|
1594
2261
|
ApplePayModal,
|
|
1595
2262
|
configureApplePay,
|
|
1596
2263
|
defineApplePayElements,
|