Reputation: 153
I have created a custom shipping method that calculates the cost of shipping from an external shipping API. I have followed the instructions found here (Woocommerce docs) and here(Tutsplus).
I have added the shipping rate as shown below
//...
public function calculate_shipping( $package ) {
//...
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => $cost //calculated based on the distance
);
$this->add_rate( $rate );
}
//...
Everything works fine up to the point where the customer has to complete the order, then the items in the cart are the only ones included in the order total.
The shipping method and cost are visible in the cart confirmation section but once the order is confirmed, the cost is not included in the order and the receipt.
The shipping method is recorded but the cost is not included.
Edit... Here is my entire shipping plugin file
<?php
/*
Woocommerce plugin details
*/
if (!defined('ABSPATH')) {
exit;
// Exit if accessed directly
}
/**
* Check if WooCommerce is active
**/
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
function my_shipping_method()
{
if (!class_exists('my_shipping_method')) {
class my_shipping_method extends WC_Shipping_Method
{
/**
* Constructor for the shipping class
*
* @access public
* @return void
*/
public function __construct()
{
$this->id = 'my_shipping_method';
$this->method_title = __('Custom Ondemand Shipping', 'my_shipping_method');
$this->method_description = __('Custom Shipping Method for Custom Ondemand', 'my_shipping_method');
// Availability & Countries
$this->availability = 'including';
$this->countries = array('KE');
$this->init();
$this->enabled = isset($this->settings['enabled']) ? $this->settings['enabled'] : 'yes';
$this->title = isset($this->settings['title']) ? $this->settings['title'] : __('Custom Ondemand Shipping', 'my_shipping_method');
$this->API_username = isset($this->settings['API_username']) ? $this->settings['API_username'] : 'myusername';
$this->API_key = isset($this->settings['API_key']) ? $this->settings['API_key'] : 'mykey';
$this->CUSTOM_LIVE_URL = 'https://api.custom.com/v1';
$this->CUSTOM_TEST_URL = 'https://apitest.custom.com/v1/';
$this->CUSTOM_URL = (isset($this->settingd['USE_LIVE_API']) && $this->settingd['USE_LIVE_API'] == 'yes' )? $this->CUSTOM_LIVE_URL : $this->CUSTOM_TEST_URL;
}
/**
* Init the settings
*
* @access public
* @return void
*/
function init()
{
// Load the settings API
$this->init_form_fields();
$this->init_settings();
// Save settings in admin if you have any defined
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
//register google maps places library
wp_register_script('mapsPlaces', 'https://maps.googleapis.com/maps/api/js?key=' . $this->settings['maps_API_key'] . '&libraries=places', array(), false);
wp_register_style('main_style', plugins_url('css/my_shipping_method-woocommerce.css', __FILE__));
wp_enqueue_style('main_style');
}
/**
* Define settings field for this shipping
* @return void
*/
function init_form_fields()
{
$this->form_fields = array(
'enabled' => array(
'title' => __('Enable', 'my_shipping_method'),
'type' => 'checkbox',
'description' => __('Enable this shipping method.', 'my_shipping_method'),
'default' => 'yes'
),
'USE_LIVE_API' => array(
'title' => __('Use Live API', 'my_shipping_method'),
'type' => 'checkbox',
'description' => __('Check if you want to use the live API or uncheck to use the test API.', 'my_shipping_method'),
'default' => 'yes'
),
'title' => array(
'title' => __('Title', 'my_shipping_method'),
'type' => 'text',
'description' => __('Title displayed to users', 'my_shipping_method'),
'default' => __('Custom Ondemand', 'my_shipping_method')
),
'API_username' => array(
'title' => __('Custom Ondemand username', 'my_shipping_method'),
'type' => 'text',
'description' => __('Custom Ondemand merchant username. You can signup here <a href="http://custom.com">http://custom.com</a>', 'my_shipping_method'),
'default' => __('myusername', 'my_shipping_method')
),
'API_key' => array(
'title' => __('Custom Ondemand API key', 'my_shipping_method'),
'type' => 'text',
'description' => __('Custom Ondemand merchant API key. You can find it in your Custom Ondemand merchant profile', 'my_shipping_method'),
'default' => __('mykey', 'my_shipping_method')
),
'maps_API_key' => array(
'title' => __('Maps API key', 'my_shipping_method'),
'type' => 'text',
'description' => __('Google maps API key. You can find it Go to the <a href="https://console.developers.google.com/project/_/apiui/apis/enabled">Google API Console</a>' .
'Click the Select a project button, then select the same project you set up for the Google Maps JavaScript API and click Open.' .
'From the list of APIs on the Dashboard, look for Google Places API Web Service.' .
'If you see the API in the list, you are all set. If the API is not listed, enable it:' .
'At the top of the page, select ENABLE API to display the Library tab. Alternatively, from the left side menu, select Library.' .
'Search for Google Places API Web Service, then select it from the results list.' .
'Select ENABLE. When the process finishes, Google Places API Web Service appears in the list of APIs on the Dashboard.'
, 'my_shipping_method'),
'default' => __('mapskey', 'my_shipping_method')
),
);
}
/**
* This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters.
*
* @access public
* @param mixed $package
* @return void
*/
public function calculate_shipping($package = Array())
{
$cost = 150;
$weight = 0;
parse_str($_POST['post_data'], $order_data);
$to_name = "";
$to_lat = "";
$to_long = "";
$recepient_name = "";
$recepient_phone = "";
$recepient_email = "";
if ($order_data['ship_to_different_address']) {
$to_name = $order_data['shipping_address_1'];
$to_lat = $order_data['shipping_lat'];
$to_long = $order_data['shipping_lng'];
$recepient_name = $order_data['shipping_first_name'] . " " . $order_data['shipping_last_name'];
$recepient_phone = isset($order_data['shipping_phone']) ? $order_data['shipping_phone'] : $order_data['billing_phone'];
$recepient_email = isset($order_data['shipping_email']) ? $order_data['shipping_email'] : $order_data['billing_email'];
} else {
$to_name = $order_data['billing_address_1'];
$to_lat = $order_data['billing_lat'];
$to_long = $order_data['billing_lng'];
$recepient_name = $order_data['billing_first_name'] . " " . $order_data['billing_last_name'];
$recepient_phone = $order_data['billing_phone'];
$recepient_email = $order_data['billing_email'];
}
foreach ($package['contents'] as $item_id => $values) {
$_product = $values['data'];
if ($_product->has_weight()) {
$weight = $weight + $_product->weight() * $values['quantity'];
}
}
$api_username = $this->settings['API_username'];
$api_key = $this->settings['API_key'];
$data = '';//data passed to the api. Tested to be okay.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL =>$this->CUSTOM_URL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
"content-type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
$cost = 200;
} else {
// echo $response;
$result = json_decode($response, true);
$cost = $result['data']['amount'];
}
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => $cost
);
$this->add_rate($rate);
}
}
}
}
add_action('woocommerce_shipping_init', 'my_shipping_method');
function add_my_shipping_method($methods)
{
$methods['my_shipping_method'] = 'my_shipping_method';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_my_shipping_method');
function my_shipping_method_validate_order($posted)
{
$packages = WC()->shipping->get_packages();
$chosen_methods = WC()->session->get('chosen_shipping_methods');
if (is_array($chosen_methods) && in_array('my_shipping_method', $chosen_methods)) {
foreach ($packages as $i => $package) {
if ($chosen_methods[$i] != "my_shipping_method") {
continue;
}
$my_shipping_method = new my_shipping_method();
$weight = 0;
foreach ($package['contents'] as $item_id => $values) {
$_product = $values['data'];
if ($_product->has_weight()) {
$weight = $weight + $_product->weight * $values['quantity'];
}
}
$weight = wc_get_weight($weight, 'kg');
}
}
}
// add_action('woocommerce_review_order_before_cart_contents', 'my_shipping_method_validate_order', 10);
// add_action('woocommerce_after_checkout_validation', 'my_shipping_method_validate_order', 10);
// Hook in
add_filter('woocommerce_checkout_fields', 'my_shipping_method_override_checkout_fields');
// Our hooked in function - $fields is passed via the filter!
function my_shipping_method_override_checkout_fields($fields)
{
// load the autocomplete script
wp_enqueue_script('my_shipping_method-woocommerce', plugin_dir_url(__FILE__) . 'js/my_shipping_method-woocommerce.js', array('mapsPlaces'));
$fields['shipping']['shipping_lat'] = array(
'label' => __('Latitude', 'my_shipping_method'),
'placeholder' => _x('Lat', 'placeholder', 'my_shipping_method'),
'required' => true,
'class' => array('form-row-first', 'placesAutoComplete', 'hidden'),
'label_class' => array('hidden'),
'clear' => true
);
$fields['shipping']['shipping_lng'] = array(
'label' => __('Longitude', 'my_shipping_method'),
'placeholder' => _x('long', 'placeholder', 'my_shipping_method'),
'required' => true,
'class' => array('form-row-last', 'placesAutoComplete', 'hidden'),
'label_class' => array('hidden'),
'clear' => true
);
$fields['billing']['billing_lat'] = array(
'label' => __('Latitude', 'my_shipping_method'),
'placeholder' => _x('Lat', 'placeholder', 'my_shipping_method'),
'required' => true,
'class' => array('form-row-first', 'placesAutoComplete', 'hidden'),
'label_class' => array('hidden'),
'clear' => true
);
$fields['billing']['billing_lng'] = array(
'label' => __('Longitude', 'my_shipping_method'),
'placeholder' => _x('long', 'placeholder', 'my_shipping_method'),
'required' => true,
'class' => array('form-row-last', 'placesAutoComplete', 'hidden'),
'label_class' => array('hidden'),
'clear' => true
);
return $fields;
}
/**
* Display field value on the order edit page
*/
add_action('woocommerce_admin_order_data_after_shipping_address', 'my_shipping_method_custom_checkout_field_display_admin_order_meta', 10, 1);
function my_shipping_method_custom_checkout_field_display_admin_order_meta($order)
{
echo '<p><strong>' . __('Delivery location') . ':</strong> ' . get_post_meta($order->get_id(), '_shipping_location', true) . '</p>';
}
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'location_checkout_field_process');
function location_checkout_field_process()
{
// // Check if set, if its not set add an error.
// if (!$_POST['shipping_location'] && !$_POST['billing_location'])
// wc_add_notice(__('Please enter a biling location.'), 'error');
//
// }
// FORCE SHIPPING COST RECALCULATION
WC()->cart->calculate_shipping();
WC()->cart->calculate_totals();
}
}
Upvotes: 0
Views: 1924
Reputation: 11
Had the same issue. What I did to rectify it:
Upvotes: 0