Understand the b2c checkout flow in Hybris

Hybris Logo

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

 

4.8 4 votes
Article Rating
Subscribe
Notify of
guest

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

31 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Teja
Teja
3 years ago

Greatwork moulad

ayoub
ayoub
3 years ago

thanks for sharing (y)

Ramesh
Ramesh
3 years ago

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
Irfan
3 years ago

Good Article. Nicely Explained.

DurgaRao G
DurgaRao G
2 years ago

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
John
2 years ago

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

rakesh
rakesh
Reply to  Mouad EL Fakir
2 years ago

could u explain the payment module integration in hybris of paypal or any other intergartion

hybris
hybris
2 years ago

t

hybris
hybris
2 years ago

Thanks for the kudos! I feel great!

Shailesh
Shailesh
2 years ago

Great explanation Mouad !!! Can you please try to add more posts on Cart, Payment Integration, Data Hub Integration

Rajesh
Rajesh
2 years ago

How can I customize/ overwrite the payment page in hybris 6.7.

Bala
Bala
2 years ago

Very nice article, can you please add the order confirmation process that will help us in end to end flow of checkout.

javed
javed
1 year ago

one of the best checkout customization tutorial.

raj
raj
1 year ago

great work man.. !!

PARTHASARATHI GHOSHAL
PARTHASARATHI GHOSHAL
1 year ago

I’m going to integrate custom payment gateway in Hybris 1905 version. Need your guidance as you skipped the part I need to know in your steps mentioned above : “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 ” How I can update and go to next step when I get success payment redirection from payment provider page. Also need to know how… Read more »

Partha
Partha
Reply to  Mouad EL Fakir
1 year ago

No issue on success / fail callback. But I need your valuable guidance how I can update payment in to order when get response from provider in my ipn_url which hits my server as and when payment success. Session not available only I get guid which I sent during payment request.

PARTHASARATHI GHOSHAL
PARTHASARATHI GHOSHAL
Reply to  Partha
1 year ago

Please help me to get cart data, user data and shipping data on with only carddata.getGuid() , so that I can place order

Mohamed BELMAHI
Reply to  Partha
1 year ago

Hello, you should check why the session is not available.
Basically you should have access to your current session, the same session that been used before redirection to payment provider.
If you fixed that you will be able to get cart from session then create order and update it.

Other thing for non received callback due to client browser issues, you have to implement a new controller to handle notification from payment provide. and in this case you have to use order_id provided during payment to get your cart and create order then update its payment info.

Partha
Partha
Reply to  Mohamed BELMAHI
1 year ago

In checkout flow for multistep ( Hybris version : 1905 ) after payment success final review comes and final order placed. I’m going to implement where qr code is getting generated in provider site ( redirected to provider site from base site) . After making payment client returned to success page as per setting during qr code generation. Secondly, as soon as payment is made via app from scanning qr code provider hits my ipn_url silently as per setting during QR code generation. I like to update payment for this order /cartData when ipn_url hits by providers serve on receipt… Read more »

Mohamed BELMAHI
Reply to  Partha
1 year ago

Yes you are right if providers service hits your server there is no session available, so in this case you should work like your received a notification form provider, you have to find a way to make provider send you an id and use this id to get your cart or whatever you need to get. on most of case the provider send a notification with payment info as parameters of its request so you can use them to update you cart/order.

Partha
Partha
Reply to  Mohamed BELMAHI
1 year ago

Yes, I’m sending guid of cart to provider which I get return on notification. My question is how I’ll get customer model and other required model to place order. Is it feasible to get all those model only by cart guid, my provider only accept and return in notify url one id that is only 32 character long. Otherwise I can sent all model id in coded form. I need help from an expert SAP developer like you.

Sri
Sri
1 year ago

Great work, what i was looking for since last months, you did it exactly , i appreciated Mouad EL Fakir

Vaishnavi Hebbar
Vaishnavi Hebbar
10 months ago

Good article… Explained well

Vicky
Vicky
7 months ago

I like the way all relevant details are provided, like sectionalized content, code references when needed, etc.
Helps understand overall flow.
Thanks.

31
0
Would love your thoughts, please comment.x
()
x