diff --git a/.gitignore b/.gitignore
index 70c1d27f..1247e42d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -115,4 +115,7 @@ composer.phar
composer.lock
# Build
-build.sh
\ No newline at end of file
+build.sh
+
+# Claude Code
+.claude
\ No newline at end of file
diff --git a/assets/js/payment-forms.js b/assets/js/payment-forms.js
index d3377905..69f89e22 100644
--- a/assets/js/payment-forms.js
+++ b/assets/js/payment-forms.js
@@ -496,6 +496,38 @@ jQuery(function ($) {
}
});
+ // Authorize.net ACH/Card payment type toggle.
+ this.form.on('change', '.getpaid-authorizenet-payment-type-selector input[type="radio"]', function () {
+ var paymentType = $(this).val();
+ var container = $(this).closest('.getpaid-gateway-description');
+
+ if (paymentType === 'ach') {
+ container.find('.getpaid-authorizenet-cc-section').hide();
+ container.find('.getpaid-authorizenet-ach-section').show();
+ } else {
+ container.find('.getpaid-authorizenet-cc-section').show();
+ container.find('.getpaid-authorizenet-ach-section').hide();
+ }
+ });
+
+ // Format ACH routing number on input (9 digits only).
+ this.form.on('input', '.getpaid-ach-routing-number', function () {
+ var input = $(this);
+ var value = input.val().replace(/\D/g, '').substring(0, 9);
+ if (input.val() !== value) {
+ input.val(value);
+ }
+ });
+
+ // Format ACH account number on input (17 digits max).
+ this.form.on('input', '.getpaid-ach-account-number', function () {
+ var input = $(this);
+ var value = input.val().replace(/\D/g, '').substring(0, 17);
+ if (input.val() !== value) {
+ input.val(value);
+ }
+ });
+
// Discounts.
if (this.form.find('.getpaid-discount-field').length) {
diff --git a/assets/js/payment-forms.min.js b/assets/js/payment-forms.min.js
index 95a309ae..69c6ecda 100644
--- a/assets/js/payment-forms.min.js
+++ b/assets/js/payment-forms.min.js
@@ -1 +1 @@
-jQuery(function($){var funcs=[];var isRecaptchaLoaded=false;function excecute_after_recaptcha_load(func){if(isRecaptchaLoaded){func();return}funcs.push(func);var interval=setInterval(function(){if(typeof grecaptcha!=="undefined"){clearInterval(interval);isRecaptchaLoaded=true;funcs.forEach(function(func){func()})}},100)}function gp_throttle(callback,limit){if(!limit){limit=200}var wait=false;var did_last=true;return function(){if(!wait){did_last=true;callback.bind(this).call();wait=true;setTimeout(function(){wait=false},limit)}else{did_last=false;var that=this;setTimeout(function(){if(!did_last){callback.bind(that).call();did_last=true}},limit)}}}window.getpaid_form=function(form){return{fetched_initial_state:0,cached_states:{},form:form,show_error(error,container){form.find(".getpaid-payment-form-errors, .getpaid-custom-payment-form-errors").html("").addClass("d-none");if(container&&form.find(container).length){form.find(container).html(error).removeClass("d-none");form.find(container).closest(".form-group").find(".form-control").addClass("is-invalid");form.find(container).closest(".form-group").find(".getpaid-custom-payment-form-success").addClass("d-none")}else{form.find(".getpaid-payment-form-errors").html(error).removeClass("d-none");form.find(".getpaid-custom-payment-form-errors").each(function(){var form_control=$(this).closest(".form-group").find(".form-control");if(form_control.val()!=""){form_control.addClass("is-valid")}})}},hide_error(){form.find(".getpaid-payment-form-errors, .getpaid-custom-payment-form-errors").html("").addClass("d-none");form.find(".is-invalid, .is-valid").removeClass("is-invalid is-valid")},cache_state(key,state){this.cached_states[key]=state},current_state_key(){return this.form.serialize()},is_current_state_cached(){return this.cached_states.hasOwnProperty(this.current_state_key())},switch_state(){this.hide_error();var state=this.cached_states[this.current_state_key()];if(!state){return this.fetch_state()}var template=this.form.find(".getpaid-tax-template");if(state.totals){for(var total in state.totals){if(state.totals.hasOwnProperty(total)){this.form.find(".getpaid-form-cart-totals-total-"+total).html(state.totals[total])}}}if(template.length){this.form.find(".getpaid-form-cart-totals-tax:not(.getpaid-tax-template)").remove();if(!Array.isArray(state.taxes)){var html=template.prop("outerHTML");for(var tax in state.taxes){if(state.taxes.hasOwnProperty(tax)){var newTax=template.before(html).prev().removeClass("getpaid-tax-template d-none");newTax.find(".getpaid-payment-form-line-totals-label").html(tax);newTax.find(".getpaid-payment-form-line-totals-value").html(state.taxes[tax])}}}}if(!Array.isArray(state.fees)){this.form.find(".getpaid-form-cart-totals-fees").removeClass("d-none")}else{this.form.find(".getpaid-form-cart-totals-fees").addClass("d-none")}if(!Array.isArray(state.discounts)){this.form.find(".getpaid-form-cart-totals-discount").removeClass("d-none")}else{this.form.find(".getpaid-form-cart-totals-discount").addClass("d-none")}if(state.items){for(var item in state.items){if(state.items.hasOwnProperty(item)){this.form.find(".getpaid-form-cart-item-subtotal-"+item).html(state.items[item])}}}if(state.selected_items){for(var item in state.selected_items){if(state.selected_items.hasOwnProperty(item)){this.form.find('input[name="getpaid-items['+item+'][price]"]').val(state.selected_items[item].price);this.form.find('input[name="getpaid-items['+item+'][quantity]"]').val(state.selected_items[item].quantity);this.form.find(".getpaid-items-"+item+"-view-price").html(state.selected_items[item].price_fmt);this.form.find(".getpaid-items-"+item+"-view-quantity").text(state.selected_items[item].quantity)}}}if(state.texts){for(var selector in state.texts){if(state.texts.hasOwnProperty(selector)){this.form.find(selector).html(state.texts[selector])}}}if(state.gateways){this.process_gateways(state.gateways,state)}if(state.invoice){if(this.form.find('input[name="invoice_id"]').length==0){this.form.append(' ')}this.form.find('input[name="invoice_id"]').val(state.invoice)}if(state.js_data){this.form.data("getpaid_js_data",state.js_data)}form.find(".getpaid-custom-payment-form-errors.d-none").each(function(){var form_control=$(this).closest(".form-group").find(".form-control");if(form_control.val()!=""){form_control.addClass("is-valid").closest(".form-group").find(".getpaid-custom-payment-form-success").removeClass("d-none")}});this.setup_saved_payment_tokens();this.form.trigger("getpaid_payment_form_changed_state",[state])},refresh_state(){if(this.is_current_state_cached()){return this.switch_state()}this.fetch_state()},fetch_state(){wpinvBlock(this.form);var key=this.current_state_key();var maybe_use_invoice=this.fetched_initial_state?"0":localStorage.getItem("getpaid_last_invoice_"+this.form.find('input[name="form_id"]').val());return $.post(WPInv.ajax_url,key+"&action=wpinv_payment_form_refresh_prices&_ajax_nonce="+WPInv.formNonce+"&initial_state="+this.fetched_initial_state+"&maybe_use_invoice="+maybe_use_invoice).done(res=>{if(res.success){this.fetched_initial_state=1;this.cache_state(key,res.data);return this.switch_state()}if(res.success===false){this.show_error(res.data.error,res.data.code);return}this.show_error(res)}).fail(()=>{this.show_error(WPInv.connectionError)}).always(()=>{wpinvUnblock(this.form)})},update_state_field(wrapper){wrapper=$(wrapper);if(wrapper.find(".wpinv_state").length){var state=wrapper.find(".getpaid-address-field-wrapper__state");wpinvBlock(state);var data={action:"wpinv_get_payment_form_states_field",country:wrapper.find(".wpinv_country").val(),form:this.form.find('input[name="form_id"]').val(),name:state.find(".wpinv_state").attr("name"),_ajax_nonce:WPInv.formNonce};$.get(WPInv.ajax_url,data,res=>{if("object"==typeof res){state.replaceWith(res.data)}}).always(()=>{wpinvUnblock(wrapper.find(".getpaid-address-field-wrapper__state"))})}},attach_events(){var that=this;var on_field_change=gp_throttle(function(){that.refresh_state()},500);this.form.on("change",".getpaid-refresh-on-change",on_field_change);this.form.on("input",".getpaid-payment-form-element-price_select :input:not(.getpaid-refresh-on-change)",on_field_change);this.form.on("change",".getpaid-payment-form-element-currency_select :input:not(.getpaid-refresh-on-change)",on_field_change);this.form.on("change",".getpaid-item-quantity-input",on_field_change);this.form.on("change",'[name="getpaid-payment-form-selected-item"]',on_field_change);this.form.on("change",".getpaid-item-mobile-quantity-input",function(){let input=$(this);input.closest(".getpaid-payment-form-items-cart-item").find(".getpaid-item-quantity-input").val(input.val()).trigger("change")});this.form.on("change",".getpaid-item-quantity-input",function(){let input=$(this);input.closest(".getpaid-payment-form-items-cart-item").find(".getpaid-item-mobile-quantity-input").val(input.val())});this.form.on("change",".getpaid-item-price-input",function(){if(!$(this).hasClass("is-invalid")){on_field_change()}});this.form.on("keypress",".getpaid-refresh-on-change, .getpaid-payment-form-element-price_select :input:not(.getpaid-refresh-on-change), .getpaid-item-quantity-input, .getpaid-item-price-input",function(e){if(e.keyCode=="13"){e.preventDefault();on_field_change()}});this.form.on("change",".getpaid-shipping-address-wrapper .wpinv_country",()=>{this.update_state_field(".getpaid-shipping-address-wrapper")});this.form.on("change",".getpaid-billing-address-wrapper .wpinv_country",()=>{this.update_state_field(".getpaid-billing-address-wrapper");if(this.form.find(".getpaid-billing-address-wrapper .wpinv_country").val()!=this.form.find(".getpaid-billing-address-wrapper .wpinv_country").data("ipCountry")){this.form.find(".getpaid-address-field-wrapper__address-confirm").removeClass("d-none")}else{this.form.find(".getpaid-address-field-wrapper__address-confirm").addClass("d-none")}on_field_change()});this.form.on("change",".getpaid-billing-address-wrapper .wpinv_state, .getpaid-billing-address-wrapper .wpinv_vat_number",()=>{on_field_change()});this.form.on("click",".getpaid-vat-number-validate",e=>{e.preventDefault();this.validate_vat_number()});this.form.on("click",'[name="confirm-address"]',()=>{on_field_change()});this.form.on("change",".getpaid-billing-address-wrapper .wpinv_vat_number",function(){var validator=$(this).parent().find(".getpaid-vat-number-validate");validator.text(validator.data("validate"))});this.form.on("input",".getpaid-format-card-number",function(){var input=$(this);var value=input.val();var formatted=value.replace(/\D/g,"").replace(/(.{4})/g,"$1 ");if(value!=formatted){input.val(formatted)}});if(this.form.find(".getpaid-discount-field").length){this.form.find(".getpaid-discount-button").on("click",function(e){e.preventDefault();on_field_change()});this.form.find(".getpaid-discount-field").on("keypress",function(e){if(e.keyCode=="13"){e.preventDefault();on_field_change()}});this.form.find(".getpaid-discount-field").on("change",function(e){on_field_change()})}this.form.on("change",".getpaid-gateway-radio input",()=>{var gateway=this.form.find(".getpaid-gateway-radio input:checked").val();form.find(".getpaid-gateway-description").slideUp();form.find(`.getpaid-description-${gateway}`).slideDown()});this.form.find(".getpaid-file-upload-element").each(function(){let dropfield=$(this),parent=dropfield.closest(".upload-file")||dropfield.closest(".form-group"),uploaded_files_div=parent.find(".getpaid-uploaded-files"),max_files=parseInt(parent.data("max")||1);let loadedFiles=[],xhr;let loadFile=function(file_data){if(!file_data){return}let progress_bar=parent.find(".getpaid-progress-template").clone().removeClass("d-none getpaid-progress-template");uploaded_files_div.append(progress_bar);progress_bar.find("a.close").on("click",function(e){e.preventDefault();let index=loadedFiles.indexOf(file_data);if(index>-1){loadedFiles=loadedFiles.splice(index,1)}progress_bar.fadeOut(300,()=>{progress_bar.remove()});try{if(xhr){xhr.abort()}}catch(e){}});progress_bar.find(".getpaid-progress-file-name").text(file_data.name).attr("title",file_data.name);progress_bar.find(".progress-bar").attr("aria-valuemax",file_data.size);let icons={"application/pdf":' ',"application/zip":' ',"application/x-gzip":' ',"application/rar":' ',"application/x-7z-compressed":' ',"application/x-tar":' ',audio:' ',image:' ',video:' ',"application/msword":' ',"application/vnd.ms-excel":' ',"application/msword":' ',"application/vnd.ms-word":' ',"application/vnd.ms-powerpoint":' '};if(file_data.type){Object.keys(icons).forEach(function(prop){if(file_data.type.indexOf(prop)!==-1){progress_bar.find(".fa.fa-file").replaceWith(icons[prop])}})}if(max_files&&loadedFiles.length>=max_files){progress_bar.find(".getpaid-progress").html('
'+WPInv.maxFilesExceeded+"
");return}let extension=file_data.name.match(/\.([^\.]+)$/)[1],extensions=parent.find(".getpaid-files-input").data("extensions");if(extensions.indexOf(extension.toString().toLowerCase())<0){progress_bar.find(".getpaid-progress").html(''+WPInv.unsupportedFile+"
");return}let form_data=new FormData;form_data.append("file",file_data);form_data.append("action","wpinv_file_upload");form_data.append("form_id",progress_bar.closest("form").find('input[name="form_id"]').val());form_data.append("_ajax_nonce",WPInv.formNonce);form_data.append("field_name",parent.data("name"));loadedFiles.push(file_data);xhr=$.ajax({url:WPInv.ajax_url,type:"POST",contentType:false,processData:false,data:form_data,xhr:function(){let _xhr=new window.XMLHttpRequest;_xhr.upload.addEventListener("progress",function(e){if(e.lengthComputable){let percentLoaded=Math.round(e.loaded*100/e.total)+"%";progress_bar.find(".progress-bar").attr("aria-valuenow",e.loaded).css("width",percentLoaded).text(percentLoaded)}},false);return _xhr},success:function(response){if(response.success){progress_bar.append(response.data)}else{progress_bar.find(".getpaid-progress").html(''+response.data+"
")}},error:function(request,status,message){progress_bar.find(".getpaid-progress").html(''+message+"
")}})};let loadFiles=function loadFiles(flist){Array.prototype.forEach.apply(flist,[loadFile])};dropfield.on("dragenter",()=>{dropfield.addClass("getpaid-trying-to-drop")}).on("dragover",e=>{e=e.originalEvent;e.stopPropagation();e.preventDefault();e.dataTransfer.dropEffect="copy"}).on("dragleave",()=>{dropfield.removeClass("getpaid-trying-to-drop")}).on("drop",e=>{e=e.originalEvent;e.stopPropagation();e.preventDefault();let files=e.dataTransfer.files;if(files.length>0){loadFiles(files)}});parent.find(".getpaid-files-input").on("change",function(e){let files=e.originalEvent.target.files;if(files){loadFiles(files);parent.find(".getpaid-files-input").val("")}})});if(jQuery.fn.popover&&this.form.find(".gp-tooltip").length){this.form.find(".gp-tooltip").popover({container:this.form[0],html:true,content:function(){return $(this).closest(".getpaid-form-cart-item-name").find(".getpaid-item-desc").html()}})}if(jQuery.fn.flatpickr&&this.form.find(".getpaid-init-flatpickr").length){this.form.find(".getpaid-init-flatpickr").each(function(){let options={},$el=jQuery(this);if($el.data("disable_alt")&&$el.data("disable_alt").length>0){options.disable=$el.data("disable_alt")}if($el.data("disable_days_alt")&&$el.data("disable_days_alt").length>0){options.disable=options.disable||[];let disabled_days=$el.data("disable_days_alt");options.disable.push(function(date){return disabled_days.indexOf(date.getDay())>=0})}jQuery(this).removeClass("flatpickr-input").flatpickr(options)})}if(WPInv.recaptchaSettings&&WPInv.recaptchaSettings.enabled&&WPInv.recaptchaSettings.version=="v2"){excecute_after_recaptcha_load(()=>{var id=this.form.find(".getpaid-recaptcha-wrapper .g-recaptcha").attr("id");if(id){grecaptcha.ready(()=>{grecaptcha.render(id,WPInv.recaptchaSettings.render_params)})}})}},process_gateways(enabled_gateways,state){this.form.data("initial_amt",state.initial_amt);this.form.data("currency",state.currency);var submit_btn=this.form.find(".getpaid-payment-form-submit");var free_label=submit_btn.data("free").replace(/%price%/gi,state.totals.raw_total);var btn_label=submit_btn.data("pay").replace(/%price%/gi,state.totals.raw_total);submit_btn.prop("disabled",false).css("cursor","pointer");if(state.is_free){submit_btn.val(free_label);this.form.find(".getpaid-gateways").slideUp();this.form.data("isFree","yes");return}this.form.data("isFree","no");this.form.find(".getpaid-gateways").slideDown();submit_btn.val(btn_label);this.form.find(".getpaid-no-recurring-gateways, .getpaid-no-subscription-group-gateways, .getpaid-no-multiple-subscription-group-gateways, .getpaid-no-active-gateways").addClass("d-none");this.form.find(".getpaid-select-gateway-title-div, .getpaid-available-gateways-div, .getpaid-gateway-descriptions-div").removeClass("d-none");if(enabled_gateways.length<1){this.form.find(".getpaid-select-gateway-title-div, .getpaid-available-gateways-div, .getpaid-gateway-descriptions-div").addClass("d-none");submit_btn.prop("disabled",true).css("cursor","not-allowed");if(state.has_multiple_subscription_groups){this.form.find(".getpaid-no-multiple-subscription-group-gateways").removeClass("d-none");return}if(state.has_subscription_group){this.form.find(".getpaid-no-subscription-group-gateways").removeClass("d-none");return}if(state.has_recurring){this.form.find(".getpaid-no-recurring-gateways").removeClass("d-none");return}this.form.find(".getpaid-no-active-gateways").removeClass("d-none");return}if(enabled_gateways.length==1){this.form.find(".getpaid-select-gateway-title-div").addClass("d-none");this.form.find(".getpaid-gateway-radio input").addClass("d-none")}else{this.form.find(".getpaid-gateway-radio input").removeClass("d-none")}this.form.find(".getpaid-gateway").addClass("d-none");$.each(enabled_gateways,(index,value)=>{this.form.find(`.getpaid-gateway-${value}`).removeClass("d-none")});if(0===this.form.find(".getpaid-gateway:visible input:checked").length){this.form.find(".getpaid-gateway:visible .getpaid-gateway-radio input").eq(0).prop("checked",true)}if(0===this.form.find(".getpaid-gateway-description:visible").length){this.form.find(".getpaid-gateway-radio input:checked").trigger("change")}},setup_saved_payment_tokens(){var currency=this.form.data("currency");this.form.find(".getpaid-saved-payment-methods").each(function(){var list=$(this);list.show();$("input",list).on("change",function(){if($(this).closest("li").hasClass("getpaid-new-payment-method")){list.closest(".getpaid-gateway-description").find(".getpaid-new-payment-method-form").slideDown()}else{list.closest(".getpaid-gateway-description").find(".getpaid-new-payment-method-form").slideUp()}});list.find("input").each(function(){if("none"!=$(this).data("currency")&¤cy!=$(this).data("currency")){$(this).closest("li").addClass("d-none");$(this).prop("checked",false)}else{$(this).closest("li").removeClass("d-none")}});if(0===$("li:not(.d-none) input",list).filter(":checked").length){$("li:not(.d-none) input",list).eq(0).prop("checked",true)}if(0===$("li:not(.d-none) input",list).filter(":checked").length){$("input",list).last().prop("checked",true)}if(2>$("li:not(.d-none) input",list).length){list.hide()}$("input",list).filter(":checked").trigger("change")})},handleAddressToggle(address_toggle){var wrapper=address_toggle.closest(".getpaid-payment-form-element-address");wrapper.find(".getpaid-billing-address-title, .getpaid-shipping-address-title, .getpaid-shipping-address-wrapper").addClass("d-none");address_toggle.on("change",function(){if($(this).is(":checked")){wrapper.find(".getpaid-billing-address-title, .getpaid-shipping-address-title, .getpaid-shipping-address-wrapper").addClass("d-none");wrapper.find(".getpaid-shipping-billing-address-title").removeClass("d-none")}else{wrapper.find(".getpaid-billing-address-title, .getpaid-shipping-address-title, .getpaid-shipping-address-wrapper").removeClass("d-none");wrapper.find(".getpaid-shipping-billing-address-title").addClass("d-none")}})},validate_vat_number(){var vat_input=this.form.find(".wpinv_vat_number");var country_input=this.form.find(".wpinv_country");var validator=vat_input.parent().find(".getpaid-vat-number-validate");if(!vat_input.length||!country_input.length){return}var vat_number=vat_input.val();var country=country_input.val();if(!vat_number||!country){this.show_error(WPInv.vatFieldsRequired,".getpaid-error-billingwpinv_vat_number");return}validator.prop("disabled",true).text(WPInv.validating);$.post(WPInv.ajax_url,{action:"wpinv_validate_vat_number",vat_number:vat_number,country:country,_ajax_nonce:WPInv.formNonce}).done(response=>{if(response.success){validator.removeClass("btn-primary").addClass("btn-success").text(WPInv.valid);vat_input.removeClass("is-invalid").addClass("is-valid");this.hide_error()}else{validator.removeClass("btn-success").addClass("btn-danger").text(WPInv.invalid);vat_input.removeClass("is-valid").addClass("is-invalid");this.show_error(response.data.message,".getpaid-error-billingwpinv_vat_number")}}).fail(()=>{validator.removeClass("btn-success").addClass("btn-warning").text(WPInv.error);this.show_error(WPInv.vatValidationError,".getpaid-error-billingwpinv_vat_number")}).always(()=>{validator.prop("disabled",false);setTimeout(()=>{validator.removeClass("btn-success btn-danger btn-warning").addClass("btn-primary").text(validator.data("validate"))},3e3)})},init(){this.setup_saved_payment_tokens();this.attach_events();this.refresh_state();this.form.find(".getpaid-payment-form-element-billing_email span.d-none").closest(".col-12").addClass("d-none");this.form.find(".getpaid-gateway-description:not(:has(*))").remove();var address_toggle=this.form.find('[name ="same-shipping-address"]');if(address_toggle.length>0){this.handleAddressToggle(address_toggle)}$("body").trigger("getpaid_setup_payment_form",[this.form])}}};var setup_form=function(form){form.find(".getpaid-gateway-descriptions-div .form-horizontal .form-group").addClass("row");function filter_form_cart(selected_items){if(0==form.find(".getpaid-payment-form-items-cart").length){return}form.find(".getpaid-payment-form-items-cart-item.getpaid-selectable").each(function(){$(this).find(".getpaid-item-price-input").attr("name","");$(this).find(".getpaid-item-quantity-input").attr("name","");$(this).hide()});$(selected_items).each(function(index,item_id){if(item_id){var item=form.find(".getpaid-payment-form-items-cart-item.item-"+item_id);item.find(".getpaid-item-price-input").attr("name","getpaid-items["+item_id+"][price]");item.find(".getpaid-item-quantity-input").attr("name","getpaid-items["+item_id+"][quantity]");item.show()}})}if(form.find(".getpaid-payment-form-items-radio").length){var filter_totals=function(){var selected_item=form.find(".getpaid-payment-form-items-radio .form-check-input:checked").val();filter_form_cart([selected_item])};var radio_items=form.find(".getpaid-payment-form-items-radio .form-check-input");radio_items.on("change",filter_totals);if(0===radio_items.filter(":checked").length){radio_items.eq(0).prop("checked",true)}filter_totals()}if(form.find(".getpaid-payment-form-items-checkbox").length){var filter_totals=function(){var selected_items=form.find(".getpaid-payment-form-items-checkbox input:checked").map(function(){return $(this).val()}).get();filter_form_cart(selected_items)};var checkbox_items=form.find(".getpaid-payment-form-items-checkbox input");checkbox_items.on("change",filter_totals);if(0===checkbox_items.filter(":checked").length){checkbox_items.eq(0).prop("checked",true)}filter_totals()}if(form.find(".getpaid-payment-form-items-select").length){var filter_totals=function(){var selected_item=form.find(".getpaid-payment-form-items-select select").val();filter_form_cart([selected_item])};var select_box=form.find(".getpaid-payment-form-items-select select");select_box.on("change",filter_totals);if(!select_box.val()){select_box.find("option:first").prop("selected","selected")}filter_totals()}getpaid_form(form).init();form.on("submit",function(e){e.preventDefault();wpinvBlock(form);form.find(".getpaid-payment-form-errors, .getpaid-custom-payment-form-errors").html("").addClass("d-none");form.find(".is-invalid,.is-valid").removeClass("is-invalid is-valid");var unique_key=form.data("key");var data={submit:true,delay:false,data:form.serialize(),form:form,key:unique_key};if("no"==form.data("isFree")){$("body").trigger("getpaid_payment_form_before_submit",[data])}if(!data.submit){wpinvUnblock(form);return}var unblock=true;var submit=function(){var done=function(res){if("string"==typeof res){form.find(".getpaid-payment-form-errors").html(res).removeClass("d-none");return}if(res.success){if(!res.data.action||"redirect"==res.data.action){window.location.href=decodeURIComponent(res.data)}if("auto_submit_form"==res.data.action){form.parent().append(''+res.data.form+"
");$(".getpaid-checkout-autosubmit-form form").submit()}if("event"==res.data.action){$("body").trigger(res.data.event,[res.data.data,form]);unblock=false}return}form.find(".getpaid-payment-form-errors").html(res.data).removeClass("d-none");form.find(".getpaid-payment-form-remove-on-error").remove();document.dispatchEvent(new Event("ayecode_reset_captcha"));if(res.invoice){localStorage.setItem("getpaid_last_invoice_"+form.find('input[name="form_id"]').val(),res.invoice);if(form.find('input[name="invoice_id"]').length==0){form.append(' ')}form.find('input[name="invoice_id"]').val(res.invoice)}};var fail=function(res){form.find(".getpaid-payment-form-errors").html(WPInv.connectionError).removeClass("d-none");form.find(".getpaid-payment-form-remove-on-error").remove()};var always=function(){if(unblock){wpinvUnblock(form)}};if(WPInv.recaptchaSettings&&WPInv.recaptchaSettings.enabled&&WPInv.recaptchaSettings.version=="v3"&&grecaptcha){return grecaptcha.ready(function(){grecaptcha.execute(WPInv.recaptchaSettings.sitekey,{action:"purchase"}).then(function(token){return $.post(WPInv.ajax_url,data.data+"&action=wpinv_payment_form&_ajax_nonce="+WPInv.formNonce+"&g-recaptcha-response="+token).done(done).fail(fail).always(always)})})}else{return $.post(WPInv.ajax_url,data.data+"&action=wpinv_payment_form&_ajax_nonce="+WPInv.formNonce).done(done).fail(fail).always(always)}};if(data.delay){var local_submit=function(){if(!data.submit){wpinvUnblock(form)}else{submit()}$("body").unbind("getpaid_payment_form_delayed_submit"+unique_key,local_submit)};$("body").bind("getpaid_payment_form_delayed_submit"+unique_key,local_submit);return}submit()})};$(".getpaid-payment-form").each(function(){setup_form($(this))});$(document).on("click",".getpaid-payment-button",function(e){e.preventDefault();$("#getpaid-payment-modal .modal-body-wrapper").html('");if(window.bootstrap&&window.bootstrap.Modal){var paymentModal=new window.bootstrap.Modal(document.getElementById("getpaid-payment-modal"));paymentModal.show()}else{$("#getpaid-payment-modal").modal()}var data=$(this).data();data.action="wpinv_get_payment_form";data._ajax_nonce=WPInv.formNonce;data.current_url=window.location.href;$.get(WPInv.ajax_url,data,function(res){$("#getpaid-payment-modal .modal-body-wrapper").html(res);if(paymentModal){paymentModal.handleUpdate()}else{$("#getpaid-payment-modal").modal("handleUpdate")}$("#getpaid-payment-modal .getpaid-payment-form").each(function(){setup_form($(this))})}).fail(function(res){$("#getpaid-payment-modal .modal-body-wrapper").html(WPInv.connectionError);if(paymentModal){paymentModal.handleUpdate()}else{$("#getpaid-payment-modal").modal("handleUpdate")}})});$(document).on("click",'a[href^="#getpaid-form-"], a[href^="#getpaid-item-"]',function(e){var attr=$(this).attr("href");if(-1!=attr.indexOf("#getpaid-form-")){var data={form:attr.replace("#getpaid-form-","")}}else if(-1!=attr.indexOf("#getpaid-item-")){var data={item:attr.replace("#getpaid-item-","")}}else{return}e.preventDefault();$("#getpaid-payment-modal .modal-body-wrapper").html('");if(window.bootstrap&&window.bootstrap.Modal){var paymentModal=new window.bootstrap.Modal(document.getElementById("getpaid-payment-modal"));paymentModal.show()}else{$("#getpaid-payment-modal").modal()}data.action="wpinv_get_payment_form";data._ajax_nonce=WPInv.formNonce;$.get(WPInv.ajax_url,data,function(res){$("#getpaid-payment-modal .modal-body-wrapper").html(res);if(paymentModal){paymentModal.handleUpdate()}else{$("#getpaid-payment-modal").modal("handleUpdate")}$("#getpaid-payment-modal .getpaid-payment-form").each(function(){setup_form($(this))})}).fail(function(res){$("#getpaid-payment-modal .modal-body-wrapper").html(WPInv.connectionError);if(paymentModal){paymentModal.handleUpdate()}else{$("#getpaid-payment-modal").modal("handleUpdate")}})});$(document).on("change",".getpaid-address-edit-form #wpinv-country",function(e){var state=$(this).closest(".getpaid-address-edit-form").find(".wpinv_state");if(state.length){wpinvBlock(state.parent());var data={action:"wpinv_get_aui_states_field",country:$(this).val(),state:state.val(),class:"wpinv_state",name:state.attr("name"),_ajax_nonce:WPInv.nonce};$.get(WPInv.ajax_url,data,res=>{if("object"==typeof res){state.parent().replaceWith(res.data.html)}}).always(()=>{wpinvUnblock(state.parent())})}});RegExp.getpaidquote=function(str){return str.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")};$(document).on("input",".getpaid-validate-minimum-amount",function(e){if(""===$(this).val()){return}var thousands=new RegExp(RegExp.getpaidquote(WPInv.thousands),"g");var decimals=new RegExp(RegExp.getpaidquote(WPInv.decimals),"g");var val=$(this).val();val=val.replace(thousands,"");val=val.replace(decimals,".");if(!isNaN(parseFloat(val))&&$(this).data("minimum-amount")&&parseFloat(val)'+message+"
")}}function wpinvUnblock(el){var $el=jQuery(el);if(1==$el.data("GetPaidIsBlocked")){$el.data("GetPaidIsBlocked",0);if(!$el.data("GetPaidWasRelative")){$el.removeClass("position-relative")}$el.children(".getpaid-block-ui").remove()}}
\ No newline at end of file
+function wpinvBlock(e,t){t=void 0!==t&&""!==t?t:WPInv.loading;var a=jQuery(e);1!=a.data("GetPaidIsBlocked")&&(a.data("GetPaidIsBlocked",1),a.data("GetPaidWasRelative",a.hasClass("position-relative")),a.addClass("position-relative"),a.append('"))}function wpinvUnblock(e){var t=jQuery(e);1==t.data("GetPaidIsBlocked")&&(t.data("GetPaidIsBlocked",0),t.data("GetPaidWasRelative")||t.removeClass("position-relative"),t.children(".getpaid-block-ui").remove())}jQuery((function(e){var t=[],a=!1;window.getpaid_form=function(i){return{fetched_initial_state:0,cached_states:{},form:i,show_error(t,a){i.find(".getpaid-payment-form-errors, .getpaid-custom-payment-form-errors").html("").addClass("d-none"),a&&i.find(a).length?(i.find(a).html(t).removeClass("d-none"),i.find(a).closest(".form-group").find(".form-control").addClass("is-invalid"),i.find(a).closest(".form-group").find(".getpaid-custom-payment-form-success").addClass("d-none")):(i.find(".getpaid-payment-form-errors").html(t).removeClass("d-none"),i.find(".getpaid-custom-payment-form-errors").each((function(){var t=e(this).closest(".form-group").find(".form-control");""!=t.val()&&t.addClass("is-valid")})))},hide_error(){i.find(".getpaid-payment-form-errors, .getpaid-custom-payment-form-errors").html("").addClass("d-none"),i.find(".is-invalid, .is-valid").removeClass("is-invalid is-valid")},cache_state(e,t){this.cached_states[e]=t},current_state_key(){return this.form.serialize()},is_current_state_cached(){return this.cached_states.hasOwnProperty(this.current_state_key())},switch_state(){this.hide_error();var t=this.cached_states[this.current_state_key()];if(!t)return this.fetch_state();var a=this.form.find(".getpaid-tax-template");if(t.totals)for(var n in t.totals)t.totals.hasOwnProperty(n)&&this.form.find(".getpaid-form-cart-totals-total-"+n).html(t.totals[n]);if(a.length&&(this.form.find(".getpaid-form-cart-totals-tax:not(.getpaid-tax-template)").remove(),!Array.isArray(t.taxes))){var s=a.prop("outerHTML");for(var r in t.taxes)if(t.taxes.hasOwnProperty(r)){var d=a.before(s).prev().removeClass("getpaid-tax-template d-none");d.find(".getpaid-payment-form-line-totals-label").html(r),d.find(".getpaid-payment-form-line-totals-value").html(t.taxes[r])}}if(Array.isArray(t.fees)?this.form.find(".getpaid-form-cart-totals-fees").addClass("d-none"):this.form.find(".getpaid-form-cart-totals-fees").removeClass("d-none"),Array.isArray(t.discounts)?this.form.find(".getpaid-form-cart-totals-discount").addClass("d-none"):this.form.find(".getpaid-form-cart-totals-discount").removeClass("d-none"),t.items)for(var o in t.items)t.items.hasOwnProperty(o)&&this.form.find(".getpaid-form-cart-item-subtotal-"+o).html(t.items[o]);if(t.selected_items)for(var o in t.selected_items)t.selected_items.hasOwnProperty(o)&&(this.form.find('input[name="getpaid-items['+o+'][price]"]').val(t.selected_items[o].price),this.form.find('input[name="getpaid-items['+o+'][quantity]"]').val(t.selected_items[o].quantity),this.form.find(".getpaid-items-"+o+"-view-price").html(t.selected_items[o].price_fmt),this.form.find(".getpaid-items-"+o+"-view-quantity").text(t.selected_items[o].quantity));if(t.texts)for(var p in t.texts)t.texts.hasOwnProperty(p)&&this.form.find(p).html(t.texts[p]);t.gateways&&this.process_gateways(t.gateways,t),t.invoice&&(0==this.form.find('input[name="invoice_id"]').length&&this.form.append(' '),this.form.find('input[name="invoice_id"]').val(t.invoice)),t.js_data&&this.form.data("getpaid_js_data",t.js_data),i.find(".getpaid-custom-payment-form-errors.d-none").each((function(){var t=e(this).closest(".form-group").find(".form-control");""!=t.val()&&t.addClass("is-valid").closest(".form-group").find(".getpaid-custom-payment-form-success").removeClass("d-none")})),this.setup_saved_payment_tokens(),this.form.trigger("getpaid_payment_form_changed_state",[t])},refresh_state(){if(this.is_current_state_cached())return this.switch_state();this.fetch_state()},fetch_state(){wpinvBlock(this.form);var t=this.current_state_key(),a=this.fetched_initial_state?"0":localStorage.getItem("getpaid_last_invoice_"+this.form.find('input[name="form_id"]').val());return e.post(WPInv.ajax_url,t+"&action=wpinv_payment_form_refresh_prices&_ajax_nonce="+WPInv.formNonce+"&initial_state="+this.fetched_initial_state+"&maybe_use_invoice="+a).done((e=>{if(e.success)return this.fetched_initial_state=1,this.cache_state(t,e.data),this.switch_state();!1!==e.success?this.show_error(e):this.show_error(e.data.error,e.data.code)})).fail((()=>{this.show_error(WPInv.connectionError)})).always((()=>{wpinvUnblock(this.form)}))},update_state_field(t){if((t=e(t)).find(".wpinv_state").length){var a=t.find(".getpaid-address-field-wrapper__state");wpinvBlock(a);var i={action:"wpinv_get_payment_form_states_field",country:t.find(".wpinv_country").val(),form:this.form.find('input[name="form_id"]').val(),name:a.find(".wpinv_state").attr("name"),_ajax_nonce:WPInv.formNonce};e.get(WPInv.ajax_url,i,(e=>{"object"==typeof e&&a.replaceWith(e.data)})).always((()=>{wpinvUnblock(t.find(".getpaid-address-field-wrapper__state"))}))}},attach_events(){var n=this,s=function(e,t){t||(t=200);var a=!1,i=!0;return function(){if(a){i=!1;var n=this;setTimeout((function(){i||(e.bind(n).call(),i=!0)}),t)}else i=!0,e.bind(this).call(),a=!0,setTimeout((function(){a=!1}),t)}}((function(){n.refresh_state()}),500);this.form.on("change",".getpaid-refresh-on-change",s),this.form.on("input",".getpaid-payment-form-element-price_select :input:not(.getpaid-refresh-on-change)",s),this.form.on("change",".getpaid-payment-form-element-currency_select :input:not(.getpaid-refresh-on-change)",s),this.form.on("change",".getpaid-item-quantity-input",s),this.form.on("change",'[name="getpaid-payment-form-selected-item"]',s),this.form.on("change",".getpaid-item-mobile-quantity-input",(function(){let t=e(this);t.closest(".getpaid-payment-form-items-cart-item").find(".getpaid-item-quantity-input").val(t.val()).trigger("change")})),this.form.on("change",".getpaid-item-quantity-input",(function(){let t=e(this);t.closest(".getpaid-payment-form-items-cart-item").find(".getpaid-item-mobile-quantity-input").val(t.val())})),this.form.on("change",".getpaid-item-price-input",(function(){e(this).hasClass("is-invalid")||s()})),this.form.on("keypress",".getpaid-refresh-on-change, .getpaid-payment-form-element-price_select :input:not(.getpaid-refresh-on-change), .getpaid-item-quantity-input, .getpaid-item-price-input",(function(e){"13"==e.keyCode&&(e.preventDefault(),s())})),this.form.on("change",".getpaid-shipping-address-wrapper .wpinv_country",(()=>{this.update_state_field(".getpaid-shipping-address-wrapper")})),this.form.on("change",".getpaid-billing-address-wrapper .wpinv_country",(()=>{this.update_state_field(".getpaid-billing-address-wrapper"),this.form.find(".getpaid-billing-address-wrapper .wpinv_country").val()!=this.form.find(".getpaid-billing-address-wrapper .wpinv_country").data("ipCountry")?this.form.find(".getpaid-address-field-wrapper__address-confirm").removeClass("d-none"):this.form.find(".getpaid-address-field-wrapper__address-confirm").addClass("d-none"),s()})),this.form.on("change",".getpaid-billing-address-wrapper .wpinv_state, .getpaid-billing-address-wrapper .wpinv_vat_number",(()=>{s()})),this.form.on("click",".getpaid-vat-number-validate",(e=>{e.preventDefault(),this.validate_vat_number()})),this.form.on("click",'[name="confirm-address"]',(()=>{s()})),this.form.on("change",".getpaid-billing-address-wrapper .wpinv_vat_number",(function(){var t=e(this).parent().find(".getpaid-vat-number-validate");t.text(t.data("validate"))})),this.form.on("input",".getpaid-format-card-number",(function(){var t=e(this),a=t.val(),i=a.replace(/\D/g,"").replace(/(.{4})/g,"$1 ");a!=i&&t.val(i)})),this.form.on("change",'.getpaid-authorizenet-payment-type-selector input[type="radio"]',(function(){var t=e(this).val(),a=e(this).closest(".getpaid-gateway-description");"ach"===t?(a.find(".getpaid-authorizenet-cc-section").hide(),a.find(".getpaid-authorizenet-ach-section").show()):(a.find(".getpaid-authorizenet-cc-section").show(),a.find(".getpaid-authorizenet-ach-section").hide())})),this.form.on("input",".getpaid-ach-routing-number",(function(){var t=e(this),a=t.val().replace(/\D/g,"").substring(0,9);t.val()!==a&&t.val(a)})),this.form.on("input",".getpaid-ach-account-number",(function(){var t=e(this),a=t.val().replace(/\D/g,"").substring(0,17);t.val()!==a&&t.val(a)})),this.form.find(".getpaid-discount-field").length&&(this.form.find(".getpaid-discount-button").on("click",(function(e){e.preventDefault(),s()})),this.form.find(".getpaid-discount-field").on("keypress",(function(e){"13"==e.keyCode&&(e.preventDefault(),s())})),this.form.find(".getpaid-discount-field").on("change",(function(e){s()}))),this.form.on("change",".getpaid-gateway-radio input",(()=>{var e=this.form.find(".getpaid-gateway-radio input:checked").val();i.find(".getpaid-gateway-description").slideUp(),i.find(`.getpaid-description-${e}`).slideDown()})),this.form.find(".getpaid-file-upload-element").each((function(){let t,a=e(this),i=a.closest(".upload-file")||a.closest(".form-group"),n=i.find(".getpaid-uploaded-files"),s=parseInt(i.data("max")||1),r=[],d=function(a){if(!a)return;let d=i.find(".getpaid-progress-template").clone().removeClass("d-none getpaid-progress-template");n.append(d),d.find("a.close").on("click",(function(e){e.preventDefault();let i=r.indexOf(a);i>-1&&(r=r.splice(i,1)),d.fadeOut(300,(()=>{d.remove()}));try{t&&t.abort()}catch(e){}})),d.find(".getpaid-progress-file-name").text(a.name).attr("title",a.name),d.find(".progress-bar").attr("aria-valuemax",a.size);let o={"application/pdf":' ',"application/zip":' ',"application/x-gzip":' ',"application/rar":' ',"application/x-7z-compressed":' ',"application/x-tar":' ',audio:' ',image:' ',video:' ',"application/msword":' ',"application/vnd.ms-excel":' ',"application/msword":' ',"application/vnd.ms-word":' ',"application/vnd.ms-powerpoint":' '};if(a.type&&Object.keys(o).forEach((function(e){-1!==a.type.indexOf(e)&&d.find(".fa.fa-file").replaceWith(o[e])})),s&&r.length>=s)return void d.find(".getpaid-progress").html(''+WPInv.maxFilesExceeded+"
");let p=a.name.match(/\.([^\.]+)$/)[1];if(i.find(".getpaid-files-input").data("extensions").indexOf(p.toString().toLowerCase())<0)return void d.find(".getpaid-progress").html(''+WPInv.unsupportedFile+"
");let l=new FormData;l.append("file",a),l.append("action","wpinv_file_upload"),l.append("form_id",d.closest("form").find('input[name="form_id"]').val()),l.append("_ajax_nonce",WPInv.formNonce),l.append("field_name",i.data("name")),r.push(a),t=e.ajax({url:WPInv.ajax_url,type:"POST",contentType:!1,processData:!1,data:l,xhr:function(){let e=new window.XMLHttpRequest;return e.upload.addEventListener("progress",(function(e){if(e.lengthComputable){let t=Math.round(100*e.loaded/e.total)+"%";d.find(".progress-bar").attr("aria-valuenow",e.loaded).css("width",t).text(t)}}),!1),e},success:function(e){e.success?d.append(e.data):d.find(".getpaid-progress").html(''+e.data+"
")},error:function(e,t,a){d.find(".getpaid-progress").html(''+a+"
")}})},o=function(e){Array.prototype.forEach.apply(e,[d])};a.on("dragenter",(()=>{a.addClass("getpaid-trying-to-drop")})).on("dragover",(e=>{(e=e.originalEvent).stopPropagation(),e.preventDefault(),e.dataTransfer.dropEffect="copy"})).on("dragleave",(()=>{a.removeClass("getpaid-trying-to-drop")})).on("drop",(e=>{(e=e.originalEvent).stopPropagation(),e.preventDefault();let t=e.dataTransfer.files;t.length>0&&o(t)})),i.find(".getpaid-files-input").on("change",(function(e){let t=e.originalEvent.target.files;t&&(o(t),i.find(".getpaid-files-input").val(""))}))})),jQuery.fn.popover&&this.form.find(".gp-tooltip").length&&this.form.find(".gp-tooltip").popover({container:this.form[0],html:!0,content:function(){return e(this).closest(".getpaid-form-cart-item-name").find(".getpaid-item-desc").html()}}),jQuery.fn.flatpickr&&this.form.find(".getpaid-init-flatpickr").length&&this.form.find(".getpaid-init-flatpickr").each((function(){let e={},t=jQuery(this);if(t.data("disable_alt")&&t.data("disable_alt").length>0&&(e.disable=t.data("disable_alt")),t.data("disable_days_alt")&&t.data("disable_days_alt").length>0){e.disable=e.disable||[];let a=t.data("disable_days_alt");e.disable.push((function(e){return a.indexOf(e.getDay())>=0}))}jQuery(this).removeClass("flatpickr-input").flatpickr(e)})),WPInv.recaptchaSettings&&WPInv.recaptchaSettings.enabled&&"v2"==WPInv.recaptchaSettings.version&&function(e){if(a)e();else{t.push(e);var i=setInterval((function(){"undefined"!=typeof grecaptcha&&(clearInterval(i),a=!0,t.forEach((function(e){e()})))}),100)}}((()=>{var e=this.form.find(".getpaid-recaptcha-wrapper .g-recaptcha").attr("id");e&&grecaptcha.ready((()=>{grecaptcha.render(e,WPInv.recaptchaSettings.render_params)}))}))},process_gateways(t,a){this.form.data("initial_amt",a.initial_amt),this.form.data("currency",a.currency);var i=this.form.find(".getpaid-payment-form-submit"),n=i.data("free").replace(/%price%/gi,a.totals.raw_total),s=i.data("pay").replace(/%price%/gi,a.totals.raw_total);return i.prop("disabled",!1).css("cursor","pointer"),a.is_free?(i.val(n),this.form.find(".getpaid-gateways").slideUp(),void this.form.data("isFree","yes")):(this.form.data("isFree","no"),this.form.find(".getpaid-gateways").slideDown(),i.val(s),this.form.find(".getpaid-no-recurring-gateways, .getpaid-no-subscription-group-gateways, .getpaid-no-multiple-subscription-group-gateways, .getpaid-no-active-gateways").addClass("d-none"),this.form.find(".getpaid-select-gateway-title-div, .getpaid-available-gateways-div, .getpaid-gateway-descriptions-div").removeClass("d-none"),t.length<1?(this.form.find(".getpaid-select-gateway-title-div, .getpaid-available-gateways-div, .getpaid-gateway-descriptions-div").addClass("d-none"),i.prop("disabled",!0).css("cursor","not-allowed"),a.has_multiple_subscription_groups?void this.form.find(".getpaid-no-multiple-subscription-group-gateways").removeClass("d-none"):a.has_subscription_group?void this.form.find(".getpaid-no-subscription-group-gateways").removeClass("d-none"):a.has_recurring?void this.form.find(".getpaid-no-recurring-gateways").removeClass("d-none"):void this.form.find(".getpaid-no-active-gateways").removeClass("d-none")):(1==t.length?(this.form.find(".getpaid-select-gateway-title-div").addClass("d-none"),this.form.find(".getpaid-gateway-radio input").addClass("d-none")):this.form.find(".getpaid-gateway-radio input").removeClass("d-none"),this.form.find(".getpaid-gateway").addClass("d-none"),e.each(t,((e,t)=>{this.form.find(`.getpaid-gateway-${t}`).removeClass("d-none")})),0===this.form.find(".getpaid-gateway:visible input:checked").length&&this.form.find(".getpaid-gateway:visible .getpaid-gateway-radio input").eq(0).prop("checked",!0),void(0===this.form.find(".getpaid-gateway-description:visible").length&&this.form.find(".getpaid-gateway-radio input:checked").trigger("change"))))},setup_saved_payment_tokens(){var t=this.form.data("currency");this.form.find(".getpaid-saved-payment-methods").each((function(){var a=e(this);a.show(),e("input",a).on("change",(function(){e(this).closest("li").hasClass("getpaid-new-payment-method")?a.closest(".getpaid-gateway-description").find(".getpaid-new-payment-method-form").slideDown():a.closest(".getpaid-gateway-description").find(".getpaid-new-payment-method-form").slideUp()})),a.find("input").each((function(){"none"!=e(this).data("currency")&&t!=e(this).data("currency")?(e(this).closest("li").addClass("d-none"),e(this).prop("checked",!1)):e(this).closest("li").removeClass("d-none")})),0===e("li:not(.d-none) input",a).filter(":checked").length&&e("li:not(.d-none) input",a).eq(0).prop("checked",!0),0===e("li:not(.d-none) input",a).filter(":checked").length&&e("input",a).last().prop("checked",!0),2>e("li:not(.d-none) input",a).length&&a.hide(),e("input",a).filter(":checked").trigger("change")}))},handleAddressToggle(t){var a=t.closest(".getpaid-payment-form-element-address");a.find(".getpaid-billing-address-title, .getpaid-shipping-address-title, .getpaid-shipping-address-wrapper").addClass("d-none"),t.on("change",(function(){e(this).is(":checked")?(a.find(".getpaid-billing-address-title, .getpaid-shipping-address-title, .getpaid-shipping-address-wrapper").addClass("d-none"),a.find(".getpaid-shipping-billing-address-title").removeClass("d-none")):(a.find(".getpaid-billing-address-title, .getpaid-shipping-address-title, .getpaid-shipping-address-wrapper").removeClass("d-none"),a.find(".getpaid-shipping-billing-address-title").addClass("d-none"))}))},validate_vat_number(){var t=this.form.find(".wpinv_vat_number"),a=this.form.find(".wpinv_country"),i=t.parent().find(".getpaid-vat-number-validate");if(t.length&&a.length){var n=t.val(),s=a.val();n&&s?(i.prop("disabled",!0).text(WPInv.validating),e.post(WPInv.ajax_url,{action:"wpinv_validate_vat_number",vat_number:n,country:s,_ajax_nonce:WPInv.formNonce}).done((e=>{e.success?(i.removeClass("btn-primary").addClass("btn-success").text(WPInv.valid),t.removeClass("is-invalid").addClass("is-valid"),this.hide_error()):(i.removeClass("btn-success").addClass("btn-danger").text(WPInv.invalid),t.removeClass("is-valid").addClass("is-invalid"),this.show_error(e.data.message,".getpaid-error-billingwpinv_vat_number"))})).fail((()=>{i.removeClass("btn-success").addClass("btn-warning").text(WPInv.error),this.show_error(WPInv.vatValidationError,".getpaid-error-billingwpinv_vat_number")})).always((()=>{i.prop("disabled",!1),setTimeout((()=>{i.removeClass("btn-success btn-danger btn-warning").addClass("btn-primary").text(i.data("validate"))}),3e3)}))):this.show_error(WPInv.vatFieldsRequired,".getpaid-error-billingwpinv_vat_number")}},init(){this.setup_saved_payment_tokens(),this.attach_events(),this.refresh_state(),this.form.find(".getpaid-payment-form-element-billing_email span.d-none").closest(".col-12").addClass("d-none"),this.form.find(".getpaid-gateway-description:not(:has(*))").remove();var t=this.form.find('[name ="same-shipping-address"]');t.length>0&&this.handleAddressToggle(t),e("body").trigger("getpaid_setup_payment_form",[this.form])}}};var i=function(t){function a(a){0!=t.find(".getpaid-payment-form-items-cart").length&&(t.find(".getpaid-payment-form-items-cart-item.getpaid-selectable").each((function(){e(this).find(".getpaid-item-price-input").attr("name",""),e(this).find(".getpaid-item-quantity-input").attr("name",""),e(this).hide()})),e(a).each((function(e,a){if(a){var i=t.find(".getpaid-payment-form-items-cart-item.item-"+a);i.find(".getpaid-item-price-input").attr("name","getpaid-items["+a+"][price]"),i.find(".getpaid-item-quantity-input").attr("name","getpaid-items["+a+"][quantity]"),i.show()}})))}if(t.find(".getpaid-gateway-descriptions-div .form-horizontal .form-group").addClass("row"),t.find(".getpaid-payment-form-items-radio").length){var i=function(){a([t.find(".getpaid-payment-form-items-radio .form-check-input:checked").val()])},n=t.find(".getpaid-payment-form-items-radio .form-check-input");n.on("change",i),0===n.filter(":checked").length&&n.eq(0).prop("checked",!0),i()}if(t.find(".getpaid-payment-form-items-checkbox").length){i=function(){a(t.find(".getpaid-payment-form-items-checkbox input:checked").map((function(){return e(this).val()})).get())};var s=t.find(".getpaid-payment-form-items-checkbox input");s.on("change",i),0===s.filter(":checked").length&&s.eq(0).prop("checked",!0),i()}if(t.find(".getpaid-payment-form-items-select").length){i=function(){a([t.find(".getpaid-payment-form-items-select select").val()])};var r=t.find(".getpaid-payment-form-items-select select");r.on("change",i),r.val()||r.find("option:first").prop("selected","selected"),i()}getpaid_form(t).init(),t.on("submit",(function(a){a.preventDefault(),wpinvBlock(t),t.find(".getpaid-payment-form-errors, .getpaid-custom-payment-form-errors").html("").addClass("d-none"),t.find(".is-invalid,.is-valid").removeClass("is-invalid is-valid");var i=t.data("key"),n={submit:!0,delay:!1,data:t.serialize(),form:t,key:i};if("no"==t.data("isFree")&&e("body").trigger("getpaid_payment_form_before_submit",[n]),n.submit){var s=!0,r=function(){var a=function(a){if("string"!=typeof a){if(a.success)return a.data.action&&"redirect"!=a.data.action||(window.location.href=decodeURIComponent(a.data)),"auto_submit_form"==a.data.action&&(t.parent().append(''+a.data.form+"
"),e(".getpaid-checkout-autosubmit-form form").submit()),void("event"==a.data.action&&(e("body").trigger(a.data.event,[a.data.data,t]),s=!1));t.find(".getpaid-payment-form-errors").html(a.data).removeClass("d-none"),t.find(".getpaid-payment-form-remove-on-error").remove(),document.dispatchEvent(new Event("ayecode_reset_captcha")),a.invoice&&(localStorage.setItem("getpaid_last_invoice_"+t.find('input[name="form_id"]').val(),a.invoice),0==t.find('input[name="invoice_id"]').length&&t.append(' '),t.find('input[name="invoice_id"]').val(a.invoice))}else t.find(".getpaid-payment-form-errors").html(a).removeClass("d-none")},i=function(e){t.find(".getpaid-payment-form-errors").html(WPInv.connectionError).removeClass("d-none"),t.find(".getpaid-payment-form-remove-on-error").remove()},r=function(){s&&wpinvUnblock(t)};return WPInv.recaptchaSettings&&WPInv.recaptchaSettings.enabled&&"v3"==WPInv.recaptchaSettings.version&&grecaptcha?grecaptcha.ready((function(){grecaptcha.execute(WPInv.recaptchaSettings.sitekey,{action:"purchase"}).then((function(t){return e.post(WPInv.ajax_url,n.data+"&action=wpinv_payment_form&_ajax_nonce="+WPInv.formNonce+"&g-recaptcha-response="+t).done(a).fail(i).always(r)}))})):e.post(WPInv.ajax_url,n.data+"&action=wpinv_payment_form&_ajax_nonce="+WPInv.formNonce).done(a).fail(i).always(r)};if(n.delay){var d=function(){n.submit?r():wpinvUnblock(t),e("body").unbind("getpaid_payment_form_delayed_submit"+i,d)};e("body").bind("getpaid_payment_form_delayed_submit"+i,d)}else r()}else wpinvUnblock(t)}))};e(".getpaid-payment-form").each((function(){i(e(this))})),e(document).on("click",".getpaid-payment-button",(function(t){if(t.preventDefault(),e("#getpaid-payment-modal .modal-body-wrapper").html('"),window.bootstrap&&window.bootstrap.Modal){var a=new window.bootstrap.Modal(document.getElementById("getpaid-payment-modal"));a.show()}else e("#getpaid-payment-modal").modal();var n=e(this).data();n.action="wpinv_get_payment_form",n._ajax_nonce=WPInv.formNonce,n.current_url=window.location.href,e.get(WPInv.ajax_url,n,(function(t){e("#getpaid-payment-modal .modal-body-wrapper").html(t),a?a.handleUpdate():e("#getpaid-payment-modal").modal("handleUpdate"),e("#getpaid-payment-modal .getpaid-payment-form").each((function(){i(e(this))}))})).fail((function(t){e("#getpaid-payment-modal .modal-body-wrapper").html(WPInv.connectionError),a?a.handleUpdate():e("#getpaid-payment-modal").modal("handleUpdate")}))})),e(document).on("click",'a[href^="#getpaid-form-"], a[href^="#getpaid-item-"]',(function(t){var a=e(this).attr("href");if(-1!=a.indexOf("#getpaid-form-"))var n={form:a.replace("#getpaid-form-","")};else{if(-1==a.indexOf("#getpaid-item-"))return;n={item:a.replace("#getpaid-item-","")}}if(t.preventDefault(),e("#getpaid-payment-modal .modal-body-wrapper").html('"),window.bootstrap&&window.bootstrap.Modal){var s=new window.bootstrap.Modal(document.getElementById("getpaid-payment-modal"));s.show()}else e("#getpaid-payment-modal").modal();n.action="wpinv_get_payment_form",n._ajax_nonce=WPInv.formNonce,e.get(WPInv.ajax_url,n,(function(t){e("#getpaid-payment-modal .modal-body-wrapper").html(t),s?s.handleUpdate():e("#getpaid-payment-modal").modal("handleUpdate"),e("#getpaid-payment-modal .getpaid-payment-form").each((function(){i(e(this))}))})).fail((function(t){e("#getpaid-payment-modal .modal-body-wrapper").html(WPInv.connectionError),s?s.handleUpdate():e("#getpaid-payment-modal").modal("handleUpdate")}))})),e(document).on("change",".getpaid-address-edit-form #wpinv-country",(function(t){var a=e(this).closest(".getpaid-address-edit-form").find(".wpinv_state");if(a.length){wpinvBlock(a.parent());var i={action:"wpinv_get_aui_states_field",country:e(this).val(),state:a.val(),class:"wpinv_state",name:a.attr("name"),_ajax_nonce:WPInv.nonce};e.get(WPInv.ajax_url,i,(e=>{"object"==typeof e&&a.parent().replaceWith(e.data.html)})).always((()=>{wpinvUnblock(a.parent())}))}})),RegExp.getpaidquote=function(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")},e(document).on("input",".getpaid-validate-minimum-amount",(function(t){if(""!==e(this).val()){var a=new RegExp(RegExp.getpaidquote(WPInv.thousands),"g"),i=new RegExp(RegExp.getpaidquote(WPInv.decimals),"g"),n=e(this).val();n=(n=n.replace(a,"")).replace(i,"."),!isNaN(parseFloat(n))&&e(this).data("minimum-amount")&&parseFloat(n) 'Checking',
+ 'savings' => 'Savings',
+ 'businessChecking' => 'Business Checking',
+ );
+
/**
* URL to view a transaction.
*
@@ -92,11 +110,27 @@ public function __construct() {
*/
public function payment_fields( $invoice_id, $form ) {
- // Let the user select a payment method.
- $this->saved_payment_methods();
+ $ach_enabled = wpinv_get_option( 'authorizenet_enable_ach' );
+ $show_type_selector = $ach_enabled && $this->is_ach_available();
- // Show the credit card entry form.
- $this->new_payment_method_entry( $this->get_cc_form( true ) );
+ // Payment type selector (CC vs ACH).
+ if ( $show_type_selector ) {
+ $this->render_payment_type_selector();
+ }
+
+ // Credit Card Section.
+ echo '';
+ $this->saved_payment_methods_by_type( 'card' );
+ $this->new_payment_method_entry( $this->get_cc_form( true ) );
+ echo '
';
+
+ // ACH Section.
+ if ( $show_type_selector ) {
+ echo '';
+ $this->saved_payment_methods_by_type( 'ach' );
+ $this->new_payment_method_entry( $this->get_ach_form( true ) );
+ echo '
';
+ }
}
/**
@@ -111,8 +145,16 @@ public function payment_fields( $invoice_id, $form ) {
*/
public function create_customer_profile( $invoice, $submission_data, $save = true ) {
- // Remove non-digits from the number
- $submission_data['authorizenet']['cc_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['cc_number'] );
+ // Determine payment type.
+ $is_ach_payment = $this->is_ach_payment( $submission_data['authorizenet'] );
+
+ // Remove non-digits from the card/account number.
+ if ( $is_ach_payment ) {
+ $submission_data['authorizenet']['ach_routing_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['ach_routing_number'] );
+ $submission_data['authorizenet']['ach_account_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['ach_account_number'] );
+ } else {
+ $submission_data['authorizenet']['cc_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['cc_number'] );
+ }
// Generate args.
$args = array(
@@ -169,12 +211,19 @@ public function create_customer_profile( $invoice, $submission_data, $save = tru
// Save the payment token.
if ( $save ) {
+ if ( $is_ach_payment ) {
+ $token_name = $this->get_ach_token_name( $submission_data['authorizenet'] );
+ } else {
+ $token_name = getpaid_get_card_name( $submission_data['authorizenet']['cc_number'] ) . '····' . substr( $submission_data['authorizenet']['cc_number'], -4 );
+ }
+
$this->save_token(
array(
- 'id' => $response->customerPaymentProfileIdList[0],
- 'name' => getpaid_get_card_name( $submission_data['authorizenet']['cc_number'] ) . '····' . substr( $submission_data['authorizenet']['cc_number'], -4 ),
- 'default' => true,
- 'type' => $this->is_sandbox( $invoice ) ? 'sandbox' : 'live',
+ 'id' => $response->customerPaymentProfileIdList[0],
+ 'name' => $token_name,
+ 'default' => true,
+ 'type' => $this->is_sandbox( $invoice ) ? 'sandbox' : 'live',
+ 'payment_method' => $is_ach_payment ? 'ach' : 'card',
)
);
}
@@ -213,26 +262,34 @@ public function get_customer_profile( $profile_id ) {
}
/**
- * Creates a customer profile.
+ * Creates a customer payment profile.
*
*
* @param string $profile_id profile id.
* @param WPInv_Invoice $invoice Invoice.
* @param array $submission_data Posted checkout fields.
* @param bool $save Whether or not to save the payment as a token.
- * @link https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-profile
+ * @link https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-payment-profile
* @return string|WP_Error Profile id.
*/
public function create_customer_payment_profile( $customer_profile, $invoice, $submission_data, $save ) {
- // Remove non-digits from the number
- $submission_data['authorizenet']['cc_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['cc_number'] );
+ // Determine payment type.
+ $is_ach_payment = $this->is_ach_payment( $submission_data['authorizenet'] );
+
+ // Remove non-digits from the card/account number.
+ if ( $is_ach_payment ) {
+ $submission_data['authorizenet']['ach_routing_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['ach_routing_number'] );
+ $submission_data['authorizenet']['ach_account_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['ach_account_number'] );
+ } else {
+ $submission_data['authorizenet']['cc_number'] = preg_replace( '/\D/', '', $submission_data['authorizenet']['cc_number'] );
+ }
- // Prepare card details.
- $payment_information = $this->get_payment_information( $submission_data['authorizenet'] );
+ // Prepare payment details.
+ $payment_information = $this->get_payment_information( $submission_data['authorizenet'] );
- // Authorize.NET does not support saving the same card twice.
- $cached_information = $this->retrieve_payment_profile_from_cache( $payment_information, $customer_profile, $invoice );
+ // Authorize.NET does not support saving the same payment method twice.
+ $cached_information = $this->retrieve_payment_profile_from_cache( $payment_information, $customer_profile, $invoice );
if ( $cached_information ) {
return $cached_information;
@@ -284,12 +341,19 @@ public function create_customer_payment_profile( $customer_profile, $invoice, $s
// Save the payment token.
if ( $save ) {
+ if ( $is_ach_payment ) {
+ $token_name = $this->get_ach_token_name( $submission_data['authorizenet'] );
+ } else {
+ $token_name = getpaid_get_card_name( $submission_data['authorizenet']['cc_number'] ) . ' ···· ' . substr( $submission_data['authorizenet']['cc_number'], -4 );
+ }
+
$this->save_token(
array(
- 'id' => $response->customerPaymentProfileId,
- 'name' => getpaid_get_card_name( $submission_data['authorizenet']['cc_number'] ) . ' ···· ' . substr( $submission_data['authorizenet']['cc_number'], -4 ),
- 'default' => true,
- 'type' => $this->is_sandbox( $invoice ) ? 'sandbox' : 'live',
+ 'id' => $response->customerPaymentProfileId,
+ 'name' => $token_name,
+ 'default' => true,
+ 'type' => $this->is_sandbox( $invoice ) ? 'sandbox' : 'live',
+ 'payment_method' => $is_ach_payment ? 'ach' : 'card',
)
);
}
@@ -489,20 +553,24 @@ public function process_charge_response( $result, $invoice ) {
* Returns payment information.
*
*
- * @param array $card Card details.
+ * @param array $data Payment form data (card or ACH details).
* @return array
*/
- public function get_payment_information( $card ) {
- return array(
-
- 'creditCard' => array(
- 'cardNumber' => $card['cc_number'],
- 'expirationDate' => $card['cc_expire_year'] . '-' . $card['cc_expire_month'],
- 'cardCode' => $card['cc_cvv2'],
- ),
+ public function get_payment_information( $data ) {
+ // Check if this is an ACH payment.
+ if ( $this->is_ach_payment( $data ) ) {
+ return $this->get_ach_payment_information( $data );
+ }
- );
- }
+ // Default to credit card.
+ return array(
+ 'creditCard' => array(
+ 'cardNumber' => $data['cc_number'],
+ 'expirationDate' => $data['cc_expire_year'] . '-' . $data['cc_expire_month'],
+ 'cardCode' => $data['cc_cvv2'],
+ ),
+ );
+ }
/**
* Returns the customer profile meta name.
@@ -515,6 +583,302 @@ public function get_customer_profile_meta_name( $invoice ) {
return $this->is_sandbox( $invoice ) ? 'getpaid_authorizenet_sandbox_customer_profile_id' : 'getpaid_authorizenet_customer_profile_id';
}
+ /**
+ * Checks if ACH payments are available for the current currency.
+ *
+ * @return bool
+ */
+ public function is_ach_available() {
+ $currency = wpinv_get_currency();
+ return in_array( $currency, $this->ach_currencies, true );
+ }
+
+ /**
+ * Checks if the payment data is for an ACH payment.
+ *
+ * @param array $data Payment data.
+ * @return bool
+ */
+ public function is_ach_payment( $data ) {
+ return isset( $data['payment_type'] ) && 'ach' === $data['payment_type'];
+ }
+
+ /**
+ * Generates a display name for an ACH token.
+ *
+ * @param array $data ACH form data.
+ * @return string
+ */
+ public function get_ach_token_name( $data ) {
+ $account_type = isset( $data['ach_account_type'] ) ? $data['ach_account_type'] : 'checking';
+ $account_number = preg_replace( '/\D/', '', isset( $data['ach_account_number'] ) ? $data['ach_account_number'] : '' );
+ $last_four = substr( $account_number, -4 );
+
+ $type_labels = array(
+ 'checking' => __( 'Checking', 'invoicing' ),
+ 'savings' => __( 'Savings', 'invoicing' ),
+ 'businessChecking' => __( 'Business Checking', 'invoicing' ),
+ );
+
+ $type_label = isset( $type_labels[ $account_type ] ) ? $type_labels[ $account_type ] : __( 'Bank Account', 'invoicing' );
+
+ return $type_label . ' ····' . $last_four;
+ }
+
+ /**
+ * Returns the ACH/eCheck form HTML.
+ *
+ * @param bool $save Whether to display the save checkbox.
+ * @return string
+ */
+ public function get_ach_form( $save = false ) {
+ ob_start();
+
+ $id_prefix = esc_attr( uniqid( $this->id . '_ach_' ) );
+ ?>
+
+
+
+ sanitize_text_field( isset( $data['ach_account_type'] ) ? $data['ach_account_type'] : 'checking' ),
+ 'routingNumber' => preg_replace( '/\D/', '', isset( $data['ach_routing_number'] ) ? $data['ach_routing_number'] : '' ),
+ 'accountNumber' => preg_replace( '/\D/', '', isset( $data['ach_account_number'] ) ? $data['ach_account_number'] : '' ),
+ 'nameOnAccount' => getpaid_limit_length( sanitize_text_field( isset( $data['ach_name_on_account'] ) ? $data['ach_name_on_account'] : '' ), 22 ),
+ 'echeckType' => 'WEB',
+ );
+
+ return array( 'bankAccount' => $bank_account );
+ }
+
+ /**
+ * Validates ACH form fields.
+ *
+ * @param array $data ACH form data.
+ * @return true|WP_Error
+ */
+ public function validate_ach_fields( $data ) {
+ // Routing number validation (9 digits).
+ $routing = preg_replace( '/\D/', '', isset( $data['ach_routing_number'] ) ? $data['ach_routing_number'] : '' );
+ if ( strlen( $routing ) !== 9 ) {
+ return new WP_Error( 'invalid_routing', __( 'Please enter a valid 9-digit routing number.', 'invoicing' ) );
+ }
+
+ // Validate routing number checksum.
+ if ( ! $this->validate_routing_number_checksum( $routing ) ) {
+ return new WP_Error( 'invalid_routing', __( 'The routing number appears to be invalid.', 'invoicing' ) );
+ }
+
+ // Account number validation (1-17 digits).
+ $account = preg_replace( '/\D/', '', isset( $data['ach_account_number'] ) ? $data['ach_account_number'] : '' );
+ if ( empty( $account ) || strlen( $account ) > 17 ) {
+ return new WP_Error( 'invalid_account', __( 'Please enter a valid account number.', 'invoicing' ) );
+ }
+
+ // Name on account validation.
+ $name = trim( isset( $data['ach_name_on_account'] ) ? $data['ach_name_on_account'] : '' );
+ if ( empty( $name ) ) {
+ return new WP_Error( 'invalid_name', __( 'Please enter the name on the account.', 'invoicing' ) );
+ }
+
+ // Account type validation.
+ $valid_types = array_keys( $this->ach_account_types );
+ $account_type = isset( $data['ach_account_type'] ) ? $data['ach_account_type'] : '';
+ if ( ! in_array( $account_type, $valid_types, true ) ) {
+ return new WP_Error( 'invalid_account_type', __( 'Please select a valid account type.', 'invoicing' ) );
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates a routing number using the ABA checksum algorithm.
+ *
+ * @param string $routing The 9-digit routing number.
+ * @return bool
+ */
+ public function validate_routing_number_checksum( $routing ) {
+ if ( strlen( $routing ) !== 9 ) {
+ return false;
+ }
+
+ $checksum = (
+ 3 * ( (int) $routing[0] + (int) $routing[3] + (int) $routing[6] ) +
+ 7 * ( (int) $routing[1] + (int) $routing[4] + (int) $routing[7] ) +
+ 1 * ( (int) $routing[2] + (int) $routing[5] + (int) $routing[8] )
+ );
+
+ return $checksum % 10 === 0;
+ }
+
+ /**
+ * Displays saved payment methods filtered by type.
+ *
+ * @param string $payment_type 'card' or 'ach'.
+ */
+ public function saved_payment_methods_by_type( $payment_type = 'card' ) {
+ $tokens = $this->get_tokens( $this->is_sandbox() );
+
+ // Filter tokens by payment method type.
+ $filtered_tokens = array();
+ foreach ( $tokens as $token ) {
+ $token_type = isset( $token['payment_method'] ) ? $token['payment_method'] : 'card';
+ if ( $token_type === $payment_type ) {
+ $filtered_tokens[] = $token;
+ }
+ }
+
+ // For cards, if no tokens have payment_method set, assume they're all cards (backwards compatibility).
+ if ( empty( $filtered_tokens ) && 'card' === $payment_type ) {
+ foreach ( $tokens as $token ) {
+ if ( ! isset( $token['payment_method'] ) || 'card' === $token['payment_method'] ) {
+ $filtered_tokens[] = $token;
+ }
+ }
+ }
+
+ $input_name = 'ach' === $payment_type ? 'getpaid-authorizenet-ach-payment-method' : 'getpaid-authorizenet-payment-method';
+ $new_label = 'ach' === $payment_type ? __( 'Use a new bank account', 'invoicing' ) : __( 'Use a new card', 'invoicing' );
+
+ echo '';
+ }
+
/**
* Validates the submitted data.
*
@@ -532,16 +896,31 @@ public function validate_submission_data( $submission_data, $invoice ) {
return new WP_Error( 'invalid_settings', __( 'Please set-up your login id and transaction key before using this gateway.', 'invoicing' ) );
}
+ // Determine if this is an ACH payment.
+ $is_ach_payment = $this->is_ach_payment( isset( $submission_data['authorizenet'] ) ? $submission_data['authorizenet'] : array() );
+ $payment_method_key = $is_ach_payment ? 'getpaid-authorizenet-ach-payment-method' : 'getpaid-authorizenet-payment-method';
+
// Validate the payment method.
- if ( empty( $submission_data['getpaid-authorizenet-payment-method'] ) ) {
- return new WP_Error( 'invalid_payment_method', __( 'Please select a different payment method or add a new card.', 'invoicing' ) );
+ if ( empty( $submission_data[ $payment_method_key ] ) ) {
+ $error_message = $is_ach_payment
+ ? __( 'Please select a different payment method or add a new bank account.', 'invoicing' )
+ : __( 'Please select a different payment method or add a new card.', 'invoicing' );
+ return new WP_Error( 'invalid_payment_method', $error_message );
}
// Are we adding a new payment method?
- if ( 'new' != $submission_data['getpaid-authorizenet-payment-method'] ) {
- return $submission_data['getpaid-authorizenet-payment-method'];
+ if ( 'new' != $submission_data[ $payment_method_key ] ) {
+ return $submission_data[ $payment_method_key ];
}
+ // Validate ACH fields if this is a new ACH payment.
+ if ( $is_ach_payment ) {
+ $ach_validation = $this->validate_ach_fields( $submission_data['authorizenet'] );
+ if ( is_wp_error( $ach_validation ) ) {
+ return $ach_validation;
+ }
+ }
+
// Retrieve the customer profile id.
$profile_id = get_user_meta( $invoice->get_user_id(), $this->get_customer_profile_meta_name( $invoice ), true );
@@ -896,6 +1275,32 @@ public function admin_settings( $admin_settings ) {
'readonly' => true,
);
+ // ACH/eCheck Settings.
+ $admin_settings['authorizenet_ach_header'] = array(
+ 'type' => 'header',
+ 'id' => 'authorizenet_ach_header',
+ 'name' => '' . __( 'ACH/eCheck Settings', 'invoicing' ) . ' ',
+ );
+
+ $admin_settings['authorizenet_enable_ach'] = array(
+ 'type' => 'checkbox',
+ 'id' => 'authorizenet_enable_ach',
+ 'name' => __( 'Enable ACH Payments', 'invoicing' ),
+ 'desc' => sprintf(
+ __( 'Allow customers to pay via bank account (ACH/eCheck). Only available for USD transactions. %1$sLearn more about ACH payments%2$s.', 'invoicing' ),
+ '',
+ ' '
+ ),
+ );
+
+ $admin_settings['authorizenet_ach_description'] = array(
+ 'type' => 'text',
+ 'id' => 'authorizenet_ach_description',
+ 'name' => __( 'ACH Description', 'invoicing' ),
+ 'desc' => __( 'Description shown to customers when they select ACH payment.', 'invoicing' ),
+ 'std' => __( 'Pay directly from your bank account.', 'invoicing' ),
+ );
+
return $admin_settings;
}