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

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,提升代码可移植性

效果验证

  1. 购物车页选择订阅补差价选项,费用成功添加
  2. 切换到结算页,费用持续存在
  3. 变更配送/支付方式,购物车更新后费用不消失
  4. 点击取消按钮,费用移除,模态框重新显示(满足条件时)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:45:53