After following the directions here:
https://docs.kentico.com/display/K82/Implementing+custom+shipping+carrier+providers
and reviewing and implementing the source code here:
http://devnet.kentico.com/articles/webinar-recap-adding-real-time-shipping-rates-to-kentico
The order total and shipping total does not update from the returned price from shipping provider's GetPrice(Delivery delivery, string currencyCode) method.
The shipping and payment stage of checkout shows the correct drop down of the 3 UPS service selections. During debug, I can follow the code when it hits the provider below, and it returns 3 prices upon showing the shipping service dropdown and returns a single price after selecting a specific service while proceeding to the next page. All the values returned from the UPS call are above $0.00 yet, the order and shipping totals do not update.
There are no service or carrier configurations in the CMS so we return Guid.Empty.
The site was originally at 8.2 and was updated to 8.2.43 to address this issue, but the problem remains. Any assistance would be appreciated.
UPSRealTimeShippingProvider.cs
using System;
using System.Collections.Generic;
using System.Web;
using System.Linq;
using System.Text;
using CMS;
using CMS.Ecommerce;
using CMS.CustomTables;
using CMS.DataEngine;
using DotNetShipping;
using System.Collections.Specialized;
using System.Configuration;
using CMS.DocumentEngine;
[assembly: RegisterCustomClass("UPSRealTimeShippingProvider", typeof(UPSRealTimeShippingProvider))]
public sealed class UPSRealTimeShippingProvider : ICarrierProvider
{
private const string NAME = "UPS Shipping";
private List<KeyValuePair<string, string>> mServices;
public string CarrierProviderName
{
get { return NAME; }
}
public List<KeyValuePair<string, string>> GetServices()
{
//new KeyValuePair<string, string>("Standard", "UPS Real-Time Calculated"),
return mServices ?? (mServices = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string,string>("UPS Next Day Air", "UPS Next Day Air"),
new KeyValuePair<string,string>("UPS 2nd Day Air", "UPS 2nd Day Air"),
new KeyValuePair<string,string>("UPS Ground", "UPS Ground")
});
}
/// <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)
{
decimal deliveryPrice = 0;
NameValueCollection appSettings = ConfigurationManager.AppSettings;
string upsLicenseNumber = appSettings["UPSLicenseNumber"];
string upsLogin = appSettings["UPSUserId"];
string upsPassword = appSettings["UPSPassword"];
string upsOriginZipCode = appSettings["UPSOriginZipCode"];
//Delivery has total weight, but we need it broken up
//Must add unit weight and boxes for each different item
CMS.DataEngine.ObjectQuery<CustomTableItem> cti = CustomTableItemProvider.GetItems("CCI.Boxes");
List<Package> packages = new List<Package>();
foreach (DeliveryItem item in delivery.Items)
{
var prod = DocumentHelper.GetDocuments("CCI.Product")
.WhereLike("SKUNumber", "%" + item.Product.SKUNumber +"%").FirstOrDefault();
//get box size
CustomTableItem BoxSize = (from x in cti.AsEnumerable()
where x.ItemID == prod.GetIntegerValue("BoxSize",0)
select x).FirstOrDefault();
if (BoxSize != null)
{
//box info
decimal width = Convert.ToDecimal(BoxSize.GetValue<float>("Width",0f));
decimal height = Convert.ToDecimal(BoxSize.GetValue<float>("Height", 0f));
decimal length = Convert.ToDecimal(BoxSize.GetValue<float>("Length", 0f));
decimal boxweight = Convert.ToDecimal(BoxSize.GetValue<float>("Weight", 0f));
//get DeliveryItem qty
decimal orderQty = item.Amount;
//get product weight
decimal itemWeight = Convert.ToDecimal(prod.GetValue<float>("ItemWeight", 0f));
//get items per box
int itemsPerBox = prod.GetIntegerValue("ItemsPerBox", 0);
//add all packages
for (int i = Convert.ToInt32(orderQty); i > 0; )
{
int productInBox = itemsPerBox < i ? itemsPerBox : i;
//min weight of 2
decimal totalWeight = (productInBox * itemWeight) + boxweight > 2 ? (productInBox * itemWeight) + boxweight : 2;
packages.Add(new Package(length, width, height, totalWeight, 0));
i = i - itemsPerBox;
}
}
}
//pass to service
if (packages.Count > 0 && delivery.ShippingOption.ShippingOptionCarrierServiceName.Contains("UPS"))
{
Address origin = new Address("", "", upsOriginZipCode, "US");
Address destination = new Address("", "", delivery.DeliveryAddress.AddressZip, "US");
RateManager rm = new RateManager();
rm.AddProvider(new DotNetShipping.ShippingProviders.UPSProvider(upsLicenseNumber, upsLogin, upsPassword, delivery.ShippingOption.ShippingOptionCarrierServiceName));
Shipment shipment = rm.GetRates(origin, destination, packages);
deliveryPrice = shipment.Rates.FirstOrDefault() != null ? shipment.Rates.First().TotalCharges : 0;
}
return deliveryPrice;
}
/// <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)
{
return true;
}
/// <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;
}
}