You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动