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);
问题原因
woocommerce_cart_calculate_fees钩子中直接使用$_POST获取日期,但WooCommerce的AJAX结账更新请求不会自动携带自定义字段值,导致后台无法实时获取日期判断是否加费。- 未将自定义日期字段值存储到WooCommerce会话中,无法在AJAX请求时持久化获取数据。
- 使用
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);
关键修改说明
- 会话存储日期:通过
woocommerce_checkout_update_order_review钩子将自定义日期字段值存储到WooCommerce会话中,确保AJAX请求时后台能获取到最新的日期选择。 - 优化日期解析:使用
explode+mktime解析mm/dd/yy格式日期,避免strtotime的兼容性问题,同时处理两位年份转换为四位。 - 合并费用函数:将原来的两个费用计算函数合并,优化代码结构,减少冗余。
- 添加UI样式:引入jQuery UI官方样式,确保日期选择器显示正常(可选,若已有样式可移除)。
内容的提问来源于stack exchange,提问作者dtheyer
相关产品推荐
相关产品推荐

