2

I need to apply an additional fee when a customer can place an order with free shipping, but wants to select COD payment. So, Free Shipping + COD payment => fee.

I tried unsuccessfully the following piece of code. Where am I wrong?

add_action( 'woocommerce_cart_calculate_fees','cod_fee' );
function cod_fee() {
    global $woocommerce;

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

        $chosen_gateway = WC()->session->chosen_payment_method;
        $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
        $chosen_shipping = $chosen_methods[0]; 
        $fee = 19;
        if ( $chosen_shipping == 'free_shipping' && $chosen_gateway == 'cod' ) { 
        WC()->cart->add_fee( 'Spese per pagamento alla consegna', $fee, false, '' );
    }
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
alemarengo
  • 91
  • 3
  • 11

1 Answers1

6

There is a mistake in your code and some additional code is needed. Try the following code that will add a specific fee when chosen payment method is Cash on delivery (cod) and when chosen shipping methods is "Free shipping":

// Add a conditional fee
add_action( 'woocommerce_cart_calculate_fees', 'add_cod_fee', 20, 1 );
function add_cod_fee( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    ## ------ Your Settings (below) ------ ##
    $your_payment_id      = 'cod'; // The payment method
    $your_shipping_method = 'free_shipping'; // The shipping method
    $fee_amount           = 19; // The fee amount
    ## ----------------------------------- ##

    $chosen_payment_method_id  = WC()->session->get( 'chosen_payment_method' );
    $chosen_shipping_method_id = WC()->session->get( 'chosen_shipping_methods' )[0];
    $chosen_shipping_method    = explode( ':', $chosen_shipping_method_id )[0];

    if ( $chosen_shipping_method == $your_shipping_method 
    && $chosen_payment_method_id == $your_payment_id ) {
        $fee_text = __( "Spese per pagamento alla consegna", "woocommerce" );
        $cart->add_fee( $fee_text, $fee_amount, false );
    }
}

// Refresh checkout on payment method change
add_action( 'wp_footer', 'refresh_checkout_script' );
function refresh_checkout_script() {
    // Only on checkout page
    if( is_checkout() && ! is_wc_endpoint_url('order-received') ) :
    ?>
    <script type="text/javascript">
    jQuery(function($){
        // On payment method change
        $('form.woocommerce-checkout').on( 'change', 'input[name="payment_method"]', function(){
            // Refresh checkout
            $('body').trigger('update_checkout');
        });
    })
    </script>
    <?php
    endif;
}

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

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • LoicTheAztec as i tried this code its working perfectly but when once order payment is failed and again user is trying to pay from order history no cod charges are getting added – Parth Shah Nov 14 '18 at 04:34
  • @ParthShah Yes that is normal as this code don't handle this case because of the hooks that is used here in checkout page only on the Cart Object. If the order is failed, in order pay the cart object no longer exist. So in this case the shop manager need to edit the order and to add the fee. – LoicTheAztec Nov 14 '18 at 04:53
  • So how can i add can you help it.. Any hooks or condition? – Parth Shah Nov 14 '18 at 04:54
  • But the mail that goes to user with final payment so we cannot change amount from backend no hooks are available for that?? – Parth Shah Nov 14 '18 at 04:58
  • I don't know… My answer here is just a working changed version from an existing non working code. So This answer just patch an existing code to make it work. What you are asking is something completely different without any provided code. – LoicTheAztec Nov 14 '18 at 05:01
  • @ParthShah But fist you need to search and to try yourself… Then you could ask a question providing some custom code (not this answer code!). – LoicTheAztec Nov 14 '18 at 05:06
  • The Above code work for me, I have to need a shipping charge conditionally, if the user selected outside of Dhaka city 120 BDT will add and Inside Dhaka City 80 BDT will add – Momin Sep 10 '22 at 05:17