Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
517 views
in Technique[技术] by (71.8m points)

php - Remove shipping cost if custom checkbox is checked in WooCommerce Checkout

I am trying to set the price of shipping rates to $0.00 if a checkbox in the checkout fields is checked.

Current Attempt:

function no_shipping_for_own_ups($rates,$package) {
    foreach ($rates as $rate) {
        //Set the price
        $rate->cost = 0;
    }
    return $rates;
}

function woo_add_cart_ups_y_n_fee( $cart ){
    if ( ! $_POST || ( is_admin() && ! is_ajax() ) ) {
        return;
    }

    if ( isset( $_POST['post_data'] ) ) {
        parse_str( $_POST['post_data'], $post_data );
    } else {
        $post_data = $_POST;
    }

    if (isset($post_data['billing_ups_yn'])) {
        add_filter( 'woocommerce_package_rates','no_shipping_for_own_ups', 99, 2 );
    }
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_ups_y_n_fee', 43, 1 );

As $post_data['billing_ups_yn'] being the checkbox that I set to update the checkout when triggered.

Simply if the checkbox is checked, then apply the filter to set shipping rates to 0.
This, however, isn't working.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

To alter shipping methods cost via Ajax on a custom javascript event in checkout page is quiet more complicated than conditionally altering fees or anything else as you will see below.

To store the Ajax data I use WC_Sessions and to alter Shipping methods costs will only work if you manipulate the shipping sessions data

The full working code:

// Add a Custom checkbox field for shipping options (just for testing)
add_action( 'woocommerce_after_checkout_billing_form', 'custom_billing_checkbox_for_testing', 10, 1 );
function custom_billing_checkbox_for_testing( $checkout ) {
    $field_id = 'billing_ups_yn';

    // Get the checked state if exist
    $billing_ups = WC()->session->get('billing_ups' );
    if(empty($billing_ups))
        $billing_ups = $checkout->get_value( $field_id );

    // Add the custom checkout field (checkbox)
    woocommerce_form_field( $field_id, array(
        'type' => 'checkbox',
        'class' => array( 'form-row-wide' ),
        'label' => __('Billing UPS'),
    ), $billing_ups );
}

// function that gets the Ajax data
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 ( $_POST['billing_ups'] == '1' ){
        WC()->session->set('billing_ups', '1' );
    } else {
        WC()->session->set('billing_ups', '0' );
    }
    echo json_encode( WC()->session->get('billing_ups' ) );
    die(); // Alway at the end (to avoid server error 500)
}

// Conditionally changing the shipping methods costs
add_filter( 'woocommerce_package_rates','conditional_custom_shipping_cost', 90, 2 );
function conditional_custom_shipping_cost( $rates, $package ) {

    if ( WC()->session->get('billing_ups' ) == '1' ){
        foreach ( $rates as $rate_key => $rate_values ) {
            // Not for "Free Shipping method" (all others only)
            if ( 'free_shipping' !== $rate_values->method_id ) {

                // Set the rate cost
                $rates[$rate_key]->cost = 0;

                // Set taxes rate cost (if enabled)
                $taxes = array();
                foreach ($rates[$rate_key]->taxes as $key => $tax)
                    if( $rates[$rate_key]->taxes[$key] > 0 ) // set the new tax cost
                        $taxes[$key] = 0;
                $rates[$rate_key]->taxes = $taxes;
            }
        }
    }
    return $rates;
}

// Enabling, disabling and refreshing session shipping methods data
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
    $bool = true;
    if ( WC()->session->get('billing_ups' ) == '1' ) $bool = false;

    // Mandatory to make it work with shipping methods
    foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
        WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
    }
    WC()->cart->calculate_shipping();
}

// The Jquery script
add_action( 'wp_footer', 'custom_checkout_script' );
function custom_checkout_script() {
    ?>
    <script type="text/javascript">
        jQuery( function($){

            // update cart on delivery location checkbox option
            $('#billing_ups_yn_field input').change( function () {
                var checked = 0;
                if ( $('#billing_ups_yn').is(':checked') )
                    checked = 1;

                $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action': 'woo_get_ajax_data',
                        'billing_ups': checked,
                    },
                    success: function (result) {
                        $('body').trigger('update_checkout');
                        console.log('response: '+result); // just for testing
                    },
                    error: function(error){
                        console.log(error); // just for testing
                    }
                });
            });
        });
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or active theme).

Tested and works.


Update related to your comment:

If you wish to have always the checkbox unchecked by default at load you will replace the first function by this one:

// Add a Custom checkbox field for shipping options (just for testing)
add_action( 'woocommerce_after_checkout_billing_form', 'custom_billing_checkbox_for_testing', 10, 1 );
function custom_billing_checkbox_for_testing( $checkout ) {
    $field_id = 'billing_ups_yn';

    // Add the custom checkout field (checkbox)
    woocommerce_form_field( $field_id, array(
        'type' => 'checkbox',
        'class' => array( 'form-row-wide' ),
        'label' => __('Billing UPS'),
    ), '' );
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...