WordPress WooCommerce购物车订阅补差价费用消失问题求助
WooCommerce订阅补差价费用持久化解决方案
问题根源
原代码依赖URL参数compra-susc传递用户选择,但结算页跳转、配送/支付方式切换时,WooCommerce会通过AJAX更新购物车,URL参数无法保留,导致费用消失。必须将用户选择存储在购物车会话中,确保跨页面和AJAX请求都能读取。
修改后的完整代码
add_action( 'woocommerce_cart_calculate_fees', 'add_fee_extra_para_completar_suscripcion_en_carrito', 10, 1 ); function add_fee_extra_para_completar_suscripcion_en_carrito( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // 获取购物车小计 $total_compra = intval( $cart->get_subtotal() ); $suma_clasica = 5000 - $total_compra; $suma_premium = 10000 - $total_compra; // 处理表单提交:更新购物车会话 if ( isset( $_REQUEST['compra-susc'] ) ) { $compra_susc = sanitize_text_field( $_REQUEST['compra-susc'] ); switch( $compra_susc ) { case 'clasica-ok': case 'premium-ok': WC()->session->set( 'compra_susc', $compra_susc ); break; case 'cancel': WC()->session->set( 'compra_susc', '' ); break; } // 提交后重定向回当前页面,避免重复提交 if ( is_cart() || is_checkout() ) { wp_redirect( get_permalink() ); exit; } } // 从会话读取用户选择 $compra_susc = WC()->session->get( 'compra_susc', '' ); // 仅在购物车/结算页,且用户非订阅用户,且小计低于5000时执行 if ( ( is_cart() || is_checkout() ) && $total_compra < 5000 && !usuario_rol( 'Premium' ) && !usuario_rol( 'Clasico' ) ) { // 显示模态框:仅当用户未选择且未取消时(仅购物车页显示) if ( $compra_susc == '' && is_cart() ) { ?> <div id="modalExtraParaSusc" class="modal fade show"> <div class="modal-dialog"> <div class="modal-content" style="background-color: #202020; border-radius: 8px; color: white; box-shadow: 0px 0px 10px;"> <div class="modal-header" style="display: flex; flex-direction: column; padding: 28px 36px 0px 36px; border: 0;"> <p style="flex-direction: row; padding-bottom: 20px; display: inline-block; text-align: center;">Puede completar su compra para la obtención de una de nuestras dos suscripciones:</p> </div> <div class="modal-body" style="padding:0;"> <div style="padding: 0px 50px;"> <table cellspacing="0"> <thead> <tr> <th class="product-name" colspan="2" style="border-width:3px;">Total del carrito</th> </tr> </thead> </table> <table cellspacing="0" class="shop_table shop_table_responsive"> <tbody> <tr class="cart-subtotal"> <th>Subtotal</th> <td data-title="Subtotal"><span class="woocommerce-Price-amount amount"><bdi style="color: white;"><span class="woocommerce-Price-currencySymbol" style="color: white;">$</span> <?php echo $total_compra; ?> </bdi></span></td> </tr> </tbody> </table> </div> </div> <div class="modal-footer" style="display: flex; flex-direction: column; border: 0;"> <form action="<?php echo get_permalink(); ?>" style="padding: 0px 50px;"> <label style="color: white;"> <input type="radio" name="compra-susc" value="clasica-ok"/> Resto para suscripción Clásica de $5000: $ <?php echo $suma_clasica; ?> </label> <label style="color: white;"> <input type="radio" name="compra-susc" value="premium-ok"/> Resto para suscripción Premium de $10000: $ <?php echo $suma_premium; ?> </label> <p class="enlace-ver-susc" style="font-size: 1.2em; margin-top: 50px;">Ver nuestras <a href="/suscripciones" style="color: #c207b2;">Suscripciones</a> </p> <div style="display: flex; justify-content: space-between; margin-top: 30px;"> <button type="submit" class="btn" style="width: 200px; height: 40px; padding: 0px 12px 4px 12px; background-color: #9ce52e !important; color: #1f2614;"> Aceptar </button> <button type="button" class="btn btn-default" data-dismiss="modal" style="width: 200px; padding: 0; margin-right: 0;"> <a href="<?php echo get_permalink(); ?>?compra-susc=cancel" style="display: block; height: 38px; border: 2px solid #9ce52e !important; background-color: #202020; color: #9ce52e !important;">Cancelar</a> </button> </div> </form> </div> </div> </div> </div> <style> #modalExtraParaSusc { display: block; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1050; outline: 0; transition: opacity .15s linear; background-color: rgb(0 0 0 / 60%); overflow-x: hidden; overflow-y: auto; } #modalExtraParaSusc > div { margin-top: calc((100vh - 536px) /2) !important; max-width: 500px; margin: 1.75rem auto; position: relative; width: auto; } </style> <?php } // 根据会话添加对应费用 if ( $compra_susc == 'clasica-ok' ) { $additional_fee_name = "Resto para suscripción Clásica"; $extra_fee = $suma_clasica; $additional_fee_taxable = true; $addedFee = false; foreach ( $cart->get_fees() as $_fee ) { if ( $_fee->id == sanitize_title($additional_fee_name) ) { $_fee->amount = (float) $extra_fee; $_fee->taxable = $additional_fee_taxable; $addedFee = true; } } if ( !$addedFee ) { $cart->add_fee( __($additional_fee_name, "woocommerce"), $extra_fee, $additional_fee_taxable ); } } if ( $compra_susc == 'premium-ok' ) { $additional_fee_name = "Resto para suscripción Premium"; $extra_fee = $suma_premium; $additional_fee_taxable = true; $addedFee = false; foreach ( $cart->get_fees() as $_fee ) { if ( $_fee->id == sanitize_title($additional_fee_name) ) { $_fee->amount = (float) $extra_fee; $_fee->taxable = $additional_fee_taxable; $addedFee = true; } } if ( !$addedFee ) { $cart->add_fee( __($additional_fee_name, "woocommerce"), $extra_fee, $additional_fee_taxable ); } } } } // 确保会话初始化(兼容部分主题) add_action( 'init', 'init_compra_susc_session' ); function init_compra_susc_session() { if ( ! is_admin() && isset( WC()->session ) && ! WC()->session->has_session() ) { WC()->session->set_customer_session_cookie( true ); } }
关键修改点
- 会话存储替代URL参数:用
WC()->session->set()和WC()->session->get()存储用户选择,确保跨页面和AJAX请求都能读取 - 表单提交处理:添加参数验证和重定向,避免重复提交,同时更新会话状态
- 模态框显示控制:仅在购物车页且用户未选择时显示,避免结算页干扰
- 会话初始化:添加
init钩子确保会话正常工作,兼容部分主题 - 移除硬编码URL:用
get_permalink()动态获取页面URL,提升代码可移植性
效果验证
- 购物车页选择订阅补差价选项,费用成功添加
- 切换到结算页,费用持续存在
- 变更配送/支付方式,购物车更新后费用不消失
- 点击取消按钮,费用移除,模态框重新显示(满足条件时)
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

