search

Home  >  Q&A  >  body text

Dynamic way to update shipping method price in WooCommerce

<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粉605233764P粉605233764487 days ago537

reply all(1)I'll reply

  • P粉718165540

    P粉7181655402023-08-14 11:18:03

    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

    reply
    0
  • Cancelreply