Implementing custom shipping carrier providers

To create shipping options not supported by Kentico out of the box, create a shipping carrier provider. Shipping carrier providers are source code packages providing shipping carriers, which you can add to your Kentico. Shipping carriers then enable new shipping options in your Kentico instance.

You can create shipping carrier providers with an off-line cost calculation, which doesn’t need to communicate with other systems (for example, shipping based on weight, based on customer’s country, based on date), or carrier providers with an on-line cost calculation, which communicate with other systems, typically with APIs of shipping companies (for example, FedEx, USPS, Australia Post). Carrier providers of this type can then provide a real-time shipping costs calculation or shipping option availability check. You can also combine both approaches to achieve your desired result.

You cancreate an installation package out of your carrier provider module and then install the package on various instances of Kentico.

Relationship between carrier providers and shipping options

In a more detailed view, when you add shipping carrier provider to Kentico, you can create new shipping carrier in the administration interface. Shipping carriers contain services, which are types of shipping of the carrier. Administrators can then create shipping options based on the services of the carrier.

For example, you can create a custom carrier provider with a FedEx carrier with two services – International Priority shipping and International Economy shipping. Then, in the administration interface of Kentico, the system allows administrators to create shipping options based on services of your carrier. They can also create more options based on one service.

Creating carrier providers

To create a custom shipping carrier, you must create a module with its user interface and then implement a class that inherits the ICarrierProvider interface.

  1. Create a custom module and a module project to represent your carrier.

    See an example to get more integral view.

  2. (Optional) In the Modules application, edit the module representing your carrier, and on the User interface tab, create a UI element which will be then used as a configuration tab of your carrier (for example, with a login form for communication with an API of its shipping company).

    • You need to create the UI element in the same module. Otherwise, it will not be included in the installation package.

    • If your carrier does not need any configuration, you do not need to create any UI element.

    • Since every carrier can have only one configuration tab, create only one UI element for it.

      To calculate shipping costs, shipping companies usually require an address of the place from where you send the bought items. You can create a text box on the configuration tab for the address.

  3. (Optional) As you did for the carrier, you can also create UI elements as configuration tabs for services of the carrier. Configuration tabs of services are then displayed while editing any shipping option based on the given service.

    • Every service can have one configuration tab.
  4. (Optional) If you need to communicate with an API of a shipping company, you may need to add their API web references to your Kentico instance:

    1. Download a WSDL file from a website of the shipping company (for example, FedEx offers its WSDL files in their Documentation and Downloads section).
    2. Right-click References in your carrier project in the Visual Studio Solution Explorer and click Add Service Reference.
      Location of the Add Service Reference button
    3. Click Advanced in the Add Service Reference dialog.
    4. In the Service Reference Settings dialog, click Add Web Reference.
    5. Enter the path of your downloaded WSDL file, and click Add Reference.
      • Visual Studio will then generate a new class according to the reference file automatically. You can then use its methods to implement the carrier provider, for example in the GetPrice method and the CanDeliver method.
  5. Create a new class in your project in Visual Studio (for example MyCustomCarrier.cs) that implements the ICarrierProvider interface.

    1. Label the class with the following assembly attribute:

      
      
      
       [assembly: RegisterCustomClass("MyCustomCarrier", typeof(MyCustomCarrier))]
       public class MyCustomCarrier : ICarrierProvider
       {
       }
      
      
       
    2. Implement the CarrierProviderName property.

      
      
      
       string CarrierProviderName
       {
               get;
       }
      
      
       

      The property returns the name of the carrier. The name is displayed in the administration interface when working with carriers or shipping options.

    3. Implement the GetServices method.

      
      
      
       List<KeyValuePair<string, string>> GetServices()
      
      
       

      The method returns a list of code names (the first element in the list) and display names (the second element in the list) of services of the carrier. You can use the code names in the code and in macros; the administration interface uses display names when working with shipping options.

      List of services

      If you have a multilingual site, create resource strings for display names of your services.

      Example:

      
      
      
       // Returns 2-day, priority and standard overnight FedEx shipping services.
       public List<KeyValuePair<string, string>> GetServices()
       {
             SortedDictionary<string, string> mServices = new SortedDictionary<string, string>
             {
                   {"PRIORITY_OVERNIGHT", "{$com.fedexcarrierprovider.priorityovernight$}"},
                   {"STANDARD_OVERNIGHT", "{$com.fedexcarrierprovider.standardovernight$}"},
                   {"FEDEX_2_DAY", "{$com.fedexcarrierprovider.2day$}"}
             };
      
             return mServices.ToList();
       }
      
      
       
    4. Implement the GetPrice method.

      
      
      
       decimal GetPrice(Delivery delivery, string currencyCode)
      
      
       

      The method calculates shipping costs of the delivery specified in the input parameters and then returns the total shipping cost in the currency also set in the input parameters.

      Parameters of GetPrice – the Delivery class

      The Delivery class represents a set of items that the on-line store ships using a shipping option. The class contains the following properties:

      • IEnumberable<DeliveryItem> Items – shipped items. Only products and product options of the Products type are present,
      • DateTime ShippingDate – the date when the store pass the package to the shipping company which provides its shipping,
      • decimal Weight – total weight of the shipped package in unit specified in the ECommerceSettings.MassUnit() setting,
      • ShippingOptionInfo ShippingOption – the shipping option used for the delivery,
      • IAddress DeliveryAddress – the address where the package is delivered,
      • IDataContainer CustomData – you can use this property for your custom data.

    Remember, you have also to take care of exchange rates when it comes to communication with an API of a shipping company when currency of a given order is not in the currency supported by carrier and the API of the shipping company.

    You can use exchange rates entered in the Store configuration application by using the CurrencyConverter.Convert(decimal amount, string inCurrencyCode, string toCurrencyCode, int siteID) method in the CMS.Ecommerce namespace, where:

     - **decimal****amount** *–* sets the price in the original currency,
     - **string inCurrencyCode** – sets the code of the original currency,
     - **string toCurrenceCode** – sets the code of the result currency to which the *decimal amount* is to be converted,
     - **int siteID** – ID of the current site.**Example:**
    
    
    
     CurrencyConverter.Convert(shippingPrice, "USD", currencyCode, delivery.ShippingOption.ShippingOptionSiteID);
    
    
     
    1. Implement the CanDeliver method.

      
      
      
       bool CanDeliver(Delivery delivery)
      
      
       

      The method checks if the shipping option (specified in the Delivery parameter) is available for shipping. See implementing theGetPricemethod above to learn more about parameters.

      If you want your services to be always available, return true.

      
      
      
       public bool CanDeliver(Delivery delivery)
       {
             return true;
       }
      
      
       
    2. Implement the GetConfigurationUIElementGUID method.

      
      
      
       Guid GetConfigurationUIElementGUID()
      
      
       

      The method returns GUID of an UI element that the carrier uses as its configuration tab (which you created in the step 2). The system then displays the configuration tab while editing a carrier on the Shipping -> Carriers tab in the Store configuration application.

      Location of another configuration tab
      If the carrier does not have any configuration tab, return Guid.Empty. To determine the GUID of a UIElement, you can use the UIElementInfoProvider.GetUIElementInfo(string resourceName, string elementName) function in the CMS.Modules namespace.

      Example:

      
      
      
       using CMS.Modules;
      
       /// <summary>
       /// Returns Guid of the configuration tab of the carrier where moduleName is the code name
       /// of the module and elementName is the code name of the UIElement.
       /// </summary>
       public Guid GetConfigurationUIElementGUID()
       {
             UIElementInfo ui = UIElementInfoProvider.GetUIElementInfo(moduleName, elementName);
             return ui.ElementGUID;
       }
      
      
       
    3. Implement the GetServiceConfigurationUIElementGUID method.

      
      
      
       Guid GetServiceConfigurationUIElementGUID(string serviceName)
      
      
       

      The method returns the GUID of a UI element that the service (specified with its code name in the serviceName property) uses as its configuration tab (which you created in the step 3). You can determine the GUID as in the GetConfigurationUIElementGUID method. The system then displays the configuration tab while editing a shipping option in the Store configuration application on the Shipping -> Shipping options tab. For example, the Weight based shipping service of the Default carrier has the Shipping costs tab. For services that do not have any configuration tabs, return Guid.Empty.

  6. Create the module installation package.

    You can see the already mentioned example.

Now you have a shipping provider that enables you to create carriers and then shipping options based on your programmed methods. You also have an installation package of the module and you can install it on other Kentico instances.