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

kev*_*kak 6 php ajax wordpress jquery woocommerce

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

基于根据所选付款方式答案代码更改 Woocommerce 购物车项目税级(更改特定付款方式的税率),我尝试自定义代码:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

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

$installation = WC()->session->get('wc_checkout_add_ons')
Run Code Online (Sandbox Code Playgroud)

没有得到很好的实施。我缺少什么?


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

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

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

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

但是,使用“WooCommerce checkout addon”插件,当选择单选按钮时,我可以在管理中的订单摘要和收到的电子邮件中看到所做的选择。

使用此代码,税费发生了变化,但我在管理或通过电子邮件中没有有关客户单选选择的信息。

你有解决办法吗?


还有一点:

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

但是当我更换这个时:

// Display radio buttons field (optional)
add_action( 'woocommerce_after_order_notes', 'installation_custom_radio_field' );
function installation_custom_radio_field( $checkout ) {
Run Code Online (Sandbox Code Playgroud)

经过

// Display radio buttons field (optional)
add_action( 'woocommerce_review_order_before_payment', 'installation_custom_radio_field' );
function installation_custom_radio_field( $checkout ) {
Run Code Online (Sandbox Code Playgroud)

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

Loi*_*tec 6

更新 2:使其工作要复杂得多,因为它还需要 Ajax 和更多附加代码\xe2\x80\xa6

\n

因此,以下内容将允许在结帐页面上更改购物车商品税级,具体取决于:

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

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

\n

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

\n
// Custom function that handle your settings\nfunction change_tax_class_settings(){\n    return array(\n        \'payment_ids\'   => array(), // (optional) Your targeted payment method Id(s) | Leave an empty array to disable.\n        \'tax_class\'     => \'Reduced rate\', // The desired tax rate\n        \'field_id\'      => \'additonal_services\', // the Field Id (from property name ="?????")\n        \'field_value\'   => \'no-dinstallation\', // The field targetted option key (value)\n\n        // The below lines are optional (used for the radio buttons field display)\n        \'field_type\'    => \'radio\', // Field type\n        \'field_title\'   =>  __(\'Additional services\', \'woocommerce\'),\n        \'field_default\' => \'basic-installation\', // The field targetted option key (value)\n        \'field_options\' => array(\n            \'basic-installation\' => __(\'Basic Installation\', \'woocommerce\'),\n            \'premium-installation\' => __(\'Premium Installation\', \'woocommerce\'),\n            \'no-dinstallation\' => __(\'No Installation\', \'woocommerce\'),\n        ),\n    );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

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

\n
// Display radio buttons field (optional)\nadd_action( \'woocommerce_review_order_before_payment\', \'installation_custom_radio_field\' );\nfunction installation_custom_radio_field() {\n    extract( change_tax_class_settings() ); // Load settings and convert them in variables\n\n    echo "<style>.$field_id-wrapper{padding:1em 1.41575em;background-color:#f5f5f5;margin-bottom:24px;}\n    .form-row.$field_id-$field_type span label{display:inline-block;margin:0 18px 0 6px;}\n    .$field_id-wrapper h3{font-weight:bold;}</style>";\n    echo \'<div class="\'.$field_id.\'-wrapper">\n    <h3>\'.$field_title.\'</h3>\';\n\n    // Get WC Session variable value\n    $value = WC()->session->get($field_id);\n\n    woocommerce_form_field( $field_id, array(\n        \'type\'     => $field_type,\n        \'label\'    => \'\',\n        \'class\'    => array(\'form-row-wide \' . $field_id . \'-\' . $field_type ),\n        \'options\'  => $field_options,\n        \'default\'  => $field_default,\n        \'required\' => true,\n    ), empty($value) ? WC()->checkout->get_value(\'_\'.$field_id) : $value );\n\n    echo \'</div>\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n
\n

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

\n
// jQuery code (client side) - Ajax sender\nadd_action(\'wp_footer\', \'installation_checkout_js_script\');\nfunction installation_checkout_js_script() {\n    if( is_checkout() && ! is_wc_endpoint_url() ) :\n    // Load settings and convert them in variables\n    extract( change_tax_class_settings() );\n\n    // jQuery Ajax code\n    ?>\n    <script type="text/javascript">\n    jQuery( function($){\n        if (typeof wc_checkout_params === \'undefined\')\n            return false;\n\n        var field = \'#<?php echo $field_id; ?>_field input\', fchecked = field+\':checked\';\n\n        // Function that sen the Ajax request\n        function sendAjaxRequest( value ) {\n            $.ajax({\n                type: \'POST\',\n                url: wc_checkout_params.ajax_url,\n                data: {\n                    \'action\': \'<?php echo $field_id; ?>\',\n                    \'value\': value\n                },\n                success: function (result) {\n                    $(document.body).trigger(\'update_checkout\'); // Refresh checkout\n                }\n            });\n        }\n\n        // On ready (DOM loaded)\n        sendAjaxRequest( $(fchecked).val() );\n\n        // On change event\n        $(document.body).on( \'change\', field, function(){\n            sendAjaxRequest( $(fchecked).val() );\n        });\n\n        // Refresh checkout on payment method change\n        $( \'form.checkout\' ).on(\'change\', \'input[name="payment_method"]\', function() {\n            $(document.body).trigger(\'update_checkout\'); // Refresh checkout\n        });\n    });\n    </script>\n    <?php\n    endif;\n}\n\n// The Wordpress Ajax PHP receiver\nadd_action( \'wp_ajax_additonal_services\', \'get_additonal_services\' );\nadd_action( \'wp_ajax_nopriv_additonal_services\', \'get_additonal_services\' );\nfunction get_additonal_services() {\n    if ( isset($_POST[\'value\']) ){\n        // Load settings and convert them in variables\n        extract( change_tax_class_settings() );\n\n        // Update session variable\n        WC()->session->set($field_id, esc_attr($_POST[\'value\']));\n\n        // Send back the data to javascript (json encoded)\n        echo $_POST[\'value\']; // optional\n        die();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
// Change the tax class conditionally\nadd_action( \'woocommerce_before_calculate_totals\', \'change_tax_class_conditionally\', 1000 );\nfunction change_tax_class_conditionally( $cart ) {\n    if ( is_admin() && ! defined( \'DOING_AJAX\' ) )\n        return;\n\n    if ( did_action( \'woocommerce_before_calculate_totals\' ) >= 2 )\n        return;\n\n    extract( change_tax_class_settings() ); // Load settings and convert them in variables\n\n    // Only for a specific defined payment methods (can be disabled in the settings, with an empty array)\n    if ( ! empty($payment_ids) && ! in_array( WC()->session->get(\'chosen_payment_method\'), $payment_ids ) )\n        return;\n\n    $choice = WC()->session->get($field_id);\n\n    // Loop through cart items\n    foreach( $cart->get_cart() as $cart_item ){\n        if( $choice === $field_value ) {\n            $cart_item[\'data\']->set_tax_class($tax_class);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
// Save custom field as order meta data\nadd_action( \'woocommerce_checkout_create_order\', \'save_additonal_services_as_order_meta\' );\nfunction save_additonal_services_as_order_meta( $order ) {\n    // Load settings and convert them in variables\n    extract( change_tax_class_settings() );\n\n    $choice = WC()->session->get($field_id);\n\n    if( ! empty( $choice ) ) {\n        $order->update_meta_data( \'_\'.$field_id, $choice );\n    }\n}\n\n// Display additonal services choice before payment method everywhere (orders and emails)\nadd_filter( \'woocommerce_get_order_item_totals\', \'display_additonal_services_on_order_item_totals\', 1000, 3 );\nfunction display_additonal_services_on_order_item_totals( $total_rows, $order, $tax_display ){\n    // Load settings and convert them in variables\n    extract( change_tax_class_settings() );\n\n    $choice = $order->get_meta( \'_\'.$field_id ); // Get additonal services choice\n\n    if( ! empty($choice) ) {\n        $new_total_rows = [];\n\n        // Loop through order total rows\n        foreach( $total_rows as $key => $values ) {\n            // Inserting the pickp store under shipping method\n            if( $key === \'payment_method\' ) {\n                $new_total_rows[$field_id] = array(\n                    \'label\' => $field_title,\n                    \'value\' => esc_html($field_options[$choice]),\n                );\n            }\n            $new_total_rows[$key] = $values;\n        }\n        return $new_total_rows;\n    }\n    return $total_rows;\n}\n\n\n// Display additonal services choice in Admin order pages\nadd_action( \'woocommerce_admin_order_data_after_billing_address\', \'admin_order_display_additonal_services\', 1000 );\nfunction admin_order_display_additonal_services( $order ) {\n    // Load settings and convert them in variables\n    extract( change_tax_class_settings() );\n\n    $choice = $order->get_meta( \'_\'.$field_id ); // Get additonal services choice\n\n    if( ! empty($choice) ) {\n        // Display\n        echo \'<p><strong>\' . $field_title . \'</strong>: \' . $field_options[$choice] . \'</p>\';\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

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

\n

在此输入图像描述

\n
\n

在管理单一订单页面上:

\n

在此输入图像描述

\n