Search code examples
phpwordpresswoocommercedistanceshipping-method

Custom WooCommerce shipping Method and distance rate value issue


I'm trying to calculate shipping rate based on distance by KM on Woocommerce by sending the total distance to an external API, so, for this purpose I have this function inside my own shipping plugin:

public function calculate_shipping( $packages = array() ) {
                    wp_parse_str( $_POST['post_data'], $post_data );

                    $cURLConnection = curl_init();

                    curl_setopt($cURLConnection, CURLOPT_URL, $this->url_api.$post_data["distancia_billing"]);
                    curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER, true);

                    $datos = curl_exec($cURLConnection);
                    curl_close($cURLConnection);

                    $jsonArrayResponse = json_decode($datos, true);

                    $rate = array(
                        'id'       => $this->id,
                        'label'    => $this->title,
                        'cost'     => isset($jsonArrayResponse["precio"]) ? $jsonArrayResponse["precio"] : '10.00',
                        'calc_tax' => 'per_order'
                    );
                    $this->add_rate( $rate );
                    
                }

Works well and show the correct price during the checkout proccess, but when the user finish the checkout proccess and I check the order on my Woocommerce panel always shows the default value (10.00) instead the calculated value on the API.

I'm missing anything on my function?

Thanks


Solution

  • You need to set the cost to a WC_Session variable to avoid loosing the distance calculated cost value, so your function code should be:

                public function calculate_shipping( $packages = array() ) {
                    wp_parse_str( $_POST['post_data'], $post_data );
    
                    $cURLConnection = curl_init();
    
                    curl_setopt($cURLConnection, CURLOPT_URL, $this->url_api.$post_data["distancia_billing"]);
                    curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER, true);
    
                    $datos = curl_exec($cURLConnection);
                    curl_close($cURLConnection);
    
                    $jsonArrayResponse = json_decode($datos, true);
                    
                    if( isset($jsonArrayResponse["precio"]) && ! empty($jsonArrayResponse["precio"]) && isset(WC()->session) ) {
                        WC()->session->set('shipping_distance_cost', floatval($jsonArrayResponse["precio"]) );
                    }
    
                    $this->add_rate( array(
                        'id'       => $this->id,
                        'label'    => $this->title,
                        'cost'     => WC()->session->__isset('shipping_distance_cost') ? WC()->session->get('shipping_distance_cost') : '10.00',
                        'calc_tax' => 'per_order'
                    ) );
                }
    

    But you should need to remove that session variable when order has been created, so outside your shipping class code, add the following:

    add_action( 'woocommerce_checkout_order_created', 'remove_wc_session_shipping_distance_cost' );
    function remove_wc_session_shipping_distance_cost( $order ) {
        if ( WC()->session->__isset('shipping_distance_cost') ) {
            WC()->session->__unset('shipping_distance_cost')
        }
    }
    

    It should work.