Handling anonymous orders in custom commerce module Drupal: 8.7.2
Commerce: 2.13

I have a custom module set up that adds the following functionality to Commerce:


It prevents the user from adding more than one item to their cart.  If they try to add a second item, it removes the first item from their cart and adds the second item.  
When clicking "Add to Cart", it redirects the user to a confirmation page.  
On that page is a button that links to the order's checkout page.


I am handling all of these via queries that use the user ID and order ID to pull the correct order/cart information.

This all works great for logged in users.  Most of our customers will be anonymous, though.  It does work for anonymous users, but my concern is that if multiple anonymous users are placing orders at the same time, their carts will get mixed up, because all anonymous users have a UID of 0.

How can I better differentiate between anonymous user's carts?  Is there a way to store their IP in the database, and then use that?

Here is my module's code:

commerce_custom.module (handles removing first item from cart, redirecting to confirmation page):

&lt;?php


use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce_order\Entity\Order;
use Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_custom_form_commerce_order_item_add_to_cart_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {
   $form['actions']['submit']['#value']='Sponsor';
   $form['#validate'][] = 'commerce_custom_form_validate';
   $form['actions']['submit']['#submit'][] = 'commerce_custom_cart_alter_redirect';
}

function commerce_custom_form_validate(array &amp;$form, FormStateInterface $form_state) {

    $user = \Drupal::currentUser()-&gt;id();
    $connection = \Drupal::database();
    $query = $connection-&gt;query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft'", [':user' =&gt; $user]);
    $result = $query-&gt;fetchAll();
    //dpm($result);

    $cart_count = $result[0]-&gt;quantity;
    $order_id = $result[0]-&gt;order_id;

    if ($cart_count &gt; 0 &amp;&amp; $order_id) {
        $order = \Drupal::entityTypeManager()-&gt;getStorage('commerce_order')-&gt;load($order_id);
        $items = $order-&gt;getItems();
        foreach($items as $item_key =&gt; $item) {
            $order-&gt;removeItem($item);
            $item-&gt;delete();
        }
    }
}

function commerce_custom_cart_alter_redirect(&amp;$form, FormStateInterface $form_state) {
  $responce =  new RedirectResponse('/how-it-works');
  $responce-&gt;send();
}


ContinueCheckoutBlock.php (creates block with button linking to checkout page):

&lt;?php

namespace Drupal\commerce_custom\Plugin\Block;
use Drupal\Core\Block\BlockBase;

class ContinueCheckoutBlock extends BlockBase {

   public function build() {

        $user = \Drupal::currentUser()-&gt;id();
        $connection = \Drupal::database();
        $query = $connection-&gt;query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft'", [':user' =&gt; $user]);
        $result = $query-&gt;fetchAll();
        $order_id = $result[0]-&gt;order_id;

        return array(
            '#type' =&gt;'markup',
            '#markup' =&gt; '&lt;a href=checkout/' . $order_id . '/order_information class=button&gt;Continue&lt;/a&gt;',
        );
   }
}
Perhaps you could use PHP's session_id()?


  session_id() is used to get or set the session id for the current session.


Basically copied from this answer.



You may also find useful information here: Anonymous Personalization Without Leaving Drupal, which appears to be a topic from DrupalCon Seattle 2019.