php - 根据单选按钮更改 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 ) {
它不再起作用了。你能解释一下为什么吗?如何让它发挥作用?
解决方案
更新 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 文件中。测试和工作。
在订单和电子邮件通知上显示的选项 (在收到订单的页面上)
在管理单一订单页面上:
推荐阅读
- python - 按列表顺序替换值
- python - lxml etree cleanup_namespaces 返回 None 而不是清理的树
- c# - 多对多关系,桥接表 - 如何插入重复的主键?
- python-3.x - Tkinter:当用户不滚动时自动滚动到底部
- node.js - 获取 Azure Blob(图像)并 POST 到外部 API
- c# - 上传 BLOB 时出现此错误“Google.Apis.Requests.RequestError Not Found [404]”的解释是什么?
- python - 这两种形式的相对导入是否完全相同?
- javascript - Asset Module Webpack 创建一个额外的文件夹
- javascript - React Map GL 不使用 create-react-app 渲染
- html - AngularJS:是否可以在表单中使用以下 URL?