allBlogsList

Creating a Custom Sitecore Commerce Engine Shipping Plugin

Under your Commerce Engine Solution, create a new .Net Core project and name it as you wish. I will name the one in this blog Custom.Plugin.Shipping.

I am using Visual Studio 2015 and my .Net framework is 4.6.1

Visual Studio new .Net Core Project

TextCartShipping

Open the project.json file under the new project and update the following

version : 1.0.1

Framework

  "frameworks": {
"net461": {
}
}

Dependencies update with the a[ppropriate version of the following:

  "dependencies": {
"Sitecore.Commerce.Core": "1.2.*",
"Sitecore.Commerce.Plugin.CsAgent": "1.2.159",
"Sitecore.Commerce.Plugin.Fulfillment": "1.2.159",
"Sitecore.Commerce.Plugin.Management": "1.2.159",
"Sitecore.Commerce.Plugin.Catalog": "1.2.159",
"Sitecore.Commerce.Plugin.Catalog.Cs": "1.2.159"
},

Create a folder named Pipelines

Inside Pipelines, create a subfolder named Blocks

Inside blocks folder, create two classes for updating cart shipping and cartline shipping

I will be naming them "TestCartShipping" and "TestCartLineShipping" respectively

Set the each of classes to inherit from : PipelineBlock<Cart, Cart, CommercePipelineExecutionContext> and implement the abstract class

Make the run method async

Switch to your TestCartShipping.cs class and add the code below to override the default shipping. It also shows the point where you can call other APIs for shipping price:

 
  /// 
    /// 
    /// 
    public class TestCartShipping : PipelineBlock<cart,>
    {
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public override async Task Run(Cart arg, CommercePipelineExecutionContext context)
        {
            // Get all the adjustments that may have been applied.
            var adjustments = arg.Adjustments;

            // If no adjustments return cart
            if (adjustments == null || adjustments.Count <= 0)
            {
                return await Task.FromResult(arg);
            }

            // Check if an adjustment has been applied by the default fulfilment plugin that is what we need to overide.
            var fulfillment = adjustments.FirstOrDefault(x => x.Name.ToLower().Contains("fulfillmentfee"));

            if (fulfillment == null)
            {
                return await Task.FromResult(arg);
            }


            // If you are at this point, the default fulfillment plugin has applied an adjustment. and we can now replace it with our own custom.

            // Go get you shipping from Fedex or USPS or UPS web service or from Sitecore 
            var customShipping = 6.95M; // This can come from calculating shipping from external source based on items in the cart above or address of the buyer

            // If already set, or same as the amount set return cart
            if (customShipping == fulfillment.Adjustment.Amount)
            {
                return await Task.FromResult(arg);
            }

            // Prepare to overide the shipping value
            var awardedAdjustment = new CartLevelAwardedAdjustment
            {
                Name = fulfillment.Name,
                DisplayName = fulfillment.DisplayName
            };

            // convert the new shipping price from decimal to money
            var money = new Money(context.CommerceContext.CurrentCurrency(), customShipping);

            // set the money as the new adjustment
            awardedAdjustment.Adjustment = money;

            awardedAdjustment.AdjustmentType = context.GetPolicy().Fulfillment;

            // populate other values with that of the default plugin value or change them to suit you.
            awardedAdjustment.IsTaxable = fulfillment.IsTaxable;

            // Set the name of the awarding block to that of the current code block
            awardedAdjustment.AwardingBlock = Name;

            // Remove the default shipping price
            adjustments.Remove(fulfillment);

            // Add the new shipping price
            adjustments.Add(awardedAdjustment);

            // Return cart
            return await Task.FromResult(arg);
        }
    }


</cart,>

Switch to your TestCartLineShipping.cs class and add the code below to override the default shipping. It also shows the point where you can call other APIs for shipping price:

    /// 
    /// 
    /// 
    public class TestCartLineShipping : PipelineBlock<cart,>
    {
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public override async Task Run(Cart arg, CommercePipelineExecutionContext context)
        {

            // If the cart is not null and has product lines
            if (arg != null && arg.Lines.Any())
            {

                // lop through to reset Shipping for all line that already has fulfilment set.
                foreach (var cartLineComponent in arg.Lines)
                {
                    // Get all adjustment applied to the cartline
                    var adjustments = cartLineComponent.Adjustments;

                    // It there are adjustments
                    if (adjustments != null && adjustments.Count > 0)
                    {

                        // Check if shipping adjustment has been applied by the default fulfillment plugin.
                        var fulfillment = adjustments.FirstOrDefault(x => x.Name.ToLower().Contains("fulfillmentfee"));

                        // If it has been applied, then we can simply replace it with our desired value based on our external APIs or internal apps.
                        if (fulfillment != null)
                        {
                            // Go get you shipping from Fedex or USPS or UPS web service or from Sitecore 
                            // This can come from calculating shipping from external source based on items in the cart above or address of the buyer
                            var customShipping = 0.99M;

                            // If already set, or same as the amount set return cart
                            if (customShipping == fulfillment.Adjustment.Amount)
                            {
                                continue;
                            }

                            // Prepare to overide the shipping value
                            var awardedAdjustment = new CartLineLevelAwardedAdjustment
                            {
                                Name = fulfillment.Name,
                                DisplayName = fulfillment.DisplayName
                            };

                            // convert the new shipping price from decimal to money
                            var money = new Money(context.CommerceContext.CurrentCurrency(), customShipping);

                            // set the money as the new adjustment
                            awardedAdjustment.Adjustment = money;


                            awardedAdjustment.AdjustmentType =
                                context.GetPolicy().Fulfillment;

                            // populate other values with that of the default plugin value or change them to suit you.
                            awardedAdjustment.IsTaxable = fulfillment.IsTaxable;

                            // Set the name of the awarding block to that of the current code block
                            awardedAdjustment.AwardingBlock = Name;

                            // Remove the default shipping price
                            adjustments.Remove(fulfillment);

                            // Add the new shipping price
                            adjustments.Add(awardedAdjustment);

                        }
                    }
                }
            }

            // Return cart
            return await Task.FromResult(arg);
        }
    }


</cart,>

To add the reference of the new plugin to your Commerce Engine solution, 

Goto your base Solution plugin such as Sitecore.Commerce.Plugin.AdventureWorks, open its project.json file and add reference to the new plugin as shown below.

Adding reference to new plugin

Also open the class ServiceCollectionExtensions.cs and replace the pipeline calls as shown below:

.Add<CalculateCartLinesFulfillmentBlock>() 

with

.Add<TestCartLineShipping>().After<CalculateCartLinesFulfillmentBlock>()

.Add<CalculateCartFulfillmentBlock>()

with 

.Add<TestCartShipping>().After<CalculateCartFulfillmentBlock>()

Replace pipeline calls

You may down load the sample plugin from Github here:

Download