3

I need to disable specific shipping method if user selected payment "Cash on Delivery". The problem is that the following code works only if I reset WooCommerce transients each time and refresh. It doesn't work on user selection back and forth.

add_filter( 'woocommerce_package_rates', 'alter_shipping_methods', 100 );
function alter_shipping_methods( $rates ) {

    $chosen_gateway = WC()->session->chosen_payment_method;

    // If payment is Cash on delivery remove specific shipping 
    if($chosen_gateway == 'cod') {

        foreach ( $rates as $rate_id => $rate ) {
           if ( $rate->label === 'Hrvatska pošta' ) {
              unset( $rates[ $rate_id ] );
            }
        }
    }
    return $rates;
}

I do have this code which should trigger and I see the output in console when I click around options.

jQuery(document.body).on('change', 'input[name="payment_method"]', function() {
    console.log('Payment method changed');
    jQuery('body').trigger('update_checkout');
});

I have tried with this, it doesn't work:

function action_woocommerce_checkout_update_order_review($array, $int) {
    WC()->cart->calculate_shipping();
    return;
}
add_action('woocommerce_checkout_update_order_review', 'action_woocommerce_checkout_update_order_review', 10, 2);

And I have also tried custom AJAX call which calls a PHP function and inside this filter, no result:

add_filter( 'woocommerce_package_rates', 'alter_shipping_methods', 100 );

What should I try next?

starball
  • 20,030
  • 7
  • 43
  • 238
Ivan Topić
  • 3,064
  • 6
  • 34
  • 47

1 Answers1

9

Updated on March 2019

For COD payment gateways, you can just add in its settings the "Flat rate" shipping methods that you want to enable for it, like:

enter image description here

For Cod and other methods or for others payment gateways, here is the complete working way to disable a specific shipping method(s) for specific payment gateway(s).

You will have to set in the first function the shipping method Id that you wish to hide.

The code:

add_action( 'woocommerce_package_rates','show_hide_shipping_methods', 10, 2 );
function show_hide_shipping_methods( $rates, $package ) {
    // HERE Define your targeted shipping method ID
    $payment_method        = 'cod';

    $chosen_payment_method = WC()->session->get('chosen_payment_method');

    if( $payment_method == $chosen_payment_method ){
        unset($rates['flat_rate:12']);
    }
    return $rates;
}

add_action( 'woocommerce_review_order_before_payment', 'payment_methods_trigger_update_checkout' );
function payment_methods_trigger_update_checkout(){
    // jQuery code
    ?>
    <script type="text/javascript">
        (function($){
            $( 'form.checkout' ).on( 'change blur', 'input[name^="payment_method"]', function() {
                setTimeout(function(){
                    $(document.body).trigger('update_checkout');
                }, 250 );
            });
        })(jQuery);
    </script>
    <?php
}

add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods' );
function refresh_shipping_methods( $post_data ){
    // HERE Define your targeted shipping method ID
    $payment_method = 'cod';
    $bool           = true;

    if ( WC()->session->get('chosen_payment_method') === $payment_method )
        $bool = false;

    // Mandatory to make it work with shipping methods
    foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
        WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
    }
    WC()->cart->calculate_shipping();
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

To be able to get the correct shipping method ID you can use your browser inspector, this way:

enter image description here

You may need to empty cart before testing this code.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Hi LoicTheAztec, can you update to hide the other PAYMENT methods too please? – FilipeOS Mar 25 '19 at 12:38
  • @FilipeOS How that *(I don't catch)*? … This answer is working as it is. – LoicTheAztec Mar 25 '19 at 12:54
  • according your answer, if you choose COD shipping method the other payment methods still show and you can ask to COD+pay for example with paypal.. This is why I want to hide the payment methods if COD shipping is selected. – FilipeOS Mar 25 '19 at 12:57
  • 1
    @FilipeOS Sorry the code was not working anymore… So I have change it and I have removed unneeded Ajax. Try it and give me some feed back. – LoicTheAztec Mar 25 '19 at 13:51
  • @LoicTheAztec I installed on the last version of WP and WC but, after the first execution, the update enter in a loop and never stops... is there an issue? – user1142705 Jun 01 '20 at 14:36
  • @user1142705 Just tested that on last WP and WC versions on last version of Storefront theme, and there is no issue . – LoicTheAztec Jun 01 '20 at 21:32
  • Hi, your code works fine, I just got a question... What about if you wanna assign next to cod paypal too? So that 2 payment methods would be available for specific shipping. – Miran Urbas Jan 11 '21 at 12:26