@economist/web-apple-pay 0.1.1-beta.2 → 0.1.3-beta.0
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 +82 -53
- package/dist/src/apple-pay-button.js +82 -53
- package/dist/src/apple-pay-button.stories.js +82 -53
- package/dist/src/apple-pay-modal.js +1 -0
- package/dist/src/apple-pay-modal.stories.js +82 -53
- package/dist/src/clients/payment-checkout/apple-session.js +60 -49
- package/dist/src/index.js +82 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -411,6 +411,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
411
411
|
detail: { skuId: offer.sku_id, country }
|
|
412
412
|
})
|
|
413
413
|
);
|
|
414
|
+
console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
|
|
414
415
|
});
|
|
415
416
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
416
417
|
"click",
|
|
@@ -786,30 +787,45 @@ function startApplePaySession(config) {
|
|
|
786
787
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
787
788
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
788
789
|
};
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
console.log("[web-apple-pay]
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
790
|
+
try {
|
|
791
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
792
|
+
console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
|
|
793
|
+
session.onvalidatemerchant = async (event) => {
|
|
794
|
+
console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
|
|
795
|
+
try {
|
|
796
|
+
const validationHost = new URL(event.validationURL).host;
|
|
797
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
798
|
+
console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
|
|
799
|
+
trackFallbackCheckout(config.skuId);
|
|
800
|
+
session.abort();
|
|
801
|
+
window.location.href = redirectToCheckoutFallback({
|
|
802
|
+
skuId: config.skuId,
|
|
803
|
+
returnUrl: config.returnUrl,
|
|
804
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
805
|
+
});
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
809
|
+
console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
|
|
810
|
+
const response = await validateAppleMerchant({
|
|
811
|
+
validationURL: event.validationURL,
|
|
812
|
+
recaptchaToken
|
|
802
813
|
});
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
814
|
+
if (!response?.merchantSession) {
|
|
815
|
+
console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
|
|
816
|
+
trackFallbackCheckout(config.skuId);
|
|
817
|
+
session.abort();
|
|
818
|
+
window.location.href = redirectToCheckoutFallback({
|
|
819
|
+
skuId: config.skuId,
|
|
820
|
+
returnUrl: config.returnUrl,
|
|
821
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
822
|
+
});
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
|
|
826
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
827
|
+
} catch (err) {
|
|
828
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
813
829
|
trackFallbackCheckout(config.skuId);
|
|
814
830
|
session.abort();
|
|
815
831
|
window.location.href = redirectToCheckoutFallback({
|
|
@@ -817,33 +833,29 @@ function startApplePaySession(config) {
|
|
|
817
833
|
returnUrl: config.returnUrl,
|
|
818
834
|
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
819
835
|
});
|
|
820
|
-
return;
|
|
821
836
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
console.
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}
|
|
844
|
-
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
845
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
846
|
-
session.begin();
|
|
837
|
+
};
|
|
838
|
+
session.onpaymentauthorized = (event) => {
|
|
839
|
+
console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
|
|
840
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
841
|
+
config.onPaymentAuthorized(event, session);
|
|
842
|
+
};
|
|
843
|
+
session.oncancel = () => {
|
|
844
|
+
console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
|
|
845
|
+
config.onCancel?.();
|
|
846
|
+
};
|
|
847
|
+
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
848
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
849
|
+
session.begin();
|
|
850
|
+
} catch (err) {
|
|
851
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
|
|
852
|
+
trackFallbackCheckout(config.skuId);
|
|
853
|
+
window.location.href = redirectToCheckoutFallback({
|
|
854
|
+
skuId: config.skuId,
|
|
855
|
+
returnUrl: config.returnUrl,
|
|
856
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
857
|
+
});
|
|
858
|
+
}
|
|
847
859
|
}
|
|
848
860
|
|
|
849
861
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1397,6 +1409,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1397
1409
|
#returnUrl = "";
|
|
1398
1410
|
#supportedBillingCountries = [];
|
|
1399
1411
|
#entryPoint = "";
|
|
1412
|
+
#recaptchaTokens = null;
|
|
1400
1413
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1401
1414
|
get offer() {
|
|
1402
1415
|
return this.#offer;
|
|
@@ -1457,6 +1470,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1457
1470
|
* and eliminating the implicit reliance on the DOM as a render-state flag.
|
|
1458
1471
|
*/
|
|
1459
1472
|
disconnectedCallback() {
|
|
1473
|
+
console.log("[web-apple-pay] disconnectedCallback: element removed from DOM, resetting state");
|
|
1460
1474
|
this.#rendering = false;
|
|
1461
1475
|
this.#readyPromise = null;
|
|
1462
1476
|
this.#sessionData = null;
|
|
@@ -1565,10 +1579,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1565
1579
|
button.addEventListener("click", () => {
|
|
1566
1580
|
this.#openModal();
|
|
1567
1581
|
});
|
|
1568
|
-
|
|
1582
|
+
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1569
1583
|
const { skuId, country } = event.detail;
|
|
1584
|
+
console.log("[web-apple-pay] apple-pay-confirmed received on document", { skuId, country });
|
|
1570
1585
|
this.#initiateApplePay(skuId, country);
|
|
1571
|
-
});
|
|
1586
|
+
}, { once: true });
|
|
1572
1587
|
}
|
|
1573
1588
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1574
1589
|
#updateDisabledState() {
|
|
@@ -1584,8 +1599,21 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1584
1599
|
}
|
|
1585
1600
|
#openModal() {
|
|
1586
1601
|
console.log("[web-apple-pay] #openModal: button clicked", { skuId: this.#offer?.sku_id });
|
|
1587
|
-
if (!this.#offer
|
|
1602
|
+
if (!this.#offer) {
|
|
1603
|
+
console.warn("[web-apple-pay] #openModal: no offer set, ignoring click");
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
1607
|
+
console.warn("[web-apple-pay] #openModal: modal already open, ignoring click");
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1588
1610
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1611
|
+
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1612
|
+
console.log("[web-apple-pay] #openModal: reCAPTCHA tokens pre-fetched");
|
|
1613
|
+
this.#recaptchaTokens = tokens;
|
|
1614
|
+
}).catch((err) => {
|
|
1615
|
+
console.warn("[web-apple-pay] #openModal: reCAPTCHA pre-fetch failed", err);
|
|
1616
|
+
});
|
|
1589
1617
|
ApplePayModal.define();
|
|
1590
1618
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1591
1619
|
modal.offer = this.#offer;
|
|
@@ -1648,7 +1676,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1648
1676
|
try {
|
|
1649
1677
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1650
1678
|
const paymentOptions = this.#paymentOptions;
|
|
1651
|
-
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1679
|
+
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1680
|
+
console.log("[web-apple-pay] #initiateApplePay: tokens ready, starting session", { prefetched: !!this.#recaptchaTokens });
|
|
1652
1681
|
startApplePaySession(
|
|
1653
1682
|
this.#buildSessionParams(
|
|
1654
1683
|
skuId,
|
|
@@ -411,6 +411,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
411
411
|
detail: { skuId: offer.sku_id, country }
|
|
412
412
|
})
|
|
413
413
|
);
|
|
414
|
+
console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
|
|
414
415
|
});
|
|
415
416
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
416
417
|
"click",
|
|
@@ -775,30 +776,45 @@ function startApplePaySession(config) {
|
|
|
775
776
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
776
777
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
777
778
|
};
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
console.log("[web-apple-pay]
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
779
|
+
try {
|
|
780
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
781
|
+
console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
|
|
782
|
+
session.onvalidatemerchant = async (event) => {
|
|
783
|
+
console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
|
|
784
|
+
try {
|
|
785
|
+
const validationHost = new URL(event.validationURL).host;
|
|
786
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
787
|
+
console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
|
|
788
|
+
trackFallbackCheckout(config.skuId);
|
|
789
|
+
session.abort();
|
|
790
|
+
window.location.href = redirectToCheckoutFallback({
|
|
791
|
+
skuId: config.skuId,
|
|
792
|
+
returnUrl: config.returnUrl,
|
|
793
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
794
|
+
});
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
798
|
+
console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
|
|
799
|
+
const response = await validateAppleMerchant({
|
|
800
|
+
validationURL: event.validationURL,
|
|
801
|
+
recaptchaToken
|
|
791
802
|
});
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
803
|
+
if (!response?.merchantSession) {
|
|
804
|
+
console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
|
|
805
|
+
trackFallbackCheckout(config.skuId);
|
|
806
|
+
session.abort();
|
|
807
|
+
window.location.href = redirectToCheckoutFallback({
|
|
808
|
+
skuId: config.skuId,
|
|
809
|
+
returnUrl: config.returnUrl,
|
|
810
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
811
|
+
});
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
|
|
815
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
816
|
+
} catch (err) {
|
|
817
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
802
818
|
trackFallbackCheckout(config.skuId);
|
|
803
819
|
session.abort();
|
|
804
820
|
window.location.href = redirectToCheckoutFallback({
|
|
@@ -806,33 +822,29 @@ function startApplePaySession(config) {
|
|
|
806
822
|
returnUrl: config.returnUrl,
|
|
807
823
|
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
808
824
|
});
|
|
809
|
-
return;
|
|
810
825
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
console.
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
}
|
|
833
|
-
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
834
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
835
|
-
session.begin();
|
|
826
|
+
};
|
|
827
|
+
session.onpaymentauthorized = (event) => {
|
|
828
|
+
console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
|
|
829
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
830
|
+
config.onPaymentAuthorized(event, session);
|
|
831
|
+
};
|
|
832
|
+
session.oncancel = () => {
|
|
833
|
+
console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
|
|
834
|
+
config.onCancel?.();
|
|
835
|
+
};
|
|
836
|
+
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
837
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
838
|
+
session.begin();
|
|
839
|
+
} catch (err) {
|
|
840
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
|
|
841
|
+
trackFallbackCheckout(config.skuId);
|
|
842
|
+
window.location.href = redirectToCheckoutFallback({
|
|
843
|
+
skuId: config.skuId,
|
|
844
|
+
returnUrl: config.returnUrl,
|
|
845
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
846
|
+
});
|
|
847
|
+
}
|
|
836
848
|
}
|
|
837
849
|
|
|
838
850
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1386,6 +1398,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1386
1398
|
#returnUrl = "";
|
|
1387
1399
|
#supportedBillingCountries = [];
|
|
1388
1400
|
#entryPoint = "";
|
|
1401
|
+
#recaptchaTokens = null;
|
|
1389
1402
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1390
1403
|
get offer() {
|
|
1391
1404
|
return this.#offer;
|
|
@@ -1446,6 +1459,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1446
1459
|
* and eliminating the implicit reliance on the DOM as a render-state flag.
|
|
1447
1460
|
*/
|
|
1448
1461
|
disconnectedCallback() {
|
|
1462
|
+
console.log("[web-apple-pay] disconnectedCallback: element removed from DOM, resetting state");
|
|
1449
1463
|
this.#rendering = false;
|
|
1450
1464
|
this.#readyPromise = null;
|
|
1451
1465
|
this.#sessionData = null;
|
|
@@ -1554,10 +1568,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1554
1568
|
button.addEventListener("click", () => {
|
|
1555
1569
|
this.#openModal();
|
|
1556
1570
|
});
|
|
1557
|
-
|
|
1571
|
+
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1558
1572
|
const { skuId, country } = event.detail;
|
|
1573
|
+
console.log("[web-apple-pay] apple-pay-confirmed received on document", { skuId, country });
|
|
1559
1574
|
this.#initiateApplePay(skuId, country);
|
|
1560
|
-
});
|
|
1575
|
+
}, { once: true });
|
|
1561
1576
|
}
|
|
1562
1577
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1563
1578
|
#updateDisabledState() {
|
|
@@ -1573,8 +1588,21 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1573
1588
|
}
|
|
1574
1589
|
#openModal() {
|
|
1575
1590
|
console.log("[web-apple-pay] #openModal: button clicked", { skuId: this.#offer?.sku_id });
|
|
1576
|
-
if (!this.#offer
|
|
1591
|
+
if (!this.#offer) {
|
|
1592
|
+
console.warn("[web-apple-pay] #openModal: no offer set, ignoring click");
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
1596
|
+
console.warn("[web-apple-pay] #openModal: modal already open, ignoring click");
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1577
1599
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1600
|
+
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1601
|
+
console.log("[web-apple-pay] #openModal: reCAPTCHA tokens pre-fetched");
|
|
1602
|
+
this.#recaptchaTokens = tokens;
|
|
1603
|
+
}).catch((err) => {
|
|
1604
|
+
console.warn("[web-apple-pay] #openModal: reCAPTCHA pre-fetch failed", err);
|
|
1605
|
+
});
|
|
1578
1606
|
ApplePayModal.define();
|
|
1579
1607
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1580
1608
|
modal.offer = this.#offer;
|
|
@@ -1637,7 +1665,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1637
1665
|
try {
|
|
1638
1666
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1639
1667
|
const paymentOptions = this.#paymentOptions;
|
|
1640
|
-
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1668
|
+
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1669
|
+
console.log("[web-apple-pay] #initiateApplePay: tokens ready, starting session", { prefetched: !!this.#recaptchaTokens });
|
|
1641
1670
|
startApplePaySession(
|
|
1642
1671
|
this.#buildSessionParams(
|
|
1643
1672
|
skuId,
|
|
@@ -411,6 +411,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
411
411
|
detail: { skuId: offer.sku_id, country }
|
|
412
412
|
})
|
|
413
413
|
);
|
|
414
|
+
console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
|
|
414
415
|
});
|
|
415
416
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
416
417
|
"click",
|
|
@@ -790,30 +791,45 @@ function startApplePaySession(config) {
|
|
|
790
791
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
791
792
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
792
793
|
};
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
console.log("[web-apple-pay]
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
794
|
+
try {
|
|
795
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
796
|
+
console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
|
|
797
|
+
session.onvalidatemerchant = async (event) => {
|
|
798
|
+
console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
|
|
799
|
+
try {
|
|
800
|
+
const validationHost = new URL(event.validationURL).host;
|
|
801
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
802
|
+
console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
|
|
803
|
+
trackFallbackCheckout(config.skuId);
|
|
804
|
+
session.abort();
|
|
805
|
+
window.location.href = redirectToCheckoutFallback({
|
|
806
|
+
skuId: config.skuId,
|
|
807
|
+
returnUrl: config.returnUrl,
|
|
808
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
809
|
+
});
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
813
|
+
console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
|
|
814
|
+
const response = await validateAppleMerchant({
|
|
815
|
+
validationURL: event.validationURL,
|
|
816
|
+
recaptchaToken
|
|
806
817
|
});
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
818
|
+
if (!response?.merchantSession) {
|
|
819
|
+
console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
|
|
820
|
+
trackFallbackCheckout(config.skuId);
|
|
821
|
+
session.abort();
|
|
822
|
+
window.location.href = redirectToCheckoutFallback({
|
|
823
|
+
skuId: config.skuId,
|
|
824
|
+
returnUrl: config.returnUrl,
|
|
825
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
826
|
+
});
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
|
|
830
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
831
|
+
} catch (err) {
|
|
832
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
817
833
|
trackFallbackCheckout(config.skuId);
|
|
818
834
|
session.abort();
|
|
819
835
|
window.location.href = redirectToCheckoutFallback({
|
|
@@ -821,33 +837,29 @@ function startApplePaySession(config) {
|
|
|
821
837
|
returnUrl: config.returnUrl,
|
|
822
838
|
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
823
839
|
});
|
|
824
|
-
return;
|
|
825
840
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
console.
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
}
|
|
848
|
-
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
849
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
850
|
-
session.begin();
|
|
841
|
+
};
|
|
842
|
+
session.onpaymentauthorized = (event) => {
|
|
843
|
+
console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
|
|
844
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
845
|
+
config.onPaymentAuthorized(event, session);
|
|
846
|
+
};
|
|
847
|
+
session.oncancel = () => {
|
|
848
|
+
console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
|
|
849
|
+
config.onCancel?.();
|
|
850
|
+
};
|
|
851
|
+
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
852
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
853
|
+
session.begin();
|
|
854
|
+
} catch (err) {
|
|
855
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
|
|
856
|
+
trackFallbackCheckout(config.skuId);
|
|
857
|
+
window.location.href = redirectToCheckoutFallback({
|
|
858
|
+
skuId: config.skuId,
|
|
859
|
+
returnUrl: config.returnUrl,
|
|
860
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
861
|
+
});
|
|
862
|
+
}
|
|
851
863
|
}
|
|
852
864
|
|
|
853
865
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1401,6 +1413,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1401
1413
|
#returnUrl = "";
|
|
1402
1414
|
#supportedBillingCountries = [];
|
|
1403
1415
|
#entryPoint = "";
|
|
1416
|
+
#recaptchaTokens = null;
|
|
1404
1417
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1405
1418
|
get offer() {
|
|
1406
1419
|
return this.#offer;
|
|
@@ -1461,6 +1474,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1461
1474
|
* and eliminating the implicit reliance on the DOM as a render-state flag.
|
|
1462
1475
|
*/
|
|
1463
1476
|
disconnectedCallback() {
|
|
1477
|
+
console.log("[web-apple-pay] disconnectedCallback: element removed from DOM, resetting state");
|
|
1464
1478
|
this.#rendering = false;
|
|
1465
1479
|
this.#readyPromise = null;
|
|
1466
1480
|
this.#sessionData = null;
|
|
@@ -1569,10 +1583,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1569
1583
|
button.addEventListener("click", () => {
|
|
1570
1584
|
this.#openModal();
|
|
1571
1585
|
});
|
|
1572
|
-
|
|
1586
|
+
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1573
1587
|
const { skuId, country } = event.detail;
|
|
1588
|
+
console.log("[web-apple-pay] apple-pay-confirmed received on document", { skuId, country });
|
|
1574
1589
|
this.#initiateApplePay(skuId, country);
|
|
1575
|
-
});
|
|
1590
|
+
}, { once: true });
|
|
1576
1591
|
}
|
|
1577
1592
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1578
1593
|
#updateDisabledState() {
|
|
@@ -1588,8 +1603,21 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1588
1603
|
}
|
|
1589
1604
|
#openModal() {
|
|
1590
1605
|
console.log("[web-apple-pay] #openModal: button clicked", { skuId: this.#offer?.sku_id });
|
|
1591
|
-
if (!this.#offer
|
|
1606
|
+
if (!this.#offer) {
|
|
1607
|
+
console.warn("[web-apple-pay] #openModal: no offer set, ignoring click");
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
1611
|
+
console.warn("[web-apple-pay] #openModal: modal already open, ignoring click");
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1592
1614
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1615
|
+
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1616
|
+
console.log("[web-apple-pay] #openModal: reCAPTCHA tokens pre-fetched");
|
|
1617
|
+
this.#recaptchaTokens = tokens;
|
|
1618
|
+
}).catch((err) => {
|
|
1619
|
+
console.warn("[web-apple-pay] #openModal: reCAPTCHA pre-fetch failed", err);
|
|
1620
|
+
});
|
|
1593
1621
|
ApplePayModal.define();
|
|
1594
1622
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1595
1623
|
modal.offer = this.#offer;
|
|
@@ -1652,7 +1680,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1652
1680
|
try {
|
|
1653
1681
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1654
1682
|
const paymentOptions = this.#paymentOptions;
|
|
1655
|
-
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1683
|
+
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1684
|
+
console.log("[web-apple-pay] #initiateApplePay: tokens ready, starting session", { prefetched: !!this.#recaptchaTokens });
|
|
1656
1685
|
startApplePaySession(
|
|
1657
1686
|
this.#buildSessionParams(
|
|
1658
1687
|
skuId,
|
|
@@ -411,6 +411,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
411
411
|
detail: { skuId: offer.sku_id, country }
|
|
412
412
|
})
|
|
413
413
|
);
|
|
414
|
+
console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
|
|
414
415
|
});
|
|
415
416
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
416
417
|
"click",
|
|
@@ -411,6 +411,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
411
411
|
detail: { skuId: offer.sku_id, country }
|
|
412
412
|
})
|
|
413
413
|
);
|
|
414
|
+
console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
|
|
414
415
|
});
|
|
415
416
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
416
417
|
"click",
|
|
@@ -775,30 +776,45 @@ function startApplePaySession(config) {
|
|
|
775
776
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
776
777
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
777
778
|
};
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
console.log("[web-apple-pay]
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
779
|
+
try {
|
|
780
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
781
|
+
console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
|
|
782
|
+
session.onvalidatemerchant = async (event) => {
|
|
783
|
+
console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
|
|
784
|
+
try {
|
|
785
|
+
const validationHost = new URL(event.validationURL).host;
|
|
786
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
787
|
+
console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
|
|
788
|
+
trackFallbackCheckout(config.skuId);
|
|
789
|
+
session.abort();
|
|
790
|
+
window.location.href = redirectToCheckoutFallback({
|
|
791
|
+
skuId: config.skuId,
|
|
792
|
+
returnUrl: config.returnUrl,
|
|
793
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
794
|
+
});
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
798
|
+
console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
|
|
799
|
+
const response = await validateAppleMerchant({
|
|
800
|
+
validationURL: event.validationURL,
|
|
801
|
+
recaptchaToken
|
|
791
802
|
});
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
803
|
+
if (!response?.merchantSession) {
|
|
804
|
+
console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
|
|
805
|
+
trackFallbackCheckout(config.skuId);
|
|
806
|
+
session.abort();
|
|
807
|
+
window.location.href = redirectToCheckoutFallback({
|
|
808
|
+
skuId: config.skuId,
|
|
809
|
+
returnUrl: config.returnUrl,
|
|
810
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
811
|
+
});
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
|
|
815
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
816
|
+
} catch (err) {
|
|
817
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
802
818
|
trackFallbackCheckout(config.skuId);
|
|
803
819
|
session.abort();
|
|
804
820
|
window.location.href = redirectToCheckoutFallback({
|
|
@@ -806,33 +822,29 @@ function startApplePaySession(config) {
|
|
|
806
822
|
returnUrl: config.returnUrl,
|
|
807
823
|
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
808
824
|
});
|
|
809
|
-
return;
|
|
810
825
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
console.
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
}
|
|
833
|
-
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
834
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
835
|
-
session.begin();
|
|
826
|
+
};
|
|
827
|
+
session.onpaymentauthorized = (event) => {
|
|
828
|
+
console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
|
|
829
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
830
|
+
config.onPaymentAuthorized(event, session);
|
|
831
|
+
};
|
|
832
|
+
session.oncancel = () => {
|
|
833
|
+
console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
|
|
834
|
+
config.onCancel?.();
|
|
835
|
+
};
|
|
836
|
+
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
837
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
838
|
+
session.begin();
|
|
839
|
+
} catch (err) {
|
|
840
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
|
|
841
|
+
trackFallbackCheckout(config.skuId);
|
|
842
|
+
window.location.href = redirectToCheckoutFallback({
|
|
843
|
+
skuId: config.skuId,
|
|
844
|
+
returnUrl: config.returnUrl,
|
|
845
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
846
|
+
});
|
|
847
|
+
}
|
|
836
848
|
}
|
|
837
849
|
|
|
838
850
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1386,6 +1398,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1386
1398
|
#returnUrl = "";
|
|
1387
1399
|
#supportedBillingCountries = [];
|
|
1388
1400
|
#entryPoint = "";
|
|
1401
|
+
#recaptchaTokens = null;
|
|
1389
1402
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1390
1403
|
get offer() {
|
|
1391
1404
|
return this.#offer;
|
|
@@ -1446,6 +1459,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1446
1459
|
* and eliminating the implicit reliance on the DOM as a render-state flag.
|
|
1447
1460
|
*/
|
|
1448
1461
|
disconnectedCallback() {
|
|
1462
|
+
console.log("[web-apple-pay] disconnectedCallback: element removed from DOM, resetting state");
|
|
1449
1463
|
this.#rendering = false;
|
|
1450
1464
|
this.#readyPromise = null;
|
|
1451
1465
|
this.#sessionData = null;
|
|
@@ -1554,10 +1568,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1554
1568
|
button.addEventListener("click", () => {
|
|
1555
1569
|
this.#openModal();
|
|
1556
1570
|
});
|
|
1557
|
-
|
|
1571
|
+
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1558
1572
|
const { skuId, country } = event.detail;
|
|
1573
|
+
console.log("[web-apple-pay] apple-pay-confirmed received on document", { skuId, country });
|
|
1559
1574
|
this.#initiateApplePay(skuId, country);
|
|
1560
|
-
});
|
|
1575
|
+
}, { once: true });
|
|
1561
1576
|
}
|
|
1562
1577
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1563
1578
|
#updateDisabledState() {
|
|
@@ -1573,8 +1588,21 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1573
1588
|
}
|
|
1574
1589
|
#openModal() {
|
|
1575
1590
|
console.log("[web-apple-pay] #openModal: button clicked", { skuId: this.#offer?.sku_id });
|
|
1576
|
-
if (!this.#offer
|
|
1591
|
+
if (!this.#offer) {
|
|
1592
|
+
console.warn("[web-apple-pay] #openModal: no offer set, ignoring click");
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
1596
|
+
console.warn("[web-apple-pay] #openModal: modal already open, ignoring click");
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1577
1599
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1600
|
+
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1601
|
+
console.log("[web-apple-pay] #openModal: reCAPTCHA tokens pre-fetched");
|
|
1602
|
+
this.#recaptchaTokens = tokens;
|
|
1603
|
+
}).catch((err) => {
|
|
1604
|
+
console.warn("[web-apple-pay] #openModal: reCAPTCHA pre-fetch failed", err);
|
|
1605
|
+
});
|
|
1578
1606
|
ApplePayModal.define();
|
|
1579
1607
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1580
1608
|
modal.offer = this.#offer;
|
|
@@ -1637,7 +1665,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1637
1665
|
try {
|
|
1638
1666
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1639
1667
|
const paymentOptions = this.#paymentOptions;
|
|
1640
|
-
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1668
|
+
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1669
|
+
console.log("[web-apple-pay] #initiateApplePay: tokens ready, starting session", { prefetched: !!this.#recaptchaTokens });
|
|
1641
1670
|
startApplePaySession(
|
|
1642
1671
|
this.#buildSessionParams(
|
|
1643
1672
|
skuId,
|
|
@@ -179,30 +179,45 @@ function startApplePaySession(config) {
|
|
|
179
179
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
180
180
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
181
181
|
};
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
console.log("[web-apple-pay]
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
182
|
+
try {
|
|
183
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
184
|
+
console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
|
|
185
|
+
session.onvalidatemerchant = async (event) => {
|
|
186
|
+
console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
|
|
187
|
+
try {
|
|
188
|
+
const validationHost = new URL(event.validationURL).host;
|
|
189
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
190
|
+
console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
|
|
191
|
+
trackFallbackCheckout(config.skuId);
|
|
192
|
+
session.abort();
|
|
193
|
+
window.location.href = redirectToCheckoutFallback({
|
|
194
|
+
skuId: config.skuId,
|
|
195
|
+
returnUrl: config.returnUrl,
|
|
196
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
197
|
+
});
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
201
|
+
console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
|
|
202
|
+
const response = await validateAppleMerchant({
|
|
203
|
+
validationURL: event.validationURL,
|
|
204
|
+
recaptchaToken
|
|
195
205
|
});
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
if (!response?.merchantSession) {
|
|
207
|
+
console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
|
|
208
|
+
trackFallbackCheckout(config.skuId);
|
|
209
|
+
session.abort();
|
|
210
|
+
window.location.href = redirectToCheckoutFallback({
|
|
211
|
+
skuId: config.skuId,
|
|
212
|
+
returnUrl: config.returnUrl,
|
|
213
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
|
|
218
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
219
|
+
} catch (err) {
|
|
220
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
206
221
|
trackFallbackCheckout(config.skuId);
|
|
207
222
|
session.abort();
|
|
208
223
|
window.location.href = redirectToCheckoutFallback({
|
|
@@ -210,33 +225,29 @@ function startApplePaySession(config) {
|
|
|
210
225
|
returnUrl: config.returnUrl,
|
|
211
226
|
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
212
227
|
});
|
|
213
|
-
return;
|
|
214
228
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
console.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
238
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
239
|
-
session.begin();
|
|
229
|
+
};
|
|
230
|
+
session.onpaymentauthorized = (event) => {
|
|
231
|
+
console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
|
|
232
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
233
|
+
config.onPaymentAuthorized(event, session);
|
|
234
|
+
};
|
|
235
|
+
session.oncancel = () => {
|
|
236
|
+
console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
|
|
237
|
+
config.onCancel?.();
|
|
238
|
+
};
|
|
239
|
+
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
240
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
241
|
+
session.begin();
|
|
242
|
+
} catch (err) {
|
|
243
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
|
|
244
|
+
trackFallbackCheckout(config.skuId);
|
|
245
|
+
window.location.href = redirectToCheckoutFallback({
|
|
246
|
+
skuId: config.skuId,
|
|
247
|
+
returnUrl: config.returnUrl,
|
|
248
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
249
|
+
});
|
|
250
|
+
}
|
|
240
251
|
}
|
|
241
252
|
export {
|
|
242
253
|
startApplePaySession
|
package/dist/src/index.js
CHANGED
|
@@ -411,6 +411,7 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
|
|
|
411
411
|
detail: { skuId: offer.sku_id, country }
|
|
412
412
|
})
|
|
413
413
|
);
|
|
414
|
+
console.log("[web-apple-pay] ApplePayModal: dispatching apple-pay-confirmed-final", { skuId: offer.sku_id, country });
|
|
414
415
|
});
|
|
415
416
|
this.querySelector("#apple-pay-modal-close")?.addEventListener(
|
|
416
417
|
"click",
|
|
@@ -786,30 +787,45 @@ function startApplePaySession(config) {
|
|
|
786
787
|
// Only request email from Apple Pay sheet if user is NOT logged in
|
|
787
788
|
...!config.userLoggedIn && { requiredShippingContactFields: ["email"] }
|
|
788
789
|
};
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
console.log("[web-apple-pay]
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
790
|
+
try {
|
|
791
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
792
|
+
console.log("[web-apple-pay] startApplePaySession: ApplePaySession created");
|
|
793
|
+
session.onvalidatemerchant = async (event) => {
|
|
794
|
+
console.log("[web-apple-pay] onvalidatemerchant: received", { validationURL: event.validationURL });
|
|
795
|
+
try {
|
|
796
|
+
const validationHost = new URL(event.validationURL).host;
|
|
797
|
+
if (!validationHost.endsWith("apple.com")) {
|
|
798
|
+
console.warn("[web-apple-pay] onvalidatemerchant: invalid host, aborting", { validationHost });
|
|
799
|
+
trackFallbackCheckout(config.skuId);
|
|
800
|
+
session.abort();
|
|
801
|
+
window.location.href = redirectToCheckoutFallback({
|
|
802
|
+
skuId: config.skuId,
|
|
803
|
+
returnUrl: config.returnUrl,
|
|
804
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
805
|
+
});
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const recaptchaToken = await getRecaptchaToken("verifyMerchant");
|
|
809
|
+
console.log("[web-apple-pay] onvalidatemerchant: calling validateAppleMerchant");
|
|
810
|
+
const response = await validateAppleMerchant({
|
|
811
|
+
validationURL: event.validationURL,
|
|
812
|
+
recaptchaToken
|
|
802
813
|
});
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
814
|
+
if (!response?.merchantSession) {
|
|
815
|
+
console.warn("[web-apple-pay] onvalidatemerchant: no merchantSession in response, aborting");
|
|
816
|
+
trackFallbackCheckout(config.skuId);
|
|
817
|
+
session.abort();
|
|
818
|
+
window.location.href = redirectToCheckoutFallback({
|
|
819
|
+
skuId: config.skuId,
|
|
820
|
+
returnUrl: config.returnUrl,
|
|
821
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
822
|
+
});
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
console.log("[web-apple-pay] onvalidatemerchant: merchant validated successfully");
|
|
826
|
+
session.completeMerchantValidation(response.merchantSession);
|
|
827
|
+
} catch (err) {
|
|
828
|
+
console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
|
|
813
829
|
trackFallbackCheckout(config.skuId);
|
|
814
830
|
session.abort();
|
|
815
831
|
window.location.href = redirectToCheckoutFallback({
|
|
@@ -817,33 +833,29 @@ function startApplePaySession(config) {
|
|
|
817
833
|
returnUrl: config.returnUrl,
|
|
818
834
|
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
819
835
|
});
|
|
820
|
-
return;
|
|
821
836
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
console.
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}
|
|
844
|
-
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
845
|
-
trackWalletPaymentSheetOpen(config.skuId);
|
|
846
|
-
session.begin();
|
|
837
|
+
};
|
|
838
|
+
session.onpaymentauthorized = (event) => {
|
|
839
|
+
console.log("[web-apple-pay] onpaymentauthorized: payment authorized by user", { skuId: config.skuId });
|
|
840
|
+
trackWalletPaymentAuthorised(config.skuId);
|
|
841
|
+
config.onPaymentAuthorized(event, session);
|
|
842
|
+
};
|
|
843
|
+
session.oncancel = () => {
|
|
844
|
+
console.log("[web-apple-pay] oncancel: payment sheet cancelled by user", { skuId: config.skuId });
|
|
845
|
+
config.onCancel?.();
|
|
846
|
+
};
|
|
847
|
+
console.log("[web-apple-pay] startApplePaySession: beginning session");
|
|
848
|
+
trackWalletPaymentSheetOpen(config.skuId);
|
|
849
|
+
session.begin();
|
|
850
|
+
} catch (err) {
|
|
851
|
+
console.error("[web-apple-pay] startApplePaySession: failed to create or begin ApplePaySession", err);
|
|
852
|
+
trackFallbackCheckout(config.skuId);
|
|
853
|
+
window.location.href = redirectToCheckoutFallback({
|
|
854
|
+
skuId: config.skuId,
|
|
855
|
+
returnUrl: config.returnUrl,
|
|
856
|
+
inlineError: MSG_PAYMENT_GENERIC_ERROR
|
|
857
|
+
});
|
|
858
|
+
}
|
|
847
859
|
}
|
|
848
860
|
|
|
849
861
|
// src/clients/payment-checkout/contact-validation.ts
|
|
@@ -1397,6 +1409,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1397
1409
|
#returnUrl = "";
|
|
1398
1410
|
#supportedBillingCountries = [];
|
|
1399
1411
|
#entryPoint = "";
|
|
1412
|
+
#recaptchaTokens = null;
|
|
1400
1413
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
1401
1414
|
get offer() {
|
|
1402
1415
|
return this.#offer;
|
|
@@ -1457,6 +1470,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1457
1470
|
* and eliminating the implicit reliance on the DOM as a render-state flag.
|
|
1458
1471
|
*/
|
|
1459
1472
|
disconnectedCallback() {
|
|
1473
|
+
console.log("[web-apple-pay] disconnectedCallback: element removed from DOM, resetting state");
|
|
1460
1474
|
this.#rendering = false;
|
|
1461
1475
|
this.#readyPromise = null;
|
|
1462
1476
|
this.#sessionData = null;
|
|
@@ -1565,10 +1579,11 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1565
1579
|
button.addEventListener("click", () => {
|
|
1566
1580
|
this.#openModal();
|
|
1567
1581
|
});
|
|
1568
|
-
|
|
1582
|
+
document.addEventListener("apple-pay-confirmed", (event) => {
|
|
1569
1583
|
const { skuId, country } = event.detail;
|
|
1584
|
+
console.log("[web-apple-pay] apple-pay-confirmed received on document", { skuId, country });
|
|
1570
1585
|
this.#initiateApplePay(skuId, country);
|
|
1571
|
-
});
|
|
1586
|
+
}, { once: true });
|
|
1572
1587
|
}
|
|
1573
1588
|
// ─── Private helpers ────────────────────────────────────────────────────────
|
|
1574
1589
|
#updateDisabledState() {
|
|
@@ -1584,8 +1599,21 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1584
1599
|
}
|
|
1585
1600
|
#openModal() {
|
|
1586
1601
|
console.log("[web-apple-pay] #openModal: button clicked", { skuId: this.#offer?.sku_id });
|
|
1587
|
-
if (!this.#offer
|
|
1602
|
+
if (!this.#offer) {
|
|
1603
|
+
console.warn("[web-apple-pay] #openModal: no offer set, ignoring click");
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
if (document.querySelector(ApplePayModal.tag)) {
|
|
1607
|
+
console.warn("[web-apple-pay] #openModal: modal already open, ignoring click");
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1588
1610
|
trackExpressWalletClick(this.#offer.sku_id);
|
|
1611
|
+
getPurchaseRecaptchaTokens().then((tokens) => {
|
|
1612
|
+
console.log("[web-apple-pay] #openModal: reCAPTCHA tokens pre-fetched");
|
|
1613
|
+
this.#recaptchaTokens = tokens;
|
|
1614
|
+
}).catch((err) => {
|
|
1615
|
+
console.warn("[web-apple-pay] #openModal: reCAPTCHA pre-fetch failed", err);
|
|
1616
|
+
});
|
|
1589
1617
|
ApplePayModal.define();
|
|
1590
1618
|
const modal = document.createElement(ApplePayModal.tag);
|
|
1591
1619
|
modal.offer = this.#offer;
|
|
@@ -1648,7 +1676,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
1648
1676
|
try {
|
|
1649
1677
|
const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
|
|
1650
1678
|
const paymentOptions = this.#paymentOptions;
|
|
1651
|
-
const recaptchaTokens = await getPurchaseRecaptchaTokens();
|
|
1679
|
+
const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
|
|
1680
|
+
console.log("[web-apple-pay] #initiateApplePay: tokens ready, starting session", { prefetched: !!this.#recaptchaTokens });
|
|
1652
1681
|
startApplePaySession(
|
|
1653
1682
|
this.#buildSessionParams(
|
|
1654
1683
|
skuId,
|
package/package.json
CHANGED