WooCommerce结账:实现基于配送日期选择的附加费用与日期选择器集成

霞舞
发布: 2025-10-31 11:13:36
原创
150人浏览过

WooCommerce结账:实现基于配送日期选择的附加费用与日期选择器集成

本教程详细指导如何在woocommerce结账页面集成xdsoft datetimepicker,并根据用户选择的配送日期(当天或次日)动态添加附加费用。文章涵盖了自定义日期字段的创建、前端日期选择器的配置、后端条件费用计算逻辑、结账页面动态更新,以及将配送日期保存并显示在订单详情和邮件中的完整实现步骤,旨在提升店铺配送的灵活性和自动化管理能力。

在WooCommerce商店中,为特定配送日期(例如当日或次日达)提供附加费用是一种常见的业务需求。这不仅能为客户提供更灵活的配送选项,也能为商家带来额外的收入。本教程将引导您完成在WooCommerce结账页面添加一个自定义配送日期选择器,并根据用户选择的日期动态计算并应用附加费用的整个过程。

1. 添加自定义配送日期字段

首先,我们需要在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初始化日期选择器的目标元素。

2. 集成并配置xdsoft DateTimePicker

为了提供友好的日期选择体验,我们将集成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 元素。

  • format: 定义日期时间的显示和提交格式。
  • minDate: 0 表示最小可选日期为今天。
  • minTime: 设置每天最早的可选时间。
  • step: 设置时间选择的步长(例如30分钟)。
  • allowTimes: 限制用户只能选择特定时间段。
  • onSelectDate 和 onSelectTime: 这两个回调函数在用户选择日期或时间后触发 update_checkout 事件。这个事件会通知WooCommerce重新计算购物车和费用,确保附加费用能够动态更新。

3. 验证配送日期选择

在用户提交订单之前,确保配送日期字段已被填写是必要的。

集简云
集简云

软件集成平台,快速建立企业自动化与智能化

集简云22
查看详情 集简云
/**
 * 验证自定义配送日期字段
 */
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 字段为空,则会显示一个错误通知,阻止订单提交。

4. 基于配送日期动态计算附加费用

这是实现核心逻辑的部分,我们将根据用户选择的配送日期来判断是否添加附加费用。

/**
 * 根据配送日期动态添加附加费用
 */
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 钩子实现费用计算。

  • 它首先解析 $_POST 数据以获取 delivery_date。
  • 然后,它将当前日期和选择的配送日期转换为 DateTime 对象,并计算它们之间的天数差异。
  • 如果差异为0(今天)或1(明天),则使用 WC()-youjiankuohaophpcncart->add_fee() 添加一个名为“快速配送费”的附加费用。
  • 如果选择的是其他日期,或者 delivery_date 未设置,它会遍历购物车中的所有费用,并移除名为“快速配送费”的费用,以确保费用只在满足条件时才显示。

5. 保存并显示配送日期信息

为了在订单管理和客户邮件中查看配送日期,我们需要将选择的日期保存到订单元数据中,并在相应位置显示。

/**
 * 保存配送日期到订单元数据
 *
 * @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_checkout_update_order_meta: 在订单创建后,将 delivery_date 字段的值保存为订单的元数据。
  • woocommerce_admin_order_data_after_billing_address: 在WooCommerce后台订单详情页面的账单地址下方显示保存的配送日期。
  • woocommerce_email_after_order_table: 在所有WooCommerce订单邮件的订单表格下方显示配送日期。

注意事项与总结

  • 代码位置:所有PHP代码应放置在您主题的 functions.php 文件中,或者更推荐的方式是创建一个自定义插件来管理这些功能。
  • 文本域:在 __('Text', 'your-text-domain') 中,请将 'your-text-domain' 替换为您主题或插件的实际文本域,以便进行国际化。
  • 费用金额:您可以根据需要修改 $fee_amount 的值来调整附加费用的金额。
  • 日期选择器配置:xdsoft DateTimePicker提供了丰富的配置选项,您可以根据业务需求调整 minDate、maxDate、allowDates、beforeShowDay 等参数,例如禁用周末或特定节假日。
  • 测试:在生产环境中使用前,请务必在开发或测试环境中进行全面测试,确保所有功能按预期工作。
  • **

以上就是WooCommerce结账:实现基于配送日期选择的附加费用与日期选择器集成的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号