Understand the b2c checkout flow in Hybris

Hybris featured image

1. Overview

In an eCommerce website, the Checkout is the set of steps showing to a customer before placing an order.

This is a simplified overview of the default checkout flow for the b2c accelerator in Hybris.

Overview of the checkout in Hybris

As a clean code and design patterns fan, the checkout is one of my favorite piece of code in Hybris.

In this article, we will try to dissect the checkout steps in details.

2. Checkout Step

A checkout step is defined by 3 main components :

  • Checkout Step object: an instance of the CheckoutStep.
  • Checkout Step controller: a Spring MVC controller.
  • Checkout Step view page: a JSP page.

Checkout step overview in Hybris

2.1. Checkout Step Object

A checkout step object is an instance of the CheckoutStep class, it’s declared in Spring by the bean id checkoutStep.

A CheckoutStep composed of 4 elements :

  • CheckoutGroup : it’s the container of all the checkout steps (see next chapter).
  • CheckoutStepValidator : every checkout step has its own validator, it’s used to check whether we are eligible to access to a checkout step or not (for example you can’t access to the payment method step without passing by the delivery address and the delivery method steps).
  • Transitions : it holds the redirection URLs to the previous, the next and the current checkout steps controllers.
  • progressBarId : it’s is a unique id of the checkout step, used for breadcrumb.

E.g. This is the definition of the delivery address step, it is located in the multi-step-checkout-config.xml.

<!-- checkout step definintion -->
<alias name="defaultResponsiveDeliveryAddressCheckoutStep" alias="responsiveDeliveryAddressCheckoutStep" />
<bean id="defaultResponsiveDeliveryAddressCheckoutStep" parent="checkoutStep">
	<property name="checkoutGroup" ref="responsiveCheckoutGroup"/>
	<property name="checkoutStepValidator" ref="defaultResponsiveDeliveryAddressCheckoutValidator"/>
	<property name="transitions">
		<map merge="true">
			<entry key="previous" value-ref="REDIRECT_TO_CART"/>
			<entry key="current" value-ref="REDIRECT_TO_DELIVERY_ADDRESS"/>
			<entry key="next" value-ref="REDIRECT_TO_DELIVERY_METHOD"/>
		</map>
	</property>
	<property name="progressBarId" value="deliveryAddress"/>
</bean>
		
<!-- Redirects -->
<bean id="REDIRECT_TO_CART" class="java.lang.String">
	<constructor-arg value="redirect:/cart"/>
</bean>
<bean id="REDIRECT_TO_DELIVERY_ADDRESS" class="java.lang.String">
	<constructor-arg value="redirect:/checkout/multi/delivery-address/add"/>
</bean>
<bean id="REDIRECT_TO_DELIVERY_METHOD" class="java.lang.String">
	<constructor-arg value="redirect:/checkout/multi/delivery-method/choose"/>
</bean>

2.2. Checkout Step Controller

The checkout step controller should extend the AbstractCheckoutStepController.javaand implement the following methods:enterStep(), next(), back() and getCheckoutStep().

  • enterStep() : it’s the first entry point to the checkout step, it should return back the checkout step view page (see next section).
  • back() : called whenever we want to go back to the previous checkout step.
  • next() : called whenever we want to go to the next checkout step.
  • getCheckoutStep() : should be implemented for the purpose of retrieving the current CheckoutStep.

E.g. This is a lite version of the checkout step controller of the delivery address step.

@Controller
@RequestMapping(value = "/checkout/multi/delivery-address")
public class DeliveryAddressCheckoutStepController extends AbstractCheckoutStepController
{
	private static final String DELIVERY_ADDRESS = "delivery-address";

	// implementation of the enterStep() method
	@Override
	@RequestMapping(value = "/add", method = RequestMethod.GET)
	@RequireHardLogIn
	@PreValidateQuoteCheckoutStep
	@PreValidateCheckoutStep(checkoutStep = DELIVERY_ADDRESS)
	public String enterStep(final Model model, final RedirectAttributes redirectAttributes) throws CMSItemNotFoundException
	{
		// ...
		
		return ControllerConstants.Views.Pages.MultiStepCheckout.AddEditDeliveryAddressPage;
	}

	// implementation of back() method : go to previous checkout step
	@RequestMapping(value = "/back", method = RequestMethod.GET)
	@RequireHardLogIn
	@Override
	public String back(final RedirectAttributes redirectAttributes)
	{
		return getCheckoutStep().previousStep();
	}

	// implementation of next() method : go to next checkout step
	@RequestMapping(value = "/next", method = RequestMethod.GET)
	@RequireHardLogIn
	@Override
	public String next(final RedirectAttributes redirectAttributes)
	{
		return getCheckoutStep().nextStep();
	}

	// implementation of the getCheckoutStep() method : get current CheckoutStep
	protected CheckoutStep getCheckoutStep()
	{
		return getCheckoutStep(DELIVERY_ADDRESS);
	}
}

The @PreValidateCheckoutStep(checkoutStep = DELIVERY_ADDRESS) calls the validator of the delivery address step defined previously in the xml.

2.3. Checkout Step View

The checkout step view page is a basic JSP page, it’s the same JSP page returned by the enterStep() method of the checkout step controller.

The checkout step view page should have a link to the next() and back() method of the checkout step controller.

E.g. The checkout JSP page for delivery address step is.

${HYBRIS_BIN_DIR}/custom/training/trainingstorefront/web/webroot/WEBINF/views/responsive/pages/checkout/multi/addEditDeliveryAddressPage.jsp

3. Checkout Group

The checkout group or checkout flow group is a container of the checkout steps, technically it’s an instance of the CheckoutGroup.

The default checkout group used for a given CMS site (e.g b2c electronics) is defined in the BaseStoreModel.

E.g. The default checkout group of the electronics b2c accelerator is responsiveCheckoutGroup.

Checkout flow group configuration in Hybris

The responsiveCheckoutGroup is defined as :

<alias name="defaultResponsiveMultiStepCheckoutGroup" alias="responsiveCheckoutGroup" />
<bean id="defaultResponsiveMultiStepCheckoutGroup"  class="de.hybris.platform.acceleratorstorefrontcommons.checkout.steps.CheckoutGroup">
	<property name="groupId"  value="responsiveCheckoutGroup"/>
	<property name="checkoutStepMap">
		<map merge="true">
			<entry key="multi" value-ref="responsiveMultiStepCheckout"/>
			<entry key="delivery-address" value-ref="responsiveDeliveryAddressCheckoutStep"/>
			<entry key="delivery-method" value-ref="responsiveDeliveryMethodCheckoutStep"/>
			<entry key="payment-method" value-ref="responsivePaymentMethodCheckoutStep"/>
			<entry key="summary" value-ref="responsiveSummaryCheckoutStep"/>
		</map>
	</property>
	<property name="validationResultsMap">
		<map merge="true">
			<entry key="FAILED" value-ref="REDIRECT_TO_CART"/>
			<entry key="REDIRECT_TO_DELIVERY_ADDRESS" value-ref="REDIRECT_TO_DELIVERY_ADDRESS"/>
			<entry key="REDIRECT_TO_CART" value-ref="REDIRECT_TO_CART"/>
			<entry key="REDIRECT_TO_PAYMENT_METHOD" value-ref="REDIRECT_TO_PAYMENT_METHOD"/>
			<entry key="REDIRECT_TO_DELIVERY_METHOD" value-ref="REDIRECT_TO_DELIVERY_METHOD"/>
			<entry key="REDIRECT_TO_SUMMARY" value-ref="REDIRECT_TO_SUMMARY"/>
		</map>
	</property>
	<property name="checkoutProgressBar">
		<map merge="true">
			<entry key="1" value-ref="responsiveDeliveryAddressCheckoutStep"/>
			<entry key="2" value-ref="responsiveDeliveryMethodCheckoutStep"/>
			<entry key="3" value-ref="responsivePaymentMethodCheckoutStep"/>
			<entry key="4" value-ref="responsiveSummaryCheckoutStep"/>
		</map>
	</property>
</bean>
  • checkoutStepMap : a map contains the reference to the CheckoutSteps.
  • validationResultsMap : redirection URLs as constants used when it’s needed.
  • checkoutProgressBar : it’s is a unique id of the checkout steps, used for breadcrumb.

4. Checkout Group Map

The checkout map group is a Map that contains all the checkout flow group, we can retrieve a specific checkout flow group from the map using its id (key).

<!--Checkout GroupMap-->
<util:map id="checkoutFlowGroupMap" >
	<entry key="apparelCheckoutGroup"  value-ref="apparelCheckoutGroup"/>
	<entry key="defaultCheckoutGroup" value-ref="defaultCheckoutGroup"/>
	<entry key="responsiveCheckoutGroup" value-ref="responsiveCheckoutGroup"/>
</util:map>
<!--Checkout GroupMap-->

5. CheckoutFacade

The CheckoutFacadeand its implementation DefaultCheckoutFacadeis crucial for a proper functioning of the checkout flow.

It’s injected by default into the AbstractCheckoutController.java, hence it could be used within the checkout step controller.

Some of the useful methods from the CheckoutFacade.java.

  • boolean hasCheckoutCart() : to check if checkout cart exist.
  • CartData getCheckoutCart() : to retrieve the current checkout cart if it exists.
  • void prepareCartForCheckout() : to prepare cart for the first time for the checkout.
  • OrderData placeOrder() : to place an order.
  • boolean setDeliveryAddress(AddressData) : to set a delivery address for the checkout cart.
  • List<DeliveryModeData> getSupportedDeliveryModes() : to get supported delivery modes for the checkout cart based on the delivery address.

6. Checkout in action

6.1. Checkout preparation

The checkout flow started when your click on the CHECK OUT button on the cart page.

Cart page checkout in Hybris

The checkout() method of the CheckoutController is the first thing getting invoked via the request URL  /checkout.

@Controller
@RequestMapping(value = "/checkout")
public class CheckoutController extends AbstractCheckoutController {
	
	//...

	@RequestMapping(method = RequestMethod.GET)
	public String checkout(final RedirectAttributes redirectModel) {
		
		if (getCheckoutFlowFacade().hasValidCart()) {
			// if cart not valid go to Cart page
			if (validateCart(redirectModel)) {
				return REDIRECT_PREFIX + "/cart";
			}
			
			// else prepare the current Cart for the checkout and redirect to /checkout/multi
			else {
				checkoutFacade.prepareCartForCheckout();
				return getCheckoutRedirectUrl();
			}
		}
		
		// No session cart or empty session cart. Bounce back to the cart page.
		return REDIRECT_PREFIX + "/cart";
	}
	
	//...
}

This is not a step of the checkout flow group, its main role is the validation and the preparation of the checkout cart then redirect to the /checkout/multi URL, which is the first step of checkout flow : responsiveMultiStepCheckout.

6.2. Multi Checkout Step

This is the first checkout step of the checkout flow group, defined with :

  • Checkout Step object idresponsiveMultiStepCheckout
  • Checkout Step ControllerMultiStepCheckoutController
  • URL Mapping/checkout/multi
  • Checkout Step View : NONE

This is just an additional verification step, then redirect the customer to the second checkout step: responsiveDeliveryAddressCheckoutStep.

 

6.3. Delivery Address Checkout Step

Is the second checkout step, in this step, the customer is invited to provide its shipping/delivery address.

Technically this checkout step is defined with :

  • Checkout Step object id : responsiveDeliveryAddressCheckoutStep
  • Checkout Step Controller : DeliveryAddressCheckoutStepController
  • URL Mapping : /checkout/multi/delivery-address
  • Checkout Step View : pages/checkout/multi/addEditDeliveryAddressPage.jsp

Delivery address checkout step Hybris

6.4. Delivery Method Checkout Step

In this step, the customer is invited to choose one of the supported delivery/shipping methods depending on its delivery address.

Technically the delivery method step is defined with :

  • Checkout Step object id : responsiveDeliveryMethodCheckoutStep
  • Checkout Step Controller : DeliveryMethodCheckoutStepController
  • URL Mapping : /checkout/multi/delivery-method
  • Checkout Step View : pages/checkout/multi/chooseDeliveryMethodPage.jsp

Delivery method checkout step Hybris

6.5. Payment Method Checkout Step

In the payment checkout step, the customer is asked to choose from one of the supported payment methods and enter it’s payment credentials.

Technically the payment method checkout step is defined with :

  • Checkout Step object id : responsivePaymentMethodCheckoutStep
  • Checkout Step Controller : PaymentMethodCheckoutStepController
  • URL Mapping : /checkout/multi/payment-method
  • Checkout Step View : pages/checkout/multi/addPaymentMethodPage.jsp

Payment method checkout step Hybris

In case of the HOP payment module, the customer will be redirected to an externally hosted page.

For the sake of simplicity, I prefer to not mention some more details about this step as I will shed lights on it later on in a separated post 🙂

6.6. Summary Checkout Step

This is the last checkout step, in this step, a detailed summary of the order is displayed to the customer, so the customer can confirm/place the order or edit it.

Technically this checkout step is defined with :

  • Checkout Step object id : responsiveSummaryCheckoutStep
  • Checkout Step Controller : SummaryCheckoutStepController
  • URL Mapping : /checkout/multi/summary
  • Checkout Step View : pages/checkout/multi/checkoutSummaryPage.jsp

 

13
Leave a Reply

avatar
8 Comment threads
5 Thread replies
7 Followers
 
Most reacted comment
Hottest comment thread
8 Comment authors
hybrisJohnDurgaRao GIrfanRamesh Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
Teja
Guest
Teja

Greatwork moulad

ayoub
Guest
ayoub

thanks for sharing (y)

Ramesh
Guest
Ramesh

good tutorial i am new to hybris could you please explain starting with ant modulegen
we will get 7 extension ex: initialdata, storefront ,core,cockpits….etc
initialdata ::storefront :: core:: what we are going to write hear
Start the hybris server and what url to use in localhost to see site

Irfan
Guest
Irfan

Good Article. Nicely Explained.

DurgaRao G
Guest
DurgaRao G

Nice explanation. Can you please share a new article with an example if possible with complete flow i.e starting from adding product to cart to delivering product to customer. It would be really helpful for people who are new to hybris.

John
Guest
John

Thanks bro…..wiki is shit compared to your website

hybris
Guest
hybris

t

hybris
Guest
hybris

Thanks for the kudos! I feel great!