@economist/web-apple-pay 0.1.3-beta.2 → 0.1.3-beta.3
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 +68 -285
- package/dist/src/apple-pay-button.js +68 -279
- package/dist/src/apple-pay-button.stories.js +68 -286
- package/dist/src/apple-pay-modal.js +1 -0
- package/dist/src/apple-pay-modal.stories.js +68 -279
- package/dist/src/clients/payment-checkout/apple-session.js +47 -103
- package/dist/src/clients/payment-checkout/config.js +0 -7
- package/dist/src/clients/payment-checkout/detects.js +1 -10
- package/dist/src/clients/payment-checkout/payment-handler.d.ts +1 -0
- package/dist/src/clients/payment-checkout/payment-handler.js +1 -35
- package/dist/src/clients/payment-checkout/shipping-contact-details.js +0 -21
- package/dist/src/clients/payment-checkout/types.d.ts +5 -6
- package/dist/src/index.js +68 -285
- package/dist/src/stories/utils/story-env.js +0 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -317,6 +317,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
317
317
|
const offer = this.#offer;
|
|
318
318
|
const country = this.#country;
|
|
319
319
|
if (!offer) {
|
|
320
|
+
console.error("ApplePayModal: Missing or invalid offer data");
|
|
320
321
|
this.remove();
|
|
321
322
|
return;
|
|
322
323
|
}
|
|
@@ -438,101 +439,11 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
438
439
|
};
|
|
439
440
|
|
|
440
441
|
// src/templates/apple-pay-button.template.html
|
|
441
|
-
var apple_pay_button_template_default =
|
|
442
|
-
/* Use CSS variables for layout so parent walls can easily override placement and sizing */
|
|
443
|
-
teg-apple-pay-button {
|
|
444
|
-
display: block;
|
|
445
|
-
margin: var(--apple-pay-margin, 0);
|
|
446
|
-
width: 100%;
|
|
447
|
-
height: 100%;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
teg-apple-pay-button .apple-pay-container {
|
|
451
|
-
display: flex;
|
|
452
|
-
flex-direction: column;
|
|
453
|
-
align-items: stretch;
|
|
454
|
-
width: 100%;
|
|
455
|
-
height: 100%;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
teg-apple-pay-button .apple-pay-btn {
|
|
459
|
-
display: flex;
|
|
460
|
-
align-items: center;
|
|
461
|
-
justify-content: center;
|
|
462
|
-
gap: 0.375rem;
|
|
463
|
-
width: 100%;
|
|
464
|
-
min-width: 0;
|
|
465
|
-
height: 100%;
|
|
466
|
-
min-height: var(--apple-pay-height, 2.75rem);
|
|
467
|
-
background-color: #000;
|
|
468
|
-
color: #fff;
|
|
469
|
-
border: none;
|
|
470
|
-
border-radius: var(--apple-pay-border-radius, 1.375rem);
|
|
471
|
-
cursor: pointer;
|
|
472
|
-
font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
|
|
473
|
-
font-size: 1.0625rem;
|
|
474
|
-
font-weight: 500;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
teg-apple-pay-button .apple-pay-btn svg {
|
|
478
|
-
flex-shrink: 0;
|
|
479
|
-
display: block;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
teg-apple-pay-button .apple-pay-btn.wap-loading {
|
|
483
|
-
position: relative;
|
|
484
|
-
cursor: default;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
teg-apple-pay-button .apple-pay-btn.wap-loading svg {
|
|
488
|
-
visibility: hidden;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
teg-apple-pay-button .apple-pay-btn.wap-loading::after {
|
|
492
|
-
content: '';
|
|
493
|
-
position: absolute;
|
|
494
|
-
left: 50%;
|
|
495
|
-
top: 50%;
|
|
496
|
-
margin-left: -0.625rem;
|
|
497
|
-
margin-top: -0.625rem;
|
|
498
|
-
width: 1.25rem;
|
|
499
|
-
height: 1.25rem;
|
|
500
|
-
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
501
|
-
border-top-color: #fff;
|
|
502
|
-
border-radius: 50%;
|
|
503
|
-
animation: wap-button-spinner 0.8s linear infinite;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
@keyframes wap-button-spinner {
|
|
507
|
-
to {
|
|
508
|
-
transform: rotate(360deg);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
</style>
|
|
512
|
-
|
|
513
|
-
<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
|
|
514
|
-
<button
|
|
515
|
-
class="apple-pay-btn"
|
|
516
|
-
type="button"
|
|
517
|
-
aria-label="Pay with Apple Pay"
|
|
518
|
-
data-analytics="paywall:apple-pay-checkout"
|
|
519
|
-
>
|
|
520
|
-
<svg width="51" height="22" aria-label="Apple Pay" role="img">
|
|
521
|
-
<use href="#apple-pay-logo" />
|
|
522
|
-
</svg>
|
|
523
|
-
</button>
|
|
524
|
-
</div>
|
|
525
|
-
`;
|
|
442
|
+
var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\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';
|
|
526
443
|
|
|
527
444
|
// src/clients/payment-checkout/config.ts
|
|
528
445
|
var runtimeConfig = null;
|
|
529
446
|
var configureApplePay = (config) => {
|
|
530
|
-
console.log("[web-apple-pay] configureApplePay called", {
|
|
531
|
-
merchantId: config.merchantId,
|
|
532
|
-
walletApiBaseUrl: config.walletApiBaseUrl,
|
|
533
|
-
debugBypassEnabled: config.debugBypassEnabled,
|
|
534
|
-
recaptchaSiteKey: config.recaptchaSiteKey ? "***" : void 0
|
|
535
|
-
});
|
|
536
447
|
runtimeConfig = {
|
|
537
448
|
...config
|
|
538
449
|
};
|
|
@@ -547,27 +458,21 @@ var isAppleDeviceOrSafari = () => {
|
|
|
547
458
|
};
|
|
548
459
|
var bypassApplePayChecks = () => new URLSearchParams(window.location.search).get("BYPASS_APPLE_PAY_CHECKS") !== null && getApplePayConfig()?.debugBypassEnabled === true;
|
|
549
460
|
var isApplePayAvailable = async () => {
|
|
550
|
-
console.log("[web-apple-pay] isApplePayAvailable: checking availability");
|
|
551
461
|
if (bypassApplePayChecks()) {
|
|
552
|
-
console.log("[web-apple-pay] isApplePayAvailable: bypass active \u2192 true");
|
|
553
462
|
return true;
|
|
554
463
|
}
|
|
555
464
|
if (!isAppleDeviceOrSafari()) {
|
|
556
|
-
console.log("[web-apple-pay] isApplePayAvailable: not Apple device or Safari \u2192 false");
|
|
557
465
|
return false;
|
|
558
466
|
}
|
|
559
467
|
const applePaySession = window.ApplePaySession;
|
|
560
468
|
if (!applePaySession) {
|
|
561
|
-
console.log("[web-apple-pay] isApplePayAvailable: ApplePaySession not found on window \u2192 false");
|
|
562
469
|
return false;
|
|
563
470
|
}
|
|
564
471
|
try {
|
|
565
472
|
if (typeof applePaySession.canMakePayments !== "function") {
|
|
566
|
-
console.log("[web-apple-pay] isApplePayAvailable: canMakePayments is not a function \u2192 false");
|
|
567
473
|
return false;
|
|
568
474
|
}
|
|
569
475
|
if (!applePaySession.canMakePayments()) {
|
|
570
|
-
console.log("[web-apple-pay] isApplePayAvailable: canMakePayments() returned false \u2192 false");
|
|
571
476
|
return false;
|
|
572
477
|
}
|
|
573
478
|
const merchantId = getApplePayConfig()?.merchantId;
|
|
@@ -577,10 +482,7 @@ var isApplePayAvailable = async () => {
|
|
|
577
482
|
);
|
|
578
483
|
return false;
|
|
579
484
|
}
|
|
580
|
-
|
|
581
|
-
const result = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
582
|
-
console.log("[web-apple-pay] isApplePayAvailable: canMakePaymentsWithActiveCard \u2192", result);
|
|
583
|
-
return result;
|
|
485
|
+
return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
|
|
584
486
|
} catch (error) {
|
|
585
487
|
console.error("Error checking Apple Pay active card status:", error);
|
|
586
488
|
return false;
|
|
@@ -841,73 +743,7 @@ var MSG_EMAIL_COLLISION = "This email address is already linked to an account. P
|
|
|
841
743
|
var MSG_CONTACT_VALIDATION_INTERNAL = "Could not validate Apple Pay contact";
|
|
842
744
|
|
|
843
745
|
// src/clients/payment-checkout/apple-session.ts
|
|
844
|
-
function redirectToFallbackCheckout(config) {
|
|
845
|
-
console.warn("[web-apple-pay] redirectToFallbackCheckout", {
|
|
846
|
-
skuId: config.skuId,
|
|
847
|
-
returnUrl: config.returnUrl,
|
|
848
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
849
|
-
});
|
|
850
|
-
trackFallbackCheckout(config.skuId);
|
|
851
|
-
window.location.href = redirectToCheckoutFallback({
|
|
852
|
-
skuId: config.skuId,
|
|
853
|
-
returnUrl: config.returnUrl,
|
|
854
|
-
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
855
|
-
});
|
|
856
|
-
}
|
|
857
|
-
async function handleMerchantValidation(event, session, config) {
|
|
858
|
-
console.log("[web-apple-pay] handleMerchantValidation: start", {
|
|
859
|
-
skuId: config.skuId,
|
|
860
|
-
validationURL: event.validationURL
|
|
861
|
-
});
|
|
862
|
-
try {
|
|
863
|
-
const validationHost = new URL(event.validationURL).host;
|
|
864
|
-
console.log("[web-apple-pay] handleMerchantValidation: host parsed", {
|
|
865
|
-
validationHost
|
|
866
|
-
});
|
|
867
|
-
if (!validationHost.endsWith("apple.com")) {
|
|
868
|
-
console.warn(
|
|
869
|
-
"[web-apple-pay] handleMerchantValidation: invalid validation host",
|
|
870
|
-
{ validationHost }
|
|
871
|
-
);
|
|
872
|
-
session.abort();
|
|
873
|
-
redirectToFallbackCheckout(config);
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
console.log("[web-apple-pay] handleMerchantValidation: requesting recaptcha token");
|
|
877
|
-
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
878
|
-
console.log("[web-apple-pay] handleMerchantValidation: recaptcha token received");
|
|
879
|
-
const response = await validateAppleMerchant({
|
|
880
|
-
validationURL: event.validationURL,
|
|
881
|
-
recaptchaToken
|
|
882
|
-
});
|
|
883
|
-
if (!response?.merchantSession) {
|
|
884
|
-
console.warn(
|
|
885
|
-
"[web-apple-pay] handleMerchantValidation: missing merchantSession in response"
|
|
886
|
-
);
|
|
887
|
-
session.abort();
|
|
888
|
-
redirectToFallbackCheckout(config);
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
console.log("[web-apple-pay] handleMerchantValidation: completing merchant validation");
|
|
892
|
-
session.completeMerchantValidation(response.merchantSession);
|
|
893
|
-
console.log("[web-apple-pay] handleMerchantValidation: success");
|
|
894
|
-
} catch (err) {
|
|
895
|
-
console.error("[web-apple-pay] handleMerchantValidation: failed", {
|
|
896
|
-
skuId: config.skuId,
|
|
897
|
-
err
|
|
898
|
-
});
|
|
899
|
-
session.abort();
|
|
900
|
-
redirectToFallbackCheckout(config);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
746
|
function startApplePaySession(config) {
|
|
904
|
-
console.log("[web-apple-pay] startApplePaySession", {
|
|
905
|
-
skuId: config.skuId,
|
|
906
|
-
countryCode: config.countryCode,
|
|
907
|
-
currencyCode: config.currencyCode,
|
|
908
|
-
totalAmount: config.totalAmount,
|
|
909
|
-
userLoggedIn: config.userLoggedIn
|
|
910
|
-
});
|
|
911
747
|
const paymentRequest = {
|
|
912
748
|
countryCode: config.countryCode,
|
|
913
749
|
currencyCode: config.currencyCode,
|
|
@@ -921,45 +757,55 @@ function startApplePaySession(config) {
|
|
|
921
757
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
922
758
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
923
759
|
};
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
760
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
761
|
+
session.onvalidatemerchant = async (event) => {
|
|
762
|
+
try {
|
|
763
|
+
const validationHost = new URL(event.validationURL).host;
|
|
764
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
765
|
+
trackFallbackCheckout(config.skuId);
|
|
766
|
+
session.abort();
|
|
767
|
+
window.location.href = redirectToCheckoutFallback({
|
|
768
|
+
skuId: config.skuId,
|
|
769
|
+
returnUrl: config.returnUrl,
|
|
770
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
771
|
+
});
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
775
|
+
const response = await validateAppleMerchant({
|
|
776
|
+
validationURL: event.validationURL,
|
|
777
|
+
recaptchaToken
|
|
940
778
|
});
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
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
|
|
947
797
|
});
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
err
|
|
960
|
-
});
|
|
961
|
-
redirectToFallbackCheckout(config);
|
|
962
|
-
}
|
|
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();
|
|
963
809
|
}
|
|
964
810
|
|
|
965
811
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1048,25 +894,13 @@ var billingContactDetails = (contact, supportedBillingCountries) => {
|
|
|
1048
894
|
// src/clients/payment-checkout/shipping-contact-details.ts
|
|
1049
895
|
var EMAIL_FORMAT_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1050
896
|
var shippingContactDetails = (shippingContact) => {
|
|
1051
|
-
console.log("[web-apple-pay] shippingContactDetails: start", {
|
|
1052
|
-
hasShippingContact: Boolean(shippingContact),
|
|
1053
|
-
hasEmailAddress: shippingContact?.emailAddress !== void 0
|
|
1054
|
-
});
|
|
1055
897
|
const errors = [];
|
|
1056
898
|
let emailAddress = "";
|
|
1057
899
|
if (shippingContact?.emailAddress === void 0 || shippingContact?.emailAddress === "") {
|
|
1058
|
-
console.log(
|
|
1059
|
-
"[web-apple-pay] shippingContactDetails: email missing or empty"
|
|
1060
|
-
);
|
|
1061
900
|
pushRequiredFieldError(errors, "shipping", "emailAddress");
|
|
1062
901
|
} else {
|
|
1063
|
-
console.log("[web-apple-pay] shippingContactDetails: email provided");
|
|
1064
902
|
emailAddress = shippingContact.emailAddress.trim();
|
|
1065
|
-
console.log("[web-apple-pay] shippingContactDetails: email trimmed", {
|
|
1066
|
-
emailLength: emailAddress.length
|
|
1067
|
-
});
|
|
1068
903
|
if (emailAddress.length > 80) {
|
|
1069
|
-
console.log("[web-apple-pay] shippingContactDetails: email too long");
|
|
1070
904
|
pushFieldError(
|
|
1071
905
|
errors,
|
|
1072
906
|
"shipping",
|
|
@@ -1075,9 +909,6 @@ var shippingContactDetails = (shippingContact) => {
|
|
|
1075
909
|
MSG_EMAIL_TOO_LONG
|
|
1076
910
|
);
|
|
1077
911
|
} else if (!EMAIL_FORMAT_REGEX.test(emailAddress)) {
|
|
1078
|
-
console.log(
|
|
1079
|
-
"[web-apple-pay] shippingContactDetails: email format invalid"
|
|
1080
|
-
);
|
|
1081
912
|
pushFieldError(
|
|
1082
913
|
errors,
|
|
1083
914
|
"shipping",
|
|
@@ -1085,17 +916,11 @@ var shippingContactDetails = (shippingContact) => {
|
|
|
1085
916
|
"format",
|
|
1086
917
|
MSG_EMAIL_WRONG_FORMAT
|
|
1087
918
|
);
|
|
1088
|
-
} else {
|
|
1089
|
-
console.log("[web-apple-pay] shippingContactDetails: email valid");
|
|
1090
919
|
}
|
|
1091
920
|
}
|
|
1092
921
|
if (errors.length > 0) {
|
|
1093
|
-
console.log("[web-apple-pay] shippingContactDetails: throwing validation error", {
|
|
1094
|
-
errorCount: errors.length
|
|
1095
|
-
});
|
|
1096
922
|
throw new ContactValidationError(errors);
|
|
1097
923
|
}
|
|
1098
|
-
console.log("[web-apple-pay] shippingContactDetails: success");
|
|
1099
924
|
return { emailAddress };
|
|
1100
925
|
};
|
|
1101
926
|
|
|
@@ -1157,27 +982,22 @@ function handleStructuredError(ctx) {
|
|
|
1157
982
|
async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
1158
983
|
const { skuId, returnUrl, queryString } = config;
|
|
1159
984
|
let validatedEmail;
|
|
1160
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: starting", { skuId, userLoggedIn: sessionData.loggedIn });
|
|
1161
985
|
try {
|
|
1162
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: step 1 \u2014 validating contacts");
|
|
1163
986
|
validatedEmail = validateContacts(
|
|
1164
987
|
event,
|
|
1165
988
|
sessionData,
|
|
1166
989
|
config.supportedBillingCountries
|
|
1167
990
|
);
|
|
1168
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: contacts valid", { validatedEmail });
|
|
1169
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: step 2 \u2014 calling performPurchase", { skuId });
|
|
1170
991
|
const result = await performPurchase({
|
|
1171
992
|
applePayToken: event.payment.token,
|
|
1172
993
|
skuId: config.skuId,
|
|
994
|
+
currency: config.currency,
|
|
1173
995
|
billingContact: event.payment.billingContact,
|
|
1174
996
|
...event.payment.shippingContact && {
|
|
1175
997
|
shippingContact: event.payment.shippingContact
|
|
1176
998
|
},
|
|
1177
999
|
recaptchaTokens: config.recaptchaTokens
|
|
1178
1000
|
});
|
|
1179
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: performPurchase succeeded", { basketId: result.basketId });
|
|
1180
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: step 3 \u2014 completing payment and redirecting");
|
|
1181
1001
|
trackWalletPaymentSuccess(skuId, result.basketId);
|
|
1182
1002
|
session.completePayment({ status: ApplePaySession.STATUS_SUCCESS });
|
|
1183
1003
|
const userStatus = sessionData.loggedIn ? "lex" : "nex";
|
|
@@ -1190,25 +1010,17 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
|
|
|
1190
1010
|
});
|
|
1191
1011
|
} catch (err) {
|
|
1192
1012
|
if (err instanceof ContactValidationError) {
|
|
1193
|
-
console.warn("[web-apple-pay] handlePaymentAuthorized: contact validation failed", err.errors);
|
|
1194
1013
|
failApplePaySession(session, err.errors);
|
|
1195
1014
|
return;
|
|
1196
1015
|
}
|
|
1197
1016
|
console.error("[web-apple-pay] onpaymentauthorized error", { skuId, err });
|
|
1198
1017
|
const walletError = parseWalletApiError(err);
|
|
1199
|
-
console.error("[web-apple-pay] handlePaymentAuthorized: BFF/network error", {
|
|
1200
|
-
skuId,
|
|
1201
|
-
errorType: walletError?.errorType ?? "UNKNOWN",
|
|
1202
|
-
message: walletError?.message
|
|
1203
|
-
});
|
|
1204
1018
|
trackWalletPaymentFailure(skuId, walletError?.errorType ?? "UNKNOWN");
|
|
1205
1019
|
failApplePaySession(session);
|
|
1206
1020
|
if (!walletError) {
|
|
1207
|
-
console.warn("[web-apple-pay] handlePaymentAuthorized: unstructured error, using generic fallback");
|
|
1208
1021
|
redirectFallback(skuId, returnUrl, { inlineError: MSG_PAYMENT_GENERIC_ERROR });
|
|
1209
1022
|
return;
|
|
1210
1023
|
}
|
|
1211
|
-
console.log("[web-apple-pay] handlePaymentAuthorized: dispatching structured error handler", { errorType: walletError.errorType });
|
|
1212
1024
|
handleStructuredError({ skuId, returnUrl, validatedEmail, walletError });
|
|
1213
1025
|
}
|
|
1214
1026
|
}
|
|
@@ -1495,15 +1307,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1495
1307
|
* Creates and configures an ApplePayButton if the feature flag is present.
|
|
1496
1308
|
*/
|
|
1497
1309
|
static createIfEnabled(offer, country, entryPoint) {
|
|
1498
|
-
if (!offer)
|
|
1499
|
-
|
|
1500
|
-
}
|
|
1501
|
-
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant)) {
|
|
1310
|
+
if (!offer) return null;
|
|
1311
|
+
if (APPLE_PAY_EXCLUDED_VARIANTS.includes(offer.product?.variant))
|
|
1502
1312
|
return null;
|
|
1503
|
-
|
|
1504
|
-
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT)) {
|
|
1313
|
+
if (!new URLSearchParams(window.location.search).has(FEATURE_APPLE_PAY_EXPRESS_CHECKOUT))
|
|
1505
1314
|
return null;
|
|
1506
|
-
}
|
|
1507
1315
|
_ApplePayButton.define();
|
|
1508
1316
|
const button = document.createElement(_ApplePayButton.tag);
|
|
1509
1317
|
button.offer = offer;
|
|
@@ -1530,7 +1338,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1530
1338
|
#returnUrl = "";
|
|
1531
1339
|
#supportedBillingCountries = [];
|
|
1532
1340
|
#entryPoint = "";
|
|
1533
|
-
#recaptchaTokens = null;
|
|
1534
1341
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1535
1342
|
get offer() {
|
|
1536
1343
|
return this.#offer;
|
|
@@ -1601,16 +1408,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1601
1408
|
async #run() {
|
|
1602
1409
|
try {
|
|
1603
1410
|
if (await this.#checkAvailability()) return;
|
|
1604
|
-
if (this.#checkOffer()) return;
|
|
1605
|
-
this.#renderTemplate();
|
|
1606
1411
|
if (await this.#checkSession()) return;
|
|
1412
|
+
if (this.#checkOffer()) return;
|
|
1607
1413
|
this.#captureReturnUrl();
|
|
1608
1414
|
this.#computeBillingCountries();
|
|
1609
1415
|
if (await this.#fetchAndCacheOptions()) return;
|
|
1610
|
-
this.#
|
|
1416
|
+
this.#renderTemplate();
|
|
1611
1417
|
} catch {
|
|
1612
1418
|
this.style.display = "none";
|
|
1613
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1614
1419
|
} finally {
|
|
1615
1420
|
this.#rendering = false;
|
|
1616
1421
|
}
|
|
@@ -1632,7 +1437,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1632
1437
|
this.#sessionData = await this.#fetchSession();
|
|
1633
1438
|
if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
|
|
1634
1439
|
this.style.display = "none";
|
|
1635
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1636
1440
|
return true;
|
|
1637
1441
|
}
|
|
1638
1442
|
return false;
|
|
@@ -1666,9 +1470,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1666
1470
|
*/
|
|
1667
1471
|
async #fetchAndCacheOptions() {
|
|
1668
1472
|
this.#paymentOptions = await this.#fetchPaymentOptions();
|
|
1669
|
-
if (!this.#paymentOptions?.
|
|
1473
|
+
if (!this.#paymentOptions?.apple_pay) {
|
|
1670
1474
|
this.style.display = "none";
|
|
1671
|
-
this.querySelector(SEL_CONTAINER)?.remove();
|
|
1672
1475
|
return true;
|
|
1673
1476
|
}
|
|
1674
1477
|
return false;
|
|
@@ -1680,30 +1483,19 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1680
1483
|
const template = document.createElement("template");
|
|
1681
1484
|
template.innerHTML = apple_pay_button_template_default;
|
|
1682
1485
|
this.appendChild(template.content.cloneNode(true));
|
|
1486
|
+
this.#updateDisabledState();
|
|
1487
|
+
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
1488
|
+
entryPoint: this.#entryPoint,
|
|
1489
|
+
country: this.#country
|
|
1490
|
+
});
|
|
1683
1491
|
const button = this.querySelector(SEL_BUTTON);
|
|
1684
|
-
button.classList.add("wap-loading");
|
|
1685
|
-
button.setAttribute("disabled", "");
|
|
1686
|
-
button.setAttribute("aria-disabled", "true");
|
|
1687
|
-
button.setAttribute("aria-busy", "true");
|
|
1688
1492
|
button.addEventListener("click", () => {
|
|
1689
|
-
if (button.classList.contains("wap-loading")) return;
|
|
1690
1493
|
this.#openModal();
|
|
1691
1494
|
});
|
|
1692
|
-
|
|
1495
|
+
this.addEventListener("apple-pay-confirmed", (event) => {
|
|
1693
1496
|
const { skuId, country } = event.detail;
|
|
1694
1497
|
this.#initiateApplePay(skuId, country);
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
#finishLoading() {
|
|
1698
|
-
const button = this.querySelector(SEL_BUTTON);
|
|
1699
|
-
if (button) {
|
|
1700
|
-
button.classList.remove("wap-loading");
|
|
1701
|
-
this.#updateDisabledState();
|
|
1702
|
-
trackExpressWalletImpression(this.#offer.sku_id, {
|
|
1703
|
-
entryPoint: this.#entryPoint,
|
|
1704
|
-
country: this.#country
|
|
1705
|
-
});
|
|
1706
|
-
}
|
|
1498
|
+
});
|
|
1707
1499
|
}
|
|
1708
1500
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1709
1501
|
#updateDisabledState() {
|
|
@@ -1712,24 +1504,14 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1712
1504
|
if (this.#offer) {
|
|
1713
1505
|
button.removeAttribute("disabled");
|
|
1714
1506
|
button.removeAttribute("aria-disabled");
|
|
1715
|
-
button.removeAttribute("aria-busy");
|
|
1716
1507
|
return;
|
|
1717
1508
|
}
|
|
1718
1509
|
button.setAttribute("disabled", "");
|
|
1719
1510
|
button.setAttribute("aria-disabled", "true");
|
|
1720
1511
|
}
|
|
1721
1512
|
#openModal() {
|
|
1722
|
-
if (!this.#offer)
|
|
1723
|
-
return;
|
|
1724
|
-
}
|
|
1725
|
-
if (document.querySelector(ApplePayModal.tag)) {
|
|
1726
|
-
return;
|
|
1727
|
-
}
|
|
1513
|
+
if (!this.#offer || document.querySelector(ApplePayModal.tag)) return;
|
|
1728
1514
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1729
|
-
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1730
|
-
this.#recaptchaTokens = tokens;
|
|
1731
|
-
}).catch(() => {
|
|
1732
|
-
});
|
|
1733
1515
|
ApplePayModal.define();
|
|
1734
1516
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1735
1517
|
modal.offer = this.#offer;
|
|
@@ -1764,7 +1546,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1764
1546
|
return {
|
|
1765
1547
|
countryCode: country,
|
|
1766
1548
|
currencyCode: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
1767
|
-
supportedNetworks: paymentOptions.
|
|
1549
|
+
supportedNetworks: paymentOptions.apple_pay.settings.supported_networks,
|
|
1768
1550
|
totalAmount,
|
|
1769
1551
|
totalLabel: TOTAL_LABEL,
|
|
1770
1552
|
skuId,
|
|
@@ -1773,6 +1555,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1773
1555
|
onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
|
|
1774
1556
|
skuId,
|
|
1775
1557
|
country,
|
|
1558
|
+
currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
|
|
1776
1559
|
returnUrl: this.#returnUrl,
|
|
1777
1560
|
queryString: buildQueryString(),
|
|
1778
1561
|
supportedBillingCountries: this.#supportedBillingCountries,
|
|
@@ -1784,7 +1567,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1784
1567
|
try {
|
|
1785
1568
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1786
1569
|
const paymentOptions = this.#paymentOptions;
|
|
1787
|
-
const recaptchaTokens =
|
|
1570
|
+
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1788
1571
|
startApplePaySession(
|
|
1789
1572
|
this.#buildSessionParams(
|
|
1790
1573
|
skuId,
|