WooCommerce 结账页根据选择的配送日期动态添加配送费用教程


WooCommerce 结账页根据选择的配送日期动态添加配送费用教程

本教程详细指导如何在 woocommerce 结账页面集成一个日期时间选择器,并根据用户选择的配送日期(当天或次日)动态计算并添加额外的“快速配送”费用。文章涵盖了自定义字段的添加、日期选择器的配置、费用的计算与移除、表单验证以及将配送日期保存至订单并显示在后台和邮件中的完整实现方案。

在电子商务运营中,为顾客提供灵活的配送选项并根据选择的紧迫性收取额外费用是一种常见的业务需求。本教程将详细介绍如何在 WooCommerce 结账页面实现一个功能,即用户在选择配送日期时,如果选择了当天或次日,系统将自动添加一笔“快速配送”费用。我们将使用 xdsoft datetimepicker 作为日期时间选择器,并通过 WooCommerce 的钩子机制实现费用的动态计算、表单验证以及订单信息的保存。

1. 添加配送日期选择字段

首先,我们需要在 WooCommerce 结账页面添加一个自定义的配送日期选择字段。这可以通过 woocommerce_form_field 函数结合 woocommerce_after_order_notes 钩子实现。

/**
 * 在结账页面添加配送日期字段
 *
 * @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', // 对应前端日期选择器ID
        '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' );

2. 加载日期时间选择器库

为了使 datepicker 字段具备日期时间选择功能,我们需要引入 xdsoft datetimepicker 相关的 J*aScript 和 CSS 库。建议将这些脚本和样式通过 wp_enqueue_script 和 wp_enqueue_style 正确加载,而不是直接在 woocommerce_after_checkout_form 中输出。但为了演示简洁,这里沿用直接输出的方式。

/**
 * 加载日期时间选择器所需的JS/CSS库
 */
function enqueue_datetimepicker_assets() {
    // 注册并加载 jQuery UI (xdsoft datetimepicker可能依赖)
    wp_enqueue_script( 'jquery-ui-datepicker' );
    wp_enqueue_style( 'jquery-ui-css', '//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css' );

    // 加载 xdsoft datetimepicker 库
    wp_enqueue_script( 'xdsoft-datetimepicker', 'https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js', array('jquery'), '2.5.20', true );
    wp_enqueue_style( 'xdsoft-datetimepicker-css', 'https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css', array(), '2.5.20' );
}
add_action( 'wp_enqueue_scripts', 'enqueue_datetimepicker_assets' ); // 最佳实践是使用wp_enqueue_scripts

/**
 * 初始化日期时间选择器并绑定事件
 */
function initialize_datetimepicker_script() {
    if ( is_checkout() ) { // 确保只在结账页加载
    ?>
    <script type="text/j*ascript">
        jQuery(document).ready(function($) {
            jQuery.datetimepicker.setLocale('en');

            var currentDate = new Date();
            var minutes = currentDate.getMinutes();
            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', 'initialize_datetimepicker_script', 20 );

注意事项:

  • onSelectDate 和 onSelectTime 事件是关键,它们会在用户选择日期或时间后触发 update_checkout 事件,从而通知 WooCommerce 重新计算购物车和费用。
  • minDate: 0 表示最小可选日期是当前日期。
  • minTime 和 allowTimes 可以根据业务需求进行调整。

3. 实现动态配送费用逻辑

核心功能是通过 woocommerce_cart_calculate_fees 钩子来动态添加或移除费用。当用户选择的配送日期是当天或次日时,我们将添加一笔“快速配送”费用。

/**
 * 根据选择的配送日期添加或移除费用
 */
function wc_add_delivery_surcharge() {
    // 确保只在非管理后台且非AJAX请求时执行,防止不必要的计算
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }

    // 解析POST数据,获取配送日期
    parse_str( $_POST['post_data'], $post_data );

    if ( isset( $post_data['delivery_date'] ) && ! empty( $post_data['delivery_date'] ) ) {
        $selected_delivery_date_str = $post_data['delivery_date'];

        // 将当前日期和选择的配送日期转换为时间戳,并只比较日期部分
        $current_date_timestamp = strtotime( date( "Y-m-d" ) );
        $selected_date_timestamp = strtotime( date( "Y-m-d", strtotime( $selected_delivery_date_str ) ) );

        // 计算日期差异(天数)
        $datediff = $selected_date_timestamp - $current_date_timestamp;
        $difference_in_days = floor( $datediff / ( 60 * 60 * 24 ) );

        $fee_name = __( 'Fast delivery charge', 'your-text-domain' );
        $fast_delivery_fee = 5.00; // 快速配送费用金额

        // 检查购物车中是否已存在快速配送费用
        $existing_fees = WC()->cart->get_fees();
        $fee_exists = false;
        foreach ( $existing_fees as $fee ) {
            if ( $fee->name === $fee_name ) {
                $fee_exists = true;
                break;
            }
        }

        // 如果差异是0(今天)或1(明天),则添加费用
        if ( $difference_in_days == 0 || $difference_in_days == 1 ) {
            if ( ! $fee_exists ) { // 如果费用不存在,则添加
                WC()->cart->add_fee( $fee_name, $fast_delivery_fee, true, 'standard' );
            }
        } else {
            // 如果日期不是今天或明天,且费用存在,则移除费用
            if ( $fee_exists ) {
                $updated_fees = array();
                foreach ( $existing_fees as $fee ) {
                    if ( $fee->name !== $fee_name ) {
                        $updated_fees[] = $fee;
                    }
                }
                WC()->cart->set_fees( $updated_fees ); // 使用 set_fees 方法更新费用列表
            }
        }
    } else {
        // 如果配送日期未设置或为空,确保移除快速配送费用
        $fee_name = __( 'Fast delivery charge', 'your-text-domain' );
        $existing_fees = WC()->cart->get_fees();
        $updated_fees = array();
        foreach ( $existing_fees as $fee ) {
            if ( $fee->name !== $fee_name ) {
                $updated_fees[] = $fee;
            }
        }
        WC()->cart->set_fees( $updated_fees );
    }
}
add_action( 'woocommerce_cart_calculate_fees', 'wc_add_delivery_surcharge' );

关键点说明:

  • parse_str($_POST['post_data'], $post_data); 用于解析 AJAX 请求中传递的表单数据。
  • strtotime() 用于将日期字符串转换为时间戳,便于计算日期差异。
  • floor($datediff/(60*60*24)) 计算天数差异。
  • WC()->cart->add_fee() 用于添加费用。true 表示费用是可税的,'standard' 是税率类别。
  • 移除费用时,需要遍历现有费用并重新设置,因为 remove_fee 函数通常需要费用对象的引用。这里通过构建一个新的费用数组并使用 WC()->cart->set_fees() 来实现。

4. 表单字段验证

为了确保用户必须选择配送日期,我们需要在结账处理阶段添加验证。

芝士饼 芝士饼

芝士饼是一个一站式AI原生应用开发平台,简单几步即可完成应用的创建与发布。

芝士饼 84 查看详情 芝士饼
/**
 * 验证配送日期字段是否已选择
 */
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' );

5. 保存并显示配送日期

为了在订单详情页和邮件中显示选择的配送日期,我们需要将其保存到订单元数据中,并在相应位置进行展示。

/**
 * 将配送日期保存到订单元数据
 *
 * @param int $order_id 订单ID
 */
function s*e_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', 's*e_delivery_date_field' );

/**
 * 在后台订单详情页显示配送日期
 *
 * @param WC_Order $order 订单对象
 */
function show_delivery_date_field_order( $order ) {
    $delivery_date = $order->get_meta( '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 );

/**
 * 在订单邮件中显示配送日期
 *
 * @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 = $order->get_meta( '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 );

6. 完整代码示例

将上述所有代码片段合并到一个自定义插件文件(例如 your-plugin-name.php)或主题的 functions.php 文件中,即可实现完整的配送日期选择和动态费用功能。

<?php
/**
 * Plugin Name: WooCommerce Custom Delivery Date Fee
 * Description: Adds a delivery date picker to checkout and applies a fee for same-day/next-day delivery.
 * Version: 1.0
 * Author: Your Name
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

/**
 * 1. 在结账页面添加配送日期字段
 */
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' );

/**
 * 2. 加载日期时间选择器所需的JS/CSS库
 */
function enqueue_datetimepicker_assets() {
    if ( is_checkout() ) {
        // 注册并加载 jQuery UI (xdsoft datetimepicker可能依赖)
        wp_enqueue_script( 'jquery-ui-datepicker' );
        wp_enqueue_style( 'jquery-ui-css', '//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css' );

        // 加载 xdsoft datetimepicker 库
        wp_enqueue_script( 'xdsoft-datetimepicker', 'https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js', array('jquery'), '2.5.20', true );
        wp_enqueue_style( 'xdsoft-datetimepicker-css', 'https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css', array(), '2.5.20' );
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_datetimepicker_assets' );

/**
 * 2.1 初始化日期时间选择器并绑定事件
 */
function initialize_datetimepicker_script() {
    if ( is_checkout() ) {
    ?>
    <script type="text/j*ascript">
        jQuery(document).ready(function($) {
            jQuery.datetimepicker.setLocale('en');

            var currentDate = new Date();
            var minutes = currentDate.getMinutes();
            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,
                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', 'initialize_datetimepicker_script', 20 );

/**
 * 3. 根据选择的配送日期添加或移除费用
 */
function wc_add_delivery_surcharge() {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }

    parse_str( $_POST['post_data'], $post_data );

    $fee_name = __( 'Fast delivery charge', 'your-text-domain' );
    $fast_delivery_fee = 5.00; // 快速配送费用金额

    // 获取当前购物车中的费用
    $existing_fees = WC()->cart->get_fees();
    $fee_to_add_or_remove = false;

    // 检查是否已存在快速配送费用
    foreach ( $existing_fees as $key => $fee ) {
        if ( $fee->name === $fee_name ) {
            $fee_to_add_or_remove = $fee;
            unset( $existing_fees[$key] ); // 暂时移除,以便后续重新添加或完全移除
            break;
        }
    }

    if ( isset( $post_data['delivery_date'] ) && ! empty( $post_data['delivery_date'] ) ) {
        $selected_delivery_date_str = $post_data['delivery_date'];

        $current_date_timestamp = strtotime( date( "Y-m-d" ) );
        $selected_date_timestamp = strtotime( date( "Y-m-d", strtotime( $selected_delivery_date_str ) ) );

        $datediff = $selected_date_timestamp - $current_date_timestamp;
        $difference_in_days = floor( $datediff / ( 60 * 60 * 24 ) );

        if ( $difference_in_days == 0 || $difference_in_days == 1 ) {
            // 如果是今天或明天,添加费用
            WC()->cart->add_fee( $fee_name, $fast_delivery_fee, true, 'standard' );
        } else {
            // 如果不是今天或明天,且之前有费用,则不添加,等于移除
            // 费用已经在上面unset了,这里不需要额外操作
        }
    } else {
        // 如果配送日期未设置或为空,确保不添加费用
    }

    // WC()->cart->set_fees() 在 add_fee() 之后不需要手动调用,add_fee 会自动处理
}
add_action( 'woocommerce_cart_calculate_fees', 'wc_add_delivery_surcharge' );


/**
 * 4. 验证配送日期字段是否已选择
 */
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' );

/**
 * 5. 将配送日期保存到订单元数据
 */
function s*e_delivery_date_field_to_order_meta( $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', 's*e_delivery_date_field_to_order_meta' );

/**
 * 5.1 在后台订单详情页显示配送日期
 */
function show_delivery_date_field_order( $order ) {
    $delivery_date = $order->get_meta( '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 );

/**
 * 5.2 在订单邮件中显示配送日期
 */
function show_delivery_date_field_emails( $order, $sent_to_admin, $plain_text, $email ) {
    $delivery_date = $order->get_meta( 'delivery

以上就是WooCommerce 结账页根据选择的配送日期动态添加配送费用教程的详细内容,更多请关注php中文网其它相关文章!


# 芝士  # 珠海seo预算  # 岳麓区品质网站建设招标  # 商业网站建设公开课视频  # 网站合理的优化措施  # 山西营销推广哪家好  # 点赞网站推广  # 睢宁网站建设销售方法  # 开封抖音图文seo推广  # 饰品网站建设素材图片  # 临清工厂网站建设  # 不需要  # 次日  # 明天  # 可选  # 自定义  # css  # 表单  # 加载  # 选择器  # 移除  # ai  # access  # app  # ajax  # 前端  # js  # html  # jquery  # java  # javascript  # php 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 《花瓣》创建专辑方法  《小黑盒》删除历史浏览方法  《百度畅听版》关闭兴趣推荐方法  铁路12306官网登录入口 铁路12306在线购票官方平台  KFC邀请码怎么使用领额外优惠_KFC邀请码输入方式与额外优惠代码获取方法  Google Drive API 认证:服务账户与OAuth 2.0的选择与实践  Windows 11怎么删除恢复分区_Windows 11使用Diskpart命令强行删除分区  word邮件合并怎么插入个性化图片_Word邮件合并插入个性化图片方法  如何测试您的网站全球打开速度-网站海外测速工  优化CSS动画与J*aScript定时器协同:构建稳定Toast提示  雨课堂官网在线登录 网页版雨课堂登录链接  PHP安全加载非公开目录图片与动态内容类型处理指南  win11自带录屏文件保存在哪里 Win11 Game Bar录制视频默认路径【分享】  c++如何链接Boost库_c++准标准库的集成与使用  在Django中动态检查模型关联:一种灵活的解决方案  NumPy 高性能技巧:基于多列条件查找最近邻行索引的向量化实现  阿里云共享相册入口在哪  iSpring三分屏制作教程  TikTok视频播放不流畅怎么办 TikTok视频播放优化方法  Teambition网盘如何共享文件  如何在CSS中使用absolute实现登录弹窗居中_transform translate结合  在React中正确处理HTML input type="number"的数值类型  《书耽》更换手机号方法  Golang如何测试结构体方法_Golang reflect方法测试与调用技巧  Lar*el Eloquent:高效删除多对多关系中无关联子记录的父模型  12306不能订票的时间段是固定的吗? | 节假日购票时间有无变化  PHP动态导航按钮:根据用户登录状态切换链接与文本  yy漫画官方网站登录入口_yy漫画在线阅读页面地址  Golang如何使用gRPC拦截器实现日志收集_Golang gRPC拦截器日志收集实践  Excel如何快速找到并断开外部数据源链接_Excel外部数据源断开方法  为什么XML解析器对大小写敏感? 理解XML规范中的大小写规则与最佳实践  从J*a应用程序中导出MySQL表数据的技术指南  《海底捞》点外卖方法  大熊猫抓取竹子的“大拇指”其实是什么?蚂蚁庄园课堂今天答案最新11月30日  如何用mysql实现客户反馈管理_mysql客户反馈数据库方法  PDF文件去水印平台入口 PDF水印删除网址  哈尔滨城市通昵称修改方法  Win10显卡驱动安装失败怎么办 Win10使用DDU彻底卸载驱动【解决】  AI图层蒙版怎么用_AI图层蒙版应用技巧与设计实例  微星主板BIOS怎么调整内存时序_内存参数手动优化BIOS设置教程  CSS过渡如何实现按钮悬停效果_transition属性控制背景颜色变化  百度地图离线地图无法加载如何解决 百度地图离线地图加载优化方法  抖音号升级企业号怎么改名字?升级企业号有哪些好处?  秋风萧瑟洪波涌起中的萧瑟指的是什么  小红书网页版在线直达 小红书网页版免费登录入口  惠普电脑BIOS界面看不懂怎么办_HP电脑BIOS功能选项解读与设置  怎样让Windows 11的开始菜单恢复经典样式_Open-Shell工具使用指南【怀旧】  Go语言中方法接收器的选择:值类型还是指针类型?  我的世界游戏平台入口 我的世界官方官网直达链接  mysql通配符能用于日志查询吗_mysql通配符在系统日志查询中的实际使用方法 

 2025-10-31

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.