Shipping row ramdom missing issue in the order details table in WooCommerce

I've been using a custom WooCommerce plugin that sets a fixed shipping value through a button click during the checkout process. While it mostly always works as expected, in about 2 out of every 20 orders, the shipping row itself is not visible in the order details table, confirmation emails, or the WooCommerce orders page after the order is placed. Here's the code I'm using, and I hope someone can help identify the issue. <?php /** * Plugin Name: Custom Shipping Value * Description: Customizations for WooCommerce. * Version: 1.0 * Author: udd_ish **/ defined( 'ABSPATH' ) or exit; add_action('wp_enqueue_scripts', 'enqueue_custom_scripts'); function enqueue_custom_scripts() { // Enqueue the custom JS file wp_enqueue_script('jquery'); wp_enqueue_script('distancecal-scripts', plugin_dir_url(__FILE__) . 'js/distancecal-scripts.js', array('jquery'), '1.0', true); wp_localize_script('distancecal-scripts', 'ajax_object', array('ajaxurl' => admin_url('admin-ajax.php'))); } function modify_shipping_cost($shipping_cost) { if ( isset($shipping_cost) ){ WC()->session->set('shipping_cost', $shipping_cost); error_log("Shipping cost set to $shipping_cost in session"); } return $shipping_cost; } add_filter( 'woocommerce_form_field_button', 'create_button_form_field_type', 10, 4 ); function create_button_form_field_type( $field, $key, $args, $value ){ return sprintf('<p class="form-row %s" id="%s_field" data-priority="%s"> <button type="%s" id="%s" class="%s">%s</button> </p>', implode(' ', $args['class']), esc_attr($key), $args['priority'] ? $args['priority'] : '', $args['type'], esc_attr($key), $args['input-class'], $args['label'] ); } add_action('woocommerce_checkout_fields', 'insert_custom_button_in_billing_form'); function insert_custom_button_in_billing_form( $fields ) { $fields['billing']['custom-button'] = array( 'type' => 'button', 'label' => __('Calculate Delivery Fee'), 'class' => array('form-row-wide'), 'input-class' => 'button alt', 'priority' => 61, // <== Field location (after Street address fields) ); return $fields; } add_filter( 'woocommerce_cart_shipping_method_full_label', 'display_only_shipping_method_price', 10, 2 ); function display_only_shipping_method_price( $label, $method ) { // HERE define your targeted rate id $targeted_rate_id = 'flat_rate:4'; if ( $method->id === $targeted_rate_id && 0 < $method->cost ) { $label = str_replace( $method->label . ': ', '', $label); } return $label; } add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 ); function shipping_package_rates_filter_callback( $rates, $package ) { // HERE define your targeted rate id $targeted_rate_id = 'flat_rate:4'; if ( ! array_key_exists($targeted_rate_id, $rates) ) return $rates; $new_cost = WC()->session->get('shipping_cost'); // Get new cost from WC sessions if ( ! empty($new_cost) ) { // Set shipping label empty $rates[$targeted_rate_id]->label = ''; $rate = $rates[$targeted_rate_id]; $cost = $rate->cost; // Set the initial cost in a variable for taxes calculations $rates[$targeted_rate_id]->cost = $new_cost; // Set the new cost $has_taxes = false; // Initializing $taxes = array(); // Initializing foreach ($rate->taxes as $key => $tax_cost){ if( $tax_cost > 0 ) { $tax_rate = $tax_cost / $cost; // Get the tax rate conversion $taxes[$key] = $new_cost * $tax_rate; // Set the new tax cost in taxes costs array $has_taxes = true; // There are taxes (set it to true) } } if( $has_taxes ) { $rates[$targeted_rate_id]->taxes = $taxes; // Set taxes costs array } } else { unset($rates[$targeted_rate_id]); } return $rates; } // PHP WP AJAX handler add_action('wp_ajax_shipping_cost_update', 'shipping_cost_update_callback'); add_action('wp_ajax_nopriv_shipping_cost_update', 'shipping_cost_update_callback'); function shipping_cost_update_callback() { $price = 100; modify_shipping_cost($price); wp_die(); // Make sure to exit after handling the AJAX request } // Refresh shipping methods add_action('woocommerce_checkout_update_order_review', 'checkout_update_refresh_shipping_methods' ); function checkout_update_refresh_shipping_methods() { if ( WC()->session->__isset('shipping_cost') ) { $packages = WC()->cart->get_shipping_packages(); foreach ($packages as $package_key => $package ) { WC()->session->set( 'shipping_for_package_' . $package_key, false ); // Or true } } } // Remove the WC session variable once the order is created add_action('woocommerce_checkout_order_created', 'remove_wc_session_shipping_cost_variable', 10, 1); function remove_wc_session_shipping_cost_variable( ) { if ( WC()->session->__isset('shipping_cost') ) { WC()->session->__unset('shipping_cost'); } } // (optional) Remove the WC Session variable on other pages than checkout add_action('template_redirect', 'wc_session_shipping_cost_variable_only_on_checkout', 10, 1); function wc_session_shipping_cost_variable_only_on_checkout() { if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) { remove_wc_session_shipping_cost_variable(); } } Here's the JS code jQuery( function($) { // Add your custom JavaScript here $(document.body).on('click', '#custom-button', function() { $('#custom-button').text('Calculating Delivery Fee').prop('disabled', true); $.ajax({ type: 'POST', url: ajax_object.ajaxurl, data: { action: 'shipping_cost_update' }, success: function(response) { console.log(response); $('#custom-button').text('Calculate Delivery Fee').prop('disabled', false); $(document.body).trigger('update_checkout', { update_shipping_method: true }); }, error: function(error) { // Handle AJAX error if needed console.error('AJAX error:', error); $('#custom-button').text('Calculate Delivery Fee').prop('disabled', false); alert('Error calculating delivery fee. Please try again.'); } }); } }); }); Inspired by: Change WooCommerce Checkout shipping method cost from a WC Session variable

Comment (0)

You’ll be in good company