Reputation: 2027
We are having a custom code to allow end user select city, date and time of his delivery. The delivery rate should change according to the city. City select box is on the checkout page.
Changing the city triggers ajax that change successfully the charge for the delivery that displayed under order review section. So far so good. Unfortunately, the price does not reach the order after submitting the order. It gets lost somewhere.
A hint may be in the fact that the same city select box is on the product page as well, and if a user does select it when adding to cart, and just then goes to checkout, the delivery rate is displayed and does not got lost when submitting the order.
Is there any refresh needs to be triggered in order for the shipping rate to be updated?
The function that updates the rates (successfully)
function adjust_shipping_rate( $rates ){
global $woocommerce;
foreach ($rates as $rate) {
$cost = $rate->cost;
$rate->cost = $_COOKIE['shipping_city_cost'];
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'adjust_shipping_rate', 50, 1 );
UPDATE 21-05-2017
This is how the cookie is updated: Once the select box is changed, async ajax call is fired and execute the following PHP code.
function get_and_set_shipping_rate(){
$shipping_city = $_POST['city'];
$shipping_cost = get_shipping_cost_by_city($shipping_city);
setcookie('shipping_city_cost', $shipping_cost, time() + (86400 * 30), '/');
$_COOKIE['shipping_city_cost'] = $shipping_cost;
echo 'Shipping cost updated: '.$shipping_city.' : '.$shipping_cost;
}
add_action( 'wp_ajax_get_and_set_shipping_rate', 'get_and_set_shipping_rate' );
add_action( 'wp_ajax_nopriv_get_and_set_shipping_rate', 'get_and_set_shipping_rate' );
Here is the ajax call:
jQuery(document).on('change', '#shipping_delivery_city', function(){
var requested_city = jQuery(this).val();
var data = {
'action': 'get_and_set_shipping_rate',
'city': requested_city
};
jQuery.ajax({
type: "POST",
url: shipping_dates.ajax_url,
data: data,
async: false,
success: function (response) {
console.log(response);
}
});
});
Upvotes: 1
Views: 10149
Reputation: 65274
With this, I have two assumptions. 1. ) You are using this code on checkout page. 2. ) You already have your own function get_shipping_cost_by_city
add_action( 'woocommerce_checkout_update_order_review', 'woocommerce_checkout_update_order_review' );
function woocommerce_checkout_update_order_review( $post_data ){
$data = array();
$vars = explode('&', $post_data);
foreach ($vars as $k => $value){
$v = explode('=', urldecode($value));
$data[$v[0]] = $v[1];
}
$shipping_cost = get_shipping_cost_by_city( $data['billing_city'] );
WC()->session->set( 'shipping_city_cost', $shipping_cost );
foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ) {
// this is needed for us to remove the session set for the shipping cost. Without this, we can't set it on the checkout page.
WC()->session->set( 'shipping_for_package_' . $package_key, false );
}
}
add_filter( 'woocommerce_package_rates', 'adjust_shipping_rate', 50 );
function adjust_shipping_rate( $rates ){
foreach ($rates as $rate) {
$cost = $rate->cost;
$rate->cost = WC()->session->get( 'shipping_city_cost' );
}
return $rates;
}
the setting/getting of shipping_city_cost
is done by WC()->session->set
and WC()->session->get
. I need not to put an ajax function for woocommerce_checkout_update_order_review
is an action hook inside an ajax call whenever an update is done on the checkout page.
for this test, I use this function:
function get_shipping_cost_by_city( $city ) {
if ( $city == 'Ormoc City' ){
return 100;
}
return 130;
}
Upvotes: 5