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

WooCommerce结账页面周日配送/取件费AJAX实时显示问题求助

WooCommerce结账页周日配送/取件费实时AJAX更新解决方案

问题背景

我运营派对租赁设备网站,在WooCommerce结账页通过woocommerce_form_field添加了Event Date、Delivery Date、Pickup Date三个jQuery Datepicker字段,设置周日(一周第0天)配送或取件时收取440美元额外费用。目前该费用仅在结账完成后显示于订单元数据或邮件中,无法在结账页面通过AJAX更新实时展示。以下是子主题functions.php中的原始代码:

//DATEPICKER STUFF
// enqueue jquery script
function enqueue_datepicker_scripts() {
    // Enqueue jQuery UI
    wp_enqueue_script('jquery-ui-datepicker');
}
add_action('wp_enqueue_scripts', 'enqueue_datepicker_scripts');

// Enqueue jquery options
function enqueue_datepicker_script() {
    ?>
    <script>
    jQuery(function ($) {
        // Datepicker options
        var datepickerOptions = {
            dateFormat: 'mm/dd/yy',
            minDate: '+3d', // Minimum date is today + 3 days
            firstDay: 0, // Start week with Sunday
            onSelect: function (dateText, inst) {
                setTimeout(function () {
                    $('body').trigger('update_checkout');
                }, 1);
            }
        };

        // Event Date
        $('#event_date').datepicker($.extend({}, datepickerOptions));

        // Delivery Date
        $('#delivery_date').datepicker($.extend({}, datepickerOptions));

        // Pickup Date
        $('#pickup_date').datepicker($.extend({}, datepickerOptions));
    });
    </script>
    <?php
}
add_action('wp_footer', 'enqueue_datepicker_script');

// Add datepicker to checkout fields
function custom_add_date_picker_fields($checkout) {
    echo '<div id="custom_date_picker"><h2>' . __('Delivery and Pickup Details') . '</h2>';

    // Event Date
    woocommerce_form_field('event_date', array(
        'type' => 'text',
        'class' => array('form-row-wide datepicker'),
        'label' => __('Event Date'),
        'required' => true,
        'default' => date('m/d/Y', strtotime('+3 days')), // Default is 3 days from today
        'custom_attributes' => array(
            'min' => date('m/d/Y', strtotime('+3 days')), // Minimum date is 3 days from today
            'max' => date('m/d/Y', strtotime('+2 years')), // Maximum date is 2 years from today
        ),
    ), $checkout->get_value('event_date'));

    // Delivery Date
    woocommerce_form_field('delivery_date', array(
        'type' => 'text',
        'class' => array('form-row-wide datepicker'),
        'label' => __('Delivery Date'),
        'required' => true,
        'default' => date('m/d/Y', strtotime('+2 days')), // Default is 1 day before the event date
    ), $checkout->get_value('delivery_date'));

    // Pickup Date
    woocommerce_form_field('pickup_date', array(
        'type' => 'text',
        'class' => array('form-row-wide datepicker'),
        'label' => __('Pickup Date'),
        'required' => true,
        'default' => date('m/d/Y', strtotime('+4 days')), // Default is 1 day after the event date
    ), $checkout->get_value('pickup_date'));

    echo '</div>';
}
add_action('woocommerce_before_order_notes', 'custom_add_date_picker_fields');


function custom_process_date_picker_fields() {
}
add_action('woocommerce_checkout_process', 'custom_process_date_picker_fields');

// save to order meta
function custom_update_date_picker_fields($order_id) {
    // Save Event Date
    if (!empty($_POST['event_date'])) {
        update_post_meta($order_id, 'Event Date', sanitize_text_field($_POST['event_date']));
    }

    // Save Delivery Date
    if (!empty($_POST['delivery_date'])) {
        update_post_meta($order_id, 'Delivery Date', sanitize_text_field($_POST['delivery_date']));
    }

    // Save Pickup Date
    if (!empty($_POST['pickup_date'])) {
        update_post_meta($order_id, 'Pickup Date', sanitize_text_field($_POST['pickup_date']));
    }
}
add_action('woocommerce_checkout_update_order_meta', 'custom_update_date_picker_fields');

// Add fee with standard tax
function custom_add_sunday_delivery_fee() {
    // Check if delivery date is set
    if (isset($_POST['delivery_date'])) {
        $delivery_date = sanitize_text_field($_POST['delivery_date']);
        $delivery_day = date('w', strtotime($delivery_date));

        // Check if delivery date is Sunday
        if ($delivery_day == 0) { // Sunday
            WC()->cart->add_fee(__('Sunday Delivery', 'woocommerce'), 440, true, 'standard');
        }
    }
}
add_action('woocommerce_cart_calculate_fees', 'custom_add_sunday_delivery_fee', 10);

// pickup fee
function custom_add_sunday_pickup_fee() {
    // Check if pickup date is set
    if (isset($_POST['pickup_date'])) {
        $pickup_date = sanitize_text_field($_POST['pickup_date']);
        $pickup_day = date('w', strtotime($pickup_date));


        // Check if pickup date is Sunday
        if ($pickup_day == 0) { // Sunday
            WC()->cart->add_fee(__('Sunday Pickup', 'woocommerce'), 440, true, 'standard');
        }
    }
}
add_action('woocommerce_cart_calculate_fees', 'custom_add_sunday_pickup_fee', 10);

问题原因

  1. woocommerce_cart_calculate_fees钩子中直接使用$_POST获取日期,但WooCommerce的AJAX结账更新请求不会自动携带自定义字段值,导致后台无法实时获取日期判断是否加费。
  2. 未将自定义日期字段值存储到WooCommerce会话中,无法在AJAX请求时持久化获取数据。
  3. 使用strtotime解析mm/dd/yy格式日期可能存在兼容性问题,导致日期判断错误。

修改后的完整代码

替换子主题functions.php中的相关代码,以下是完整修正版:

//DATEPICKER STUFF
// enqueue jquery script
function enqueue_datepicker_scripts() {
    // Enqueue jQuery UI
    wp_enqueue_script('jquery-ui-datepicker');
    // 引入jQuery UI样式(可选,确保日期选择器显示正常)
    wp_enqueue_style('jquery-ui-css', 'https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css');
}
add_action('wp_enqueue_scripts', 'enqueue_datepicker_scripts');

// Enqueue jquery options
function enqueue_datepicker_script() {
    ?>
    <script>
    jQuery(function ($) {
        // Datepicker options
        var datepickerOptions = {
            dateFormat: 'mm/dd/yy',
            minDate: '+3d', // Minimum date is today + 3 days
            firstDay: 0, // Start week with Sunday
            onSelect: function (dateText, inst) {
                setTimeout(function () {
                    $('body').trigger('update_checkout');
                }, 100);
            }
        };

        // Event Date
        $('#event_date').datepicker($.extend({}, datepickerOptions));

        // Delivery Date
        $('#delivery_date').datepicker($.extend({}, datepickerOptions));

        // Pickup Date
        $('#pickup_date').datepicker($.extend({}, datepickerOptions));
    });
    </script>
    <?php
}
add_action('wp_footer', 'enqueue_datepicker_script');

// Add datepicker to checkout fields
function custom_add_date_picker_fields($checkout) {
    echo '<div id="custom_date_picker"><h2>' . __('Delivery and Pickup Details') . '</h2>';

    // Event Date
    woocommerce_form_field('event_date', array(
        'type' => 'text',
        'class' => array('form-row-wide datepicker'),
        'label' => __('Event Date'),
        'required' => true,
        'default' => date('m/d/Y', strtotime('+3 days')), // Default is 3 days from today
        'custom_attributes' => array(
            'min' => date('m/d/Y', strtotime('+3 days')), // Minimum date is 3 days from today
            'max' => date('m/d/Y', strtotime('+2 years')), // Maximum date is 2 years from today
        ),
    ), $checkout->get_value('event_date'));

    // Delivery Date
    woocommerce_form_field('delivery_date', array(
        'type' => 'text',
        'class' => array('form-row-wide datepicker'),
        'label' => __('Delivery Date'),
        'required' => true,
        'default' => date('m/d/Y', strtotime('+2 days')), // Default is 1 day before the event date
    ), $checkout->get_value('delivery_date'));

    // Pickup Date
    woocommerce_form_field('pickup_date', array(
        'type' => 'text',
        'class' => array('form-row-wide datepicker'),
        'label' => __('Pickup Date'),
        'required' => true,
        'default' => date('m/d/Y', strtotime('+4 days')), // Default is 1 day after the event date
    ), $checkout->get_value('pickup_date'));

    echo '</div>';
}
add_action('woocommerce_before_order_notes', 'custom_add_date_picker_fields');


function custom_process_date_picker_fields() {
}
add_action('woocommerce_checkout_process', 'custom_process_date_picker_fields');

// save to order meta
function custom_update_date_picker_fields($order_id) {
    // Save Event Date
    if (!empty($_POST['event_date'])) {
        update_post_meta($order_id, 'Event Date', sanitize_text_field($_POST['event_date']));
    }

    // Save Delivery Date
    if (!empty($_POST['delivery_date'])) {
        update_post_meta($order_id, 'Delivery Date', sanitize_text_field($_POST['delivery_date']));
    }

    // Save Pickup Date
    if (!empty($_POST['pickup_date'])) {
        update_post_meta($order_id, 'Pickup Date', sanitize_text_field($_POST['pickup_date']));
    }
}
add_action('woocommerce_checkout_update_order_meta', 'custom_update_date_picker_fields');

// 存储日期字段到WC会话
function custom_store_dates_to_session() {
    if (isset($_POST['event_date']) && !empty($_POST['event_date'])) {
        WC()->session->set('event_date', sanitize_text_field($_POST['event_date']));
    }
    if (isset($_POST['delivery_date']) && !empty($_POST['delivery_date'])) {
        WC()->session->set('delivery_date', sanitize_text_field($_POST['delivery_date']));
    }
    if (isset($_POST['pickup_date']) && !empty($_POST['pickup_date'])) {
        WC()->session->set('pickup_date', sanitize_text_field($_POST['pickup_date']));
    }
}
add_action('woocommerce_checkout_update_order_review', 'custom_store_dates_to_session');

// 添加周日配送/取件额外费用
function custom_add_sunday_fees() {
    // 获取会话中的日期
    $delivery_date = WC()->session->get('delivery_date');
    $pickup_date = WC()->session->get('pickup_date');

    // 处理配送日期周日费用
    if (!empty($delivery_date)) {
        // 解析mm/dd/yy格式日期,避免strtotime解析错误
        list($month, $day, $year) = explode('/', $delivery_date);
        // 处理两位年份,转换为四位
        if ($year < 100) $year += 2000;
        $delivery_timestamp = mktime(0, 0, 0, $month, $day, $year);
        $delivery_day = date('w', $delivery_timestamp);
        
        if ($delivery_day == 0) {
            WC()->cart->add_fee(__('Sunday Delivery', 'woocommerce'), 440, true, 'standard');
        }
    }

    // 处理取件日期周日费用
    if (!empty($pickup_date)) {
        list($month, $day, $year) = explode('/', $pickup_date);
        if ($year < 100) $year += 2000;
        $pickup_timestamp = mktime(0, 0, 0, $month, $day, $year);
        $pickup_day = date('w', $pickup_timestamp);
        
        if ($pickup_day == 0) {
            WC()->cart->add_fee(__('Sunday Pickup', 'woocommerce'), 440, true, 'standard');
        }
    }
}
add_action('woocommerce_cart_calculate_fees', 'custom_add_sunday_fees', 10);

关键修改说明

  1. 会话存储日期:通过woocommerce_checkout_update_order_review钩子将自定义日期字段值存储到WooCommerce会话中,确保AJAX请求时后台能获取到最新的日期选择。
  2. 优化日期解析:使用explode+mktime解析mm/dd/yy格式日期,避免strtotime的兼容性问题,同时处理两位年份转换为四位。
  3. 合并费用函数:将原来的两个费用计算函数合并,优化代码结构,减少冗余。
  4. 添加UI样式:引入jQuery UI官方样式,确保日期选择器显示正常(可选,若已有样式可移除)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:48:10