I am trying to generate a dropdown list of available shipping methods based on the selected state by visitor, however, the page is never get updated, and the JSON response always has a 0 at the end of it which makes the parsing failed.
main.js
of the plugin:
jQuery('#billing_state').on('change', function(event) {
event.preventDefault();
let dataVariable = {
'action': 'yalidine_shippings_methods',
'state': this.value
};
jQuery.ajax({
url: yalidine_shippings_methods.ajaxurl,
type:'POST',
data: dataVariable,
success:function(response) {
console.log('html shipping_fees: ', shipping_fees.html())
console.log('html response: ', response)
let options = ` <option value="pickup">Self pickup</option>
<option value="home">Home</option>`;
try {
let res = JSON.parse(response);
for(let stopdesk in res.stop_desks) {
options += `<option value="${stopdesk}">${stopdesk}</option>`;
}
shipping_fees.html('<th>Shipping</th><td data-title="Shipping"><select id="shipping-method-list">' + options + '</select></td>');
shipping_method = jQuery('#shipping-method-list');
}
catch(err) {
}
},
error: function(err) {
console.log('error: ', err)
}
});
});
yalidine_woocommerce.php
plugin:
function yalidine_shippings_methods() {
//file_put_contents('_POST.txt', json_encode($_POST) . '\r\n' . 'dd');
$data = [];
if(isset($_POST['action']) && $_POST['action'] == 'yalidine_shippings_methods') {
$wilaya_id = explode('-', $_POST['state']);
$wilaya_id = (int)$wilaya_id[1];
$yalidine_options = get_option('WOO_YALIDINE_SETTINGS');
$api_id = isset($yalidine_options['stopdesk']) ? key($yalidine_options['stopdesk']) : null;
if($api_id !== null) {
$api_token = $yalidine_options['stopdesk'][$api_id]['token'];
$http_request = new CurlHttpRequest();
$yalidine = new YalidineAPI($http_request);
$yalidine->setApiKeys($api_id, $api_token);
$response = $yalidine->getWilayaStopDesks($wilaya_id);
$response2 = $yalidine->getWilayaDeliveryFees($wilaya_id);
if(isset($response['total_data']) && $response['total_data'] > 0
&& isset($response2['total_data']) && $response2['total_data'] > 0) {
foreach($response['data'] as $stopdesk) {
$data['stop_desks'][] = $stopdesk['name'];
}
$data['fee'] = ['home' => $response2['data'][0]['home_fee'], 'stop_desk' => $response2['data'][0]['desk_fee']];
}
}
}
echo json_encode($data);
}
add_action('wp_ajax_yalidine_shippings_methods', 'yalidine_shippings_methods' );
add_action('wp_ajax_yalidine_shippings_methods', 'yalidine_shippings_methods' );
What I was need is to extend the WC_Shipping_Method and create my own shipping method, A full tutorial about that can be found here, and a general skeleton(from the tutorial mentioned) of a shipping method would look like this:
<?php
/**
* Plugin Name: TutsPlus Shipping
* Plugin URI: http://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098
* Description: Custom Shipping Method for WooCommerce
* Version: 1.0.0
* Author: Igor Benić
* Author URI: http://www.ibenic.com
* License: GPL-3.0+
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
* Domain Path: /lang
* Text Domain: tutsplus
*/
if ( ! defined( 'WPINC' ) ) {
die;
}
/*
* Check if WooCommerce is active
*/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
function tutsplus_shipping_method() {
if ( ! class_exists( 'TutsPlus_Shipping_Method' ) ) {
class TutsPlus_Shipping_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* @access public
* @return void
*/
public function __construct() {
$this->id = 'tutsplus';
$this->method_title = __( 'TutsPlus Shipping', 'tutsplus' );
$this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' );
// Availability & Countries
$this->availability = 'including';
$this->countries = array(
'US', // Unites States of America
'CA', // Canada
'DE', // Germany
'GB', // United Kingdom
'IT', // Italy
'ES', // Spain
'HR' // Croatia
);
$this->init();
$this->enabled = isset( $this->settings['enabled'] ) ? $this->settings['enabled'] : 'yes';
$this->title = isset( $this->settings['title'] ) ? $this->settings['title'] : __( 'TutsPlus Shipping', 'tutsplus' );
}
/**
* Init your 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' ) );
}
/**
* Define settings field for this shipping
* @return void
*/
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'tutsplus' ),
'type' => 'checkbox',
'description' => __( 'Enable this shipping.', 'tutsplus' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'tutsplus' ),
'type' => 'text',
'description' => __( 'Title to be display on site', 'tutsplus' ),
'default' => __( 'TutsPlus Shipping', 'tutsplus' )
),
'weight' => array(
'title' => __( 'Weight (kg)', 'tutsplus' ),
'type' => 'number',
'description' => __( 'Maximum allowed weight', 'tutsplus' ),
'default' => 100
),
);
}
/**
* 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 ) {
$weight = 0;
$cost = 0;
$country = $package["destination"]["country"];
foreach ( $package['contents'] as $item_id => $values )
{
$_product = $values['data'];
$weight = $weight + $_product->get_weight() * $values['quantity'];
}
$weight = wc_get_weight( $weight, 'kg' );
if( $weight <= 10 ) {
$cost = 0;
} elseif( $weight <= 30 ) {
$cost = 5;
} elseif( $weight <= 50 ) {
$cost = 10;
} else {
$cost = 20;
}
$countryZones = array(
'HR' => 0,
'US' => 3,
'GB' => 2,
'CA' => 3,
'ES' => 2,
'DE' => 1,
'IT' => 1
);
$zonePrices = array(
0 => 10,
1 => 30,
2 => 50,
3 => 70
);
$zoneFromCountry = $countryZones[ $country ];
$priceFromZone = $zonePrices[ $zoneFromCountry ];
$cost += $priceFromZone;
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => $cost
);
$this->add_rate( $rate );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'tutsplus_shipping_method' );
function add_tutsplus_shipping_method( $methods ) {
$methods[] = 'TutsPlus_Shipping_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'add_tutsplus_shipping_method' );
function tutsplus_validate_order( $posted ) {
$packages = WC()->shipping->get_packages();
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
if( is_array( $chosen_methods ) && in_array( 'tutsplus', $chosen_methods ) ) {
foreach ( $packages as $i => $package ) {
if ( $chosen_methods[ $i ] != "tutsplus" ) {
continue;
}
$TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method();
$weightLimit = (int) $TutsPlus_Shipping_Method->settings['weight'];
$weight = 0;
foreach ( $package['contents'] as $item_id => $values )
{
$_product = $values['data'];
$weight = $weight + $_product->get_weight() * $values['quantity'];
}
$weight = wc_get_weight( $weight, 'kg' );
if( $weight > $weightLimit ) {
$message = sprintf( __( 'Sorry, %d kg exceeds the maximum weight of %d kg for %s', 'tutsplus' ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title );
$messageType = "error";
if( ! wc_has_notice( $message, $messageType ) ) {
wc_add_notice( $message, $messageType );
}
}
}
}
}
add_action( 'woocommerce_review_order_before_cart_contents', 'tutsplus_validate_order' , 10 );
add_action( 'woocommerce_after_checkout_validation', 'tutsplus_validate_order' , 10 );
}