diff --git a/modules/ppcp-button/resources/js/button.js b/modules/ppcp-button/resources/js/button.js index 40997d15a..9bc2e4b49 100644 --- a/modules/ppcp-button/resources/js/button.js +++ b/modules/ppcp-button/resources/js/button.js @@ -40,11 +40,6 @@ const bootstrap = () => { ); const spinner = new Spinner(); - let creditCardRenderer = new HostedFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner); - if (typeof paypal.CardFields !== 'undefined') { - creditCardRenderer = new CardFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner); - } - const formSaver = new FormSaver( PayPalCommerceGateway.ajax.save_checkout_form.endpoint, PayPalCommerceGateway.ajax.save_checkout_form.nonce, @@ -73,13 +68,7 @@ const bootstrap = () => { && document.querySelector(PayPalCommerceGateway.messages.wrapper); } - const onSmartButtonClick = async (data, actions) => { - window.ppcpFundingSource = data.fundingSource; - const requiredFields = jQuery('form.woocommerce-checkout .validate-required:visible :input'); - requiredFields.each((i, input) => { - jQuery(input).trigger('validate'); - }); - + const doBasicCheckoutValidation = () => { if (PayPalCommerceGateway.basic_checkout_validation_enabled) { // A quick fix to get the errors about empty form fields before attempting PayPal order, // it should solve #513 for most of the users, but it is not a proper solution. @@ -117,9 +106,26 @@ const bootstrap = () => { errorHandler.message(PayPalCommerceGateway.labels.error.required.generic); } - return actions.reject(); + return false; } } + return true; + }; + + const onCardFieldsBeforeSubmit = () => { + return doBasicCheckoutValidation(); + }; + + const onSmartButtonClick = async (data, actions) => { + window.ppcpFundingSource = data.fundingSource; + const requiredFields = jQuery('form.woocommerce-checkout .validate-required:visible :input'); + requiredFields.each((i, input) => { + jQuery(input).trigger('validate'); + }); + + if (!doBasicCheckoutValidation()) { + return actions.reject(); + } const form = document.querySelector(checkoutFormSelector); if (form) { @@ -149,6 +155,12 @@ const bootstrap = () => { jQuery(document).trigger('ppcp-smart-buttons-init', this); buttonsSpinner.unblock(); }; + + let creditCardRenderer = new HostedFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner); + if (typeof paypal.CardFields !== 'undefined') { + creditCardRenderer = new CardFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner, onCardFieldsBeforeSubmit); + } + const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick, onSmartButtonsInit); const messageRenderer = new MessageRenderer(PayPalCommerceGateway.messages); diff --git a/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js b/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js index 93ecf7c8f..75b5f9848 100644 --- a/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js +++ b/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js @@ -18,7 +18,7 @@ class CheckoutActionHandler { try { await validateCheckoutForm(this.config); } catch (error) { - throw {type: 'form-validation-error'}; + throw { type: 'form-validation-error' }; } return actions.subscription.create({ @@ -48,7 +48,13 @@ class CheckoutActionHandler { configuration() { const spinner = this.spinner; - const createOrder = (data, actions) => { + const createOrder = async (data, actions) => { + try { + await validateCheckoutForm(this.config); + } catch (error) { + throw { type: 'form-validation-error' }; + } + const payer = payerData(); const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : ''; @@ -136,7 +142,7 @@ class CheckoutActionHandler { console.error(err); spinner.unblock(); - if (err && err.type === 'create-order-error') { + if (err && (err.type === 'create-order-error' || err.type === 'form-validation-error')) { return; } diff --git a/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js b/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js index 377568fcb..babb2b4fc 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js @@ -3,7 +3,7 @@ import {cardFieldStyles} from "../Helper/CardFieldsHelper"; class CardFieldsRenderer { - constructor(defaultConfig, errorHandler, spinner) { + constructor(defaultConfig, errorHandler, spinner, onCardFieldsBeforeSubmit) { this.defaultConfig = defaultConfig; this.errorHandler = errorHandler; this.spinner = spinner; @@ -11,6 +11,7 @@ class CardFieldsRenderer { this.formValid = false; this.emptyFields = new Set(['number', 'cvv', 'expirationDate']); this.currentHostedFieldsInstance = null; + this.onCardFieldsBeforeSubmit = onCardFieldsBeforeSubmit; } render(wrapper, contextConfig) { @@ -110,10 +111,20 @@ class CardFieldsRenderer { return; } + if (typeof this.onCardFieldsBeforeSubmit === 'function' && !this.onCardFieldsBeforeSubmit()) { + this.spinner.unblock(); + return; + } + cardField.submit() .catch((error) => { this.spinner.unblock(); console.error(error) + + if (error.type === 'form-validation-error') { + return; + } + this.errorHandler.message(this.defaultConfig.hosted_fields.labels.fields_not_valid); }); });