Search code examples
phpwordpresswoocommercecartcoupon

Apply coupon automatically for one shipping method in Woocommerce


On Woocommerce, I am trying to apply a coupon based on a specific shipping method.

There is two shipping method set:

  1. Free Shipping (3 Days): £0.00
  2. DPD Next Day: £4.00

If the customer selects DPD Next Day: £4.00 shipping method, a specific coupon code "discount4" should be applied automatically.

If the customer selects Free Shipping (3 Days): £0.00 shipping method, the coupon code shouldn't be applied.

Any help or track is appreciated.


Solution

  • The following code will auto apply a coupon, if the chosen Shipping Method is not "Free shipping" and will remove that coupon if it's applied and customer change to "Free shipping":

    // Add / remove coupon based on cosen shipping
    add_action( 'woocommerce_before_calculate_totals', 'adding_removing_coupon_shipping_based' );
    function adding_removing_coupon_shipping_based( $cart ) {
        if (is_admin() && !defined('DOING_AJAX'))
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // HERE the specific coupon code
        $coupon_code = 'discount4';
    
        $coupon_code     = wc_format_coupon_code( $coupon_code );
        $chosen_shipping = WC()->session->get('chosen_shipping_methods')[0];
        $applied_coupons = $cart->get_applied_coupons();
    
        $is_free = strpos( $chosen_shipping, 'free_shipping' ) !== false;
        $is_applied = in_array( $coupon_code, $applied_coupons );
    
    
        if ( $is_applied && $is_free )
            $cart->remove_coupon( $coupon_code );
        elseif ( ! $is_applied && ! $is_free )
            $cart->apply_coupon( $coupon_code );
    }
    

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

    If you have multiple shipping methods, you should give in your question the correct shipping method rate ID like "flat_rate:18" for DPD Next Day: £4.00, to be targeted in the code instead of free shipping which always start by free_shipping

    enter image description here