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

WooCommerce结账时基于自定义字段添加额外费用的实现方法

实现WooCommerce结账页自定义字段调整总额的方案

完全可行,通过WooCommerce的钩子和前端JS就能实现这个需求,下面是具体实现步骤:

1. 优化原有自定义字段代码

先把原代码里的print换成更规范的输出方式,避免潜在的格式问题:

add_action( 'woocommerce_checkout_before_order_review', 'person_details' );
function person_details( $checkout ) {
    global $woocommerce;

    $count = $woocommerce->cart->cart_contents_count;
    $i = 0;

    for( $k=1; $k<= $count; $k++ ) {
        $i++;
        
        echo '<h3>' . esc_html__( 'Gegevens van kind #'.$i, 'njengah' ) . '</h3>';

        woocommerce_form_field( 'cstm_care'.$i, array(
            'type'       => 'select',
            'required'   => true,
            'class'      => array( 'my-field-class form-row-last care-selection' ),
            'label'      => __( 'Voor- en na zorg', 'njengah' ),
            'options'    => array(
                'Geen'                   => __( 'Geen', 'njengah' ),
                'Voorzorg'               => __( 'Pre-care (€30)', 'njengah' ),
                'Nazorg'                 => __( 'Aftercare (€30)', 'njengah' ),
                'Voor- en na zorg'       => __( 'Pre- & Aftercare (€50)', 'njengah' )
            )
        ), $checkout->get_value( 'cstm_care'.$i ));
    }
}

这里给选择框加了care-selection类,方便后续JS定位。

2. 前端实时更新总额(可选但推荐)

添加JS监听选择框变化,通过AJAX实时更新购物车总额,提升用户体验:

add_action( 'wp_footer', 'care_selection_ajax_update' );
function care_selection_ajax_update() {
    if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script>
jQuery(document).ready(function($) {
    // 监听护理选项变化
    $(document).on('change', '.care-selection', function() {
        var careData = {};
        // 收集所有护理选项的值
        $('.care-selection').each(function(index) {
            var fieldName = $(this).attr('name');
            careData[fieldName] = $(this).val();
        });

        // 发送AJAX请求更新总额
        $.ajax({
            type: 'POST',
            url: wc_checkout_params.ajax_url,
            data: {
                action: 'update_care_fees',
                care_options: careData,
                security: wc_checkout_params.update_order_review_nonce
            },
            success: function(response) {
                // 更新结账区域的总额
                $('body').trigger('update_checkout');
            }
        });
    });
});
</script>
<?php
    endif;
}

3. 后端计算并添加额外费用

使用woocommerce_cart_calculate_fees钩子,根据用户选择计算并添加对应费用:

add_action( 'woocommerce_cart_calculate_fees', 'add_care_selection_fees' );
function add_care_selection_fees( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

    // 只有在结账页处理
    if ( ! is_checkout() ) return;

    // 获取购物车内商品数量(对应孩子数量)
    $item_count = $cart->get_cart_contents_count();
    $total_fee = 0;

    // 遍历每个孩子的护理选项
    for ( $i = 1; $i <= $item_count; $i++ ) {
        $care_option = isset( $_POST['cstm_care'.$i] ) ? sanitize_text_field( $_POST['cstm_care'.$i] ) : '';
        
        // 根据选项计算费用
        switch( $care_option ) {
            case 'Voorzorg':
            case 'Nazorg':
                $total_fee += 30;
                break;
            case 'Voor- en na zorg':
                $total_fee += 50;
                break;
            default:
                // 选择Geen时不加费用
                break;
        }
    }

    // 如果有费用,添加到购物车
    if ( $total_fee > 0 ) {
        $cart->add_fee( __( 'Kinderopvangkosten', 'njengah' ), $total_fee, true );
        // 第三个参数true表示费用会计算税费,不需要的话改成false
    }
}

// 处理AJAX请求的回调函数
add_action( 'wp_ajax_update_care_fees', 'update_care_fees_callback' );
add_action( 'wp_ajax_nopriv_update_care_fees', 'update_care_fees_callback' );
function update_care_fees_callback() {
    check_ajax_referer( 'update_order_review', 'security' );
    
    // 这里不需要额外处理,因为add_care_selection_fees会在update_checkout时触发
    wp_send_json_success();
}

4. 保存护理选项到订单元数据

确保用户选择的护理选项被保存到订单里,方便后续查看和管理:

add_action( 'woocommerce_checkout_create_order', 'save_care_selection_to_order' );
function save_care_selection_to_order( $order ) {
    $item_count = WC()->cart->get_cart_contents_count();

    for ( $i = 1; $i <= $item_count; $i++ ) {
        if ( isset( $_POST['cstm_care'.$i] ) ) {
            $care_value = sanitize_text_field( $_POST['cstm_care'.$i] );
            $order->update_meta_data( '_cstm_care_' . $i, $care_value );
        }
    }
}

5. 结账字段验证

确保每个孩子的护理选项都被正确选择:

add_action( 'woocommerce_checkout_process', 'validate_care_selection_fields' );
function validate_care_selection_fields() {
    $item_count = WC()->cart->get_cart_contents_count();

    for ( $i = 1; $i <= $item_count; $i++ ) {
        if ( ! isset( $_POST['cstm_care'.$i] ) || empty( $_POST['cstm_care'.$i] ) ) {
            wc_add_notice( __( 'Selecteer een zorgoptie voor kind #' . $i, 'njengah' ), 'error' );
        }
    }
}

把以上代码添加到你的主题functions.php文件或者自定义插件里即可实现需求,所有费用会自动加入结账总额,并且订单里会保留每个孩子的护理选项记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:37:38