copying discussion from https://github.com/drupalcommerce/commerce/pull/859

Feature request:
add /checkout route as a convenient, paramater-free way to redirect users to appropriate step of checkout

Use case:
I want to send a user to checkout, but don't know their cart id

Comments

aaronbauman created an issue. See original summary.

aaronbauman’s picture

StatusFileSize
new4.9 KB

Here's a patch which is similar to what I'm running with locally, though in a custom module.

I'm not sure if it makes sense for all use cases to expose this path - maybe there's a configuration switch?
Maybe it's an add-on module?

I don't expect this patch will pass tests or get committed, but offer it as a starting point

mglaman’s picture

Status: Active » Needs review
anybody’s picture

We're having the same requirement and yes, I think that makes sense and the implementation seems good to me.
Perhaps a Commerce maintainer should have a view?

+1 for RTBC.

john_b’s picture

The user is guaranteed to have only one cart if the site is using commerce_combine_checkout module.

@AaronBauman would you share the custom module version, please?

aaronbauman’s picture

In my case, I created a route at "/checkout" with this setup:

example_module.routing.yml:

checkout:
  path: '/checkout'
  defaults:
    _controller: '\Drupal\example_module\Controller\ExampleCheckoutController::checkout'
  options:
    no_cache: TRUE
  requirements:
    _access: 'TRUE'

Controller:


namespace Drupal\example_module\Controller;

use Drupal\commerce_cart\CartProviderInterface;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Example checkout controller provides the /checkout route.
 */
class ExampleCheckoutController extends ControllerBase {

  /**
   * Cart provider.
   *
   * @var \Drupal\commerce_cart\CartProviderInterface*/
  protected $cartProvider;

  /**
   * {@inheritdoc}
   */
  public function __construct(CartProviderInterface $cartProvider) {
    $this->cartProvider = $cartProvider;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container->get('commerce_cart.cart_provider'));
  }

  /**
   * Send a user to checkout, or to /cart if their cart is empty.
   */
  public function checkout() {
    $carts = $this->cartProvider->getCarts();
    $carts = array_filter($carts, function ($cart) {
      /** @var \Drupal\commerce_order\Entity\OrderInterface $cart */
      return $cart->hasItems();
    });
    if (empty($carts)) {
      return $this->redirect('commerce_cart.page');
    }
    $cart = current($carts);
    return $this->redirect('commerce_checkout.form', ['commerce_order' => $cart->id()]);
  }

}

john_b’s picture

@AaronBauman Thanks!

rszrama’s picture

Status: Needs review » Needs work

Just found this issue while trying to see if I should create it or not. : )

Re: the logic in the new controller function, are we sure current() is the right approach? I'm just not clear if the loop leaves the pointer at the end or will reset it to the beginning of the array. (Edit: fwiw, it's the first element.)

As a core feature, to avoid any confusion in the event a customer does legitimately have multiple carts, perhaps we should redirect back to /cart if we find more than one cart with items?

This will need tests before we can commit it.

anybody’s picture

Thank you for your feedback @rszrama!

As a core feature, to avoid any confusion in the event a customer does legitimately have multiple carts, perhaps we should redirect back to /cart if we find more than one cart with items?

Yes I think so and I'd suggest to log a message to watchdog (to inform the shop owner) and show a configurable message to the user?

lukasss’s picture

+1 for this

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new6.9 KB
new6.2 KB

The attached patch addresses the comments from #8, and adds tests coverage.

Additionally, I made the following changes / improvements:

  1. The /checkout route now checks the "access checkout" permission.
  2. The UrlGeneratorTrait is actually deprecated, so we can't use it.
  3. Just like Commerce 1.x, when there are no carts/no cart items, the following message is displayed: "Add some items to your cart and then try checking out.".
  4. When there are multiple carts, we simply redirect to the cart page (not sure what message we could possibly display in this case though)...
rszrama’s picture

Status: Needs review » Reviewed & tested by the community

I think it's fine not to have a message in the event of multiple carts. In such a scenario, selecting the cart to proceed with should be understood to be the first step in the checkout process. The default verbiage for the status message is fine with me. Worked great in local testing!

anybody’s picture

Great work, thanks a lot @jsacksick! I can also confirm RTBC.

jsacksick’s picture

Status: Reviewed & tested by the community » Fixed

Committed! Thanks for the help with review/testing!

  • jsacksick committed c6677d0 on 8.x-2.x
    Issue #2994356 by jsacksick, AaronBauman, Anybody, rszrama: Add a /...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.