diff --git a/assets/shop/controllers/apple-pay_controller.js b/assets/shop/controllers/apple-pay_controller.js index e9d99adc..fe977eb6 100644 --- a/assets/shop/controllers/apple-pay_controller.js +++ b/assets/shop/controllers/apple-pay_controller.js @@ -1,166 +1,181 @@ import { Controller } from '@hotwired/stimulus'; -import $ from 'jquery'; /* stimulusFetch: 'lazy' */ export default class extends Controller { - connect() { - this.applePayHandler(); + static values = { + paymentInputId: String, + settings: Object, + notice: String, } - showApplePayButton() { - const applePayButton = $(document).find("apple-pay-button"); - if (applePayButton.length) { - applePayButton.addClass('enabled'); + + connect() { + this.applePayButton = this.element.querySelector('apple-pay-button'); + this.onApplePayButtonClick = this.onApplePayButtonClick.bind(this); + + if (this.applePayButton) { + this.applePayButton.addEventListener('click', this.onApplePayButtonClick); } + + this.retryCount = 0; + this.initApplePay(); } - hideApplePayButton() { - const applePayButton = $(document).find("apple-pay-button.enabled"); - if (applePayButton.length) { - applePayButton.removeClass('enabled'); + + initApplePay() { + if (typeof window.ApplePaySession !== 'undefined') { + this.checkSupport(); + return; + } + + if (this.retryCount < 20) { // Try for 2 seconds + this.retryCount++; + setTimeout(() => this.initApplePay(), 100); + } else { + this.disablePaymentMethod(); } } - applePayHandler() { - const applePayChoice = $(".payment-item .checkbox-applepay input:radio"); - if (applePayChoice) { - if (applePayChoice.is(':checked')) { - this.disableNextStepButton(); - this.showApplePayButton(); + + checkSupport() { + try { + const isSupported = window.ApplePaySession.canMakePayments(); + + if (isSupported && this.applePayButton) { + this.applePayButton.classList.add('enabled'); } else { - this.enableNextStepButton(); - this.hideApplePayButton(); + this.disablePaymentMethod(); } + } catch (e) { + this.disablePaymentMethod(); } - $(".payment-item .checkbox input:radio").on('change', this.onPaymentMethodChoice); - $(document).find("apple-pay-button").on('click', this.onApplePayButtonClick); } - onPaymentMethodChoice(event) { - const isApplePay = $(event.currentTarget).closest('.checkbox-applepay').length; - if (isApplePay) { - this.showApplePayButton(); - this.disableNextStepButton(); - } else { - this.hideApplePayButton(); - this.enableNextStepButton(); + + disablePaymentMethod() { + if (!this.paymentInputIdValue) return; + + const input = document.getElementById(this.paymentInputIdValue); + if (!input) return; + + const container = input.closest('.card, .item, .form-check, .field'); + if (container) { + container.style.opacity = '0.5'; + container.style.pointerEvents = 'none'; + container.classList.add('apple-pay-ineligible'); + + // Add a small info message if not already present + if (!container.querySelector('.apple-pay-notice')) { + const notice = document.createElement('div'); + notice.className = 'apple-pay-notice small text-muted mt-2'; + notice.style.padding = '0 1rem 1rem'; + notice.innerText = this.noticeValue || 'Apple Pay is not available on this browser or device.'; + container.appendChild(notice); + } + + if (input.checked) { + input.checked = false; + input.dispatchEvent(new Event('change', { bubbles: true })); + } + } + + input.disabled = true; + + if (this.element) { + this.element.style.display = 'none'; } } - onApplePayButtonClick(event) { - const applePayButton = $(event.currentTarget); - if (applePaySessionRequestSettings === undefined) { + async onApplePayButtonClick(event) { + const applePayButton = event.currentTarget; + + if (!this.settingsValue) { console.error('Invalid Apple Pay settings!'); - return false; + return; } - // Create ApplePaySession - const session = new ApplePaySession(3, applePaySessionRequestSettings); + if (typeof window.ApplePaySession === 'undefined') { + return; + } - session.onvalidatemerchant = async event => { - $.ajax({ - url: applePayButton.data('validate-merchant-route'), - method: 'POST', - cache: false, - data: {}, - success: (authorization) => { - let result = authorization.merchant_session; - console.log(result); + // Prepare settings + const settings = { ...this.settingsValue }; + if (settings.applePayDomain) { + settings.applicationData = btoa(JSON.stringify({ + 'apple_pay_domain': settings.applePayDomain + })); + delete settings.applePayDomain; + } + + try { + const version = window.ApplePaySession.supportsVersion(14) ? 14 : 3; + const session = new window.ApplePaySession(version, settings); + + session.onvalidatemerchant = async (event) => { + try { + const response = await fetch(applePayButton.dataset.validateMerchantRoute, { + method: 'POST', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + }, + }); + const authorization = await response.json(); if (authorization.success === true) { - console.log(authorization.merchant_session); - session.completeMerchantValidation(result); + session.completeMerchantValidation(authorization.merchant_session); } else { session.abort(); } - }, - error: (XHR, status, error) => { - console.log(XHR, status, error); + } catch (error) { + console.error(error); session.abort(); window.location.reload(); - }, - }); - }; - - session.onpaymentauthorized = event => { - $.ajax({ - url: applePayButton.data('payment-authorized-route'), - method: 'POST', - cache: false, - data: { - token: event.payment.token - }, - success: (authorization) => { - try { - var apple_pay_Session_status = ApplePaySession.STATUS_SUCCESS; - - console.log(authorization); - console.log(authorization.data.responseToApple.status); - if (authorization.data.responseToApple.status != 1) { - apple_pay_Session_status = ApplePaySession.STATUS_FAILURE; - } - - const result = { - "status": apple_pay_Session_status - }; - - console.log(apple_pay_Session_status); - console.log(result); - - session.completePayment(result); - - console.log(authorization.data.returnUrl); - window.location.href = authorization.data.returnUrl; - } catch (err) { - console.error(err); - window.location.reload(); + } + }; + + session.onpaymentauthorized = async (event) => { + try { + const response = await fetch(applePayButton.dataset.paymentAuthorizedRoute, { + method: 'POST', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + token: event.payment.token, + }), + }); + const authorization = await response.json(); + + let applePaySessionStatus = window.ApplePaySession.STATUS_SUCCESS; + + if (authorization.data.responseToApple.status !== 1) { + applePaySessionStatus = window.ApplePaySession.STATUS_FAILURE; } - }, - error: (XHR, status, error) => { - console.log(XHR, status, error); - session.abort(); + + session.completePayment({ "status": applePaySessionStatus }); + window.location.href = authorization.data.returnUrl; + } catch (error) { + console.error(error); window.location.reload(); - }, - }); - }; - - session.oncancel = event => { - console.log('Cancelling Apple Pay session!'); - - $.ajax({ - url: applePayButton.data('session-cancel-route'), - cache: false, - method: 'POST', - data: {}, - success: (authorization) => { - console.log('Cancelled!'); - console.log(authorization.data.returnUrl); + } + }; + + session.oncancel = async (event) => { + try { + const response = await fetch(applePayButton.dataset.sessionCancelRoute, { + method: 'POST', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + }, + }); + const authorization = await response.json(); window.location.href = authorization.data.returnUrl; - }, - error: (XHR, status, error) => { - console.log(XHR, status, error); + } catch (error) { + console.error(error); window.location.reload(); - }, - }); - }; + } + }; - session.begin(); - } - disableNextStepButton() { - const nextStepButton = $('form[name*="checkout_select_payment"] [data-test-next-step]'); - nextStepButton.replaceWith( - $("", { - id: 'next-step', - class: 'btn btn-primary btn-icon', - html: nextStepButton.html() - }) - ); - } - enableNextStepButton() { - const nextStepButton = $('form[name*="checkout_select_payment"] [data-test-next-step]'); - nextStepButton.replaceWith( - $("