如何通过WC Session变量更新WooCommerce结算页配送费用?
问题
在WooCommerce结算页的账单详情区域添加了自定义按钮,期望点击按钮时更新订单预览表中的手动配送费用。使用测试值测试时,订单预览表并未同步更新该费用。
更新说明
已定义测试值并分配给配送标签,且能通过Ajax响应获取到更新后的值,但订单预览表中的配送费用仍未更新。相关代码如下:
PHP代码
<?php /* Plugin Name: Change Shipping Value Description: Customizations for WooCommerce. Version: 1.0 Author: udd_ish */ function enqueue_custom_scripts() { // Enqueue the custom JS file wp_enqueue_script('jquery'); wp_enqueue_script('distancecal-scripts', plugin_dir_url(__FILE__) . 'js/distancecal-scripts.js', array('jquery'), '1.0', true); wp_localize_script('distancecal-scripts', 'ajax_object', array('ajaxurl' => admin_url('admin-ajax.php'))); } add_action('wp_enqueue_scripts', 'enqueue_custom_scripts'); // Add a button after the billing form in WooCommerce checkout add_action('woocommerce_after_checkout_billing_form', 'add_custom_button_after_billing_form'); function add_custom_button_after_billing_form() { include_once(plugin_dir_path(__FILE__) . 'distancecal.php'); // Include PHP functions file ?> <div id="custom-button-wrapper"> <button type="button" id="custom-button" class="button alt">Calculate Delivery Fee</button> </div> <?php } function modify_shipping_cost($shipping_cost) { if ( isset($shipping_cost) ){ WC()->session->set('shipping_cost', $shipping_cost); return $shipping_cost; } } add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 ); function shipping_package_rates_filter_callback( $rates, $package ) { // The defined rate id $shipping_rate_id = 'flat_rate:4'; //Use your own shipping method id $tax_rate = 0.1; // 10% if( isset(WC()->session->get('shipping_cost') ) ) { $shipping_cost = WC()->session->get('shipping_cost' ); $rates = array( $shipping_rate_id => $rates[ $shipping_rate_id ] ); // Set rate cost $rates[$shipping_rate_id ]->cost = $shipping_cost; // Set taxes rate cost (if enabled) $taxes = array(); foreach ($rates[$shipping_rate_id ]->taxes as $key => $tax){ if( $rates[$shipping_rate_id ]->taxes[$key] > 0 ) $taxes[$key] = $shipping_cost * $tax_rate; } $rates[$shipping_rate_id ]->taxes = $taxes; } else { unset( $rates[ $shipping_rate_id ] ); } return $rates; } // AJAX handler for updating checkout add_action('wp_ajax_update_checkout', 'update_checkout_callback'); function update_checkout_callback() { $testvalue = 100; // Update the shipping cost with the new test value $newvalue = modify_shipping_cost($testvalue); wp_send_json(array('updated_fee' => $newvalue)); // Make sure to exit after handling the AJAX request wp_die(); } ?>
JS代码
jQuery(document).ready(function($) { // Add your custom JavaScript here $('#custom-button').on('click', function() { var streetAddress = $('#billing_address_1').val(); $.ajax({ type: 'POST', url: ajax_object.ajaxurl, data: { action: 'update_checkout', street_address: streetAddress }, success: function(response) { console.log(response); $('body').trigger('update_checkout', { update_shipping_method: true }); }, error: function(error) { // Handle AJAX error if needed console.error('AJAX error:', error); } }); }); });
解决方案
问题根源在于动作名冲突、费率缓存未清除以及未支持访客用户,以下是修复后的完整代码:
修改后的PHP代码
<?php /* Plugin Name: Change Shipping Value Description: Customizations for WooCommerce. Version: 1.0 Author: udd_ish */ function enqueue_custom_scripts() { wp_enqueue_script('jquery'); wp_enqueue_script('distancecal-scripts', plugin_dir_url(__FILE__) . 'js/distancecal-scripts.js', array('jquery'), '1.0', true); wp_localize_script('distancecal-scripts', 'ajax_object', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('distance_cal_nonce') // 添加安全验证 )); } add_action('wp_enqueue_scripts', 'enqueue_custom_scripts'); // 添加结算页按钮 add_action('woocommerce_after_checkout_billing_form', 'add_custom_button_after_billing_form'); function add_custom_button_after_billing_form() { include_once(plugin_dir_path(__FILE__) . 'distancecal.php'); ?> <div id="custom-button-wrapper"> <button type="button" id="custom-button" class="button alt">计算配送费</button> </div> <?php } // 更新会话中的运费并清除缓存 function modify_shipping_cost($shipping_cost) { if (isset($shipping_cost)){ WC()->session->set('shipping_cost', $shipping_cost); // 清除配送费率缓存,强制刷新 WC()->session->set('shipping_for_package_0', false); return $shipping_cost; } } // 过滤配送费率 add_filter('woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2); function shipping_package_rates_filter_callback($rates, $package) { $shipping_rate_id = 'flat_rate:4'; $tax_rate = 0.1; $shipping_cost = WC()->session->get('shipping_cost'); if (!empty($shipping_cost) && isset($rates[$shipping_rate_id])) { // 仅修改目标配送方式的费用,不重置所有选项 $rates[$shipping_rate_id]->cost = $shipping_cost; // 更新税费 $taxes = array(); foreach ($rates[$shipping_rate_id]->taxes as $key => $tax) { if ($tax > 0) { $taxes[$key] = $shipping_cost * $tax_rate; } } $rates[$shipping_rate_id]->taxes = $taxes; } elseif (empty($shipping_cost) && isset($rates[$shipping_rate_id])) { unset($rates[$shipping_rate_id]); } return $rates; } // 自定义AJAX处理函数,避免与内置动作冲突 add_action('wp_ajax_update_shipping_fee', 'update_shipping_fee_callback'); add_action('wp_ajax_nopriv_update_shipping_fee', 'update_shipping_fee_callback'); // 支持未登录用户 function update_shipping_fee_callback() { // 安全验证 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'distance_cal_nonce')) { wp_send_json_error('权限验证失败'); } $testvalue = 100; $newvalue = modify_shipping_cost($testvalue); wp_send_json_success(array('updated_fee' => $newvalue)); wp_die(); } ?>
修改后的JS代码
jQuery(document).ready(function($) { $('#custom-button').on('click', function() { var streetAddress = $('#billing_address_1').val(); $.ajax({ type: 'POST', url: ajax_object.ajaxurl, data: { action: 'update_shipping_fee', // 使用自定义动作名 street_address: streetAddress, nonce: ajax_object.nonce // 传递安全验证参数 }, success: function(response) { if (response.success) { console.log('更新后的配送费:', response.data.updated_fee); // 触发结算更新 $('body').trigger('update_checkout'); } else { console.error('更新失败:', response.data); } }, error: function(error) { console.error('AJAX请求错误:', error); } }); }); });
关键修复点
- 避免动作名冲突:将原
update_checkout动作名改为自定义的update_shipping_fee,防止覆盖WooCommerce内置逻辑 - 清除费率缓存:添加
WC()->session->set('shipping_for_package_0', false)强制清除配送费率缓存,确保新费用生效 - 支持访客用户:添加
wp_ajax_nopriv_前缀的动作钩子,让未登录用户也能使用功能 - 安全验证:加入Nonce验证,符合WordPress安全开发规范
- 优化费率处理:不再重置整个
$rates数组,仅修改目标配送方式的费用,避免影响其他配送选项
内容的提问来源于stack exchange,提问作者udd_ish
相关产品推荐
相关产品推荐

