diff --git a/CRM/Stripe/AJAX.php b/CRM/Stripe/AJAX.php index 3986f30e1cbf56c18dd9801f5d67bdbef5f8d616..e0c2b5c19efadc1d4c75f4fb657f5cf0af670d4c 100644 --- a/CRM/Stripe/AJAX.php +++ b/CRM/Stripe/AJAX.php @@ -9,6 +9,8 @@ +--------------------------------------------------------------------+ */ +use CRM_Stripe_ExtensionUtil as E; + /** * Class CRM_Stripe_AJAX */ @@ -154,7 +156,13 @@ class CRM_Stripe_AJAX { } else { // Invalid status - CRM_Utils_JSON::output(['error' => ['message' => 'Invalid PaymentIntent status: ' . $intent->status]]); + if (isset($intent->last_payment_error->message)) { + $message = E::ts('Payment failed: %1', [1 => $intent->last_payment_error->message]); + } + else { + $message = E::ts('Payment failed.'); + } + CRM_Utils_JSON::output(['error' => ['message' => $message]]); } } diff --git a/js/civicrmStripeConfirm.js b/js/civicrmStripeConfirm.js index a540f5c0c6d377f97d4f29e2c3a42c3e1ad6e153..a75252aec2e3e0b6b1c37aa639182275185d5002 100644 --- a/js/civicrmStripeConfirm.js +++ b/js/civicrmStripeConfirm.js @@ -14,6 +14,10 @@ if (result.error) { // Show error from server on payment form CRM.payment.debugging(confirm.scriptName, result.error.message); + confirm.swalFire({ + title: result.error.message, + icon: 'error', + }); } else if (result.requires_action) { @@ -23,6 +27,10 @@ else { // All good, nothing more to do CRM.payment.debugging(confirm.scriptName, 'success - payment captured'); + confirm.swalFire({ + title: 'Payment successful', + icon: 'success', + }); } }, @@ -62,6 +70,13 @@ handleCardConfirm: function() { CRM.payment.debugging(confirm.scriptName, 'handle card confirm'); + confirm.swalFire({ + title: 'Please wait...', + allowOutsideClick: false, + onBeforeOpen: () => { + Swal.showLoading(); + }, + }); // Send paymentMethod.id to server var url = CRM.url('civicrm/stripe/confirm-payment'); $.post(url, { @@ -70,10 +85,15 @@ id: CRM.vars.stripe.id, description: document.title, csrfToken: CRM.vars.stripe.csrfToken, - }).then(function (result) { - // Handle server response (see Step 3) - confirm.handleServerResponse(result); - }); + }) + .done(function (result) { + confirm.swalClose(); + // Handle server response (see Step 3) + confirm.handleServerResponse(result); + }) + .fail(function() { + confirm.swalClose(); + }); }, checkAndLoad: function () { @@ -103,6 +123,18 @@ }); } }, + + swalFire: function(parameters) { + if (typeof Swal === 'function') { + Swal.fire(parameters); + } + }, + + swalClose: function() { + if (typeof Swal === 'function') { + Swal.close(); + } + } }; if (typeof CRM.payment === 'undefined') { diff --git a/js/civicrm_stripe.js b/js/civicrm_stripe.js index 21ad1d3d9d8960d1e9e9408c9ec0ae179b2cac97..d324b87914cb5e85dd1ac0d6f0fbb8b6170b61f8 100644 --- a/js/civicrm_stripe.js +++ b/js/civicrm_stripe.js @@ -86,7 +86,7 @@ CRM.$(function($) { var errorElement = document.getElementById('card-errors'); errorElement.style.display = 'block'; errorElement.textContent = errorMessage; - form.dataset.submitted = false; + form.dataset.submitted = 'false'; if (typeof submitButtons !== 'undefined') { for (i = 0; i < submitButtons.length; ++i) { submitButtons[i].removeAttribute('disabled'); @@ -152,6 +152,14 @@ CRM.$(function($) { } else { // Send paymentMethod.id to server + debugging('Waiting for pre-auth'); + Swal.fire({ + title: 'Please wait while we pre-authorize your card...', + allowOutsideClick: false, + onBeforeOpen: () => { + Swal.showLoading(); + }, + }); var url = CRM.url('civicrm/stripe/confirm-payment'); $.post(url, { payment_method_id: result.paymentMethod.id, @@ -160,10 +168,14 @@ CRM.$(function($) { id: CRM.vars.stripe.id, description: document.title, csrfToken: CRM.vars.stripe.csrfToken, - }).then(function (result) { - // Handle server response (see Step 3) - handleServerResponse(result); - }); + }) + .done(function (result) { + // Handle server response (see Step 3) + handleServerResponse(result); + }) + .always(function() { + Swal.close(); + }); } } }); @@ -270,6 +282,7 @@ CRM.$(function($) { dataType: 'script', cache: true, timeout: 5000, + crossDomain: true, }) .done(function(data) { stripeLoading = false; @@ -352,7 +365,7 @@ CRM.$(function($) { // If another submit button on the form is pressed (eg. apply discount) // add a flag that we can set to stop payment submission - form.dataset.submitdontprocess = false; + form.dataset.submitdontprocess = 'false'; // Find submit buttons which should not submit payment var nonPaymentSubmitButtons = form.querySelectorAll('[type="submit"][formnovalidate="1"], ' + @@ -365,7 +378,7 @@ CRM.$(function($) { function submitDontProcess() { debugging('adding submitdontprocess'); - form.dataset.submitdontprocess = true; + form.dataset.submitdontprocess = 'true'; } for (i = 0; i < submitButtons.length; ++i) { @@ -373,17 +386,13 @@ CRM.$(function($) { } function submitButtonClick(event) { - if (form.dataset.submitted === true) { - return; - } - form.dataset.submitted = true; // Take over the click function of the form. if (typeof CRM.vars.stripe === 'undefined') { // Submit the form return nonStripeSubmit(); } debugging('clearing submitdontprocess'); - form.dataset.submitdontprocess = false; + form.dataset.submitdontprocess = 'false'; // Run through our own submit, that executes Stripe submission if // appropriate for this submit. @@ -420,6 +429,11 @@ CRM.$(function($) { event.preventDefault(); debugging('submit handler'); + if (form.dataset.submitted === 'true') { + return; + } + form.dataset.submitted = 'true'; + if (($(form).valid() === false) || $(form).data('crmBillingFormValid') === false) { debugging('Form not valid'); $('div#card-errors').hide(); @@ -462,11 +476,6 @@ CRM.$(function($) { return true; } - if (form.dataset.submitted === true) { - debugging('form already submitted'); - return false; - } - var stripeProcessorId = parseInt(CRM.vars.stripe.id); var chosenProcessorId = null; @@ -510,7 +519,7 @@ CRM.$(function($) { return true; } // Don't handle submits generated by the CiviDiscount button. - if (form.dataset.submitdontprocess === true) { + if (form.dataset.submitdontprocess === 'true') { debugging('non-payment submit detected - not submitting payment'); return true; } @@ -538,16 +547,6 @@ CRM.$(function($) { return nonStripeSubmit(); } - // Lock to prevent multiple submissions - if (form.dataset.submitted === true) { - // Previously submitted - don't submit again - alert('Form already submitted. Please wait.'); - return false; - } else { - // Mark it so that the next submit can be ignored - form.dataset.submitted = true; - } - // Disable the submit button to prevent repeated clicks for (i = 0; i < submitButtons.length; ++i) { submitButtons[i].setAttribute('disabled', true); @@ -723,7 +722,7 @@ CRM.$(function($) { if (event.code === 'Enter') { event.preventDefault(); debugging('adding submitdontprocess'); - form.dataset.submitdontprocess = true; + form.dataset.submitdontprocess = 'true'; } };