4

基于Woocommerce 结帐分析代码中的单选按钮动态更新费用。我正在尝试使其与 WooCommerce 结帐时的不同包装选项一起使用。

这个想法是能够提供礼品包装、袋装等选项。

问题是,它为我提供了可选择的选项,但是因为它正在打印标签的 HTML 而不是什么,所以一切都搞砸了。

这是我正在使用的代码:

add_action( 'woocommerce_form_field_radio', 'gift_bag_none', 20, 4 );
function gift_bag_none( $field, $key, $args, $value ) {
if ( ! empty( $args['options'] ) && is_checkout() ) {
$field = str_replace( '</label><input ', '</label><br><input ', $field );
$field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
}
return $field;
}

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

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

        if( $packing_fee === 'box' )
            $fee = 29.00;
    
            else if( $packing_fee === 'none' )
            $fee = 0.00;
        
            else if( $packing_fee === 'both' )
        
            $fee = 25.00;
        else
        $fee = 5.00;

    $cart->add_fee( __( 'Packaging Cost', 'woocommerce' ), $fee );
}

add_action( 'woocommerce_review_order_after_shipping', 'checkout_packing_addition', 20 );
function checkout_packing_addition() {

    $domain = 'woocommerce';

    echo '<tr><th>' . __('Packaging Options', $domain) . '</th><td>';

    echo '<tr class="packing-select"><th>' . __('In a bag?<br>Boxed and wrapped as gift?<br><span style="color:red;">Boxed, wrapped and in a bag?</span><br>Or just the product?', $domain) . '</th><td>';

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

    $chosen = empty($chosen) ? WC()->checkout->get_value('radio_packing') : $chosen;

    $chosen = empty($chosen) ? 'none' : $chosen;

    woocommerce_form_field( 'radio_packing', array(
    'type' => 'radio',
    'class' => array( 'form-row-wide packing' ),
    'options' => array(
    'bag' => __('Yes, give it to me in a bag for '.wc_price(5.00), $domain),
    'box' => __('Giftbox + Wrapping for '.wc_price(29.00), $domain),
    'both' => __('Wrapped Giftbox in a Bag for '.wc_price(25.00), $domain),
    'none' => __('Just the product at no extra cost '.wc_price(0.00), $domain)
    ),
    'default' => $chosen,
    ), $chosen );
    echo '</td></tr>';
}

add_action( 'wp_footer', 'checkout_packing_script' );
function checkout_packing_script(){ ?>

    <script type="text/javascript">
    jQuery( function($) {

        $('form.checkout').on('change', 'input[name=radio_packing]', function(e){

            e.preventDefault();

            var p = $(this).val();

            $.ajax({

                type: 'POST',

                url: wc_checkout_params.ajax_url,

                data: {
    'action': 'woo_get_ajax_data',
    'packing': p,
    },

        success: function (result) {
    
            $('body').trigger('update_checkout');
    
        },
    
        error: function(error){
        }
    });
    });
    });
</script>
<?php
}

add_action('wp_ajax_woo_get_ajax_data', 'packing_ajax_data');
add_action('wp_ajax_nopriv_woo_get_ajax_data', 'packing_ajax_data');
function packing_ajax_data() {

    if ( isset($_POST['packing']) ){

        $packing = sanitize_key( $_POST['packing'] );

        WC()->session->set('chosen_packing', $packing );

        echo json_encode( $packing );
}
    die();
}
4

1 回答 1

4

更新:10/2021 - 在 WordPress 5.8.1 和 WooCommerce 5.7.1 中测试


你的代码有一些小错误

  • 使用add_filter( 'woocommerce_form_field_radio'代替add_action(..
  • 使用strip_tags( wc_price() )反对wc_price()

所以你得到:

// Customizing WooCommerce radio form field
function filter_woocommerce_form_field_radio( $field, $key, $args, $value ) {   
    // Specific key and apply on checkout page
    if ( ! empty( $args['options'] ) && $key == 'radio_packing' && is_checkout() ) {
        $field = str_replace( '</label><input ', '</label><br><input ', $field );
        $field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
    }
    
    return $field;
}
add_filter( 'woocommerce_form_field_radio', 'filter_woocommerce_form_field_radio', 20, 4 );

function action_woocommerce_cart_calculate_fees( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    
    // Dynamic packing fee
    $packing_fee = WC()->session->get( 'chosen_packing' );
    
    // Determine packing fee
    if ( $packing_fee === 'bag' ) {
        $fee = 5.00;
    } else if( $packing_fee === 'box' ) {
        $fee = 29.00;
    } else if( $packing_fee === 'both' ) {
        $fee = 25.00;
    } else {
        $fee = 0.00;
    }
    
    // Add fee: name - amount - taxable 
    $cart->add_fee( __( 'Packaging fee', 'woocommerce' ), $fee, true );
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );

// Add a custom radio fields for packaging selection
function action_woocommerce_review_order_after_shipping() {
    // Domain
    $domain = 'woocommerce';

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

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

    $chosen = empty( $chosen ) ? WC()->checkout->get_value( 'radio_packing' ) : $chosen;

    $chosen = empty( $chosen ) ? 'none' : $chosen;

    // Add a custom checkbox field
    woocommerce_form_field( 'radio_packing', array(
        'type'      => 'radio',
        'class'     => array( 'form-row-wide packing' ),
        'options'   => array(
            'bag'       => sprintf( __( 'Yes, give it to me in a bag for %s', $domain ), strip_tags( wc_price( 5.00 ) ) ),
            'box'       => sprintf( __( 'Giftbox + Wrapping for %s', $domain ), strip_tags( wc_price( 29.00 ) ) ),
            'both'      => sprintf( __( 'Wrapped Giftbox in a Bag for %s', $domain ), strip_tags( wc_price( 25.00 ) ) ),
            'none'      => sprintf( __( 'Just the product at no extra cost %s', $domain ), strip_tags( wc_price( 0.00 ) ) )
        ),
        'default'   => $chosen,
    ), $chosen );
    
    echo '</td></tr>';
}
add_action( 'woocommerce_review_order_after_shipping', 'action_woocommerce_review_order_after_shipping', 10, 0 );

// jQuery - Ajax script
function action_wp_footer() {
    if ( ! is_checkout() )
        return; // Only checkout page
    ?>
    <script type="text/javascript">
    jQuery( function($){
        $('form.checkout').on('change', 'input[name=radio_packing]', function(e){
            e.preventDefault();
            var p = $(this).val();
            $.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

}
add_action( 'wp_footer', 'action_wp_footer', 10, 0 );

// Php Ajax (Receiving request and saving to WC session)
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(); // Always at the end (to avoid server error 500)
}
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' );
于 2021-05-10T07:31:56.613 回答