
本教程详细指导如何在woocommerce结账页面集成xdsoft datetimepicker,并根据用户选择的配送日期(当天或次日)动态添加附加费用。文章涵盖了自定义日期字段的创建、前端日期选择器的配置、后端条件费用计算逻辑、结账页面动态更新,以及将配送日期保存并显示在订单详情和邮件中的完整实现步骤,旨在提升店铺配送的灵活性和自动化管理能力。
在WooCommerce商店中,为特定配送日期(例如当日或次日达)提供附加费用是一种常见的业务需求。这不仅能为客户提供更灵活的配送选项,也能为商家带来额外的收入。本教程将引导您完成在WooCommerce结账页面添加一个自定义配送日期选择器,并根据用户选择的日期动态计算并应用附加费用的整个过程。
首先,我们需要在WooCommerce结账页面添加一个用于选择配送日期的文本输入框。这个输入框将作为日期选择器的载体。
/**
 * 在WooCommerce结账页面添加自定义配送日期字段
 *
 * @param WC_Checkout $checkout WooCommerce结账对象
 */
function custom_delivery_date_field( $checkout ) {
    woocommerce_form_field( 'delivery_date', array(
        'type'          => 'text',
        'class'         => array('form-row-wide'),
        'id'            => 'datepicker',
        'required'      => true,
        'label'         => __('Select Delivery Date', 'your-text-domain'),
        'placeholder'   => __('Click to select date', 'your-text-domain'),
    ));
}
add_action( 'woocommerce_after_order_notes', 'custom_delivery_date_field' );这段代码通过 woocommerce_after_order_notes 钩子在订单备注下方添加了一个名为 delivery_date 的文本字段。id 设置为 datepicker,这将是前端JavaScript初始化日期选择器的目标元素。
为了提供友好的日期选择体验,我们将集成xdsoft DateTimePicker。此步骤包括加载必要的CSS和JavaScript库,并初始化日期选择器。
/**
 * 加载xdsoft DateTimePicker脚本并初始化
 *
 * @param array $available_gateways 可用的支付网关
 */
function load_and_init_datetimepicker( $available_gateways ) {
   ?>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css"/ >
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>    
    <script type="text/javascript">
        jQuery(document).ready(function($) {
            jQuery.datetimepicker.setLocale('en'); // 设置语言环境
            var currentDate = new Date();
            var minutes = currentDate.getMinutes();
            // 将当前分钟数向上取整到最近的30分钟,例如15->30, 40->60 (变为下一小时的00)
            var m = (Math.ceil(minutes / 30) * 30) % 60;
            currentDate.setMinutes(m);          
            jQuery('#datepicker').datetimepicker({
                // beforeShowDay: $.datepicker.noWeekends, // 如果需要禁用周末,请取消注释此行
                format: 'Y/m/d H:i:s', // 日期时间格式
                minDate: 0,             // 最小可选日期为今天
                minTime: '8:00',        // 最小可选时间
                step: 30,               // 时间步长为30分钟
                allowTimes:[            // 允许选择的时间段
                    '09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', 
                    '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'
                ],
                onSelectDate:function(ct,$i){
                    // 每次选择日期后触发结账页面更新,以便重新计算费用
                    $( 'body' ).trigger( 'update_checkout' );
                },
                onSelectTime:function(ct,$i){
                    // 每次选择时间后触发结账页面更新,以便重新计算费用
                    $( 'body' ).trigger( 'update_checkout' );
                }             
            });
        });
    </script>
   <?php 
}
add_action( 'woocommerce_after_checkout_form', 'load_and_init_datetimepicker', 20 );这段代码通过 woocommerce_after_checkout_form 钩子在结账表单加载后执行。它会加载xdsoft DateTimePicker的CSS和JS文件,并初始化 #datepicker 元素。
在用户提交订单之前,确保配送日期字段已被填写是必要的。
/**
 * 验证自定义配送日期字段
 */
function validate_delivery_date_field() {       
    if ( isset( $_POST['delivery_date'] ) && empty( $_POST['delivery_date'] ) ) {
        wc_add_notice( __( 'Please select the Delivery Date', 'your-text-domain' ), 'error' ); 
    }
}
add_action( 'woocommerce_checkout_process', 'validate_delivery_date_field' );woocommerce_checkout_process 钩子在结账表单处理时触发。如果 delivery_date 字段为空,则会显示一个错误通知,阻止订单提交。
这是实现核心逻辑的部分,我们将根据用户选择的配送日期来判断是否添加附加费用。
/**
 * 根据配送日期动态添加附加费用
 */
function wc_add_delivery_surcharge() { 
    // 仅在非后台页面且非AJAX请求时执行,防止不必要的计算
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }
    // 解析POST数据,因为在AJAX请求中,数据可能在$_POST['post_data']中
    $post_data = array();
    if ( isset( $_POST['post_data'] ) ) {
        parse_str($_POST['post_data'], $post_data);
    } else {
        $post_data = $_POST;
    }
    // 检查配送日期是否已设置
    if ( isset( $post_data['delivery_date'] ) && ! empty( $post_data['delivery_date'] ) ) {
        $selected_date_str = sanitize_text_field( $post_data['delivery_date'] );
        // 获取当前日期(不包含时间部分,以便进行天数比较)
        $current_date_obj = new DateTime(date("Y-m-d"));
        // 获取用户选择的日期(不包含时间部分)
        $selected_date_obj = new DateTime(date("Y-m-d", strtotime($selected_date_str)));
        // 计算日期差异
        $interval = $current_date_obj->diff($selected_date_obj);
        $difference_days = (int)$interval->format('%R%a'); // 获取带符号的天数差异
        // 定义附加费用金额
        $fee_amount = 5.00; // 例如,5.00元作为快速配送费
        // 如果选择的日期是今天(0天差异)或明天(1天差异),则添加费用
        if ( $difference_days == 0 || $difference_days == 1 ) {
            // 添加费用,名称为“快速配送费”,金额为$fee_amount,可征税,税率等级为“standard”
            WC()->cart->add_fee( __( 'Fast delivery charge', 'your-text-domain' ), $fee_amount, true, 'standard' );  
        } else {
            // 如果选择的是其他日期,确保移除可能存在的“快速配送费”
            // 注意:woocommerce_cart_calculate_fees 每次都会重新计算,
            // 如果不满足条件,WC()->cart->add_fee() 将不会被调用,
            // 但为确保万无一失,可以显式移除。
            $fees = WC()->cart->get_fees();
            foreach ( $fees as $key => $fee ) {
                if ( $fee->name === __( "Fast delivery charge", 'your-text-domain' ) ) {
                    unset( $fees[$key] );
                }
            }
            // 重新设置购物车费用(如果有费用被移除)
            if ( ! empty( $fees ) ) {
                 WC()->cart->fees_api()->set_fees($fees);
            } else {
                // 如果所有费用都被移除,则清空费用数组
                WC()->cart->fees_api()->set_fees(array());
            }
        } 
    } else {
        // 如果delivery_date未设置或为空,确保移除可能存在的快速配送费
        $fees = WC()->cart->get_fees();
        foreach ( $fees as $key => $fee ) {
            if ( $fee->name === __( "Fast delivery charge", 'your-text-domain' ) ) {
                unset( $fees[$key] );
            }
        }
        if ( ! empty( $fees ) ) {
             WC()->cart->fees_api()->set_fees($fees);
        } else {
            WC()->cart->fees_api()->set_fees(array());
        }
    }
}
add_action( 'woocommerce_cart_calculate_fees','wc_add_delivery_surcharge' );这段代码通过 woocommerce_cart_calculate_fees 钩子实现费用计算。
为了在订单管理和客户邮件中查看配送日期,我们需要将选择的日期保存到订单元数据中,并在相应位置显示。
/**
 * 保存配送日期到订单元数据
 *
 * @param int $order_id 订单ID
 */
function save_delivery_date_field( $order_id ) { 
    if ( isset( $_POST['delivery_date'] ) && ! empty( $_POST['delivery_date'] ) ) {
        update_post_meta( $order_id, 'delivery_date', sanitize_text_field( $_POST['delivery_date'] ) );
    }
}  
add_action( 'woocommerce_checkout_update_order_meta', 'save_delivery_date_field' );
/**
 * 在WooCommerce后台订单详情页显示配送日期
 *
 * @param WC_Order $order 订单对象
 */
function show_delivery_date_field_order( $order ) {    
   $delivery_date = get_post_meta( $order->get_id(), 'delivery_date', true );
   if ( $delivery_date ) {
       echo '<p><strong>' . __( 'Delivery Date', 'your-text-domain' ) . ':</strong> ' . esc_html( $delivery_date ) . '</p>';
   }
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'show_delivery_date_field_order', 10, 1 );
/**
 * 在WooCommerce订单邮件中显示配送日期
 *
 * @param WC_Order $order 订单对象
 * @param bool $sent_to_admin 是否发送给管理员
 * @param bool $plain_text 是否为纯文本邮件
 * @param WC_Email $email 邮件对象
 */
function show_delivery_date_field_emails( $order, $sent_to_admin, $plain_text, $email ) {
    $delivery_date = get_post_meta( $order->get_id(), 'delivery_date', true );
    if ( $delivery_date ) {
        echo '<p><strong>' . __( 'Delivery Date', 'your-text-domain' ) . ':</strong> ' . esc_html( $delivery_date ) . '</p>';
    }
}
add_action( 'woocommerce_email_after_order_table', 'show_delivery_date_field_emails', 20, 4 );以上就是WooCommerce结账:实现基于配送日期选择的附加费用与日期选择器集成的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
 
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号