首页 > 解决方案 > 如何根据自定义字段动态更改 WooCommerce 结帐中的运费?

问题描述

如何通过 Ajax 请求更改 Woocommerce 中的运费?我试过这个:

add_action('wp_ajax_set_shipping_price', 'set_shipping_price');
add_action('wp_ajax_nopriv_set_shipping_price', 'set_shipping_price');
function set_shipping_price(){
    $packages = WC()->cart->get_shipping_packages();
    foreach ($packages as $package_key => $package){
        $session_key  = 'shipping_for_package_'.$package_key;
        $stored_rates = WC()->session->__unset( $session_key );
        $WC_Shipping = new WC_Shipping();
        $WC_Shipping->calculate_shipping_for_package( $package, $package_key = 0);
        WC()->cart->calculate_shipping();
        WC()->cart->calculate_totals();
    }
    wp_die();
}

和:

add_filter( 'woocommerce_package_rates', 'custom_shipping_costs', 20, 2 );
function custom_shipping_costs( $rates, $package ) {
    if (isset($_POST['cost'])){
        $new_cost = $_POST['cost'];
    }
    $new_cost = 0;
    $tax_rate = 0.2;

    foreach( $rates as $rate_key => $rate ){
        if( $rate->method_id != 'free_shipping'){
            $rates[$rate_key]->cost = $new_cost;
            $taxes = array();
            foreach ($rates[$rate_key]->taxes as $key => $tax){
            if( $rates[$rate_key]->taxes[$key] > 0 )
                $taxes[$key] = $new_cost * $tax_rate;
            }
            $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

该钩子woocommerce_package_rates在页面加载时起作用,但通过 ajax 什么也不做。请帮忙。

标签: wordpresswoocommerce

解决方案


Here is the explanation on how to get post data from an Ajax call.

Additionally, you can use the WooCommerce update_checkout event to update the checkout (and thus recalculate shipping costs) after a field in the checkout has changed or been clicked (instead of creating a custom Ajax call). Here you will find a complete list.

So, assuming you want to recalculate shipping costs when the field with id custom_shipping_price (for example) changes, you can use this script:

// updates the checkout (and shipping charge calculation) when the value of a field changes
add_action( 'wp_footer', 'update_checkout' );
function update_checkout() {

    // only in the checkout
    if ( ! is_checkout() ) {
        return;
    }

    ?>
    <script type="text/javascript">
    jQuery( document ).ready(function( $ ) {
        // when the value of the field with id "custom_shipping_price" changes it updates the checkout
        jQuery('#custom_shipping_price').change(function(){
            jQuery('body').trigger('update_checkout');
        });
    });
    </script>
    <?php
}

Now you will need to use the woocommerce_package_rates hook to calculate the new shipping cost.

Make sure you initialize the value of the $new_cost variable in case the custom field is not set or is empty.

Here the function:

// update the shipping cost based on a custom field in the checkout
add_filter( 'woocommerce_package_rates', 'update_shipping_cost_based_on_custom_field', 10, 2 );
function update_shipping_cost_based_on_custom_field( $rates, $package ) {

    if ( ! $_POST || is_admin() || ! is_ajax() ) {
        return;
    }

    // gets the post serialized data sent with the Ajax call
    if ( isset( $_POST['post_data'] ) ) {
        parse_str( $_POST['post_data'], $post_data );
    } else {
        $post_data = $_POST;
    }
    
    // set the cost of shipping (if the custom field should be empty)
    $new_cost = 0;

    // if the field is set it gets the value
    if ( isset( $post_data['custom_shipping_price'] ) && ! empty( $post_data['custom_shipping_price'] ) ) {
        // forces conversion of value into number
        $new_cost = (float) str_replace( ',', '.', $post_data['custom_shipping_price'] );
    }
    // set the percentage of taxes (ex. 22%)
    $tax_rate = 0.22;

    foreach( $rates as $rate_key => $rate ) {
        if ( 'free_shipping' !== $rate->method_id ) {
            // set rate cost
            $rates[$rate_key]->cost = $new_cost;
            // set taxes rate cost (if enabled)
            $taxes = array();
            foreach ( $rates[$rate_key]->taxes as $key => $tax ) {
                if ( $rates[$rate_key]->taxes[$key] > 0 ) {
                    $taxes[$key] = $new_cost * $tax_rate;
                }
            }
            $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

Both codes have been tested and work. Add them to your active theme's functions.php.


推荐阅读