/** * Create an order. Error codes: * 520 - Cannot insert order into the database. * 521 - Cannot get order after creation. * 522 - Cannot update order. * 525 - Cannot create line item. * 526 - Cannot create fee item. * 527 - Cannot create shipping item. * 528 - Cannot create tax item. * 529 - Cannot create coupon item. * * @throws Exception * @param $data Posted data. * @return int|WP_ERROR */ public function create_order($data) { // Give plugins the opportunity to create an order themselves. if ($order_id = apply_filters('woocommerce_create_order', null, $this)) { return $order_id; } try { $order_id = absint(WC()->session->get('order_awaiting_payment')); $cart_hash = md5(json_encode(wc_clean(WC()->cart->get_cart_for_session())) . WC()->cart->total); /** * If there is an order pending payment, we can resume it here so * long as it has not changed. If the order has changed, i.e. * different items or cost, create a new order. We use a hash to * detect changes which is based on cart items + order total. */ if ($order_id && ($order = wc_get_order($order_id)) && $order->has_cart_hash($cart_hash) && $order->has_status(array('pending', 'failed'))) { // Action for 3rd parties. do_action('woocommerce_resume_order', $order_id); // Remove all items - we will re-add them later. $order->remove_order_items(); } else { $order = new WC_Order(); } foreach ($data as $key => $value) { if (is_callable(array($order, "set_{$key}"))) { $order->{"set_{$key}"}($value); } } $order->set_created_via('checkout'); $order->set_cart_hash($cart_hash); $order->set_customer_id(apply_filters('woocommerce_checkout_customer_id', get_current_user_id())); $order->set_currency(get_woocommerce_currency()); $order->set_prices_include_tax('yes' === get_option('woocommerce_prices_include_tax')); $order->set_customer_ip_address(WC_Geolocation::get_ip_address()); $order->set_customer_user_agent(wc_get_user_agent()); $order->set_customer_note(isset($data['order_comments']) ? $data['order_comments'] : ''); $order->set_payment_method($data['payment_method']); $order->set_shipping_total(WC()->cart->shipping_total); $order->set_discount_total(WC()->cart->get_cart_discount_total()); $order->set_discount_tax(WC()->cart->get_cart_discount_tax_total()); $order->set_cart_tax(WC()->cart->tax_total); $order->set_shipping_tax(WC()->cart->shipping_tax_total); $order->set_total(WC()->cart->total); $this->create_order_line_items($order); $this->create_order_fee_lines($order); $this->create_order_shipping_lines($order); $this->create_order_tax_lines($order); $this->create_order_coupon_lines($order); $order_id = $order->save(); // Let plugins add their own meta data. do_action('woocommerce_checkout_update_order_meta', $order_id, $data); return $order_id; } catch (Exception $e) { return new WP_Error('checkout-error', $e->getMessage()); } }
/** * Create an order. Error codes: * 520 - Cannot insert order into the database. * 521 - Cannot get order after creation. * 522 - Cannot update order. * 525 - Cannot create line item. * 526 - Cannot create fee item. * 527 - Cannot create shipping item. * 528 - Cannot create tax item. * 529 - Cannot create coupon item. * @throws Exception * @return int|WP_ERROR */ public function create_order() { global $wpdb; // Give plugins the opportunity to create an order themselves if ($order_id = apply_filters('woocommerce_create_order', null, $this)) { return $order_id; } try { // Start transaction if available wc_transaction_query('start'); // Insert or update the post data $order_id = absint(WC()->session->order_awaiting_payment); $cart_hash = md5(json_encode(wc_clean(WC()->cart->get_cart_for_session())) . WC()->cart->total); /** * If there is an order pending payment, we can resume it here so * long as it has not changed. If the order has changed, i.e. * different items or cost, create a new order. We use a hash to * detect changes which is based on cart items + order total. */ if ($order_id && ($order = wc_get_order($order_id)) && $order->has_cart_hash($cart_hash) && $order->has_status(array('pending', 'failed'))) { // Action for 3rd parties. do_action('woocommerce_resume_order', $order_id); // Remove all items - we will re-add them later. $order->remove_order_items(); /** * Not resuming - lets create a new order object. */ } else { $order = new WC_Order(); } $order->set_created_via('checkout'); $order->set_cart_hash($cart_hash); $order->set_customer_id($this->customer_id); $order->set_currency(get_woocommerce_currency()); $order->set_prices_include_tax('yes' === get_option('woocommerce_prices_include_tax')); $order->set_customer_ip_address(WC_Geolocation::get_ip_address()); $order->set_customer_user_agent(wc_get_user_agent()); $order->set_customer_note(isset($this->posted['order_comments']) ? $this->posted['order_comments'] : ''); $order->set_payment_method($this->payment_method); $order->set_shipping_total(WC()->cart->shipping_total); $order->set_discount_total(WC()->cart->get_cart_discount_total()); $order->set_discount_tax(WC()->cart->get_cart_discount_tax_total()); $order->set_cart_tax(WC()->cart->tax_total); $order->set_shipping_tax(WC()->cart->shipping_tax_total); $order->set_total(WC()->cart->total); // Billing and shipping addresses if ($address_keys = array_merge(array_keys($this->checkout_fields['billing']), array_keys($this->checkout_fields['shipping']))) { foreach ($address_keys as $key) { if (is_callable(array($order, "set_{$key}"))) { $order->{"set_{$key}"}($this->get_posted_address_data(str_replace(array('billing_', 'shipping_'), '', $key), strstr($key, 'billing_') ? 'billing' : 'shipping')); } } } // Add line items. foreach (WC()->cart->get_cart() as $cart_item_key => $values) { $product = $values['data']; $item = new WC_Order_Item_Product(array('quantity' => $values['quantity'], 'name' => $product ? $product->get_title() : '', 'tax_class' => $product ? $product->get_tax_class() : '', 'product_id' => $product && isset($product->id) ? $product->id : 0, 'variation_id' => $product && isset($product->variation_id) ? $product->variation_id : 0, 'variation' => $values['variation'], 'subtotal' => $values['line_subtotal'], 'total' => $values['line_total'], 'subtotal_tax' => $values['line_subtotal_tax'], 'total_tax' => $values['line_tax'], 'taxes' => $values['line_tax_data'])); $item->set_backorder_meta(); // Set this to pass to legacy actions @todo remove in future release $item->legacy_values = $values; $item->legacy_cart_item_key = $cart_item_key; $order->add_item($item); } // Add fees foreach (WC()->cart->get_fees() as $fee_key => $fee) { $item = new WC_Order_Item_Fee(array('name' => $fee->name, 'tax_class' => $fee->taxable ? $fee->tax_class : 0, 'total' => $fee->amount, 'total_tax' => $fee->tax, 'taxes' => array('total' => $fee->tax_data))); // Set this to pass to legacy actions @todo remove in future release $item->legacy_fee = $fee; $item->legacy_fee_key = $fee_key; $order->add_item($item); } // Store shipping for all packages foreach (WC()->shipping->get_packages() as $package_key => $package) { if (isset($package['rates'][$this->shipping_methods[$package_key]])) { $shipping_rate = $package['rates'][$this->shipping_methods[$package_key]]; $item = new WC_Order_Item_Shipping(array('method_title' => $shipping_rate->label, 'method_id' => $shipping_rate->id, 'total' => wc_format_decimal($shipping_rate->cost), 'taxes' => $shipping_rate->taxes, 'meta_data' => $shipping_rate->get_meta_data())); // Set this to pass to legacy actions @todo remove in future release $item->legacy_package_key = $package_key; $order->add_item($item); } } // Store tax rows foreach (array_keys(WC()->cart->taxes + WC()->cart->shipping_taxes) as $tax_rate_id) { if ($tax_rate_id && apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') !== $tax_rate_id) { $order->add_item(new WC_Order_Item_Tax(array('rate_id' => $tax_rate_id, 'tax_total' => WC()->cart->get_tax_amount($tax_rate_id), 'shipping_tax_total' => WC()->cart->get_shipping_tax_amount($tax_rate_id), 'rate_code' => WC_Tax::get_rate_code($tax_rate_id), 'label' => WC_Tax::get_rate_label($tax_rate_id), 'compound' => WC_Tax::is_compound($tax_rate_id)))); } } // Store coupons foreach (WC()->cart->get_coupons() as $code => $coupon) { $item = new WC_Order_Item_Coupon(array('code' => $code, 'discount' => WC()->cart->get_coupon_discount_amount($code), 'discount_tax' => WC()->cart->get_coupon_discount_tax_amount($code))); $order->add_item($item); } // Save the order $order_id = $order->save(); // Update user meta $this->update_customer_data(); // Let plugins add their own meta data do_action('woocommerce_checkout_update_order_meta', $order_id, $this->posted); // If we got here, the order was created without problems! wc_transaction_query('commit'); } catch (Exception $e) { // There was an error adding order data! wc_transaction_query('rollback'); return new WP_Error('checkout-error', $e->getMessage()); } return $order_id; }
/** * Test: has_cart_hash */ function test_has_cart_hash() { $object = new WC_Order(); $this->assertFalse($object->has_cart_hash('12345')); $set_to = '12345'; $object->set_cart_hash($set_to); $this->assertTrue($object->has_cart_hash('12345')); }
/** * Create a new order programmatically. * * Returns a new order object on success which can then be used to add additional data. * * @param array $args * @return WC_Order */ function wc_create_order($args = array()) { $default_args = array('status' => null, 'customer_id' => null, 'customer_note' => null, 'parent' => null, 'created_via' => null, 'cart_hash' => null, 'order_id' => 0); $args = wp_parse_args($args, $default_args); $order = new WC_Order($args['order_id']); // Update props that were set (not null) if (!is_null($args['parent'])) { $order->set_parent_id(absint($args['parent'])); } if (!is_null($args['status'])) { $order->set_status($args['status']); } if (!is_null($args['customer_note'])) { $order->set_customer_note($args['customer_note']); } if (!is_null($args['customer_id'])) { $order->set_customer_id(is_numeric($args['customer_id']) ? absint($args['customer_id']) : 0); } if (!is_null($args['created_via'])) { $order->set_created_via(sanitize_text_field($args['created_via'])); } if (!is_null($args['cart_hash'])) { $order->set_cart_hash(sanitize_text_field($args['cart_hash'])); } // Update other order props set automatically $order->set_currency(get_woocommerce_currency()); $order->set_prices_include_tax('yes' === get_option('woocommerce_prices_include_tax')); $order->set_customer_ip_address(WC_Geolocation::get_ip_address()); $order->set_customer_user_agent(wc_get_user_agent()); $order->save(); return $order; }