Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Woocommerce to only run javascript if a specific payment method is selected

I have developed a payment gateway plugin for Woocommerce, and it relies heavily on some javascript which loads a popup to capture user details. I need that javascript to run only if THAT gateway is selected from the radio buttons. For some reason it doesn't work. Here's my code

jQuery(document).ready(function() {
  usingGateway();
  jQuery('form[name="checkout"] input[name="payment_method"]:checked').change(function(){
    usingGateway();
  });
});

function usingGateway(){
    console.log(jQuery("input[name='payment_method']:checked").val());
    if(jQuery('form[name="checkout"] input[name="payment_method"]:checked').val() == 'my_gateway'){
        console.log("Using my gateway");
        //Etc etc
    }else{
         console.log("Not using my gateway. Proceed as usual");
    }
}

It seems woocommerce overrides the javascript in some way, because even though the radio button is selected, my console.log for payment_method is always undefined. Then the IF block is skipped and it always says "Not using my gateway. When I comment out the IF statement, the payment gateway works fine.

But I need it to work because if a user selects another payment method (even BACS or offline payments), the javascript will still load the popup and attempt to process the payment using my custom gateway.

Update: According to rnevius comment, I checked the woocommerce checkout.js and copied this from there into my plugin javascript:

var payment_methods = jQuery('.woocommerce-checkout').find( 'input[name="payment_method"]' );
if ( 0 === payment_methods.filter( ':checked' ).size() ) {
payment_methods.eq(0).attr( 'checked', 'checked' );
}

So essentially if nothing is already checked, woocommerce will force-check the first item. No idea why I need to do that since woocommerce already does that in checkout.js That works now but if my gateway isn't already the first one selected, the "change" function still isn't working (when you change to my gateway from another one). Please help.

like image 843
Cogicero Avatar asked Dec 18 '22 21:12

Cogicero


2 Answers

Try this to assign callback on payment method select

jQuery(function(){
    jQuery( 'body' )
    .on( 'updated_checkout', function() {
          usingGateway();

        jQuery('input[name="payment_method"]').change(function(){
            console.log("payment method changed");
              usingGateway();

        });
    });
});


function usingGateway(){
    console.log(jQuery("input[name='payment_method']:checked").val());
    if(jQuery('form[name="checkout"] input[name="payment_method"]:checked').val() == 'my_gateway'){
        console.log("Using my gateway");
        //Etc etc
    }else{
         console.log("Not using my gateway. Proceed as usual");
    }
}   
like image 176
Swarnendu Paul Avatar answered Dec 21 '22 10:12

Swarnendu Paul


It turned out that the area I referred to as "Etc etc" had the key to the final part of the problem. Here is what eventually worked, but I am thankfully accepting Swarnendu's answer for his efforts. It turns out that when the gateway is in use, I was binding the form submit process.

This means that when the gateway is selected by default, the form is already binded to that payment gateway. Then, when the user changes the payment method, the form still tries to use that gateway even though another method has been selected.

The solution was to
(a) Force-check a radio option as the default one (deals with the "undefined" issue. No idea why this is necessary since woocommerce checkout.js already does it).
(b) If after changing payment method, no radio option is selected then select the current one (a weird issue that happens sometimes due to interference from woocommerce checkout.js. Officially, this can be overcome by including your own checkout.js into the theme folder, but for a plugin that will be used on different sites, there is no such way to override checkout.js) so then repeat "a" using an "on" change delegation.
(c) If the gateway is not in use, unbind the submit method that was used by default to patch through to the gateway.

jQuery(document).ready(function() {
  jQuery('form[name="checkout"] input[name="payment_method"]').eq(0).prop('checked', true).attr( 'checked', 'checked' );
  usingGateway();
});

jQuery(document).on("change", "form[name='checkout'] input[name='payment_method']", function(){
  if ( 0 === jQuery('form[name="checkout"] input[name="payment_method"]' ).filter( ':checked' ).size() ) {
    jQuery(this).prop('checked', true).attr( 'checked', 'checked' );
  };
  usingGateway();
});

function usingGateway(){
  if(jQuery("form[name='checkout'] input[name='payment_method']:checked").val() == 'my_gateway'){
      console.log("Using my gateway");
      jQuery('form[name="checkout"]').on('submit', function(e){
         // Process using custom gateway
         // Etc etc
         e.preventDefault();
      });
  }else{
   // Not using gateway
   console.log("Not using my gateway. Proceed as usual");
   jQuery('form[name="checkout"]').unbind('submit');
   }
};
like image 37
Cogicero Avatar answered Dec 21 '22 10:12

Cogicero