In WooCommerce checkout page, shipping cost not updated when changing payment type, But shipping cost changes when updating address fields.
Requirement :
If the payment type is COD, then shipping cost is 100;
If the payment type is UPI, then shipping cost is 70;
Following are the two files, we use to address the requirement
custom-functions.php
// Adjust shipping cost based on the selected payment method
add_filter('woocommerce_package_rates', 'adjust_shipping_based_on_payment_method', 10, 2);
function adjust_shipping_based_on_payment_method($rates, $package) {
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if ($chosen_payment_method) {
foreach ($rates as $rate_key => $rate) {
if ($chosen_payment_method === 'cod') {
$rates[$rate_key]->cost = 100;
} elseif ($chosen_payment_method === 'wc-upi') {
$rates[$rate_key]->cost = 70;
}
}
}
return $rates;
}
// Enqueue custom JavaScript
function enqueue_custom_shipping_scripts() {
if (is_checkout()) {
wp_enqueue_script('custom-shipping-js', plugin_dir_url(__FILE__) . 'custom-shipping.js', array('jquery', 'wc-checkout'), '1.0', true);
wp_localize_script('custom-shipping-js', 'customShippingParams', array(
'ajax_url' => admin_url('admin-ajax.php'),
));
}
}
add_action('wp_enqueue_scripts', 'enqueue_custom_shipping_scripts');
// Handle AJAX request to update shipping cost
add_action('wp_ajax_update_shipping_cost', 'update_shipping_cost');
add_action('wp_ajax_nopriv_update_shipping_cost', 'update_shipping_cost');
function update_shipping_cost() {
if (isset($_POST['payment_method'])) {
WC()->session->set('chosen_payment_method', sanitize_text_field($_POST['payment_method']));
}
WC()->cart->calculate_totals();
WC()->cart->maybe_set_cart_cookies();
wp_send_json_success();
}
custom-shipping.js
jQuery(document).ready(function($) {
// Detect changes in payment method selection
$('form.checkout').on('change', 'input[name="payment_method"]', function() {
var paymentMethod = $(this).val();
console.log("Selected Payment Method: " + paymentMethod); // Log selected payment method
// Update session and trigger checkout update via AJAX
$.ajax({
type: 'POST',
url: customShippingParams.ajax_url,
data: {
action: 'update_shipping_cost',
payment_method: paymentMethod,
},
success: function(response) {
console.log("AJAX Response: ", response); // Log the response
if (response.success) {
console.log('Success');
// Trigger WooCommerce update checkout event
$(document.body).trigger('update_checkout');
// location.reload(true);
}
},
error: function(error) {
console.error('AJAX error:', error); // Debugging
}
});
});
// Prevent the 'update_checkout' event from being triggered infinitely
var isUpdating = false;
$(document.body).on('update_checkout', function() {
if (!isUpdating) {
isUpdating = true;
$('body').trigger('update_checkout');
isUpdating = false;
}
});
});
What I am doing wrong?
2
Answers
The following code only works with Classic Checkout (but not with newly Checkout Block).
For info, here is the way to switch back to legacy Classic Checkout (shortcode).
Your code is much more complicated than needed. There are some mistakes, your custom Ajax is not needed and there are important missing things.
In the first function below (settings), we define the shipping cost by payment method Id.
Try the following instead:
Code goes in function.php file of your child theme (or in a plugin). Tested and works.
This works @LoicTheAztec! Thank you!
How would the code change when also PayPal or credit cards gateway is used?