---
title: Example - Creating a shipping carrier provider with costs based on the country
related:
  - https://docs.kentico.com/k82/e-commerce-features/customizing-and-developing-your-store/implementing-custom-shipping-carrier-providers.md
  - https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/configuring-shipping-options/configuring-shipping-carriers.md
  - https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/configuring-shipping-options.md
  - https://docs.kentico.com/k82/custom-development/customizing-providers.md
  - https://docs.kentico.com/k82/custom-development/customizing-providers/custom-info-provider-example/example-custom-shipping-option-selection.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

In this example, you can learn how to create a custom shipping carrier provider which calculates the shipping cost based on the country to which the package is shipped. This shipping carrier provider:

- Is based on the general instructions in [Implementing custom shipping carrier providers](https://docs.kentico.com/k82/e-commerce-features/customizing-and-developing-your-store/implementing-custom-shipping-carrier-providers.md).
- Allows to create [shipping carriers](https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/configuring-shipping-options/configuring-shipping-carriers.md) with [shipping options](https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/configuring-shipping-options.md) that are displayed only when the shipping address is in the USA, Canada or Mexico.
- Has the shipping costs saved in the programming code and does not use any user interface for settings.

  > **Tip:** If you want to use the user interface for setting the shipping costs, you can either create user interface tab as written in [Implementing custom shipping carrier providers](https://docs.kentico.com/k82/e-commerce-features/customizing-and-developing-your-store/implementing-custom-shipping-carrier-providers.md) or [create a custom table](https://docs.kentico.com/k82/developing-websites/defining-website-data-structure/custom-tables/creating-custom-tables.md) and use the [custom table API](https://docs.kentico.com/k82/custom-development/custom-table-internals-and-api.md) to add the values for the _Dictionary_ variable with the shipping costs. Do not forget to [set caching](https://docs.kentico.com/k82/configuring-kentico/optimizing-website-performance/configuring-caching.md) (you can use the [CacheHelper](https://docs.kentico.com/k82/custom-development/caching-in-custom-code.md) class).
- Does not use a [packageable module](https://docs.kentico.com/k82/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md).

  > **Tip:** Read [Example - Creating a packageable module](https://docs.kentico.com/k82/custom-development/creating-custom-modules/creating-installation-packages-for-modules/example-creating-a-packageable-module.md) to see an example of a packageable module.
- Uses [resource strings](https://docs.kentico.com/k82/multilingual-websites/setting-up-a-multilingual-user-interface/working-with-resource-strings.md) to provide [multilingual support](https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/multilingual-store.md) in your store.

> **Info:** If you place the **Customer address** [web part](https://docs.kentico.com/k82/developing-websites/developing-websites-using-the-portal-engine/using-and-configuring-web-parts.md) (where the customer enters the shipping address) and the **Shipping option selection** web part (where the customer selects the desired shipping option) on the same page, you need to select the **Propagate changes on postback** field while editing the **Customer address** web part. This ensures that when the customer changes the shipping country, the shipping options that the **Shipping option selection** web part offers are recalculated and the web part then offers the shipping options available in the currently selected country.

To implement the shipping carrier provider example:

1. Open your web project in Visual Studio.
2. Create a new class in the **App\_Code** folder (or **CMSApp\_AppCode -> Old\_App\_Code** on web application projects). For example, name the class **CountryCarrierProvider.cs**.

   ```csharp

   using System;
   using System.Collections.Generic;
   using System.Linq;
   using System.Text;
   using CMS.Ecommerce;

   /// <summary>
   /// Sample carrier provider providing shipping costs based on the delivery country.
   /// The cost is charged for deliveries to USA, Canada and Mexico.
   /// </summary>
   [assembly: RegisterCustomClass("CountryCarrierProvider", typeof(CountryCarrierProvider))]
   public sealed class CountryCarrierProvider : ICarrierProvider
   {
       private const string NAME = "{$com.countrycarrierprovider.name$}";
       private List<KeyValuePair<string, string>> mServices;
       private Dictionary<string, decimal> mCountryCosts;

       /// <summary>
       /// Gets a dictionary of 3-letter country codes and shipping costs. 
       /// The dictionary contains all countries where the delivery is possible.
       /// </summary>
       private Dictionary<string, decimal> CountryCosts
       {
           get
           {
               return mCountryCosts ?? (mCountryCosts = new Dictionary<string, decimal>
                   {
                       { "CAN", 12.99m },
                       { "MEX", 33.33m },
                       { "USA", 5.0m }
                   });
           }
       }

       /// <summary>
       /// Gets the name of the carrier provider.
       /// </summary>
       public string CarrierProviderName
       {
           get
           {
               return NAME;
           }
       }

       /// <summary>
       /// Returns a list of service code names and display names.
       /// </summary>
       public List<KeyValuePair<string, string>> GetServices()
       {
           return mServices ?? (mServices = new List<KeyValuePair<string, string>>
           {
               new KeyValuePair<string, string>("CostByCountry", "Shipping cost to USA, CAN and MEX")
           });
       }

       /// <summary>
       /// Calculates the shipping cost of the given delivery.
       /// </summary>
       /// <param name="delivery">The shipped delivery.</param>
       /// <param name="currencyCode">The code of the currency in which the shipping price should be calculated (e.g. USD or EUR).</param>
       /// <returns>The price in the currency specified by currencyCode.</returns>
       public decimal GetPrice(Delivery delivery, string currencyCode)
       {
           // Gets the 3-letter country code of the target country of the delivery.
           var countryCode = delivery.DeliveryAddress.GetCountryThreeLetterCode();

           // Checks whether the shipping option is available for the specified country code.
           if (CountryCosts.ContainsKey(countryCode))
           {
               // Returns the shipping price converted to the specified currency.
               return CurrencyConverter.Convert(CountryCosts[countryCode], "USD", currencyCode, delivery.ShippingOption.ShippingOptionSiteID);
           }

           return 0;
       }

       /// <summary>
       /// Checks whether the shipping option is available for the specified shipping address.
       /// The only supported shipping addresses are to USA, Canada or Mexico.
       /// </summary>
       /// <param name="delivery">The shipped delivery.</param>
       public bool CanDeliver(Delivery delivery)
       {
           // Checks whether a shipping option and a delivery address is assigned to the delivery
           // and checks whether the shipping option is available for the specified shipping country.
           if ((delivery.ShippingOption == null) || (delivery.DeliveryAddress == null) || !CanDeliverToCountry(delivery.DeliveryAddress))
           {
               return false;
           }

           // Returns true if the carrier provider supports the shipping service.
           return SupportsService(delivery.ShippingOption.ShippingOptionCarrierServiceName);
       }

       /// <summary>
       /// Returns Guid.Empty. This carrier does not have or need any configuration tab.
       /// </summary>
       public Guid GetConfigurationUIElementGUID()
       {
           return Guid.Empty;
       }

       /// <summary>
       /// Returns Guid.Empty. Service configuration is not required.
       /// </summary>
       /// <param name="serviceName">Service name.</param>
       public Guid GetServiceConfigurationUIElementGUID(string serviceName)
       {
           return Guid.Empty;
       }

       /// <summary>
       /// Returns true if the carrier provider can handle the selected shipping service.
       /// </summary>
       /// <param name="serviceName">The name of the used shipping service.</param>
       private bool SupportsService(string serviceName)
       {
           return GetServices().Any(item => item.Key == serviceName);
       }

       /// <summary>
       /// Checks whether the package can be delivered to the selected country.
       /// </summary>
       /// <param name="address">The delivery address.</param>
       private bool CanDeliverToCountry(IAddress address)
       {
           // Gets the 3-letter country code from the delivery address.
           var countryCode = address.GetCountryThreeLetterCode();

           // Returns true if the country code is found among country codes supported by the carrier provider.
           return CountryCosts.ContainsKey(countryCode);
       }
   }

   ```
3. Save the **CountryCarrierProvider.cs** file.

If [customers](https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/customers.md) now order a [product](https://docs.kentico.com/k82/e-commerce-features/configuring-and-managing-your-store/products.md) that needs shipping and their delivery address is in the USA, Canada or Mexico, the customers are able to select the shipping option based on this shipping carrier provider.
