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