Programmatically creating new order in Woocommerce

2019-01-13 14:02发布

问题:

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'      => 'joe@testing.com',
      '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!

回答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'      => 'joe@testing.com',
      '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.



回答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();


回答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');


回答4:

you almost had it, add_action( 'woocommerce_init', 'create_vip_order' ); woocommerce_init is too early, you need to change your hook to at least init, your errors

[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

show that it's happening the $order variable has been returned false and hence you can't use $order->add_product

here's my working code

function create_vip_order() {

  global $woocommerce;

  $address = array(
      'first_name' => '111Joe',
      'last_name'  => 'Conlin',
      'company'    => 'Speed Society',
      'email'      => 'joe@testing.com',
      '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( '129' ), 1 ); // This is an existing SIMPLE product
  $order->set_address( $address, 'billing' );
  //
  $order->calculate_totals();
  $order->update_status("Completed", 'Imported order', TRUE);

}

add_action( 'init', 'create_vip_order' );

Good luck and happy coding :D