SXA Storefront calls to Commerce Engine

Abstract

Overview of how SXA Storefront makes calls to Commerce Engine.

Because Commerce Connect was designed to work with different external commerce systems, it comes with default domain models for each service layer. These domain models represent the common data needed for the scenarios that each service layer API targets. Before Sitecore XC 9.3, all API calls to the Commerce Engine went through the Commerce Connect service layers. Commerce Connect also serves as an integration with experience analytics in Sitecore triggering analytic events in xDB. In cases where analytics are not needed, it makes more sense for calls to go directly from the storefront to the Commerce Engine, as the following diagram shows, bypassing the unnecessary need to map data to and from the domain models.

Storefront calls to Commerce Engine

The service layer APIs pass common data between the storefront and the Commerce Engine. The service layer APIs are integrated with Experience Analytics (XA) so that detailed data can be collected to enable reporting, personalization, and marketing automation based on actions performed by the customer in commerce scenarios. When no integration with XA is needed, bypassing Commerce Connect provides more flexibility and better performance. Calling Commerce Engine directly eliminates the mapping of data to domain models and the calls back from the domain models. The mapping itself consumes resources and is not easily extended because custom objects must be defined and registered to accommodate the extensions. Passing data in JSON format is more easily extended and consumed because it does not require code registration and there is less performance overhead. This is why, beginning in Sitecore XC 9.3, API calls that do not involve interaction with Experience Analytics and go directly to Commerce Engine have been introduced for new functionality.

In the following sections, you can see examples that show the implementation pattern for direct calls, as well as how to make a direct call to the Commerce Engine.

Note

Currently, calls still go through the Content Delivery (CD) server role. This means that in the case of AJAX calls, they are still made from the customer’s browser and go to the CD instance first and from there directly to the Commerce Engine. In future releases the calls can possibly be made directly from the customer’s browser and go to the Commerce Engine bypassing the CD instance, assuming that the right security measures around the Commerce Engine APIs are in place.

A generic description of the implementation pattern has six parts:

  1. Obtain URI to targeted method for Commerce Engine.

  2. Add context information in HTTP request header.

  3. In the body of the request, add input parameters.

  4. Send the HTTP request asynchronously.

  5. Wait for the result.

  6. Return the body of the HTTP result as a string value, which will always be in a JSON format (to be interpreted by the calling code).

The following code is an example of the implementation pattern for making a direct call from the storefront to Commerce Engine to get the price of the product bundle based on the customer configuration and selections.

 /// <summary>
        /// Gets the bundle selection price.
        /// </summary>
        /// <param name="model"></param>
        /// <returns>string of JSON containing prices</returns>  
        public virtual async Task<string>  GetBundleSelectionPrice(BundleItemModel model)
        {
            // Obtain URI to targeted method for Commerce Engine
            var uri = new Uri(CommerceEngineConfiguration.Instance.ShopsServiceUrl + "GetBundleSelectionPrice");
                           // Add context information in header
            var request = new HttpRequestMessage(HttpMethod.Post, uri);
            request.Headers.Add("ShopName", StorefrontContext.CurrentStorefront.ShopName);
            request.Headers.Add("Environment", EngineConnectUtility.GetShopEnvironment());
            request.Headers.Add("EffectiveDate", GetCurrentDate().ToString(CultureInfo.InvariantCulture));
            request.Headers.Add("Language", Context.Culture.Name);
            request.Headers.Add("Currency", StorefrontContext.CurrentStorefront.SelectedCurrency);
            request.Headers.Add("IsRegistered", Context.User.IsAuthenticated.ToString(CultureInfo.InvariantCulture));
            request.Headers.Add("Authorization", CommerceEngineConfiguration.Instance.AccessToken);

            // set content by adding the input parameter containing the model
            var modelStr = JsonConvert.SerializeObject(model);
            request.Content = new StringContent(modelStr, Encoding.UTF8, "application/json");

                            // Wait for the result
            var result = await HttpClient.SendAsync(request).ConfigureAwait(false);

            return await 
result.Content.ReadAsStringAsync().ConfigureAwait(false);
        }