首页 > 解决方案 > 根据单选按钮更改 WooCommerce 结帐中的项目税率

问题描述

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

基于Change Woocommerce cart items tax class based on selected payment method answer code that change tax rate for specific payment method,我尝试自定义代码:

// 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;
}

但我不知道如何使它适用于我的情况。我明白那个:

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

没有很好地执行。我错过了什么?


更新 - 添加(与下面的答案相关)

由于我不需要付款方式限制,因此我删除了此相关行:

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

然后代码现在确实像我预期的那样运行良好。

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.

使用此代码,税收会发生变化,但我没有关于客户在管理员或电子邮件中选择的收音机的信息。

你有解决方案吗?


别的东西:

我想在付款前移动单选按钮。

但是当我替换这个时:

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

经过

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

它不再起作用了。你能解释一下为什么吗?如何让它发挥作用?

标签: phpjqueryajaxwordpresswoocommerce

解决方案


更新 2:让它工作要复杂得多,因为它还需要 Ajax 和更多额外的代码......</p>

因此,以下将允许在结帐页面上更改购物车项目税类,具体取决于:

  • (可选)选择的支付网关(这里它被一个空数组禁用)。
  • 选择的单选按钮值(来自自定义单选按钮)。

由于人们不使用您的WooCommerce 结帐附加组件商业插件,因此下面的代码在结帐页面上显示了一些单选按钮。

为了使代码更加动态,我们从一个自定义函数开始,它将处理所有必需的设置:

// 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'),
        ),
    );
}

现在我们可以在需要的任何功能上加载该设置。


然后在付款方式结帐部分之前显示的单选按钮:

// 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>';
}

在此处输入图像描述


Ajax 部分(jQuery Ajax 和 PHP Admin Wordpress Ajax 发送者和接收者 + WC Session 变量)

// 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();
    }
}

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

// 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);
        }
    }
}

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

// 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>';
    }
}

所有代码都在您的活动子主题(或主题)的functions.php 文件中。测试和工作。


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

在此处输入图像描述


在管理单一订单页面上:

在此处输入图像描述


推荐阅读