Sitecore Experience Commerce 9: Making an External Product Pricing Request

A lot of organisations have requirements to integrate more than just a product and orders feed. A common ask from some customers is to integrate with their bespoke pricing API. In this post I’ll take you through just how easy it is with Sitecore Experience Commerce 9.

The Product Setup

We setup a normal sellable-item with the bare minimum required. Notice there is no pricing configured for the sellable-item, there’s no list price configured and no sell price configured (price card).

image

The External API

For this example I’ll be using CMYKhub’s publicly available test API – https://github.com/CMYKhub/. Using postman we can really easily simulate a pricing call for the product we’ve configured.

image

The Plugin

Now it’s time to create a Sitecore Commerce plugin to make the external pricing request. Here is the working example: https://github.com/kazimnami/Sitecore.Commerce.ExternalPricing

The bulk of the work is done in a single pipeline block

namespace Feature.Pricing.Engine
{
    [PipelineDisplayName(Constants.Pipelines.Blocks.CalculateCartLinesPrice)]
    public class CalculateCartLinesPriceBlock : PipelineBlock
    {
        private readonly CommerceCommander _commerceCommander;

        public CalculateCartLinesPriceBlock(CommerceCommander commerceCommander)
          : base(null)
        {
            _commerceCommander = commerceCommander;
        }

        public override async Task Run(Cart arg, CommercePipelineExecutionContext context)
        {
            Condition.Requires(arg).IsNotNull($"{Name}: Cart cannot be null.");
            Condition.Requires(arg.Lines).IsNotNull($"{Name}: The cart's lines cannot be null");

            if (!arg.Lines.Any())
                return arg;

            // Valid cart items
            var validCartLines = arg.Lines
                .Where(line =>
                    line != null
                    && line.HasComponent()
                    && !string.IsNullOrEmpty(line.ItemId)
                    && line.ItemId.Split('|').Length >= 2);

            // Iterate valid cart items
            foreach (var line in validCartLines)
            {
                // Get sellable items (products)
                SellableItem sellableItem = await _commerceCommander.Command().Process(context.CommerceContext, line.ItemId, false);
                if (sellableItem == null)
                {
                    context.Logger.LogError($"{Name}-SellableItemNotFound for Cart Line: ItemId={line.ItemId}|CartId={arg.Id}|LineId={line.Id}");
                    return arg;
                }

                // Set list & sell pricing
                line.UnitListPrice = sellableItem.ListPrice;

                if (sellableItem.Manufacturer.Equals("CMYKhub", StringComparison.OrdinalIgnoreCase))
                {
                    var request = new
                    {
                        ProductId = sellableItem.FriendlyId,
                        Quantity = (int)line.Quantity,
                        Kinds = 1
                    };

                    var cmykHubPrice = await CreatePriceAsync(request);
                    if (cmykHubPrice != null)
                    {
                        var optionMoneyPolicy = new PurchaseOptionMoneyPolicy
                        {
                            SellPrice = new Sitecore.Commerce.Core.Money("USD", cmykHubPrice.Price.IncTax) // new Sitecore.Commerce.Core.Money(cmykHubPrice.Price.Currency.Code, cmykHubPrice.Price.IncTax);
                        };

                        line.Policies.Remove(line.Policies.OfType().FirstOrDefault());
                        line.SetPolicy(optionMoneyPolicy);

                        // Add to pricing messaging
                        var lineMessages = line.GetComponent();
                        lineMessages.AddMessage(context.GetPolicy().Pricing, $"CartItem.SellPrice<=CMYKhub.Pricing: Price={optionMoneyPolicy.SellPrice.AsCurrency()}");
                    }
                };
            }
            return arg;
        }
    }
}

The Result

From the product detail page (PDP) we can see the sellable item has no price.

image

When we add to cart, the cart line calculation block will trigger and make a call to CMYKhub’s pricing API and return a price for the product.

image

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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