I am trying to update the shipping cost after the address is entered. When the client starts typing the address, and autocomplete function helps the client find the street name, building, floor and side.
Once the address is entered javascript calculates the distance and the price.
Then the price is via ajax send to
shipment.php
include '../../../../wp-load.php';
add_action( 'woocommerce_flat_rate_shipping_add_rate','add_another_custom_flat_rate', 10, 2 );
function add_another_custom_flat_rate( $method, $rate ) {
$new_rate = $rate;
$new_rate['cost'] = 50; // Update the cost to 50
$method->add_rate( $new_rate );
}
I think that You don't need Query ajax to update the price directly for this calculated shipping cost and you don't need a custom shipping method as in your code or linked tutorial.
THERE IS THREE STEPS:
1) In your existing Ajax driven PHP function, you will set the calculated price in a custom WC_Session attribute where $shipping_cost
variable will be the collected value of the calculated shipping cost passed via JS Ajax:
WC()->session->set( 'shipping_calculated_cost', $shipping_cost );
Then in jQuery Ajax "on success" event you will update checkout with the following:
$('body').trigger('update_checkout');
That will refresh checkout data…
2) In the custom function hooked in woocommerce_package_rates
filer hook, you will get the session value of the calculated shipping cost…
IMPORTANT: In WooCommerce settings > shipping, you will set the "flat rate" cost to
1
…
In The function code you will set the default price for this flat rate (that will be used when the shipping cost calculation doesn't exist yet):
add_filter('woocommerce_package_rates', 'update_shipping_costs_based_on_cart_session_custom_data', 10, 2);
function update_shipping_costs_based_on_cart_session_custom_data( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// SET HERE the default cost (when "calculated cost" is not yet defined)
$cost = '50';
// Get Shipping rate calculated cost (if it exists)
$calculated_cost = WC()->session->get( 'shipping_calculated_cost');
// Iterating though Shipping Methods
foreach ( $rates as $rate_key => $rate_values ) {
$method_id = $rate_values->method_id;
$rate_id = $rate_values->id;
// For "Flat rate" Shipping" Method only
if ( 'flat_rate' === $method_id ) {
if( ! empty( $calculated_cost ) ) {
$cost = $calculated_cost;
}
// Set the rate cost
$rates[$rate_id]->cost = number_format($rates[$rate_id]->cost * $cost, 2);
// Taxes rate cost (if enabled)
foreach ($rates[$rate_id]->taxes as $key => $tax){
if( $rates[$rate_id]->taxes[$key] > 0 ){ // set the new tax cost
$taxes[$key] = number_format( $rates[$rate_id]->taxes[$key] * $cost, 2 );
$has_taxes = true;
} else {
$has_taxes = false;
}
}
if( $has_taxes )
$rates[$rate_id]->taxes = $taxes;
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
3) Refresh the shipping caches (needed sometimes):
- First empty your cart.
- This code is already saved on your function.php file.
- Go in a shipping zone settings and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done and you can test it.
This should work for you,
If you have many different "flat rates" by shipping zones, you will need to make some changes in my code, if the default cost is different for each…