Manually add order item with fixed product_id in WooCommerce

I know is a little bit late but maybe my anwser is helpfuly for someone else. I used WordPress in version 4.9.7 and WooCommerce in version 3.4.3

To extend the buttons you can use the woocommerce action “woocommerce_order_item_add_action_buttons“.
You find the declaration of that action in the file “woocommerce/includes/admin/meta-boxes/views/html-order-items.php”

The following code use this action and add a new button (“Add Special Product”) to the existing buttons.

function my_function_to_add_the_button($order)
{   
    // Add the "Special Product" button
    // the button tag gets as data attributes your product id and the order id
    // later we will grab this data and send them to the server
    echo '<button id="my_special_button"  type="button" class="button add-special-item" data-order_id="'. esc_attr($order->get_id())  .'" data-product_id="798" >Add Special Product</button>';
}  

/**
 * hook to add the button
 */
add_action('woocommerce_order_item_add_action_buttons', 'my_function_to_add_the_button');

Then you could bind same JavaScript code to the button and send the order_id and product_id to the server.

The following code tells WordPress to load an new JavaScript file in the footer.

/**
 * Add javascript
 */
function my_function_to_add_the_js_file()
{

    wp_enqueue_script( 'my_button_script', plugin_dir_url(__FILE__) ."/js/my-button-script.js", array('jquery'), NULL, true );

    // send the admin ajax url to the script
    wp_localize_script( 'my_button_script', 'mb_script_var', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}

/**
 * hook to add the javascript file
 */
add_action( 'admin_enqueue_scripts', 'my_function_to_add_the_js_file' );

The next code shows the content of that file.

(function( $ ) {
    'use strict';

    $('.inside').on('click','#my_special_button', function(){

        // get the order_id from the button tag
        var order_id = $(this).data('order_id');

        // get the product_id from the button tag
        var product_id = $(this).data('product_id');

        // send the data via ajax to the sever
        $.ajax({
            type: 'POST',
            url: mb_script_var.ajaxurl,
            dataType: 'json',
            data: {
                action: 'add_my_product_to_order',
                order_id: order_id, 
                product_id: product_id
            },
            success: function (data, textStatus, XMLHttpRequest) {

                if(data.error == 0)
                { 
                  // trigger the "Recalculate" button to recalculate the order price 
                  // and to show the new product in the item list
                  $('.calculate-action').trigger('click'); 
                }

                // show the control message
                alert(data.msg);


            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert(errorThrown);
            }
        });

    });


})( jQuery );

The JavaScript code binds a click function to the new button. If somebody click on that button, the JavaScript code grabs the product_id and the order_id from the tag and send them via ajax to the server.

On the server the product will be add to the order.

The following code shows the “ajax” function that will be called by the JavaScript.

/**
 * Ajax callback
 */
function my_function_to_add_the_product() 
{   
   /////////////////////////////////////////////////////////////////////////////
   /// Attention, to keep the example simple we will not check any ajax data. //
   /////////////////////////////////////////////////////////////////////////////
   //
   // the data from the ajax call
   $order_id = intval($_POST['order_id']);

   $product_id = intval($_POST['product_id']);

   //getting order Object
   $order = wc_get_order($order_id); 

   // gettting the product
   $product = wc_get_product($product_id);

   $back_data = array('error' => 0, 'msg' => '');
   if($order !== false AND $product !== false)
   {   
       // Add the product to the order 
       $order->add_product($product, 1);

       // Save the order data
       $order->save(); 

       $back_data['msg'] = 'The procuct was added';

   }
   else
   {
       $back_data['error'] = 1;
       $back_data['msg'] = 'No product was added';
   }


   wp_send_json( $msg );
}

/**
 * hook to add the ajax callback
 */
add_action( 'wp_ajax_add_my_product_to_order', 'my_function_to_add_the_product' );