skip to Main Content

class CheckoutTax
{
    public function __construct()
    {
        // add a note after the order details, when a tax is charged and country changes 
        
        // the html snippet is shown after the order details on a page refresh
        add_action('woocommerce_review_order_before_payment', array($this, 'checkout_note_tax'));

        // the action is called when the country changes
        // but it does not show the html snippet at the correct place
        add_action('woocommerce_cart_calculate_fees', array($this, 'checkout_note_tax'));

        // how to combine
        // - show HTML snippet after the order details
        // - act on a country change
    }

    /**
     * Show checkout note, tax paid
     *
     * @return void
     */
    function checkout_note_tax() {
        
        if (is_admin() && !defined('DOING_AJAX')) return;

        if (!is_checkout()) return;

        global $WOOCS;

        $total_tax = WC()->cart->get_totals()['total_tax'];
        $shipping_country = WC()->customer->get_shipping_country();

        error_log( $total_tax );
        error_log( $shipping_country );

        if( $total_tax > 0 && $shipping_country != 'CH') {
            ?>
            <h3>VAT / Custom Duties</h3>
            <?php
        }
    }
}

The hook woocommerce_review_order_before_payment shows the html snippet at the correct page, but only on a page refresh.

The hook woocommerce_cart_calculate_fees triggers changes made to the country field.

How can I combine an action to show a HTML snippet after the order details on the checkout page and update the HTML snippet when the shipping country is changed?

2

Answers


  1. Chosen as BEST ANSWER

    Here is another solution, although it will show in the order table before the total. (I used something similar to add checkboxes for shipping insurance and calculating the insurance fee).

    class CheckoutTax
    {
        public function __construct()
        {
            add_filter( 'woocommerce_cart_totals_before_order_total',  array($this, 'checkout_note_tax'));
            add_filter( 'woocommerce_review_order_before_order_total',  array($this, 'checkout_note_tax'));
        }
     
        /**
         * Show checkout note, tax/customs paid
         *
         * @return void
         */
        function checkout_note_tax() {
            
            if (is_admin() && !defined('DOING_AJAX')) return;
    
            global $WOOCS;
    
            $total_tax = WC()->cart->get_totals()['total_tax'];
            $shipping_country = WC()->customer->get_shipping_country();
    
            if( $total_tax > 0 && $shipping_country != 'CH') {
                ?>
                    <tr class="woocommerce-shipping-insurance shipping">
                        <th><?php _e('VAT / Custom Duties', 'woocommerce'); ?></th>
                        <td data-title="<?php echo esc_attr('checkout_note_tax'); ?>">
                            <p>VAT and custom duties ...
                        </td>
                    </tr>
                <?php
            }
        }
    
    }
    

  2. You need something a bit different to get your custom content refreshed on checkout_update Ajax event. I have replaced woocommerce_review_order_before_payment hook with a more convenient one.

    Now your content is also added to Ajax "order review fragments", so on "Update checkout" event your display gets refreshed dynamically.

    Try the following (commented):

    class CheckoutTax
    {
    
        public function __construct()
        {
            add_action( 'woocommerce_checkout_order_review', array( $this, 'checkout_display_custom_taxes'), 15 );
            add_filter( 'woocommerce_update_order_review_fragments', array( $this, 'update_checkout_custom_fragments') );
        }
    
        /**
         * Here your HTML content
         *
         * @return string
         */   
        public function output() {
            $total_tax = WC()->cart->get_totals()['total_tax'];
            $shipping_country = WC()->customer->get_shipping_country();
        
            $html = '<div class="woocommerce-checkout-custom-tax">'; // Mandatory wrapper html
        
            if( $total_tax > 0 && $shipping_country !== 'CH') {
                $html .= sprintf('<h3>%s</h3>', __('VAT / Custom Duties', 'woocommerce') );
            }
            return $html . '</div>';
        }
    
        /**
         * Output html content in checkout page
         *
         * @return void
         */   
        public function checkout_display_custom_taxes() {
            echo $this->output();
        }
    
        /**
         * Add the html content to be refreshed on checkout update Ajax event
         *
         * @return array
         */   
        public function update_checkout_custom_fragments( $fragments ){
            // We add the selector class of our wrapper div as array key
            $fragments['.woocommerce-checkout-custom-tax'] = $this->output();
        
            return $fragments;
        }
    }
    

    For testing purpose in the child theme’s functions.php file, I use additionally:

    add_action('woocommerce_checkout_init', function(){
        $CheckoutTax = new CheckoutTax();
    });
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.


    Related:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search