WooCommerce 3.3中基于Google Map API的结账动态费用计算问题
适配最新版WooCommerce的动态区域差异费用方案
嘿,我懂你遇到的麻烦——之前在WooCommerce 3.1.2版本跑得好好的动态费用代码,升级到最新版就不管用了对吧?这很正常,毕竟WooCommerce后续版本对结账流程、AJAX机制和钩子都做了不少优化调整。咱们来重构一下代码,完美适配新版,实现「客户结账选的billing_area和卖家资料里的billing_city不一致时添加动态费用」的需求。
第一步:前端监听下拉框变化并发送AJAX请求
新版WooCommerce的结账表单事件绑定逻辑有变化,咱们用更稳妥的方式监听billing_area下拉框的变化,把选中值传给后端:
jQuery(document).ready(function($) { // 监听billing_area下拉框的变化事件 $(document.body).on('change', '#billing_area', function() { var selectedArea = $(this).val(); // 适配购物车和直接结账场景,获取当前关联产品ID var productId = $('input[name="add-to-cart"]').val() || Object.values(wc_cart_params.cart_contents)[0].product_id; // 发送AJAX请求到后端 $.ajax({ url: wc_cart_params.ajax_url, type: 'POST', data: { action: 'check_area_fee', security: wc_cart_params.cart_hash, // 用WooCommerce自带的安全验证 selected_area: selectedArea, product_id: productId }, success: function(response) { // 触发购物车更新,让费用实时生效 $(document.body).trigger('update_checkout'); } }); }); });
第二步:后端处理逻辑,对比区域并添加动态费用
咱们用WooCommerce官方推荐的钩子来处理费用计算,同时适配新版的用户数据获取方式:
// 注册AJAX动作,处理前端的区域验证请求 add_action('wp_ajax_check_area_fee', 'check_area_and_add_fee'); add_action('wp_ajax_nopriv_check_area_fee', 'check_area_and_add_fee'); function check_area_and_add_fee() { // 安全验证,防止非法请求 if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'wc-cart')) { wp_send_json_error('Invalid security token'); } // 获取前端传过来的参数并做安全处理 $selected_area = sanitize_text_field($_POST['selected_area']); $product_id = intval($_POST['product_id']); // 获取当前产品的卖家(作者)ID $seller_id = get_post_field('post_author', $product_id); if (!$seller_id) { wp_send_json_success(); exit; } // 获取卖家资料里的billing_city $seller_billing_city = get_user_meta($seller_id, 'billing_city', true); // 对比区域,不一致则添加动态费用 if ($selected_area !== $seller_billing_city && !empty($selected_area) && !empty($seller_billing_city)) { // 这里可以自定义费用名称和金额,第三个参数为true表示费用含税 WC()->cart->add_fee('跨区域配送费', 15.00, true, 'standard'); } else { // 如果区域一致,移除之前添加的费用(避免缓存残留问题) foreach (WC()->cart->get_fees() as $key => $fee) { if ($fee->name === '跨区域配送费') { unset(WC()->cart->fees[$key]); } } } wp_send_json_success(); exit; } // 结账页面兜底逻辑,确保AJAX失效时费用仍能正确计算 add_action('woocommerce_cart_calculate_fees', 'calculate_area_fee_on_checkout'); function calculate_area_fee_on_checkout() { if (is_checkout() && !is_wc_endpoint_url()) { $selected_area = isset($_POST['billing_area']) ? sanitize_text_field($_POST['billing_area']) : WC()->customer->get_billing_area(); // 获取购物车中第一个产品的卖家ID(若有多卖家场景,可根据需求调整为遍历所有产品) $cart_items = WC()->cart->get_cart(); if (!empty($cart_items)) { $first_item = reset($cart_items); $seller_id = get_post_field('post_author', $first_item['product_id']); $seller_billing_city = get_user_meta($seller_id, 'billing_city', true); if ($selected_area !== $seller_billing_city && !empty($selected_area) && !empty($seller_billing_city)) { WC()->cart->add_fee('跨区域配送费', 15.00, true, 'standard'); } } } }
关键适配说明
- 前端用
$(document.body).on('change')事件委托,避免新版WooCommerce动态加载结账表单导致的事件绑定失效; - 后端采用WooCommerce自带的
wc_cart_params安全验证,替代旧版自定义nonce,更符合新版规范; - 添加
woocommerce_cart_calculate_fees钩子作为兜底,确保AJAX请求异常时,结账页面仍能正确计算费用; - 新增费用移除逻辑,避免用户切换回相同区域后费用残留的问题。
你可以把PHP代码放到主题的functions.php文件里,或者封装成一个自定义插件;jQuery代码可以放到主题的js目录下的自定义脚本文件中,再通过wp_enqueue_script方法加载到结账页面。
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

