Commit a179000c authored by mattwire's avatar mattwire
Browse files

Validate payment forms using javascript so we don't create multiple uncaptured...

Validate payment forms using javascript so we don't create multiple uncaptured paymentIntents when the form is not valid
parent d274d0c8
......@@ -330,6 +330,9 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
// Assign to smarty so we can add via Card.tpl for drupal webform because addVars doesn't work in that context
$form->assign('stripeJSVars', $jsVars);
// Enable JS validation for forms so we only (submit) create a paymentIntent when the form has all fields validated.
$form->assign('isJsValidate', TRUE);
// Add help and javascript
CRM_Core_Region::instance('billing-block')->add(
['template' => 'CRM/Core/Payment/Stripe/Card.tpl', 'weight' => -1]);
......
......@@ -299,6 +299,11 @@ CRM.$(function($) {
event.preventDefault();
debugging('submit handler');
if ($(form).valid() === false) {
debugging('Form not valid');
return false;
}
if (typeof CRM.vars.stripe === 'undefined') {
debugging('Submitting - not a stripe processor');
return true;
......
CRM.$(function(d){f("civicrm_stripe loaded, dom-ready function firing.");if(window.civicrmStripeHandleReload){f("calling existing civicrmStripeHandleReload.");window.civicrmStripeHandleReload();return}var o;var b;var c;var a;var n=false;window.onbeforeunload=null;window.civicrmStripeHandleReload=function(){f("civicrmStripeHandleReload");var y=document.getElementById("card-element");if((typeof y!=="undefined")&&(y)){if(!y.children.length){f("checkAndLoad from document.ready");l()}}};window.civicrmStripeHandleReload();function t(z){f("paymentIntent confirmation success");var y=document.createElement("input");y.setAttribute("type","hidden");y.setAttribute("name","paymentIntentID");y.setAttribute("value",z.id);c.appendChild(y);c.submit()}function g(y){f("error: "+y.error.message);var z=document.getElementById("card-errors");z.style.display="block";z.textContent=y.error.message;document.querySelector("#billing-payment-block").scrollIntoView();window.scrollBy(0,-50);a.removeAttribute("disabled")}function w(){f("handle card payment");o.createPaymentMethod("card",b).then(function(y){if(y.error){g(y)}else{var z=CRM.url("civicrm/stripe/confirm-payment");d.post(z,{payment_method_id:y.paymentMethod.id,amount:p(),currency:CRM.vars.stripe.currency,id:CRM.vars.stripe.id}).then(function(A){u(A)})}})}function u(y){f("handleServerResponse");if(y.error){g(y)}else{if(y.requires_action){q(y)}else{t(y.paymentIntent)}}}function q(y){o.handleCardAction(y.payment_intent_client_secret).then(function(z){if(z.error){g(z)}else{t(z.paymentIntent)}})}d(document).ajaxComplete(function(A,B,z){if((z.url.match("civicrm(/|%2F)payment(/|%2F)form")!==null)||(z.url.match("civicrm(/|%2F)contact(/|%2F)view(/|%2F)participant")!==null)){if(typeof CRM.vars.stripe==="undefined"){return}var y=j();if(y!==null){if(y!==parseInt(CRM.vars.stripe.id)){f("payment processor changed to id: "+y);if(y===0){return k()}CRM.api3("PaymentProcessor","getvalue",{"return":"user_name",id:y,payment_processor_type_id:CRM.vars.stripe.paymentProcessorTypeID}).done(function(C){var D=C.result;if(D){f("Setting new stripe key to: "+D);CRM.vars.stripe.publishableKey=D}else{return k()}f("checkAndLoad from ajaxComplete");l()})}}}});function k(){f("New payment processor is not Stripe, clearing CRM.vars.stripe");if((typeof b!=="undefined")&&(b)){f("destroying card element");b.destroy();b=undefined}delete (CRM.vars.stripe)}function l(){if(typeof CRM.vars.stripe==="undefined"){f("CRM.vars.stripe not defined! Not a Stripe processor?");return}if(typeof Stripe==="undefined"){if(n){return}n=true;f("Stripe.js is not loaded!");d.getScript("https://js.stripe.com/v3",function(){f("Script loaded and executed.");n=false;e()})}else{e()}}function e(){f("loadStripeBillingBlock");if(typeof o==="undefined"){o=Stripe(CRM.vars.stripe.publishableKey)}var E=o.elements();var B={base:{fontSize:"20px"}};b=E.create("card",{style:B});b.mount("#card-element");f("created new card element",b);document.getElementsByClassName("billing_postal_code-"+CRM.vars.stripe.billingAddressID+"-section")[0].setAttribute("hidden",true);b.addEventListener("change",function(F){s(F)});c=h();if(typeof c.length==="undefined"||c.length===0){f("No billing form!");return}a=x();c.dataset.submitdontprocess=false;var y=c.querySelectorAll('[type="submit"][formnovalidate="1"], [type="submit"][formnovalidate="formnovalidate"], [type="submit"].cancel, [type="submit"].webform-previous'),A;for(A=0;A<y.length;++A){y[A].addEventListener("click",D())}function D(){f("adding submitdontprocess");c.dataset.submitdontprocess=true}a.addEventListener("click",z);function z(F){if(c.dataset.submitted){return}c.dataset.submitted=true;if(typeof CRM.vars.stripe==="undefined"){return c.submit()}f("clearing submitdontprocess");c.dataset.submitdontprocess=false;return C(F)}a.removeAttribute("onclick");m();if(v()){d("[type=submit]").click(function(){r(this.value)});c.addEventListener("keydown",function(F){if(F.keyCode===13){r(this.value);C(event)}});d("#billingcheckbox:input").hide();d('label[for="billingcheckbox"]').hide()}function C(H){H.preventDefault();f("submit handler");if(typeof CRM.vars.stripe==="undefined"){f("Submitting - not a stripe processor");return true}if(c.dataset.submitted===true){f("form already submitted");return false}var J=CRM.vars.stripe.id;var G=null;if(v()){J=CRM.vars.stripe.id;if(!d('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]').length){G=J}else{G=c.querySelector('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]:checked').val()}}else{if((c.querySelector(".crm-section.payment_processor-section")!==null)||(c.querySelector(".crm-section.credit_card_info-section")!==null)){J=CRM.vars.stripe.id;if(c.querySelector('input[name="payment_processor_id"]:checked')!==null){G=c.querySelector('input[name="payment_processor_id"]:checked').value}}}if((G===0)||(J===null)||((G===null)&&(J===null))){f("Not a Stripe transaction, or pay-later");return true}else{f("Stripe is the selected payprocessor")}if(typeof CRM.vars.stripe.publishableKey==="undefined"){f("submit missing stripe-pub-key element or value");return true}if(c.dataset.submitdontprocess===true){f("non-payment submit detected - not submitting payment");return true}if(v()){if(d("#billing-payment-block").is(":hidden")){f("no payment processor on webform");return true}var I=d('[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]');if(I.length){if(I.filter(":checked").val()==="0"||I.filter(":checked").val()===0){f("no payment processor selected");return true}}}var F=p();if(F=="0"){f("Total amount is 0");return true}if(c.dataset.submitted===true){alert("Form already submitted. Please wait.");return false}else{c.dataset.submitted=true}a.setAttribute("disabled",true);w();return true}}function v(){if(c!==null){return c.classList.contains("webform-client-form")||c.classList.contains("webform-submission-form")}return false}function h(){var y=d("div#card-element").closest("form").prop("id");if((typeof y==="undefined")||(!y.length)){y=d("input[name=hidden_processor]").closest("form").prop("id")}return document.getElementById(y)}function x(){var y=null;if(v()){y=c.querySelector('[type="submit"].webform-submit');if(!y){y=c.querySelector('[type="submit"].webform-button--submit')}}else{y=c.querySelector('[type="submit"].validate')}return y}function p(){var y=null;if(typeof calculateTotalFee=="function"){y=calculateTotalFee()}else{if(v()){d(".line-item:visible","#wf-crm-billing-items").each(function(){y+=parseFloat(d(this).data("amount"))})}else{if(document.getElementById("total_amount")){return document.getElementById("total_amount").value}}}return y}function s(y){if(!y.complete){return}document.getElementById("billing_postal_code-"+CRM.vars.stripe.billingAddressID).value=y.value.postalCode}function m(){cividiscountElements=c.querySelectorAll("input#discountcode");var y=function(z){if(z.keyCode===13){z.preventDefault();f("adding submitdontprocess");c.dataset.submitdontprocess=true}};for(i=0;i<cividiscountElements.length;++i){cividiscountElements[i].addEventListener("keydown",y)}}function f(y){if((typeof(CRM.vars.stripe)==="undefined")||(Boolean(CRM.vars.stripe.jsDebug)===true)){console.log(new Date().toISOString()+" civicrm_stripe.js: "+y)}}function r(z){var y=null;if(document.getElementById("action")!==null){y=document.getElementById("action")}else{y=document.createElement("input")}y.setAttribute("type","hidden");y.setAttribute("name","op");y.setAttribute("id","action");y.setAttribute("value",z);c.appendChild(y)}function j(){if((typeof c==="undefined")||(!c)){c=h();if(!c){return null}}var y=c.querySelector('input[name="payment_processor_id"]:checked');if(y!==null){return parseInt(y.value)}return null}});
\ No newline at end of file
CRM.$(function(d){f("civicrm_stripe loaded, dom-ready function firing.");if(window.civicrmStripeHandleReload){f("calling existing civicrmStripeHandleReload.");window.civicrmStripeHandleReload();return}var o;var b;var c;var a;var n=false;window.onbeforeunload=null;window.civicrmStripeHandleReload=function(){f("civicrmStripeHandleReload");var y=document.getElementById("card-element");if((typeof y!=="undefined")&&(y)){if(!y.children.length){f("checkAndLoad from document.ready");l()}}};window.civicrmStripeHandleReload();function t(z){f("paymentIntent confirmation success");var y=document.createElement("input");y.setAttribute("type","hidden");y.setAttribute("name","paymentIntentID");y.setAttribute("value",z.id);c.appendChild(y);c.submit()}function g(y){f("error: "+y.error.message);var z=document.getElementById("card-errors");z.style.display="block";z.textContent=y.error.message;document.querySelector("#billing-payment-block").scrollIntoView();window.scrollBy(0,-50);a.removeAttribute("disabled")}function w(){f("handle card payment");o.createPaymentMethod("card",b).then(function(y){if(y.error){g(y)}else{var z=CRM.url("civicrm/stripe/confirm-payment");d.post(z,{payment_method_id:y.paymentMethod.id,amount:p(),currency:CRM.vars.stripe.currency,id:CRM.vars.stripe.id}).then(function(A){u(A)})}})}function u(y){f("handleServerResponse");if(y.error){g(y)}else{if(y.requires_action){q(y)}else{t(y.paymentIntent)}}}function q(y){o.handleCardAction(y.payment_intent_client_secret).then(function(z){if(z.error){g(z)}else{t(z.paymentIntent)}})}d(document).ajaxComplete(function(A,B,z){if((z.url.match("civicrm(/|%2F)payment(/|%2F)form")!==null)||(z.url.match("civicrm(/|%2F)contact(/|%2F)view(/|%2F)participant")!==null)){if(typeof CRM.vars.stripe==="undefined"){return}var y=j();if(y!==null){if(y!==parseInt(CRM.vars.stripe.id)){f("payment processor changed to id: "+y);if(y===0){return k()}CRM.api3("PaymentProcessor","getvalue",{"return":"user_name",id:y,payment_processor_type_id:CRM.vars.stripe.paymentProcessorTypeID}).done(function(C){var D=C.result;if(D){f("Setting new stripe key to: "+D);CRM.vars.stripe.publishableKey=D}else{return k()}f("checkAndLoad from ajaxComplete");l()})}}}});function k(){f("New payment processor is not Stripe, clearing CRM.vars.stripe");if((typeof b!=="undefined")&&(b)){f("destroying card element");b.destroy();b=undefined}delete (CRM.vars.stripe)}function l(){if(typeof CRM.vars.stripe==="undefined"){f("CRM.vars.stripe not defined! Not a Stripe processor?");return}if(typeof Stripe==="undefined"){if(n){return}n=true;f("Stripe.js is not loaded!");d.getScript("https://js.stripe.com/v3",function(){f("Script loaded and executed.");n=false;e()})}else{e()}}function e(){f("loadStripeBillingBlock");if(typeof o==="undefined"){o=Stripe(CRM.vars.stripe.publishableKey)}var E=o.elements();var B={base:{fontSize:"20px"}};b=E.create("card",{style:B});b.mount("#card-element");f("created new card element",b);document.getElementsByClassName("billing_postal_code-"+CRM.vars.stripe.billingAddressID+"-section")[0].setAttribute("hidden",true);b.addEventListener("change",function(F){s(F)});c=h();if(typeof c.length==="undefined"||c.length===0){f("No billing form!");return}a=x();c.dataset.submitdontprocess=false;var y=c.querySelectorAll('[type="submit"][formnovalidate="1"], [type="submit"][formnovalidate="formnovalidate"], [type="submit"].cancel, [type="submit"].webform-previous'),A;for(A=0;A<y.length;++A){y[A].addEventListener("click",D())}function D(){f("adding submitdontprocess");c.dataset.submitdontprocess=true}a.addEventListener("click",z);function z(F){if(c.dataset.submitted){return}c.dataset.submitted=true;if(typeof CRM.vars.stripe==="undefined"){return c.submit()}f("clearing submitdontprocess");c.dataset.submitdontprocess=false;return C(F)}a.removeAttribute("onclick");m();if(v()){d("[type=submit]").click(function(){r(this.value)});c.addEventListener("keydown",function(F){if(F.keyCode===13){r(this.value);C(event)}});d("#billingcheckbox:input").hide();d('label[for="billingcheckbox"]').hide()}function C(H){H.preventDefault();f("submit handler");if(d(c).valid()===false){f("Form not valid");return false}if(typeof CRM.vars.stripe==="undefined"){f("Submitting - not a stripe processor");return true}if(c.dataset.submitted===true){f("form already submitted");return false}var J=CRM.vars.stripe.id;var G=null;if(v()){J=CRM.vars.stripe.id;if(!d('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]').length){G=J}else{G=c.querySelector('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]:checked').val()}}else{if((c.querySelector(".crm-section.payment_processor-section")!==null)||(c.querySelector(".crm-section.credit_card_info-section")!==null)){J=CRM.vars.stripe.id;if(c.querySelector('input[name="payment_processor_id"]:checked')!==null){G=c.querySelector('input[name="payment_processor_id"]:checked').value}}}if((G===0)||(J===null)||((G===null)&&(J===null))){f("Not a Stripe transaction, or pay-later");return true}else{f("Stripe is the selected payprocessor")}if(typeof CRM.vars.stripe.publishableKey==="undefined"){f("submit missing stripe-pub-key element or value");return true}if(c.dataset.submitdontprocess===true){f("non-payment submit detected - not submitting payment");return true}if(v()){if(d("#billing-payment-block").is(":hidden")){f("no payment processor on webform");return true}var I=d('[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]');if(I.length){if(I.filter(":checked").val()==="0"||I.filter(":checked").val()===0){f("no payment processor selected");return true}}}var F=p();if(F=="0"){f("Total amount is 0");return true}if(c.dataset.submitted===true){alert("Form already submitted. Please wait.");return false}else{c.dataset.submitted=true}a.setAttribute("disabled",true);w();return true}}function v(){if(c!==null){return c.classList.contains("webform-client-form")||c.classList.contains("webform-submission-form")}return false}function h(){var y=d("div#card-element").closest("form").prop("id");if((typeof y==="undefined")||(!y.length)){y=d("input[name=hidden_processor]").closest("form").prop("id")}return document.getElementById(y)}function x(){var y=null;if(v()){y=c.querySelector('[type="submit"].webform-submit');if(!y){y=c.querySelector('[type="submit"].webform-button--submit')}}else{y=c.querySelector('[type="submit"].validate')}return y}function p(){var y=null;if(typeof calculateTotalFee=="function"){y=calculateTotalFee()}else{if(v()){d(".line-item:visible","#wf-crm-billing-items").each(function(){y+=parseFloat(d(this).data("amount"))})}else{if(document.getElementById("total_amount")){return document.getElementById("total_amount").value}}}return y}function s(y){if(!y.complete){return}document.getElementById("billing_postal_code-"+CRM.vars.stripe.billingAddressID).value=y.value.postalCode}function m(){cividiscountElements=c.querySelectorAll("input#discountcode");var y=function(z){if(z.keyCode===13){z.preventDefault();f("adding submitdontprocess");c.dataset.submitdontprocess=true}};for(i=0;i<cividiscountElements.length;++i){cividiscountElements[i].addEventListener("keydown",y)}}function f(y){if((typeof(CRM.vars.stripe)==="undefined")||(Boolean(CRM.vars.stripe.jsDebug)===true)){console.log(new Date().toISOString()+" civicrm_stripe.js: "+y)}}function r(z){var y=null;if(document.getElementById("action")!==null){y=document.getElementById("action")}else{y=document.createElement("input")}y.setAttribute("type","hidden");y.setAttribute("name","op");y.setAttribute("id","action");y.setAttribute("value",z);c.appendChild(y)}function j(){if((typeof c==="undefined")||(!c)){c=h();if(!c){return null}}var y=c.querySelector('input[name="payment_processor_id"]:checked');if(y!==null){return parseInt(y.value)}return null}});
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment