Dynamic way to update shipping method price in WooCommerce
P粉605233764
P粉605233764 2023-08-13 18:08:43
0
1
521
<p>I'm trying to dynamically update shipping prices for my shipping methods. I get the shipping price from the api and want to update the price when I successfully get the price from the api response. I'm using the following code: </p> <pre class="brush:php;toolbar:false;">function handle_api_response( $rates ) { //The api calling code is here..... if ($response_code === 200){ $response_data = json_decode($response, true); $price = $response_data['shipments'] } add_filter( 'woocommerce_package_rates', 'set_shipping_prices', PHP_INT_MAX, 1 ); function set_shipping_prices( $rates ) { foreach ( $rates as $rate_id => $rate ) { $rates[ $rate_id ]->cost = $price; } return $rates; } }</pre> <p>The above code doesn't work, but if I move the filter out of the handle_api_response function and set some static value to the fee, it seems to work. Like this: </p> <pre class="brush:php;toolbar:false;">function handle_api_response( $rates ) { //The api calling code is here..... if ($response_code === 200){ $response_data = json_decode($response, true); $price = $response_data['shipments'] } } add_filter( 'woocommerce_package_rates', 'set_shipping_prices', PHP_INT_MAX, 1 ); function set_shipping_prices( $rates ) { foreach ( $rates as $rate_id => $rate ) { $rates[ $rate_id ]->cost = 50; } return $rates; }</pre> <p>My problem is that since I'm getting the price value from the api, I need to pass the price from the api response to the set_shipping_prices function that runs when the filter is triggered. </p>
P粉605233764
P粉605233764

reply all(1)
P粉718165540

This code is untested and may need some tweaking, but it can be the correct path to make your external API calls work.

We can try to use the WC_Session variable to set the shipping fee we want to pass:

function handle_api_response( $rates ) {

    // 在这里编写API调用代码.....
 
    if ($response_code === 200){
        $response_data = json_decode($response, true);
        $cost = $response_data['shipments'];
         
        if ( $cost > 0 ) {
            // 将费用设置为WC Session变量
            WC()->session->set('shipment_cost', floatval($cost));

            // 尝试触发“更新结账”Ajax事件
            ?><script>jQuery('body').trigger('update_checkout');</script><?php
        }
    }
}

Then we can call the WC_Session variable in your hook function:

add_filter('woocommerce_package_rates', 'update_shipping_costs', 10, 2);
function update_shipping_costs( $rates, $package ) {
    foreach ( $rates as $rate_id => $rate ) {
        // 从Session变量中获取新的费用
        $new_cost = WC()->session->get('shipment_cost');

        if( isset($rate->cost) && $rate->cost > 0 && $new_cost > 0 ) {
            $rates[ $rate_id ]->cost = $new_cost; // 设置新的费用
        }
    }
    return $rates;
}

However, we need something else to refresh the cached shipping method in order for it to take effect:

add_action('woocommerce_checkout_update_order_review', 'refresh_shipping_methods');
function refresh_shipping_methods( $post_data ){
    $bool = true;

    // 我们检查Session变量
    if ( WC()->session->get('shipment_cost') > 0 ) {
        $bool = false;
    }

    // 与运输方法一起使用时是必需的
    foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
        WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
    }
    WC()->cart->calculate_shipping();
}

Finally, we unset the WC Session variable (on checkout first load and thank you page) :

add_action('wp_footer', 'reset_wc_session_variable');
function reset_wc_session_variable() {
    if (is_checkout() && WC()->session->get('shipment_cost') > 0) {
        WC()->session->__unset('shipment_cost');
    }
}

Put the code into your child theme's functions.php file (or into a plugin). It may work.

Related: Remove shipping costs after checking custom checkbox in WooCommerce checkout

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template