class PaymentWidget { promocodeRoute; stripe; elements; card; iban; submitting; constructor() { this.promocodeRoute = null; this.stripe = null; this.elements = null; this.card = null; this.iban = null; this.submitting = false; this.paymentForm = document.getElementById('payment-form'); this.promocodeElement = document.querySelector('input[name="promocode"]'); this.initialize(); } /** * @param {string} key * @param {string} phColor * @param {string} autofillColor */ initStripe(key, phColor = '#aab7c4', autofillColor = '#32325d') { if (document.getElementById('card-element') === null) { return; } let style = { base: { color: '', fontFamily: '"Helvetica Neue", Helvetica, sans-serif', fontSmoothing: 'antialiased', fontSize: '16px', '::placeholder': { color: phColor }, ':-webkit-autofill': { color: autofillColor, }, }, invalid: { color: '#fa755a', iconColor: '#fa755a', ':-webkit-autofill': { color: '#fa755a', }, } } this.stripe = Stripe(key); this.elements = this.stripe.elements(); this.card = this.elements.create('card', { hidePostalCode: true, style: style }); this.card.mount('#card-element'); // Create an instance of the IBAN Element this.iban = this.elements.create('iban', {style, supportedCountries: ['SEPA']}); // Add an instance of the IBAN Element into the `iban-element`
if (document.getElementById('iban-element')) { this.iban.mount('#iban-element'); } this.card.addEventListener('change', event => { let displayError = document.getElementById('card-errors'); displayError.textContent = event.error?.message ?? ''; }); } /** * @param {string} promocodeRoute */ setPromocodeRoute(promocodeRoute) { this.promocodeRoute = promocodeRoute; } getPromocodeRoute() { return this.promocodeRoute; } initialize() { document.querySelectorAll('[data-payment-mode="iban"]') .forEach(mode => mode.classList?.add('d-none')); document.querySelectorAll('button[data-toggle-show]') .forEach(element => { element.addEventListener('click', () => { let paymentModes = document.querySelectorAll('[data-payment-mode]'); paymentModes.forEach(mode => mode.classList.toggle('d-block')); paymentModes.forEach(mode => mode.classList.toggle('d-none')); }) }) if (this.promocodeElement) { this.promocodeElement .addEventListener('keyup', Commons.debounce(this.checkPromocode.bind(this), 750)); } if (this.paymentForm) { this.paymentForm.addEventListener('submit', this.onSubmitPaymentForm.bind(this)); } } checkPromocode(event) { let value = event.target.value; if (value.length > 3) { let route = this.getPromocodeRoute().replace('VALUE', value); fetch(route) .then(response => response.json()) .then(data => { let resultContainer = document.getElementById('promocode-res'); resultContainer.innerHTML = `${data.message}`; resultContainer.classList.remove('d-none'); }) } } onSubmitPaymentForm(event) { if (this.submitting) { return; } let form = event.target; event.preventDefault(); this.submitting = true; form.querySelectorAll('button').forEach(btn => btn.disabled = true) let cardholderName = document.getElementById('cardholder-name'); let email = document.getElementById('email'); if (!cardholderName.value) { document.getElementById('cardholderName-error')?.classList?.remove('d-none'); form.querySelectorAll('button').forEach(btn => btn.disabled = false) this.submitting = false; return false; } let submitButton = document.getElementById(event.submitter.id); let billingDetails = { name: cardholderName.value, email: email.value, address: {} }; let billingPhone = document.getElementById('billing-phone'); let billingCity = document.getElementById('billing-city'); let billingCountry = document.getElementById('billing-country_iso'); let billingAddress = document.getElementById('billing-address'); let billingZipcode = document.getElementById('billing-zipcode'); if (billingPhone?.value) { billingDetails.phone = billingPhone.value; } if (billingCity?.value) { billingDetails.address.city = billingCity.value; } if (billingCountry?.value) { billingDetails.address.country = billingCountry.value; } if (billingAddress?.value) { billingDetails.address.line1 = billingAddress.value; } if (billingZipcode?.value) { billingDetails.address.postal_code = billingZipcode.value; } if (event.submitter.id === 'iban-button') { this.stripe.confirmSepaDebitSetup( submitButton.dataset.secret, { payment_method: { sepa_debit: this.iban, billing_details: billingDetails }, } ).then(result => this.handleResult(result, 'iban-errors')); } else { Commons.setSpinner(form); this.stripe.handleCardSetup( submitButton.dataset.secret, this.card, { payment_method_data: { billing_details: billingDetails } } ).then(result => this.handleResult(result, 'card-errors')); } form.querySelectorAll('button').forEach(btn => btn.disabled = false) this.submitting = false; } /** * @param {object} result * @param {string} destId */ handleResult(result, destId) { let form = document.getElementById('payment-form'); console.log(result); Commons.unsetSpinner(form); if (result.error) { // Inform the user if there was an error. let errorElement = document.getElementById(destId); errorElement.textContent = result.error.message; return; } let hiddenInput = document.createElement('input'); hiddenInput.setAttribute('type', 'hidden'); hiddenInput.setAttribute('name', 'setupIntentId'); hiddenInput.setAttribute('value', result.setupIntent.id); form.appendChild(hiddenInput); form.submit(); } }