3

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

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Fabricio
  • 306
  • 1
  • 2
  • 12

1 Answers1

3

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.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399