WC_Checkout::create_orderpublicWC 1.0

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.

Метод класса: WC_Checkout{}

Возвращает

int|WP_ERROR.

Использование

$WC_Checkout = new WC_Checkout();
$WC_Checkout->create_order( $data );
$data(массив) (обязательный)
Posted data.

Код WC_Checkout::create_order() WC 11.0.1

public function create_order( $data ) {
	/**
	 * Gives plugins an opportunity to create a new order themselves.
	 *
	 * @since 3.0.0 or earlier
	 *
	 * @param int|null    $order_id Can be set to an order ID to short-circuit the default order creation process.
	 * @param WC_Checkout $checkout Reference to the current WC_Checkout instance.
	 */
	$order_id = apply_filters( 'woocommerce_create_order', null, $this );
	if ( $order_id ) {
		return $order_id;
	}

	try {
		$order_id           = absint( WC()->session->get( 'order_awaiting_payment' ) );
		$cart_hash          = WC()->cart->get_cart_hash();
		$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
		$order              = $order_id ? wc_get_order( $order_id ) : null;

		/**
		 * 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 && $order->has_cart_hash( $cart_hash ) && $order->has_status( array( OrderStatus::PENDING, OrderStatus::FAILED ) ) ) {
			/**
			 * Indicates that we are resuming checkout for an existing order (which is pending payment, and which
			 * has not changed since it was added to the current shopping session).
			 *
			 * @since 3.0.0 or earlier
			 *
			 * @param int $order_id The ID of the order being resumed.
			 */
			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();
		}

		$fields_prefix = array(
			'shipping' => true,
			'billing'  => true,
		);

		foreach ( $data as $key => $value ) {
			if ( is_callable( array( $order, "set_{$key}" ) ) ) {
				$order->{"set_{$key}"}( $value );
				// Store custom fields prefixed with either shipping_ or billing_. This is for backwards compatibility with 2.6.x.
			} elseif (
				isset( $fields_prefix[ current( explode( '_', $key ) ) ] )
				&& ! in_array( $key, self::SHIPPING_FIELDS_EXCLUDED_FROM_META, true )
			) {
				$order->update_meta_data( '_' . $key, $value );
			}
		}

		if ( isset( $data['billing_email'] ) ) {
			$order->hold_applied_coupons( $data['billing_email'] );
		}

		$order->set_created_via( 'checkout' );
		$order->set_cart_hash( $cart_hash );
		/**
		 * This action is documented in woocommerce/includes/class-wc-checkout.php
		 *
		 * @since 3.0.0 or earlier
		 */
		$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( isset( $available_gateways[ $data['payment_method'] ] ) ? $available_gateways[ $data['payment_method'] ] : $data['payment_method'] );
		$this->set_data_from_cart( $order );

		if ( $order->has_cogs() && $this->cogs_is_enabled() ) {
			$order->calculate_cogs_total_value();
		}

		/**
		 * Action hook to adjust order before save.
		 *
		 * @since 3.0.0
		 */
		do_action( 'woocommerce_checkout_create_order', $order, $data );

		// Save the order.
		$order_id = $order->save();

		// Defense-in-depth: if the cart still has items but the persisted order has none,
		// the save silently dropped every line item (e.g. a $wpdb->insert() returning false
		// in save_items()). Re-read the order from the data store so we check DB state, not
		// the in-memory copy that save_items() populated. Bail out so the caller can retry
		// rather than completing a paid-but-empty order.
		//
		// This is intentionally narrow: it catches the catastrophic "no items at all" case,
		// not partial item loss where some inserts succeed and some fail. Wider parity checks
		// would need to reconcile quantities across products, bundles, fees, shipping, etc.,
		// which is out of scope for the silent-failure guard.
		if ( WC()->cart->get_cart_contents_count() > 0 ) {
			$persisted_order = wc_get_order( $order_id );
			if ( ! $persisted_order || 0 === count( $persisted_order->get_items() ) ) {
				throw new Exception( __( 'Order items could not be saved. Please try again.', 'woocommerce' ) );
			}
		}

		/**
		 * Action hook fired after an order is created used to add custom meta to the order.
		 *
		 * @since 3.0.0
		 */
		do_action( 'woocommerce_checkout_update_order_meta', $order_id, $data );

		/**
		 * Action hook fired after an order is created.
		 *
		 * @since 4.3.0
		 */
		do_action( 'woocommerce_checkout_order_created', $order );

		return $order_id;
	} catch ( Exception $e ) {
		if ( $order && $order instanceof WC_Order ) {
			wc_release_coupons_for_order( $order );
			/**
			 * Action hook fired when an order is discarded due to Exception.
			 *
			 * @since 4.3.0
			 */
			do_action( 'woocommerce_checkout_order_exception', $order );
		}
		return new WP_Error( 'checkout-error', $e->getMessage() );
	}
}