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

WooCommerce购物车添加自定义计算价格遇阻,求技术解决

问题排查与解决方案

先梳理下你代码里的几个核心问题,这些是导致自定义费用无法正确计入总计的关键:

1. 语法错误导致代码整体失效

你的代码最后一行是未闭合的add_action('woocommerce_before_cart_item_quantity_z,这会让PHP解析失败,后续所有钩子逻辑都无法执行,得先把这个残缺代码删掉或者补全。

2. 原生Session的使用冲突

WooCommerce自带一套会话管理机制,直接用PHP原生session_start()和$_SESSION很容易和WooCommerce的session冲突,导致自定义费用数据丢失。应该改用WooCommerce官方推荐的WC()->session来存储临时数据。

3. 费用计算方式不合理

你用woocommerce_before_calculate_totals修改产品本身的价格,不仅会让用户混淆原始价格和额外费用的区分,还可能在WooCommerce的一些流程中被重置。正确做法是用woocommerce_cart_calculate_fees钩子单独添加自定义费用,这样能在总计前显示独立的费用行,也更贴合WooCommerce的费用计算逻辑。

4. woocommerce_cart_calculate_fees钩子未正确取数

你之前尝试这个钩子但显示$0,大概率是因为没从购物车项中正确读取到自定义费用值,或者数据在传递过程中丢失了。


修复后的完整代码

<?php
/**
 * Check if WooCommerce is active
 */
if ( class_exists( 'WooCommerce' ) ) {

    // Enqueue styles and scripts
    add_action('woocommerce_single_product_summary','extra_enqueue_scripts');
    function extra_enqueue_scripts() {
        wp_enqueue_style('custom_style', plugins_url('/assets/css/custom_style.css', __FILE__));
        wp_register_script( 'item_add', plugins_url('/assets/js/item_add.js', __FILE__), array('jquery'), false, true );
        wp_enqueue_script('item_add');
        wp_localize_script( 'item_add', 'wdm_object', array( 
            'ajax_file_path' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('extra_custom_nonce') // 添加nonce验证,提升安全性
        ));
    }

    // Add custom field before add-to-cart button
    add_action( 'woocommerce_before_add_to_cart_button', 'extra_add_custom_field', 0 );
    function extra_add_custom_field() {
        $currency = get_woocommerce_currency_symbol();
        echo "<div class='custom-text text'><p>Extra Charge ($currency):</p> 
              <input type='text' name='custom_price' value='' placeholder='e.g. 10' title='Custom Text' class='custom_price text_custom text'>
              </div>";
    }

    // AJAX callback to save custom fee to WC session
    add_action('wp_ajax_extra_add_user_custom_data_options_callback', 'extra_add_user_custom_data_options_callback');
    add_action('wp_ajax_nopriv_extra_add_user_custom_data_options_callback', 'extra_add_user_custom_data_options_callback');
    function extra_add_user_custom_data_options_callback() {
        // 验证nonce,防止CSRF攻击
        if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'extra_custom_nonce')) {
            wp_send_json_error('Invalid nonce');
        }

        if (isset($_POST['custom_price'])) {
            $custom_fee = (float)sanitize_text_field($_POST['custom_price']);
            // 使用WooCommerce session存储数据
            WC()->session->set('user_custom_data', $custom_fee);
            wp_send_json_success();
        }
        wp_send_json_error('No custom fee provided');
    }

    // Add custom fee data to cart item
    add_filter('woocommerce_add_cart_item_data','extra_add_custom_field_data', 10, 2);
    function extra_add_custom_field_data($cart_item_data, $product_id) {
        $custom_fee = WC()->session->get('user_custom_data');
        
        if (!empty($custom_fee)) {
            $cart_item_data['user_custom_data_value'] = $custom_fee;
            // 添加唯一键,确保每次添加都生成新的购物车项(如需支持修改数量保留费用可调整)
            $cart_item_data['unique_key'] = md5(microtime().rand());
            // 清除session中的数据,避免重复添加
            WC()->session->__unset('user_custom_data');
        }
        
        return $cart_item_data;
    }

    // Retrieve custom fee data from session for cart items
    add_filter('woocommerce_get_cart_item_from_session', 'extra_get_cart_items_from_session', 10, 3 );
    function extra_get_cart_items_from_session($item, $values, $key) {
        if (isset($values['user_custom_data_value'])) {
            $item['user_custom_data_value'] = $values['user_custom_data_value'];
        }
        return $item;
    }

    // Display custom fee in cart/checkout item details
    add_filter('woocommerce_cart_item_name', 'extra_display_custom_fee_in_cart', 10, 3);
    add_filter('woocommerce_checkout_cart_item_quantity', 'extra_display_custom_fee_in_cart', 10, 3);
    function extra_display_custom_fee_in_cart($display_text, $cart_item, $cart_item_key) {
        if (isset($cart_item['user_custom_data_value']) && $cart_item['user_custom_data_value'] > 0) {
            $currency = get_woocommerce_currency_symbol();
            $custom_fee = $cart_item['user_custom_data_value'];
            $display_text .= "<br><small>" . __('Extra Charge:', 'woocommerce') . " {$currency}{$custom_fee}</small>";
        }
        return $display_text;
    }

    // Calculate and add custom fee to cart totals
    add_action('woocommerce_cart_calculate_fees', 'extra_add_custom_fee_to_totals');
    function extra_add_custom_fee_to_totals($cart) {
        if (is_admin() && !defined('DOING_AJAX')) return;

        $total_custom_fee = 0;
        // 遍历所有购物车项,累加自定义费用
        foreach ($cart->get_cart() as $cart_item) {
            if (isset($cart_item['user_custom_data_value'])) {
                $total_custom_fee += $cart_item['user_custom_data_value'];
            }
        }

        if ($total_custom_fee > 0) {
            // 添加自定义费用到总计,第一个参数是费用名称,第二个是金额
            $cart->add_fee(__('Extra Charge', 'woocommerce'), $total_custom_fee);
        }
    }

    // Remove custom fee data when cart item is removed
    add_action('woocommerce_cart_item_removed', 'extra_remove_custom_fee_on_item_remove', 10, 2);
    function extra_remove_custom_fee_on_item_remove($cart_item_key, $cart) {
        // 费用实时计算,移除项后下一次计算会自动扣除,无需额外操作
    }
}

关键修改说明

  • 替换原生Session为WC Session:用WC()->session->set()和WC()->session->get()存储临时数据,避免冲突,保证数据可靠传递。
  • 添加Nonce验证:在AJAX请求中加入nonce,防止恶意请求,提升安全性。
  • 改用woocommerce_cart_calculate_fees钩子:这个钩子专门用于添加自定义费用,会在购物车总计前显示独立的“额外费用”行,金额正确计入总计。
  • 优化购物车项数据存储:给带自定义费用的购物车项添加唯一键,确保每次添加都是独立项(如需支持修改数量保留费用可按需调整)。
  • 修复显示逻辑:用woocommerce_cart_item_name钩子在商品名称下方显示额外费用,让用户清晰看到费用构成。

前端JS代码调整(item_add.js)

记得在AJAX请求中加入nonce参数:

jQuery(document).ready(function($) {
    $('form.cart').on('submit', function(e) {
        var customPrice = $('.custom_price').val();
        if (customPrice) {
            $.ajax({
                url: wdm_object.ajax_file_path,
                type: 'POST',
                data: {
                    action: 'extra_add_user_custom_data_options_callback',
                    custom_price: customPrice,
                    nonce: wdm_object.nonce // 传递nonce
                },
                success: function(response) {
                    if (response.success) {
                        $('form.cart').submit();
                    } else {
                        alert('Error: ' + response.data);
                    }
                },
                error: function() {
                    alert('Failed to save custom charge');
                }
            });
            e.preventDefault();
        }
    });
});

修改后,自定义费用会显示在购物车每个商品的名称下方,同时在总计区域单独列出“额外费用”,金额也会正确计入购物车总计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:31:36