php - 根据单选按钮更改 WooCommerce 结帐中的商品税率

标签 php jquery ajax wordpress woocommerce

在 WooCommerce 中,我使用插件 [WooCommerce checkout addon][1] 并且我在结账页面添加了一个由单选按钮(多选)组成的附加字段。当客户在该单选按钮字段上选择特定选项时,我想更改税率。
基于 Change Woocommerce cart items tax class based on chosen 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.
使用此代码,税费发生了变化,但我在管理员或电子邮件中没有关于客户 radio 选择的信息。
你有解决方案吗?

其他:
我想在付款前移动单选按钮。
但是当我替换它时:
// 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 ) {
它不再起作用了。 你能解释一下为什么吗?如何使它工作?

最佳答案

更新 2:让它工作要复杂得多,因为它还需要 Ajax 和更多的附加代码......
因此,以下内容将允许在结帐页面上更改购物车商品税类,具体取决于:

  • (可选)选择的支付网关(此处使用空数组禁用)。
  • 选择的单选按钮值(来自自定义单选按钮)。

  • 由于人们不使用您的 WooCommerce checkout Add-ons商业插件,下面的代码在结帐页面上显示了一些单选按钮。
    为了使代码更具动态性,我们从一个自定义函数开始,该函数将处理所有必需的设置:
    // 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>';
    }
    
    enter image description here

    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 文件中。测试和工作。

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

    在管理单一订单页面上:
    enter image description here

    关于php - 根据单选按钮更改 WooCommerce 结帐中的商品税率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63204952/

    相关文章:

    javascript - jQuery 自动完成与 Ajax 建议不返回

    javascript - 使用 php+mysql 和 jquery ajax post 填充三个后续选择列表

    php - Laravel Eloquent 与逗号分隔时间戳之间的关系?

    php - Magento 获取属性类型(例如下拉列表或文本)

    php - 链式选择菜单效果很好,但需要稍作调整

    jquery - 如何在响应式图像上使悬停状态背景为 100% 宽度

    javascript - 如何使用javascript/react获取两个日期之间的完整日期?

    javascript - JQuery 获取元素的值 : onfocus ="inputInlineHint(self);"

    php - TCPDF 只打印最后一行

    php和mysql不显示数据,不进入foreach循环