WP WooCommerce:从结账下拉菜单获取国家用于钩子及运费API问题
解决WooCommerce中获取默认国家及切换时重新请求运费的问题
我完全懂你现在的困境——已经能通过硬编码参数调用第三方运费API,但卡在了两个关键点:拿不到默认的英国国家值,还有用户切换国家时没法自动重新请求运费,而且试了woocommerce_shipping_fields钩子也没效果。下面给你几个实用的解决方案:
1. 轻松获取默认国家
WooCommerce的默认国家其实存在站点选项里,根本不用绕woocommerce_shipping_fields这个钩子,直接用get_option()就能拿到:
// 获取站点默认配送国家,格式一般是「国家代码:州代码」,比如英国是GB $default_country = get_option('woocommerce_default_country'); // 拆分出纯国家代码 list($country_code, $state) = explode(':', $default_country); // 现在$country_code就是你要的GB啦
如果是要获取当前用户的默认配送国家(比如登录用户自己设置的地址),可以用WC_Customer对象,它会自动 fallback 到站点默认:
$customer = new WC_Customer(); $user_default_country = $customer->get_shipping_country(); // 如果用户没设置过,就用站点默认的国家代码 if(empty($user_default_country)){ $user_default_country = $country_code; }
2. 用户切换国家时自动重新请求运费
当用户在结算页切换国家时,WooCommerce会触发前端的变化事件,咱们可以用JS监听这个动作,然后发起AJAX请求调用第三方API更新运费:
前端JS代码(放到主题的js文件里)
jQuery(document).ready(function($){ // 监听结算页的国家选择框变化(配送/账单地址的国家都监听) $('body').on('change', '#shipping_country, #billing_country', function(){ // 拿到选中的国家代码 const selectedCountry = $(this).val(); // 获取购物车总重量(WooCommerce自带的全局参数) const cartWeight = wc_cart_params.cart_weight; // 发起AJAX请求到后端 $.ajax({ url: wc_cart_params.ajax_url, type: 'POST', data: { action: 'fetch_shipping_via_api', // 后端钩子的动作名 country: selectedCountry, weight: cartWeight, service: 'standard' // 这里可以设置默认服务类型,或者让用户选择 }, success: function(response){ if(response.success){ // 把返回的运费更新到页面上,根据你的页面结构调整选择器 $('.woocommerce-shipping-methods .shipping-price').text(response.data.formatted_cost); } else { console.error('获取运费失败:', response.data); } }, error: function(){ alert('抱歉,获取运费时出现错误,请稍后重试'); } }); }); });
后端PHP AJAX处理代码(放到主题functions.php或自定义插件里)
// 注册AJAX钩子,登录/未登录用户都能访问 add_action('wp_ajax_fetch_shipping_via_api', 'fetch_shipping_via_api_callback'); add_action('wp_ajax_nopriv_fetch_shipping_via_api', 'fetch_shipping_via_api_callback'); function fetch_shipping_via_api_callback(){ // 验证请求合法性(可选但推荐,防止恶意请求) check_ajax_referer('woocommerce-cart', 'security'); // 接收并清洗前端传过来的参数 $country = isset($_POST['country']) ? sanitize_text_field($_POST['country']) : ''; $weight = isset($_POST['weight']) ? floatval($_POST['weight']) : 0; $service = isset($_POST['service']) ? sanitize_text_field($_POST['service']) : 'standard'; // 调用第三方API $api_endpoint = 'https://你的第三方API地址.com/get-shipping-rates'; $api_request = wp_remote_post($api_endpoint, array( 'body' => array( 'country' => $country, 'weight' => $weight, 'service' => $service ), 'timeout' => 15, // 设置超时时间,避免卡页面 'sslverify' => true // 如果API是HTTPS,建议开启验证 )); // 处理API请求错误 if(is_wp_error($api_request)){ wp_send_json_error('API请求失败:' . $api_request->get_error_message()); } // 解析API返回的数据 $api_response = json_decode(wp_remote_retrieve_body($api_request), true); // 提取运费并返回给前端 if(isset($api_response['rate'])){ // 用WooCommerce的价格格式化函数,自动适配站点货币设置 $formatted_cost = wc_price($api_response['rate']); wp_send_json_success(array('formatted_cost' => $formatted_cost)); } else { wp_send_json_error('未获取到有效运费数据'); } }
3. 关于woocommerce_shipping_fields钩子的小补充
这个钩子主要是用来修改配送字段的属性(比如字段标签、是否必填、默认显示值等),不是用来获取当前选中或默认国家的。如果你是想给配送国家字段设置默认值,倒是可以用它,但获取值还是用前面提到的方法更直接。
内容的提问来源于stack exchange,提问作者BadAddy




