Exploration of Sitecore OrderCloud Architecture and Headstart Setup
written by Himadri Chakrabarti
|July 2022
Sitecore OrderCloud is an API-first, Headless, truly cloud-native B2B eCommerce platform. It features a MACH certified architecture (Microservices, API-first, Cloud & Headless), which tells a lot about a platform. An eCommerce platform that follows MACH architecture is modular and truly open for integration to other systems via microservices and APIs. A typical MACH certified eCommerce platform architecture looks like the diagram below:
Source: machalliance.org
Functional Architecture
Speaking about architecture, let's talk about the functional architecture of OrderCloud. It will help us to understand as a product what OrderCloud offers and what kind of B2B Commerce solutions we can create from it. In the core of OrderCloud following are the important entities that exist.
Seller: Seller is the orchestrator of the business. A Seller defines how the business will be done. If the Seller is a Manufacturer, they might be selling products only to Buyers. But if the Seller is a Distributor, in addition to selling products to a Buyer, they might be connecting the Suppliers with the Buyers. Seller users are the admin users with highest privilege to OrderCloud APIs.
Buyer: A Buyer is a customer or an organization with an account with the Seller so that they can purchase products. A Buyer has one or more users. A user authenticates to the Storefront and orders products for the Buyer. Buyer users can be put into groups for managing access levels and personalizing the buying experience.
Supplier: A Supplier is an organization in OrderCloud that fulfills orders placed by buyers of their products. Supplier is an optional construct in OrderCloud. A Seller can be the only Supplier in the system. Supplier users have restricted access to the Seller admin site where they can manage their products, orders, supplier information, and users.
The Supplier can assign different roles to their users. Some can be responsible for managing products, some can be responsible for managing orders, etc.
User: User is someone who authenticates to the Storefront as a Buyer User or to the Admin Site as a Seller User. Users can be assigned to User Groups for managing their access to the system as well as provide a personalizing shopping experience to buyers.
User Group: User Groups are roles when it comes to the administration of the application, but they also contain information that leads to personalized shopping from the buyers perspective.
For example, information like Catalogs and Locations are assigned to User Groups. This drives the configuration of customer specific products in specific buyer locations.
Roles in User Groups determine what users belong to a User Group can manage as far as administering the application. For example, if a Buyer User Group has AddressAdmin Role, a user in that group can add/modify/delete buyer addresses.
Address: A Buyer or a Supplier can have multiple addresses. From the Buyer's perspective, the address is where to order items will be shipped. Orders in OrderCloud can be shipped to multiple places because addresses can be attached at the line level.
From the Supplier's perspective addresses are locations and these can be the addresses of warehouses. Seller's addresses are locations for the sellers. When a Seller is a sole supplier, these addresses can be warehouse addresses for fulfillment.
Catalog: A Catalog defines a set of products. It drives what products a Buyer can or cannot see in the storefront. A product can be assigned to more than one catalog. Products are organized in different categories. A Product in a Seller organization can be added by the seller or supplier selling the product. Although Suppliers can add products to the system, they cannot assign products to catalogs or organize them in categories, only sellers can do that.
Order: An Order in OrderCloud represents the cart as well as the order submitted to the system. An order goes through a different state. If the status is ‘Unsubmitted', it is a cart. If the status is ‘Open' it is submitted to the system as an order.
An order has directions in OrderCloud. An order from the Buyer's perspective is an outgoing order, but from the Seller or Supplier perspective, it is an incoming order. The Supplier doesn't see the order until the order is submitted, but the Seller can see the order (cart) as an incoming order before submission. After submission of the order from the Seller's perspective, the order is both incoming (from the Buyer) and outgoing (to the Supplier).
The same order from the Supplier perspective is an incoming order. This concept applies when accessing orders from the system using OrderCloud API. You need to use proper direction based on the API credential. If you are using the Buyer's credentials, you have to use ‘outgoing' as the direction, but you are using the Supplier's credentials, you need to use the ‘incoming' direction. The below image on the OrderCloud website describes this relationship.
Order Directions, Source: OrderClould.io
I haven't seen any mention of invoices in OrderCloud. In many eCommerce platforms orders represent invoices after the order is completely fulfilled. Some eCommerce platform invoices are maintained separately. Invoices enable the buyer to make the payments after the invoices are generated by the seller. Often eCommerce platform integrates with third party invoice payment system like BillTrust which makes it easy for the buyer to manage their invoices of different purchases in one place.
Storefront: A Seller may host more than one eCommerce website to sell products. A very common scenario for this is separate retail (B2C) website from B2B website. Some Sellers choose to separate B2C sites from B2B sites because the Buyers' experience in B2C sites is quite different than in B2B sites.
This is not the only reason to host more than one website. A Seller may be in the business of more than one brand and that may require a separate website as well. A Storefront in OrderCloud represents a website. You can have one organization in OrderCloud with multiple storefronts. Each storefront can have multiple Suppliers and Buyers associated with it.
In addition to the above entities, there are the usual eCommerce entities that exist in the system, like Promotion, Price, Shipping, etc. which drive eCommerce functions. But the above entities provide functional structure in OrderCloud. You can use the above-described constructs to define a business. There are different business models described using the above constructs in the Commerce Strategy section in the OrderCloud documentation.
Technical Architecture
OrderCloud Portal: OrderCloud Portal is where you will define your Seller Organization. Once you sign up and define your Seller Organization, that becomes your eCommerce system which will be used for providing service to your Buyers and optionally to your Suppliers. All this will be done using Restful APIs.
OrderCloud Portal provides a nice API Console that you can use to query your eCommerce data as well as modify them if needed. The user has to authenticate to use APIs. OrderCloud uses OpenId Connect and OAuth2 for securing APIs. Every client who connects to OrderCloud for access to API must have a ClientId and Client Secret. Below is a screenshot of the API Console.
Middleware: In the OrderCloud architecture, middleware is where integration to third services and cloud services happens. For example, if you want to integrate OrderCloud with an ERP, you will be implementing that in the middleware. Also, if you want to integrate Cloud Services like App Configuration, Blob Storage, etc., you will be implementing that here.
Middleware can also be used to integrate with OrderCloud webhooks via API endpoints in the middleware. All services in the middleware should be exposed by APIs in a headless manner. OrderCloud has provided a starter middleware project Catalyst in github.
Buyer UI: Buyer UI is the eCommerce Storefront that end users use to browse and purchase products. Storefront functionalities are implemented by integrating with middleware and OrderCloud APIs. Since OrderCloud is headless, Buyer UI can be implemented in any language and platform, either client-side or server-side technology. OrderCloud has provided both .Net SDK and Javascript SDK for this purpose.
Seller / Supplier Admin: Seller / Supplier Admin is the Admin Portal to manage the eCommerce backend. Seller Admin Portal provides restricted access to Supplier users so that they can manage products they are selling, manage orders placed to them, warehouse inventory, and manage their users. Whereas Seller Admin users have full access so that they can define and manage the business.
Seller Admin connects to the eCommerce backend via OrderCloud APIs. It can have its middleware if it requires to connect to any system other than OrderCloud. For example, the Seller may want to manage the payment from Seller Admin. In that case, Seller Admin must be integrated with the payment system and that will require a middleware to be created.
Unlike, Buyer UI, I imagine Seller Admin functionalities will not change from client to client. Also, Seller Admin bit more tightly coupled with OrderCloud architecture. For this reason, providing a fully functional but extensible Seller Admin by Sitecore will make sense. This will reduce the implementation cost as well as enable partners to extend the Seller Admin.
Webhook: Webhook is the way OrderCloud let the integrated system know that some event occurred in OrderCloud. For example, if you want to send an email notification when order status changes, you can create a webhook in OrderCloud's order API and that will call your send order status API associated with the webhook.
There are pre-hook and post-hook types. Sending email on order status change is a post-hook because the webhook gets called after order status changes. You can add webhook configurations like type of Webhook, Payload URL, OrderCloud API endpoints and API method, etc. in the OrderCloud API Console.
Typically, you will host the Payload API in the middleware. This document describes how to create a webhook in the OrderCloud platform.
Extending OrderCloud
Whatever eCommerce platform you choose, there will always be requirements to customize it. The OrderCloud platform architecture supports the Open-Closed Design Principle. It means, the platform is open for extension but closed for modification. You will not be able to modify the core platform and that makes the platform easier to upgrade. Since it is open for extension, you can easily add custom features on the top of the core platform.
There are generally three ways to extend the OrderCloud platform:
- For outside integration, middleware services should be used
- For injecting your operational code into OrderCloud operations you should use webhooks. You can implement your webhook APIs in the middleware or a separate service.
- If you want to extend the OrderCloud schema to store additional data, you need to use an Extended Property (XP). OrderCloud stores XP as JSON and you can have an elaborately constructed JSON.
There are two things to remember: 1) the entire XP object cannot be more than 8000 bytes, and 2) the XP should be consistent within an object (if you create an XP for an Order, the structure of that XP should always be the same). Data included in an XP can be searched, filtered, and sorted. Typically, an XP should be used when a small amount of additional data needs to be added. If the need is to add a new object in the implementation, middleware is the way to go. This article has nicely described how an XP works in OrderCloud.
Headstart Application
Architecture
Below is the high-level architecture of the Headstart application. It is important to note that Headstart is a sample application. In actual implementation, the architecture may change quite a bit.
Setting up Headstart
You will find Headstart in Github. The ReadMe instruction is quite good, but I did face some issues. To set up Headstart you need an Azure account. You can create a free Azure account here. The issues and the solutions for them are described below.
Setup Issues
Registering with Third Party Services: My goal was not to set up Headstart and making it fully functional. For this reason, I haven't configured all third-party services. This caused some issues, especially with Avalara. It can take a long time to configure Avalara to return proper tax. So, I faked the Avalara calls in the middleware. I changed the code in AvalaraCommand class. I configured SmartyStreet, which is required for address validation and easy to configure. I also configured Sendgrid for sending emails using the provided templates in the Headstart solution.
Seller UI Build Issue: I had a problem with building Seller App. The issue was finding Python version 2 in my machine. I resolved that by installing Windows Build Tools in my machine using npm (npm install –global windows-build-tools). Before installing, I removed node modules from Seller App.
Issue with OrderCloud CMS API: After building Seller App, I was getting 400 Bad Request errors from ordercloud-cms-test.azurewebsites.net. This issue has been fixed in the Headstart repository. I resolved it by merging the original repository to my forked repository. This Stackoverflow thread helped me to understand, How to Sync a Forked Repository in Github.
Azure DevOps Deployment Issue: The ReadMe in the Headstart repository has not fully explained how Azure DevOps Deployment works. I resolved the issues below:
- The azure-pipelines.yml was not generating a zipped artifact for the Middleware project. In the middleware publish task, I had to change zipAfterPublish: true.
- For Build Once, Deploy Many, you need to add “node inject-css defaultbuyer-test && node inject-appconfig defaultbuyer-test” in the Buyer release pipeline and “node inject-appconfig defaultadmin-test” in the Seller release pipeline. For this, you need to add ‘bash' task in your release pipelines for Buyer and Seller.
- The idea of Build Once, Deploy Many applies when you have multiple environments to deploy your application. This requires you to create Slots in Azure App Service and configure the release pipelines against those Slots. Each Slot in an App Service is used for an environment. I created Test Slots for the middleware, Buyer, and Seller Apps and deployed the code there. If I need to deploy code to UAT, I must create Slots for that each in App Services and create a release pipeline to deploy code in UAT Slots.
Conclusion
I enjoyed setting up Headstart because it helped me understand the OrderCloud architecture. I like that OrderCloud is a highly extensible, cloud-native platform with micro service-based architecture and it does not limit me to any particular technology for using the platform. I hope my exploration of the platform and this article helps others to onboard to the OrderCloud platform quickly.
Acknowledgment
I would like to thank my colleague Daniel Govier for helping me with the Azure DevOps configuration. Without his help, it wouldn't be possible for me to configure Azure DevOps deployment.