Programmatically creating new order in Woocommerce
I am having the hardest time programmatically creating an order in WooCommerce. I am using the code below and is DOES create an order BUT I cannot get customer information OR product line items added to the order. The new order that is create is simply as Guest with no items, user information, etc.
The issue seems to be that once the order object is created, it is failing when trying to add data to the order.
function create_vip_order() {
global $woocommerce;
$address = array(
'first_name' => '111Joe',
'last_name' => 'Conlin',
'company' => 'Speed Society',
'email' => '[email protected]',
'phone' => '760-555-1212',
'address_1' => '123 Main st.',
'address_2' => '104',
'city' => 'San Diego',
'state' => 'Ca',
'postcode' => '92121',
'country' => 'US'
);
// Now we create the order
$order = wc_create_order();
// The add_product() function below is located in /plugins/woocommerce/includes/abstracts/abstract_wc_order.php
$order->add_product( get_product( '275962' ), 1 ); // This is an existing SIMPLE product
$order->set_address( $address, 'billing' );
//
$order->calculate_totals();
$order->update_status("Completed", 'Imported order', TRUE);
}
add_action( 'woocommerce_init', 'create_vip_order' );
Here is the error I am getting in my logs:
[19-Apr-2016 21:16:38 UTC] PHP Fatal error: Uncaught Error: Call to a member function add_product() on boolean in /Users/joe/Sites/speedsociety-2/wp-content/themes/ss/lib/contests/order.php:107
Stack trace:
#0 /Users/joe/Sites/speedsociety-2/wp-includes/plugin.php(525): create_vip_order('')
#1 /Users/joe/Sites/speedsociety-2/wp-content/plugins/woocommerce/woocommerce.php(330): do_action('woocommerce_ini...')
#2 /Users/joe/Sites/speedsociety-2/wp-includes/plugin.php(525): WooCommerce->init('')
#3 /Users/joe/Sites/speedsociety-2/wp-settings.php(392): do_action('init')
#4 /Users/joe/Sites/speedsociety-2/wp-config.php(67): require_once('/Users/joe/Site...')
#5 /Users/joe/Sites/speedsociety-2/wp-load.php(37): require_once('/Users/joe/Site...')
#6 /Users/joe/Sites/speedsociety-2/wp-admin/admin.php(31): require_once('/Users/joe/Site...')
#7 /Users/joe/Sites/speedsociety-2/wp-admin/edit.php(10): require_once('/Users/joe/Site...')
#8 {main}
thrown in /Users/joe/Sites/speedsociety-2/wp-content/themes/ss/lib/contests/order.php on line 107
Any help on this would be MOST appreciated!
Solution 1:
The problem is in your action hook. Use following hook :
add_action('woocommerce_checkout_process', 'create_vip_order');
function create_vip_order() {
global $woocommerce;
$address = array(
'first_name' => '111Joe',
'last_name' => 'Conlin',
'company' => 'Speed Society',
'email' => '[email protected]',
'phone' => '760-555-1212',
'address_1' => '123 Main st.',
'address_2' => '104',
'city' => 'San Diego',
'state' => 'Ca',
'postcode' => '92121',
'country' => 'US'
);
// Now we create the order
$order = wc_create_order();
// The add_product() function below is located in /plugins/woocommerce/includes/abstracts/abstract_wc_order.php
$order->add_product( get_product('275962'), 1); // This is an existing SIMPLE product
$order->set_address( $address, 'billing' );
//
$order->calculate_totals();
$order->update_status("Completed", 'Imported order', TRUE);
}
Make sure the product id given should exists in the system.
Solution 2:
Well you can do this without wc_create_order function.
$order_data = array();
$order_data[ 'post_type' ] = 'shop_order';
$order_data[ 'post_status' ] = 'wc-' . apply_filters( 'woocommerce_default_order_status', 'pending' );
$order_data[ 'ping_status' ] = 'closed';
$order_data[ 'post_author' ] = 1;
$order_data[ 'post_password' ] = uniqid( 'order_' );
$order_data[ 'post_title' ] = sprintf( __( 'Order – %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce' ), strtotime( $post_date ) ) );
$order_data[ 'post_parent' ] = 12; // parent post id
$order_data[ 'post_content' ] = "";
$order_data[ 'comment_status' ] = "open";
$order_data[ 'post_name' ] = sanitize_title( sprintf( __( 'Order – %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce' ), strtotime( $post_date) ) ) );
$order_id = wp_insert_post( apply_filters( 'woocommerce_new_order_data', $order_data ), true );
Then you can use this $order_id for adding other details, like...
$order = wc_get_order( $order_id );
$product_item_id = $order->add_product( wc_get_product( $product_id ));
wc_add_order_item_meta($product_item_id,"meta_key","meta_values");
$addressShipping = array(
'first_name' => $shippingName,
'email' => $user_email_id,
'phone' => $billingPhone,
'address_1' => $shippingAddress,
'address_2' => $shippingAddress2,
'city' => $shippingCity,
'state' => $shippingStateCode,
'postcode' => $shippingZip,
'country' => 'US');
$order->set_address( $addressShipping, 'shipping' );
$addressBilling = array(
'first_name' => $billingName,
'email' => $user_email_id,
'phone' => $billingPhone,
'address_1' => $billingAddress,
'address_2' => $billingAddress2,
'city' => $billingCity,
'state' => $billingStateCode,
'postcode' => $billingZip,
'country' => 'US');
$order->set_address( $addressBilling, 'billing' );
$order->calculate_totals();
Solution 3:
I actually couldn't figure out your problem but providing you another alternative, this might help you.
I have added products in $woocommerce->cart
first and then assign that cart data to new order created like this :
//For simple product
$woocommerce->cart->add_to_cart($product_id, $quantity);
//For variable product
$woocommerce->cart->add_to_cart($product_id, $quantity, $variationID, $attr_array);
$order_data = array(
'status' => apply_filters('woocommerce_default_order_status', 'processing'),
'customer_id' => $user_id
);
$new_order = wc_create_order($order_data);
foreach ($woocommerce->cart->get_cart() as $cart_item_key => $values) {
$item_id = $new_order->add_product(
$values['data'], $values['quantity'], array(
'variation' => $values['variation'],
'totals' => array(
'subtotal' => $values['line_subtotal'],
'subtotal_tax' => $values['line_subtotal_tax'],
'total' => $values['line_total'],
'tax' => $values['line_tax'],
'tax_data' => $values['line_tax_data'] // Since 2.2
)
)
);
}
$new_order->set_address($address, 'billing');
$new_order->set_address($address, 'shipping');