4

On Checkout page payment methods are presented and the first one is selected by default and automatically. I need to prevent the selection so no payment method is initially selected by WC.

I tried 2 things so far:

  1. jQuery from Chrome console:

    jQuery( '.payment_methods input.input-radio' ).prop('checked', false);

result:

[<input id=​"payment_method_paypal" type=​"radio" class=​"input-radio" name=​"payment_method" value=​"paypal" data-order_button_text=​"Proceed to PayPal" checked=​"checked">​, 
<input id=​"payment_method_accountfunds" type=​"radio" class=​"input-radio" name=​"payment_method" value=​"accountfunds" data-order_button_text>​]
  1. Remove the code from payment-method.php Woocommerce template file:

    checked( $gateway->chosen, false );

Neither is working. How to do it? Any snippet or suggestion for that, please?

EDIT:

Also tried this:

function wpchris_filter_gateways( $gateways ){

global $woocommerce;

foreach ($gateways as $gateway) {
    $gateway->chosen = 0;
}
return $gateways;

}
add_filter( 'woocommerce_available_payment_gateways', 'wpchris_filter_gateways', 1);
CJ Kepinsky
  • 648
  • 3
  • 8
  • 16
  • Try `removeAttr('checked')` ? – meder omuraliev Aug 12 '15 at 14:03
  • tried this as well... nothing different from the result above. – CJ Kepinsky Aug 12 '15 at 14:25
  • Why are you trying to do this? Won't allowing people to proceed without selecting a payment method create more problems? – helgatheviking Aug 12 '15 at 14:35
  • my client needs to be no method selected initially.Propably it's because we are adding handling fee to one of these payment methods. Therefore, if no method is selected iniatially then the client will see how the price is changing from one payment menthod to another. – CJ Kepinsky Aug 12 '15 at 14:38
  • 1
    It looks like something is overwriting my changes. When I refresh the Checkout page then for a moment I see no radio selected and then there is a change. – CJ Kepinsky Aug 12 '15 at 14:52

10 Answers10

3

OK, got it working. Here is how:

  1. Copy the javascript file from:

/wp-content/plugins/woocommerce/assets/js/frontend/checkout.js

into:

/wp-content/themes/Your-Theme/woocommerce/js/checkout.js

  1. Open that newly created file and search for the following code:

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

It Should be around line 298. Go ahead and comment it out.

  1. Add this to your functions.php file:

        function wpchris_override_woo_checkout_scripts() {
            wp_deregister_script('wc-checkout');
            wp_enqueue_script('wc-checkout', get_stylesheet_directory_uri() . '/woocommerce/js/checkout.js', array('jquery', 'woocommerce', 'wc-country-select', 'wc-address-i18n'), null, true);
        }
        add_action('wp_enqueue_scripts', 'wpchris_override_woo_checkout_scripts');
    
        function wpchris_unselect_payment_method() {
            echo "<script>jQuery( '.payment_methods input.input-radio' ).removeProp('checked');</script>";
        }
        add_action('woocommerce_review_order_before_submit','wpchris_unselect_payment_method' );
    
        function wpchris_filter_gateways( $gateways ){
            global $woocommerce;
    
            foreach ($gateways as $gateway) {
                $gateway->chosen = 0;
            }
    
            return $gateways;
        }
        add_filter( 'woocommerce_available_payment_gateways', 'wpchris_filter_gateways', 1);
    

Now, the default payment method should not get checked when you refresh the Checkout page.

jezmck
  • 1,138
  • 3
  • 18
  • 38
CJ Kepinsky
  • 648
  • 3
  • 8
  • 16
  • Three comments. Firstly: In line 4, where you say `get_stylesheet_directory_uri() . '/woocommerce/js/checkout.json_encode'`, I guess you mean `.js` instead of `.json_encode`? Secondly: is the jQuery unselect still necessary when you already set `$gateway->chosen = 0`? Finally: Instead of `$gateway->chosen = 0;` I would suggest `$gateway->chosen = false;`, to indicate a true/false value rather than an actual integer (which could lead to different interpretations of the variable `chosen`). – Daan Wilmer Nov 03 '15 at 12:22
2

I have the same problem and I have solved this way:

  1. Override the checkout-js file with my child theme checkout-override-js.

  2. Then commented out the following code:

line: 48 : this.init_payment_methods();
line: 58 :

init_payment_methods: function() {
            var $payment_methods = $( '.woocommerce-checkout' ).find( 'input[name="payment_method"]' );

        // If there is one method, we can hide the radio input
        if ( 1 === $payment_methods.size() ) {
            $payment_methods.eq(0).hide();
        }

        // If there are none selected, select the first.
        if ( 0 === $payment_methods.filter( ':checked' ).size() ) {
            $payment_methods.eq(0).attr( 'checked', 'checked' );
        }

        // Trigger click event for selected method
        $payment_methods.filter( ':checked' ).eq(0).trigger( 'click' );
    },

line: 113: wc_checkout_form.init_payment_methods();

This will remove the default payment method selection. You can play with these code to make it to fit with your requirement.

2

There is not a good way of achieving this through a filter, this doesn't work with latest versions of woocommerce 4.x:

//DEPRECATED. Will not work with woocommerce 4.x and above    
add_filter( 'pre_option_woocommerce_default_gateway' . '__return_false', 99 );

Instead of overwriting Woocommerce core JS files as the other anwers suggest, do this instead:

var $paymentCheckboxes = $( ".woocommerce-checkout-payment" ).find( '[name="payment_method"]');
$paymentCheckboxes.attr('checked', false);
svelandiag
  • 4,231
  • 1
  • 36
  • 72
Tosh
  • 1,789
  • 15
  • 20
  • Hey, in which file you would put this code, in any custom js? Please add more context. Cheers – Viktor Borítás Oct 14 '20 at 10:19
  • 1
    Hi @ViktorBorítás, any file that get's executed wil work, just make sure you wrap it a $(document).ready(function() {}) like svelandia answer – Tosh Oct 15 '20 at 10:31
  • I tried as you instructed, but for me doesn't work. Maybe it depends where i place it, and my extension got still overridden by the core js code by some internal priority order? Tried in clean chrome + edge. Have you tested this? – Viktor Borítás Oct 15 '20 at 12:33
  • update: now it seems i made it work, but only if i wrap your code into a setTimeout() with at least around 1500 millisec.. (to actually get beyond the point where a (core) setTimeout 1000 in the `checkout.min.js` fires off). – Viktor Borítás Oct 15 '20 at 13:01
1

Complementing @Tosh answer, but adding the javascript callback so it runs every time checkout updates through ajax.

jQuery(document).ready(function( $ ){
    $( document ).on( 'updated_checkout', function() {
        var $paymentCheckboxes = $( ".woocommerce-checkout-payment" ).find( '[name="payment_method"]');
        $paymentCheckboxes.attr('checked', false);
        $('.payment_box').hide();
    });
});

Tested and working.

svelandiag
  • 4,231
  • 1
  • 36
  • 72
  • So this does work initially but when a customer selects a payment method it doesn't stay selected which makes it impossible to checkout. – Alex Banks Oct 07 '20 at 12:34
  • That's not true. The last step the user performs is selecting the payment method. It will remeain selected as long as you do not edit your address in the checkout form. – svelandiag Oct 07 '20 at 20:42
  • Sorry I don't understand. I have it live on my checkout and when I select a payment method it opens up but then deselects itself. So I cannot select a payment method to checkout. – Alex Banks Oct 12 '20 at 09:39
  • What this JS does is to add a callback every time the order details update in the checkout, it updates when you type your address in the checkout form for example...This code works if choosing the payment method is the last step in your checkout. – svelandiag Oct 14 '20 at 19:43
  • @AlexBanks Maybe [this solution](https://stackoverflow.com/a/64368522/9022150) would do the trick for you. – Viktor Borítás Oct 15 '20 at 09:25
  • Better to use prop instead attr. – Harry Aug 09 '21 at 10:12
  • instead of attr('checked', false) try prop('checked', false) – Yatix Mar 03 '22 at 19:48
1

I solved this problem with jQuery. All I do is write a function that is triggered by the scroll gesture after the page has loaded. It really works, anyone can add the following code to the bottom of the footer.php file in the theme files. Also, don't forget to edit the payment_method_name according to you.

jQuery(document).ready(function($){
  $(window).scroll(function() {
    if ($(this).scrollTop() > 0) {
      if (!this.done) {
        this.done = true;
        var $paymentCheckboxes = $('.woocommerce-checkout-payment').find('[name="PAYMENT_METHOD_NAME_HERE"]');
        $paymentCheckboxes.removeAttr('checked');
        $('.payment_box').hide();
        $('#PAYMENT_METHOD_NAME_HERE').prop("checked", false);
      }
    }
  });
});
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
0

None of these solutions worked well for me.

My solution was: Let WooCommerce behave like it wants to I added a payment option (In this case COD) to the top of the list. With CSS, I hid the entire <li>

Then I added validation in 'woocommerce_after_checkout_validation'. If the user chose this one, I simply returned an error of 'no payment selected'

Seems to be working just fine.

Yoni
  • 316
  • 2
  • 13
  • I would like to build on top of this brilliant idea. Instead of reusing the existing payment method I would create a new payment gateway plugin and in process_payment() method I would simply have wc_add_notice( 'custom error message', 'error' ). This would allow to reuse the code on multiple stores by just enabling plugin. You also don't have to worry about WooCommerce updates. – mindo Jan 29 '21 at 12:26
0
$(document).on('updated_checkout',function() {
$('input[type=radio][name=payment_method]').change(function() {
$('body').addClass('payment_selection_made');
});
if (!$('body').hasClass('payment_selection_made')) {     
$('.woocommerce-checkout-payment input[name="payment_method"]').attr('checked', false);
$('.woocommerce-checkout-payment .payment_box').hide();         
}
});
Linden
  • 99
  • 1
  • 4
0

I used @Viktor Borítás answer and worked fine in WooCommerce 6.0.0. To overridde checkout.min.js and make it independent from updates i used the function below in child theme functions.php file.

//override WooCommerce Frontend Script (checkout.min.js)
add_action('wp_enqueue_scripts', 'override_woo_frontend_scripts');
function override_woo_frontend_scripts() {
    wp_deregister_script('wc-checkout');
    wp_enqueue_script('wc-checkout', get_stylesheet_directory_uri() . '/woocommerce/js/checkout.min.js', array('jquery', 'woocommerce', 'wc-country-select', 'wc-address-i18n'), null, true);
}

I needed to change Woocommerce default payment method on Checkout page (nothing else i tried did the job!) so didn't commented this code:

if ( 0 === $payment_methods.filter( ':checked' ).length ) {
                $payment_methods.eq(0).prop( 'checked', true );

Instead i changed the value of payment_methods selection to something else.

0

Maybe such a crutch will help someone. In the file payment-method.php add <input type="radio" class="input-radio" name="payment_method" style="display:none;" checked>

-1

In payment-method.php i simply commented out this part (line 23 as of WooCommerce 4.5.2)

<?php //checked( $gateway->chosen, true ); ?>

(If you have child theme, place the modified file into wp-content/themes/yourchildtheme/woocommerce/checkout/ directory.)

and,

Need to make changes in checkout.min.js (at wp-content/plugins/woocommerce/assets/js/frontend/) too. Commented this out this at line 80 (WooCommerce 4.5.2)

/*if ( 0 === $payment_methods.filter( ':checked' ).length ) {
                $payment_methods.eq(0).prop( 'checked', true );*/

This second file unfortunately can't be overridden simply by copying it into the child theme folder. This solution isn't update-proof yet. But maybe an OK base to continue with and make it update-proof on a smart and (as) native (as possible) way. Here are some solutions i found for that.

p.s: this solution preserves the selected payment method even if customer changes zip code, address data etc.

Viktor Borítás
  • 135
  • 2
  • 11