0

On Woocommerce, I have enabled 2 shipping methods: Free shipping or Flat rate. I have enabled 2 payment methods: Bank transfer (bacs) and PayPal (paypal).

What I want to achieve: If a customer selects PayPal as payment type he should be forced to select "Flat rate" as shipping method. "Free shipping" should be either hidden or greyed out or something like that.

If bank transfer is chosen then both shipping methods should be available.

Any help is appreciated.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Andy
  • 57
  • 1
  • 7

2 Answers2

2

Update 2: The following code will disable "free_shipping" shipping method (method ID) when "paypal" is the chosen payment method:

add_filter( 'woocommerce_package_rates', 'shipping_methods_based_on_chosen_payment', 100, 2 );
function shipping_methods_based_on_chosen_payment( $rates, $package ) {
    // Checking if "paypal" is the chosen payment method
    if ( WC()->session->get( 'chosen_payment_method' ) === 'paypal' ) {
        // Loop through shipping methods rates
        foreach( $rates as $rate_key => $rate ){
            if ( 'free_shipping' === $rate->method_id ) {
                unset($rates[$rate_key]); // Remove 'Free shipping'shipping method
            }
        }
    }
    return $rates;
}

// Enabling, disabling and refreshing session shipping methods data
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
    $bool = true;
    if ( WC()->session->get('chosen_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();
}

// Jquery script for checkout page
add_action('wp_footer', 'refresh_checkout_on_payment_method_change' );
function refresh_checkout_on_payment_method_change() {
    // Only checkout page
    if( is_checkout() && ! is_wc_endpoint_url() ):
    ?>
    <script type="text/javascript">
    jQuery(function($){
        // On shipping method change
        $('form.checkout').on( 'change', 'input[name^="payment_method"]', function(){
            $('body').trigger('update_checkout'); // Trigger Ajax checkout refresh
        });
    })
    </script>
    <?php
    endif;
}

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

To get the related shipping methods rate IDs, something like flat_rate:12, inspect with your browser code inspector each related radio button attribute name like:

enter image description here


Note: Since WooCommerce new versions changes, sorry, the code doesn't work anymore.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Thank you, but it doesn't work for me, unfortunately. I changed the "Untracked" in line 7 to "Priority Lieferung (3-5 Werktage)" because that's how the name of the shipping method is. Is there anything else I need to change or should try? – Andy Dec 10 '18 at 19:04
  • Thanks for clarifying! I found out the shipping rate ID for the untracked shipping method is "free_shipping:2", so I inserted this in line 4 of your code instead of "flat_rate:12", right? The problem is that it removes this shipping method (untracked/Priority Lieferung) even when bank transfer is chosen as payment method. – Andy Dec 11 '18 at 21:30
  • How can I find out what I am doing wrong? I have a customization, that removes the footer of the website, but I don't think that interacts with your code. I have the "Checkout Field Editor for WooCommerce" installed. – Andy Dec 12 '18 at 17:16
  • I tried it again, but it still doesn't work. I refreshed cached shipping data, but in the checkout page the code for me doesn't work as it should. – Andy Dec 19 '18 at 12:30
  • So, it works...somewhat. For me it only works when I change the shipping country. So when the shipping country is set to Germany and I click PayPal, nothing changes, but when I change the country to lets say Norway the untracked shipping method disappears. Any idea what causes that? – Andy Dec 20 '18 at 17:30
  • Dear @LoicTheAztec you rock as always. However, I have one question. I use the code you provided and sometimes it does not work. To be more specific it seems that the payment method a user selects is saved in the session and is used after the second change of the payment methods dropdown. So in my code, I would like the free shipping to be unset when the user selects the COD payment however the free shipping is unset when the user selects another payment method AFTER firstly has selected COD. Do you have any clue why is this happening? – Archimidis M Feb 13 '21 at 00:56
  • @ArchimidisM I remember now *(so I don't rock)*:I have never been able to find the way to make it work… So forget it. – LoicTheAztec Feb 13 '21 at 02:41
2

If anyone is interested, I found a solution:

function alter_payment_gateways( $list ){
    // Retrieve chosen shipping options from all possible packages
    $chosen_rates = ( isset( WC()->session ) ) ? WC()->session->get( 'chosen_shipping_methods' ) : array();
    if( in_array( 'free_shipping:1', $chosen_rates ) ) {
        $array_diff = array('WC_Gateway_Paypal');
        $list = array_diff( $list, $array_diff );
    }
    return $list;
}
add_action('woocommerce_payment_gateways', 'alter_payment_gateways');

This code will deactivate PayPal if a customer selects free shipping.

Andy
  • 57
  • 1
  • 7
  • Can i do it the other way around? So that if the customer clicks paypal as payment option, then a shipping option is removed? I tried editing your snippit but with no luck :/ – Vegapunk Dec 07 '20 at 14:31