Search code examples
phpwordpresswoocommercesmshook-woocommerce

How to send a WooCommerce order tracking code with SMS


I wrote a WooCommerce plugin for sending tracking codes with SMS for customer's billing_phone each in the order edit page.

After the package is sent by the sending company (for example, Post, Tipax, FedEx, etc.), the tracking code is received from them. And I want to send that code to the customer via SMS.

<?php
/*
Plugin Name: Order Tracking Plugin
Plugin URI: #
Description: A plugin for sending order tracking codes via SMS.
Version: 1.0
Author: Paul Vek
*/

// Add order tracking fields after shipping address
add_action('woocommerce_admin_order_data_after_shipping_address', 'display_order_tracking_fields');
function display_order_tracking_fields($order) {
    // Retrieve order and customer information
    $order_id = $order->get_id();
    $billing_first_name = $order->get_billing_first_name();
    $billing_last_name = $order->get_billing_last_name();
    $customer_phone = $order->get_billing_phone();
    $order_number = $order->get_order_number();
    $tracking_code = get_post_meta($order_id, 'tracking_code', true);

    // Display order tracking fields
    ?>
    <div class="order_tracking_container">
        <h3><?php esc_html_e('Order Tracking', 'your-textdomain'); ?></h3>
        <p>
            <label for="tracking_code"><?php esc_html_e('Tracking Code:', 'your-textdomain'); ?></label>
            <input type="text" id="tracking_code" name="tracking_code" value="<?php echo esc_attr($tracking_code); ?>">
        </p>
        <p>
            <label for="sending_method"><?php esc_html_e('Sending Method:', 'your-textdomain'); ?></label>
            <select id="sending_method" name="sending_method">
                <option value="tipax">Tipax</option>
                <option value="post">Post</option>
                <option value="chapar">Chapar</option>
            </select>
        </p>
        <p>
            <label for="tracking_address"><?php esc_html_e('Tracking Address:', 'your-textdomain'); ?></label>
            <select id="tracking_address" name="tracking_address">
                <option value="trcking.post.ir">trcking.post.ir</option>
                <option value="tipaxco.com">tipaxco.com</option>
            </select>
        </p>
        <p>
            <button id="send_tracking_code" class="button"><?php esc_html_e('Send Tracking Code', 'your-textdomain'); ?></button>
        </p>
        <div id="tracking_code_message"></div>
    </div>

    <script>
        jQuery(document).ready(function($) {
            $('#send_tracking_code').click(function() {
                var tracking_code = $('#tracking_code').val();
                var sending_method = $('#sending_method').val();
                var tracking_address = $('#tracking_address').val();
                var order_id = $('input[name="post_ID"]').val();

                $.ajax({
                    type: 'POST',
                    url: '<?php echo admin_url('admin-ajax.php'); ?>',
                    data: {
                        action: 'send_tracking_code',
                        tracking_code: tracking_code,
                        sending_method: sending_method,
                        tracking_address: tracking_address,
                        order_id: order_id
                    },
                    success: function(response) {
                        $('#tracking_code_message').html(response);
                    },
                    error: function(xhr, status, error) {
                        console.log(xhr.responseText);
                    }
                });
            });
        });
    </script>
    <?php
}

// AJAX handler for sending tracking code
add_action('wp_ajax_send_tracking_code', 'send_tracking_code');
function send_tracking_code() {
    // Check if the request is coming from an AJAX call
    if (!defined('DOING_AJAX') || !DOING_AJAX) {
        wp_die();
    }

    // Get the order ID and tracking details from the AJAX request
    $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
    $tracking_code = isset($_POST['tracking_code']) ? sanitize_text_field($_POST['tracking_code']) : '';
    $sending_method = isset($_POST['sending_method']) ? sanitize_text_field($_POST['sending_method']) : '';
    $tracking_address = isset($_POST['tracking_address']) ? sanitize_text_field($_POST['tracking_address']) : '';

    // Check if all required data is present
    if (empty($order_id) || empty($tracking_code) || empty($sending_method) || empty($tracking_address)) {
        wp_send_json_error(__('Missing required parameters.', 'order-tracking-plugin'));
    }

    // Compose message
    $order = wc_get_order($order_id);
    $billing_first_name = $order->get_billing_first_name();
    $billing_last_name = $order->get_billing_last_name();
    $order_id = $order->get_order_id();
    $message = sprintf(__('Hello %s %s dear. The order %s was sent through %s. Tracking code: %s. To track it, go to this address: %s.', 'order-tracking-plugin'), $billing_first_name, $billing_last_name, $order_id, $sending_method, $tracking_code, $tracking_address);

    // Send SMS using API
    $api_key = '';
    $sender_number = '3000505';
    $username = '';
    $password = '';
    $rcpt_nm = array($billing_phone); // Use customer's phone number as recipient

    $url = "https://ippanel.com/services.jspd";
    $params = array(
        'uname' => $username,
        'pass' => $password,
        'from' => $sender_number,
        'message' => $message,
        'to' => json_encode($rcpt_nm), // Use rcpt_nm as recipients
        'op' => 'send'
    );

    $handler = curl_init($url);
    curl_setopt($handler, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($handler, CURLOPT_POSTFIELDS, $params);
    curl_setopt($handler, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($handler);
    $response = json_decode($response);

    // Check if SMS was sent successfully
    if ($response[0] != 200) {
        wp_send_json_error(__('Failed to send tracking code.', 'order-tracking-plugin'));
    }

    // Prevent order from being saved during AJAX request
    add_filter('woocommerce_before_order_object_save', 'disable_order_save_during_ajax');

    // Return success message
    wp_send_json_success(__('Tracking code sent successfully.', 'order-tracking-plugin'));
}

fields show correct

Enter image description here

But my code has two problems

  1. Instead of sending by Ajax and displaying the result of sending, for example, in the form of a message on the same page, the page is updated and the order is updated! If I don't want any updates to be done, and no changes to the database. Only the code must be sent.

  2. SMS is not sent at all and my plugin does not work

Here is my web service FarazSms/ippanel (an SMS service company) example code for sending SMS. Have I used this method correctly in my plugin or not?

<?php
        $url = "https://ippanel.com/services.jspd";

        $rcpt_nm = array('9121111111','9122222222');
        $param = array
                    (
                        'uname'=>'',
                        'pass'=>'',
                        'from'=>'',
                        'message'=>'test',
                        'to'=>json_encode($rcpt_nm),
                        'op'=>'send'
                    );

        $handler = curl_init($url);
        curl_setopt($handler, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($handler, CURLOPT_POSTFIELDS, $param);
        curl_setopt($handler, CURLOPT_RETURNTRANSFER, true);
        $response2 = curl_exec($handler);

        $response2 = json_decode($response2);
        $res_code = $response2[0];
        $res_data = $response2[1];

        echo $res_data;
?>

You can also see more details at this link.


Solution

  • There are some missing things in your first function to avoid the issue you are facing (avoiding the order post update with a reload).

    Also, the JavaScript code should be preferably in the footer instead.

    Replace your first function with the following:

    // Add order tracking fields after shipping address
    add_action('woocommerce_admin_order_data_after_shipping_address', 'display_order_tracking_fields');
    function display_order_tracking_fields($order) {
        // Retrieve order and customer information
        $order_id = $order->get_id();
        $billing_first_name = $order->get_billing_first_name();
        $billing_last_name = $order->get_billing_last_name();
        $customer_phone = $order->get_billing_phone();
        $order_number = $order->get_order_number();
        $tracking_code = get_post_meta($order_id, 'tracking_code', true);
    
        // Display order tracking fields
        ?>
        <div class="order_tracking_container">
            <h3><?php esc_html_e('Order Tracking', 'your-textdomain'); ?></h3>
            <p>
                <label for="tracking_code"><?php esc_html_e('Tracking Code:', 'your-textdomain'); ?></label>
                <input type="text" id="tracking_code" name="tracking_code" value="<?php echo esc_attr($tracking_code); ?>">
            </p>
            <p>
                <label for="sending_method"><?php esc_html_e('Sending Method:', 'your-textdomain'); ?></label>
                <select id="sending_method" name="sending_method">
                    <option value="tipax">Tipax</option>
                    <option value="post">Post</option>
                    <option value="chapar">Chapar</option>
                </select>
            </p>
            <p>
                <label for="tracking_address"><?php esc_html_e('Tracking Address:', 'your-textdomain'); ?></label>
                <select id="tracking_address" name="tracking_address">
                    <option value="trcking.post.ir">trcking.post.ir</option>
                    <option value="tipaxco.com">tipaxco.com</option>
                </select>
            </p>
            <p>
                <button type="button" id="send_tracking_code" class="button"><?php esc_html_e('Send Tracking Code', 'your-textdomain'); ?></button>
            </p>
            <div id="tracking_code_message"></div>
        </div>
        <?php    
    }
    
    // Jquery code
    add_action( 'admin_footer', 'wc_order_admin_footer_script' );
    function wc_order_admin_footer_script() {
        global $pagenow, $typenow;
    
        if( $pagenow === 'post.php' && $typenow === 'shop_order' ) :
        ?>
        <script>
        jQuery( function($) {
            $('#send_tracking_code').click(function(e) {
                e.preventDefault();
    
                var tracking_code = $('#tracking_code').val();
                var sending_method = $('#sending_method').val();
                var tracking_address = $('#tracking_address').val();
                var order_id = $('input[name="post_ID"]').val();
    
                $.ajax({
                    type: 'POST',
                    url: '<?php echo admin_url('admin-ajax.php'); ?>',
                    data: {
                        action: 'send_tracking_code',
                        tracking_code: tracking_code,
                        sending_method: sending_method,
                        tracking_address: tracking_address,
                        order_id: order_id
                    },
                    success: function(response) {
                        $('#tracking_code_message').html(response);
                    },
                    error: function(xhr, status, error) {
                        console.log(xhr.responseText);
                    }
                });
            });
        });
        </script>
        <?php
        endif;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should solve the issue.

    Changes in your code:

    • Added type="button" to the button HTML.
    • Added preventDefault() to your jQuery click event.
    • Removed jQuery code from your 1st function to add it in the footer via a function hooked in admin_footer action hook.