WC_Connect_API_Client::get_shipping_rates PHP Method

get_shipping_rates() public method

Gets shipping rates (for checkout) from the Connect for WooCommerce Server
public get_shipping_rates ( $services, $package, $boxes ) : object | WP_Error
$services All settings for all services we want rates for
$package Package provided to WC_Shipping_Method::calculate_shipping()
return object | WP_Error
        public function get_shipping_rates($services, $package, $boxes)
        {
            // First, build the contents array
            // each item needs to specify quantity, weight, length, width and height
            $contents = array();
            foreach ($package['contents'] as $item_id => $values) {
                $product_id = absint($values['data']->id);
                $product = wc_get_product($product_id);
                if ($values['quantity'] > 0 && $product->needs_shipping()) {
                    if (!$product->has_weight()) {
                        return new WP_Error('product_missing_weight', sprintf("Product ( ID: %d ) did not include a weight. Shipping rates cannot be calculated.", $product_id));
                    }
                    $height = 0;
                    $length = 0;
                    $weight = $product->get_weight();
                    $width = 0;
                    if ($product->has_dimensions()) {
                        $height = $product->get_height();
                        $length = $product->get_length();
                        $width = $product->get_width();
                    }
                    $contents[] = array('height' => $height, 'product_id' => isset($values['data']->variation_id) ? $values['data']->variation_id : $values['data']->id, 'length' => $length, 'quantity' => $values['quantity'], 'weight' => $weight, 'width' => $width);
                }
            }
            if (empty($contents)) {
                return new WP_Error('nothing_to_ship', 'No shipping rate could be calculated. No items in the package are shippable.');
            }
            // Then, make the request
            $body = array('contents' => $contents, 'destination' => $package['destination'], 'services' => $services, 'boxes' => $boxes);
            return $this->request('POST', '/shipping/rates', $body);
        }

Usage Example

 public function calculate_shipping($package = array())
 {
     if (!$this->is_valid_package_destination($package)) {
         return;
     }
     $service_settings = $this->get_service_settings();
     $settings_keys = get_object_vars($service_settings);
     if (empty($settings_keys)) {
         return $this->log(sprintf('Service settings empty. Skipping %s rate request (instance id %d).', $this->id, $this->instance_id), __FUNCTION__);
     }
     // TODO: Request rates for all Connect for WooCommerce powered methods in
     // the current shipping zone to avoid each method making an independent request
     $services = array(array('id' => $this->id, 'instance' => $this->instance_id, 'service_settings' => $service_settings));
     $boxes = $this->service_settings_store->get_packages();
     $response_body = $this->api_client->get_shipping_rates($services, $package, $boxes);
     if (is_wp_error($response_body)) {
         $this->log(sprintf('Error. Unable to get shipping rate(s) for %s instance id %d.', $this->id, $this->instance_id), __FUNCTION__);
         $this->set_last_request_failed();
         $this->log($response_body, __FUNCTION__);
         return;
     }
     if (!property_exists($response_body, 'rates')) {
         $this->set_last_request_failed();
         return;
     }
     $instances = $response_body->rates;
     foreach ((array) $instances as $instance) {
         if (!property_exists($instance, 'rates')) {
             continue;
         }
         $packaging_lookup = $this->service_settings_store->get_package_lookup_for_service($instance->id);
         foreach ((array) $instance->rates as $rate_idx => $rate) {
             $package_names = array();
             foreach ($rate->packages as $rate_package) {
                 $package_format = '';
                 $items = array();
                 foreach ($rate_package->items as $package_item) {
                     $product = $this->lookup_product($package, $package_item->product_id);
                     if ($product) {
                         $items[] = $product->get_title();
                     }
                 }
                 if (!property_exists($rate_package, 'box_id')) {
                     $package_format = __('Unknown package (%s)', 'connectforwoocommerce');
                 } else {
                     if ('individual' === $rate_package->box_id) {
                         $package_format = __('Individual packaging (%s)', 'connectforwoocommerce');
                     } else {
                         if (isset($packaging_lookup[$rate_package->box_id]) && isset($packaging_lookup[$rate_package->box_id]['name'])) {
                             $package_format = $packaging_lookup[$rate_package->box_id]['name'] . ' (%s)';
                         }
                     }
                 }
                 $package_names[] = sprintf($package_format, implode(', ', $items));
             }
             $packaging_info = implode(', ', $package_names);
             $rate_to_add = array('id' => self::format_rate_id($instance->id, $instance->instance, $rate_idx), 'label' => self::format_rate_title($rate->title), 'cost' => $rate->rate, 'calc_tax' => 'per_item', 'meta_data' => array('wc_connect_packages' => json_encode($rate->packages), __('Packaging', 'connectforwoocommerce') => $packaging_info));
             $this->add_rate($rate_to_add);
         }
     }
     $this->update_last_rate_request_timestamp();
     $this->set_last_request_failed(0);
 }