You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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);
            }
        });
    });
});

关键修复点

  1. 避免动作名冲突:将原update_checkout动作名改为自定义的update_shipping_fee,防止覆盖WooCommerce内置逻辑
  2. 清除费率缓存:添加WC()->session->set('shipping_for_package_0', false)强制清除配送费率缓存,确保新费用生效
  3. 支持访客用户:添加wp_ajax_nopriv_前缀的动作钩子,让未登录用户也能使用功能
  4. 安全验证:加入Nonce验证,符合WordPress安全开发规范
  5. 优化费率处理:不再重置整个$rates数组,仅修改目标配送方式的费用,避免影响其他配送选项

内容的提问来源于stack exchange,提问作者udd_ish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:50:54