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
相关产品推荐
相关产品推荐

