本文介绍了根据单选按钮更改 WooCommerce 结帐中的商品税率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 WooCommerce 中,我使用插件 [WooCommerce checkout addon][1] 并且我在结账页面添加了一个由单选按钮(多选)组成的附加字段.当客户在该单选按钮字段上选择特定选项时,我想更改税率.

基于


Ajax 部分(jQuery Ajax 和 PHP Admin Wordpress Ajax 发送方和接收方 + WC 会话变量):

//jQuery 代码(客户端)- Ajax 发送方add_action('wp_footer', 'installation_checkout_js_script');函数 installation_checkout_js_script() {if( is_checkout() && ! is_wc_endpoint_url() ) ://加载设置并将它们转换为变量提取(change_tax_class_settings());//jQuery Ajax 代码?><script type="text/javascript">jQuery(函数($){if (typeof wc_checkout_params === '未定义')返回假;var field = '#<?php echo $field_id;?>_field input', fchecked = field+':checked';//发送 Ajax 请求的函数函数 sendAjaxRequest( 值 ) {$.ajax({类型:'POST',网址:wc_checkout_params.ajax_url,数据: {'action': '<?php echo $field_id;?>',价值":价值},成功:功能(结果){$(document.body).trigger('update_checkout');//刷新结帐}});}//准备好(DOM 加载)sendAjaxRequest( $(fchecked).val() );//改变事件$(document.body).on('change', field, function(){sendAjaxRequest( $(fchecked).val() );});//在付款方式更改时刷新结帐$( 'form.checkout' ).on('change', 'input[name="payment_method"]', function() {$(document.body).trigger('update_checkout');//刷新结帐});});<?php万一;}//Wordpress Ajax PHP 接收器add_action('wp_ajax_additonal_services', 'get_additonal_services');add_action('wp_ajax_nopriv_additonal_services', 'get_additonal_services');函数 get_additonal_services() {if ( isset($_POST['value']) ){//加载设置并将它们转换为变量提取(change_tax_class_settings());//更新会话变量WC()->session->set($field_id, esc_attr($_POST['value']));//将数据发送回 javascript(json 编码)echo $_POST['value'];//可选的死();}}

然后根据客户的选择有条件地更改购物车项目税类的功能:

//有条件地改变税种add_action('woocommerce_before_calculate_totals', 'change_tax_class_conditionally', 1000);函数 change_tax_class_conditionally( $cart ) {if ( is_admin() && !defined( 'DOING_AJAX' ) )返回;if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )返回;提取(change_tax_class_settings());//加载设置并将它们转换为变量//仅针对特定定义的付款方式(可在设置中禁用,数组为空)if ( !empty($payment_ids) && ! in_array( WC()->session->get('chosen_payment_method'), $payment_ids ) )返回;$choice = WC()->session->get($field_id);//遍历购物车项目foreach( $cart->get_cart() as $cart_item ){if( $choice === $field_value ) {$cart_item['data']->set_tax_class($tax_class);}}}

附加:将客户选择保存到订单中,并在前端、管理员和电子邮件通知的订单上随处显示:

//将自定义字段保存为订单元数据add_action('woocommerce_checkout_create_order', 'save_additonal_services_as_order_meta');函数 save_additonal_services_as_order_meta( $order ) {//加载设置并将它们转换为变量提取(change_tax_class_settings());$choice = WC()->session->get($field_id);如果(!空($选择)){$order->update_meta_data('_'.$field_id, $choice);}}//在任何地方(订单和电子邮件)付款方式之前显示附加服务选择add_filter( 'woocommerce_get_order_item_totals', 'display_additonal_services_on_order_item_totals', 1000, 3 );函数 display_additonal_services_on_order_item_totals( $total_rows, $order, $tax_display ){//加载设置并将它们转换为变量提取(change_tax_class_settings());$choice = $order->get_meta('_'.$field_id);//获取附加服务选择如果(!空($选择)){$new_total_rows = [];//遍历订单总行数foreach( $total_rows as $key => $values ) {//在送货方式下插入取货商店if( $key === 'payment_method' ) {$new_total_rows[$field_id] = 数组('标签' =>$field_title,'价值' =>esc_html($field_options[$choice]),);}$new_total_rows[$key] = $values;}返回 $new_total_rows;}返回 $total_rows;}//在管理订单页面中显示附加服务选项add_action('woocommerce_admin_order_data_after_billing_address', 'admin_order_display_additonal_services', 1000);功能 admin_order_display_additonal_services( $order ) {//加载设置并将它们转换为变量提取(change_tax_class_settings());$choice = $order->get_meta('_'.$field_id);//获取附加服务选择如果(!空($选择)){//展示回声'<p><strong>'.$field_title .'</strong>:'.$field_options[$choice] .'</p>';}}

所有代码都在活动子主题(或主题)的functions.php 文件中.经测试有效.


在订单和电子邮件通知上显示的选项 (在订单接收页面上)


在管理单一订单页面上:

In WooCommerce I use the plugin [WooCommerce checkout addon][1] and I have added to checkout page an additional field made of radio buttons (multiple choice). I would like to change the tax rate when customer selects a specific choice on that radio buttons field.

Based on Change Woocommerce cart items tax class based on chosen payment method answer code that change tax rate for specific payment method, I have tried to customized the code:

// Change Tax
add_action( 'woocommerce_before_calculate_totals', 'change_tax_class_based_on_radio_choice', 10, 1 );
function change_tax_class_based_on_radio_choice( $cart ) {
    $installation = WC()->session->get('wc_checkout_add_ons') ; // This code must be change
    $value = 'pas-dinstallation' ; // the value of the radio button "woocommerce checkout addon"
    $value2 = 'bacs' ; // value of payement methode
    $payement_methode = WC()->session->get('chosen_payment_method') ;
    //if ( $payement_methode !== $value2 ) //this one is ok for change tax if payement methode is bank transfert
        //return;
    if ( $installation !== $value ) // here i try to set the same condition with one of radio button "woocommerce checkout addon"


    return;

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

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach( $cart->get_cart() as $cart_item ){
        // We set "Zero rate" tax class
        $cart_item['data']->set_tax_class("Reduced rate");
    }
}

add_action('wp_footer', 'option_trigger_update_checkout');
function option_trigger_update_checkout() {
    if( is_checkout() && ! is_wc_endpoint_url() ) :
    ?>
    <script type="text/javascript">
        jQuery(function($){
            $( 'form.checkout' ).on('change', 'input[type="radio"]', function() {
                $(document.body).trigger('update_checkout');
            });
        });
    </script>
    <?php
    endif;
}

But I don't know how to make it work for my case yet. I understand that:

$installation = WC()->session->get('wc_checkout_add_ons')

is not well implemented. What I am missing?


Update - addition (related to the answer below):

As I don't need to payment method restrictions, I have removed this related line:

// Only for a specific defined payment method
if ( ! in_array( WC()->session->get('chosen_payment_method'), $payment_ids ) )
    return;

Then code works well indeed now as I expected.

However, with the "WooCommerce checkout addon" plugin, when a radio button is selected, I can see in administration in the summary of the order and in the email received, what choice has been made.

with this code, the tax is changed, but I have no information on the customer's radio choice in admin or by email.

Have you solution?


Something else:

I want to move the radio buttons before payment.

But when I replace this:

// Display radio buttons field (optional)
add_action( 'woocommerce_after_order_notes', 'installation_custom_radio_field' );
function installation_custom_radio_field( $checkout ) {

by

// Display radio buttons field (optional)
add_action( 'woocommerce_review_order_before_payment', 'installation_custom_radio_field' );
function installation_custom_radio_field( $checkout ) {

It doesn't work anymore. Can you explain why? How to make it work?

解决方案

Update 2: It's much more complicated to make it work as it requires also Ajax and much more additional code…

So the following will allow to change cart items tax class on checkout page, depending on:

  • (optional) The chosen payment gateway (Here it's disabled with an empty array).
  • The chosen radio button value (from custom radio buttons).

As people don't use your WooCommerce checkout Add-ons commercial plugin, the code below displays some radio buttons on checkout page.

To make the code more dynamic, we start with a custom function that will handle all required settings:

// Custom function that handle your settings
function change_tax_class_settings(){
    return array(
        'payment_ids'   => array(), // (optional) Your targeted payment method Id(s) | Leave an empty array to disable.
        'tax_class'     => 'Reduced rate', // The desired tax rate
        'field_id'      => 'additonal_services', // the Field Id (from property name ="?????")
        'field_value'   => 'no-dinstallation', // The field targetted option key (value)

        // The below lines are optional (used for the radio buttons field display)
        'field_type'    => 'radio', // Field type
        'field_title'   =>  __('Additional services', 'woocommerce'),
        'field_default' => 'basic-installation', // The field targetted option key (value)
        'field_options' => array(
            'basic-installation' => __('Basic Installation', 'woocommerce'),
            'premium-installation' => __('Premium Installation', 'woocommerce'),
            'no-dinstallation' => __('No Installation', 'woocommerce'),
        ),
    );
}

Now we can load that settings on any function where it's required.


Then the radio buttons displayed before payment methods checkout section:

// Display radio buttons field (optional)
add_action( 'woocommerce_review_order_before_payment', 'installation_custom_radio_field' );
function installation_custom_radio_field() {
    extract( change_tax_class_settings() ); // Load settings and convert them in variables

    echo "<style>.$field_id-wrapper{padding:1em 1.41575em;background-color:#f5f5f5;margin-bottom:24px;}
    .form-row.$field_id-$field_type span label{display:inline-block;margin:0 18px 0 6px;}
    .$field_id-wrapper h3{font-weight:bold;}</style>";
    echo '<div class="'.$field_id.'-wrapper">
    <h3>'.$field_title.'</h3>';

    // Get WC Session variable value
    $value = WC()->session->get($field_id);

    woocommerce_form_field( $field_id, array(
        'type'     => $field_type,
        'label'    => '',
        'class'    => array('form-row-wide ' . $field_id . '-' . $field_type ),
        'options'  => $field_options,
        'default'  => $field_default,
        'required' => true,
    ), empty($value) ? WC()->checkout->get_value('_'.$field_id) : $value );

    echo '</div>';
}

The Ajax Part (jQuery Ajax and PHP Admin Wordpress Ajax sender and receiver + WC Session variable):

// jQuery code (client side) - Ajax sender
add_action('wp_footer', 'installation_checkout_js_script');
function installation_checkout_js_script() {
    if( is_checkout() && ! is_wc_endpoint_url() ) :
    // Load settings and convert them in variables
    extract( change_tax_class_settings() );

    // jQuery Ajax code
    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof wc_checkout_params === 'undefined')
            return false;

        var field = '#<?php echo $field_id; ?>_field input', fchecked = field+':checked';

        // Function that sen the Ajax request
        function sendAjaxRequest( value ) {
            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': '<?php echo $field_id; ?>',
                    'value': value
                },
                success: function (result) {
                    $(document.body).trigger('update_checkout'); // Refresh checkout
                }
            });
        }

        // On ready (DOM loaded)
        sendAjaxRequest( $(fchecked).val() );

        // On change event
        $(document.body).on( 'change', field, function(){
            sendAjaxRequest( $(fchecked).val() );
        });

        // Refresh checkout on payment method change
        $( 'form.checkout' ).on('change', 'input[name="payment_method"]', function() {
            $(document.body).trigger('update_checkout'); // Refresh checkout
        });
    });
    </script>
    <?php
    endif;
}

// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_additonal_services', 'get_additonal_services' );
add_action( 'wp_ajax_nopriv_additonal_services', 'get_additonal_services' );
function get_additonal_services() {
    if ( isset($_POST['value']) ){
        // Load settings and convert them in variables
        extract( change_tax_class_settings() );

        // Update session variable
        WC()->session->set($field_id, esc_attr($_POST['value']));

        // Send back the data to javascript (json encoded)
        echo $_POST['value']; // optional
        die();
    }
}

Then the function that change cart item tax class conditionally depending on customer choices:

// Change the tax class conditionally
add_action( 'woocommerce_before_calculate_totals', 'change_tax_class_conditionally', 1000 );
function change_tax_class_conditionally( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    extract( change_tax_class_settings() ); // Load settings and convert them in variables

    // Only for a specific defined payment methods (can be disabled in the settings, with an empty array)
    if ( ! empty($payment_ids) && ! in_array( WC()->session->get('chosen_payment_method'), $payment_ids ) )
        return;

    $choice = WC()->session->get($field_id);

    // Loop through cart items
    foreach( $cart->get_cart() as $cart_item ){
        if( $choice === $field_value ) {
            $cart_item['data']->set_tax_class($tax_class);
        }
    }
}

Addition: Saving the customer choice to the order and displaying that everywhere on orders in front end, admin and on email notifications:

// Save custom field as order meta data
add_action( 'woocommerce_checkout_create_order', 'save_additonal_services_as_order_meta' );
function save_additonal_services_as_order_meta( $order ) {
    // Load settings and convert them in variables
    extract( change_tax_class_settings() );

    $choice = WC()->session->get($field_id);

    if( ! empty( $choice ) ) {
        $order->update_meta_data( '_'.$field_id, $choice );
    }
}

// Display additonal services choice before payment method everywhere (orders and emails)
add_filter( 'woocommerce_get_order_item_totals', 'display_additonal_services_on_order_item_totals', 1000, 3 );
function display_additonal_services_on_order_item_totals( $total_rows, $order, $tax_display ){
    // Load settings and convert them in variables
    extract( change_tax_class_settings() );

    $choice = $order->get_meta( '_'.$field_id ); // Get additonal services choice

    if( ! empty($choice) ) {
        $new_total_rows = [];

        // Loop through order total rows
        foreach( $total_rows as $key => $values ) {
            // Inserting the pickp store under shipping method
            if( $key === 'payment_method' ) {
                $new_total_rows[$field_id] = array(
                    'label' => $field_title,
                    'value' => esc_html($field_options[$choice]),
                );
            }
            $new_total_rows[$key] = $values;
        }
        return $new_total_rows;
    }
    return $total_rows;
}


// Display additonal services choice in Admin order pages
add_action( 'woocommerce_admin_order_data_after_billing_address', 'admin_order_display_additonal_services', 1000 );
function admin_order_display_additonal_services( $order ) {
    // Load settings and convert them in variables
    extract( change_tax_class_settings() );

    $choice = $order->get_meta( '_'.$field_id ); // Get additonal services choice

    if( ! empty($choice) ) {
        // Display
        echo '<p><strong>' . $field_title . '</strong>: ' . $field_options[$choice] . '</p>';
    }
}

All code goes on functions.php file of your active child theme (or theme). Tested and works.


Displayed choice on Orders and Email notifications (here on Order received page)


On Admin Single Orders pages:

这篇关于根据单选按钮更改 WooCommerce 结帐中的商品税率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 00:17