根据 WooCommerce Checkout 中的选择字段添加动态费用

Posted

技术标签:

【中文标题】根据 WooCommerce Checkout 中的选择字段添加动态费用【英文标题】:Add a dynamic fee based on a select field in WooCommerce Checkout 【发布时间】:2020-01-05 22:49:16 【问题描述】:

我正在使用 Update fee dynamically based on radio buttons in Woocommerce checkout 答案代码解决方案,该解决方案非常适合我为每个复选框添加不同价格的字段,并且价格变化会反映在结帐中。

但是我需要一些帮助:当我选择了一种附加税的包装时,它出现在后端的订单区,但只显示价格,我想显示标题也是。

复选框选项有:

'options' => array (
    'bag' => __ ('In a bag' .wc_price (3.00), $ domain),
    'box' => __ ('In a gift box' .wc_price (9.00), $ domain),
),

如何让它在订单上显示名字? 另外是否可以将复选框更改为选择字段?

【问题讨论】:

【参考方案1】:

我对原始代码进行了一些更改:

显示自定义选择字段(而不是单选按钮输入字段) 如果客户未选择包装选项,则显示自定义错误通知 在任何地方显示所选的包装类型(在订单和电子邮件通知上)

代码:

// Add a custom select fields for packing option fee
add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_form_packing_addition', 20 );
function checkout_shipping_form_packing_addition( ) 
    $domain = 'woocommerce';

    echo '<tr class="packing-select"><th>' . __('Packing options', $domain) . '</th><td>';

    $chosen   = WC()->session->get('chosen_packing');

    // Add a custom checkbox field
    woocommerce_form_field( 'chosen_packing', array(
        'type'      => 'select',
        'class'     => array( 'form-row-wide packing' ),
        'options'   => array(
            ''    => __("Choose a packing option ...", $domain),
            'bag' => sprintf( __("In a bag (%s)", $domain), strip_tags( wc_price(3.00) ) ),
            'box' => sprintf( __("In a gift box (%s)", $domain), strip_tags( wc_price(9.00) ) ),
        ),
        'required'  => true,
    ), $chosen );

    echo '</td></tr>';


// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_shipping_packing_script' );
function checkout_shipping_packing_script() 
    // Only checkout page
    if ( is_checkout() && ! is_wc_endpoint_url() ) :

    WC()->session->__unset('chosen_packing');
    ?>
    <script type="text/javascript">
    jQuery( function($)
        $('form.checkout').on('change', 'select#chosen_packing', function()
            var p = $(this).val();
            console.log(p);
            $.ajax(
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: 
                    'action': 'woo_get_ajax_data',
                    'packing': p,
                ,
                success: function (result) 
                    $('body').trigger('update_checkout');
                    console.log('response: '+result); // just for testing | TO BE REMOVED
                ,
                error: function(error)
                    console.log(error); // just for testing | TO BE REMOVED
                
            );
        );
    );
    </script>
    <?php
    endif;


// Php Ajax (Receiving request and saving to WC session)
add_action( 'wp_ajax_woo_get_ajax_data', 'woo_get_ajax_data' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'woo_get_ajax_data' );
function woo_get_ajax_data() 
    if ( isset($_POST['packing']) )
        $packing = sanitize_key( $_POST['packing'] );
        WC()->session->set('chosen_packing', $packing );
        echo json_encode( $packing );
    
    die(); // Alway at the end (to avoid server error 500)


// Add a custom dynamic packaging fee
add_action( 'woocommerce_cart_calculate_fees', 'add_packaging_fee', 20, 1 );
function add_packaging_fee( $cart ) 
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $domain      = "woocommerce";
    $packing_fee = WC()->session->get( 'chosen_packing' ); // Dynamic packing fee

    if ( $packing_fee === 'bag' ) 
        $label = __("Bag packing fee", $domain);
        $cost  = 3.00;
     elseif ( $packing_fee === 'box' ) 
        $label = __("Gift box packing fee", $domain);
        $cost  = 9.00;
    

    if ( isset($cost) )
        $cart->add_fee( $label, $cost );


// Field validation, as this packing field is required
add_action('woocommerce_checkout_process', 'packing_field_checkout_process');
function packing_field_checkout_process() 
    // Check if set, if its not set add an error.
    if ( isset($_POST['chosen_packing']) && empty($_POST['chosen_packing']) )
        wc_add_notice( __( "Please choose a packing option...", "woocommerce" ), 'error' );

代码在您的活动子主题(或活动主题)的functions.php 文件中。经过测试并且可以工作。

客户未选择包装选项时的错误消息:

【讨论】:

太好了,非常感谢,我已经尝试过了,它完全符合我的需要。我只做了一个很小的修改,因此它也允许从总数中减去一个值,因为最初如果这是负数 (-),那么什么都不会显示。非常感谢您的宝贵帮助! @kamuran 我更新了代码以处理负成本费用。在add_packaging_fee() 功能代码中将if ( isset($cost) &amp;&amp; $cost &gt; 0 ) 替换为if ( isset($cost) )。它现在应该可以工作了。 感谢您的代码,我试图通过更改挂钩名称将此 sn-p 的位置从结帐页面更改为购物车。但没有成功 woocommerce_cart_calculate_fees ..我做错了什么?

以上是关于根据 WooCommerce Checkout 中的选择字段添加动态费用的主要内容,如果未能解决你的问题,请参考以下文章

Woocommerce Checkout:在国家下拉列表中添加占位符[重复]

支付网关未触发 woocommerce_payment_complete 和 woocommerce_after_checkout_validation 挂钩

根据 Woocommerce 3 中的运输方式显示或隐藏结帐字段

根据排除某些产品的 WooCommerce 购物车小计自动应用优惠券

如何删除 Woocommerce Checkout 页面中的“Hello Member”?

php 更改YITH PayPal Express Checkout for WooCommerce的Set Express Checkout Request参数