---
url: 'https://metadrop.net/en/articles/drupal-8-commerce-2-create-an-order-programmatically'
title: 'Drupal 8 Commerce 2, create an order programmatically'
author: 'Cristian Aliaga'
date: '2019-04-04T14:45:30+00:00'
updated: '2026-06-10T08:17:37+00:00'
type: article
summary: 'How to create an order programmatically, redirect user to the payment step (in a form submit workflow), and manage anonymous user session.'
tags:
  - 'Drupal Planet'
  - E-Commerce
published: true
og:
  determiner: Automatic
  site_name: Metadrop
  'image:alt': 'Drupal 8 Commerce 2, create an order programmatically'
  street_address: 'Calle Manuel Luna, 12, 3 Dcha'
  locality: Madrid
  region: Madrid
  postal_code: '28020'
  country_name: España
  email: hola@metadrop.net
  phone_number: '910053180'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      '@type': Article
      '@id': 'https://metadrop.net/en/articles/drupal-8-commerce-2-create-an-order-programmatically#article'
      name: 'Drupal 8 Commerce 2, create an order programmatically'
      headline: 'Drupal 8 Commerce 2, create an order programmatically'
      description: "How to create an order programmatically,\_redirect user to the payment step (in a form submit workflow), and manage anonymous user session."
      about: E-Commerce
      datePublished: '2020-03-13T16:33:00+0100'
      dateModified: '2026-06-10T10:17:37+0200'
      author:
        '@type': Person
        name: 'Cristian Aliaga'
      publisher:
        '@type': Organization
        '@id': 'https://metadrop.net/#organization'
      mainEntityOfPage: 'https://metadrop.net/en/articles/drupal-8-commerce-2-create-an-order-programmatically'
    -
      '@type': Organization
      '@id': 'https://metadrop.net/#organization'
      url: 'https://metadrop.net/'
      name: Metadrop
      sameAs:
        - 'https://www.drupal.org/metadrop'
        - 'https://twitter.com/metadrop'
        - 'https://asociaciondrupal.es/partner/metadrop'
        - 'https://www.linkedin.com/company/metadrop'
      logo:
        '@type': ImageObject
        url: 'https://metadrop.net/themes/custom/mdrop_radix/logo-metadrop-500-500.jpg'
        width: '500'
        height: '500'
    -
      '@type': ItemPage
      '@id': 'https://metadrop.net/en/articles/drupal-8-commerce-2-create-an-order-programmatically'
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Home
            item: 'https://metadrop.net/en'
          -
            '@type': ListItem
            position: 2
            name: 'Expert Drupal & Tech Articles'
            item: 'https://metadrop.net/en/articles'
      publisher:
        '@type': Organization
        '@id': 'https://metadrop.net/#organization'
---
 1. [Articles](https://metadrop.net/en/articles)
 
  

# Drupal 8 Commerce 2, create an order programmatically

Friday, March 13, 2020

 

 



How to create an **order** **programmatically**, **redirect** user to the **payment** step (in a form submit workflow), and manage **anonymous** user **session**.



   



In some situations we may need to create an order using custom code. For example, if we want to create an order quickly after a user action without having to go through the entire process (searching for the product, selecting units and adding them to the cart) or if we want to hide the Commerce interface and use a custom interface.

## Where to start the process

The first thing is to determine where to add the code that creates the order. This will depend on what action the order will be created in response to. Normally we'll create our own Drupal service to do the job and call that service from where we want to create the order. Using the service we can also easily use dependency injection, which is the best way to add external dependencies to our classes.

## Create the order

In the file in charge of adding the order we must import the following classes:

```php
use Drupal\commerce_price\Price;
use Drupal\commerce_order\Entity\OrderItem;
use Drupal\commerce_order\Entity\Order;
```

### Order item

**First** we need to create an **order item** and save it:

```php
$order_item = OrderItem::create([
  'type' => 'awesome_order_item_type',
  'purchased_entity' => 1,
  'quantity' => 1,
  // Omit these lines to preserve original product price.
  'unit_price' => new Price(80, 'EUR'),
  'overridden_unit_price' => TRUE,
]);
$order_item->save();
```

### Order

**Then** create **order** and attach the previous order item generated:

```php
$order = Order::create([
  'type' => 'donation',
  'mail' => \Drupal::currentUser()->getEmail(),
  'uid' => \Drupal::currentUser()->id(),
  'store_id' => 1,
  'order_items' => [$order_item],
  'placed' => \Drupal::time()->getCurrentTime(),
  'payment_gateway' => 'example_payment',
  'checkout_step' => 'payment',
  'state' => 'draft',
]);
```

**Recalculate order total** and save order:

```php
$order->recalculateTotalPrice();
$order->save();
```

**Add order number** and save (based in order id):

```php
$order->set('order_number', $order->id());
$order->save();
```

### Anonymous cart session

For anonymouse users Commerce links the cart with the user session. Because we have added the order using custom code we need to explicitly do the same process if we want to send the user to the checkout. For this, we'll need **commerce** **cart** **session** **service** in order to provide user the correct **access** to view this order payment (**checkout** **path,** @see \\Drupal\\commerce\_checkout\\Controller\\ CheckoutController::checkAccess).

```php
$cart_session = \Drupal::service('commerce_cart.cart_session');
if (\Drupal::currentUser()->isAnonymous()) {
  $cart_session->addCartId($order->id());
}
```

In case of not doing so, the anonymous user will receive an error when accessing the payment.

For registered users none action is needed.

### Redirect

After creating the order the usual case is to send the user to the checkout. As we'll normally have created the request in a form submit in response to a user action we'll use the **redirect** mechanism in the **form submission flow**, which would be as follows:

```php
$form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order->id()]);
```

That's it, now user will be directly in the checkout workflow.

### Additional useful snippets related

**Prevent** user to add **multiple** **orders** to **session**  (that is, if for example there is already some product in the cart because it has been left halfway through a previous process), one good strategy is to move to the canceled state all previous not completed orders in cart session (type active):

```php
$cart_session = \Drupal::service('commerce_cart.cart_session');
$current_orders = $cart_session->getCartIds();
foreach ($current_orders as $order_id) {
  $order = Order::load($order_id);
  $order->state = 'canceled';
  $order->save();
  // Use just this to remove from cart session.
  $cart_session->deleteCartId($order_id);
}
```

After all (after redirecting in a custom "CheckoutPane" for example), you can **destroy** **generated** user **session if the "completed" page does not require any special access**, this means a different one of checkout complete default path (that way user can keep browsing cached version of site). This way Drupal can serve cached pages to the user if is anonymous (because the user session prevents Drupal to use cached pages).

```php
if (\Drupal::currentUser()->isAnonymous()) {
  \Drupal::service('session_manager')->destroy();
}
```



[E-Commerce](https://metadrop.net/en/articles?text=E-Commerce)

 

[Drupal Commerce Agency](https://metadrop.net/en/solutions/drupal-commerce-agency " See Drupal Commerce Agency")

Metadrop is a leading Drupal Commerce agency, building scalable ecommerce platforms with advanced inventory management, payment integrations, and complex B2B commerce workflows.

 

 See more