I have created three separate order types for my site:
- Merch: physical products (using commerce_cart normally)
- Booking: bookings (not shipping-enabled)
- Vouchers: gift vouchers (shipping enabled)
All are for anonymous orders, and all use the 'Default' workflow. Each has its own dedicated checkout flow, though those for Merch and Vouchers are identical (duplicated from the built-in "Shipping" flow, with just the user login/registration step removed). Merch is what I'd call wholly "vanilla" Commerce + Shipping usage and has no issues. For Booking and Vouchers, orders are created programmatically via bespoke Forms using this basic routine in the submit handler:
//First delete any existing carts in the session
$cart_session = \Drupal::service('commerce_cart.cart_session');
$current_orders = $cart_session->getCartIds();
foreach ($current_orders as $order_id) {
$xorder = Order::load($order_id);
$xorder->state = 'canceled';
$xorder->save();
$cart_session->deleteCartId($order_id);
}
//Extending classes define ORDER_TYPE and STORE_ID constants
$order = Order::create([
'uid' => \Drupal::currentUser()->id(),
'type' => static::ORDER_TYPE,
'state' => 'draft',
'checkout_step' => 'order_information',
'store_id' => static::STORE_ID,
]);
$order->save();
//Extending classes add their own order items
foreach(static::orderItems($form_state) as $item) {
$order->addItem($item)->save();
}
if(\Drupal::currentUser()->isAnonymous()) {
$cart_session->addCartId($order->id());
}
$form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order->id()]);
For Booking, which is not shipping-enabled, this code works without problems. For Vouchers, the destination checkout page (Order Information) shows two problems: The Order Summary sidebar does not render at all; and ajax actions (such as unchecking "Billing address is same as shipping") get an access denied error, e.g.
Path: /checkout/1/order_information?ajax_form=1&_wrapper_format=drupal_ajax. Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: in Drupal\Core\Routing\AccessAwareRouter->checkAccess() (line 117 of /var/www/proj/web/core/lib/Drupal/Core/Routing/AccessAwareRouter.php).
Due to the errors no shipping rates are presented and the checkout cannot progress. Reloading the page results in Access Denied for the whole page.
If I try to use the same Form while logged-in as admin, the Vouchers checkout works as intended.
The combo of programmatically creating the order + anonymous orders + shipping leads to the user losing access to the whole order or to some key part of it. Can anyone advise how I can debug this further, or what my code might be missing?