I set shipping total and total via AJAX:
add_action('wp_ajax_wc_shipper_set_rate', 'wc_shipper_set_rate');
add_action('wp_ajax_nopriv_wc_shipper_set_rate', 'wc_shipper_set_rate');
function wc_shipper_set_rate(){
$object_id = strval($_POST['object_id']);
$order_id = intval($_POST['order_id']);
$rate = false;
//Find rate by object_id
$rates = WC()->session->get('wc_shipper_rates');
foreach ($rates as $_rate) {
if ($_rate['object_id'] == $object_id) {
WC()->session->set('wc_shipper_chosen_rate', $_rate);
$rate = $_rate;
}
}
if($rate){
//Calculate new totals
$totals = WC()->cart->get_totals();
$new_total = floatval($totals['total']) - floatval($totals['shipping_total']) + floatval($rate['amount']);
// Set cart totals
WC()->cart->set_shipping_total($rate['amount']);
WC()->cart->set_total($new_total);
$totals = WC()->cart->get_totals();
WC()->cart->calculate_shipping();
WC()->cart->calculate_totals();
// Change shipping total in order
$order = wc_get_order($order_id);
$order->set_shipping_total($rate['amount']);
$order->set_total($new_total);
$order->save();
// Change shipping total in session
WC()->session->set('shipping_total', $rate['amount']);
WC()->session->set('total', $new_total);
WC()->session->set('cart_totals', $totals);
update_post_meta($order_id, '_wc_shipper_object_id', $rate['object_id']);
}
echo json_encode(['status' => 'ok', 'totals' => $totals], JSON_UNESCAPED_UNICODE);
exit;
}
In WP-ADMIN new totals and the shipping total are visible:
New totals in the order
But on the checkout page there are old totals. New totals are visible after double page refresh.
Old totals
The WC method is useless.
WC()->cart->calculate_shipping();
WC()->cart->calculate_totals();
I use the last release WooCommerce and WordPress.
New contributor
Andrei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2