private string CreateRequest(string username, string password, GetShippingOptionRequest getShippingOptionRequest)
        {
            var usedMeasureWeight = _measureService.GetMeasureWeightBySystemKeyword(MEASUREWEIGHTSYSTEMKEYWORD);

            if (usedMeasureWeight == null)
            {
                throw new SmartException(string.Format("USPS shipping service. Could not load \"{0}\" measure weight", MEASUREWEIGHTSYSTEMKEYWORD));
            }

            var baseusedMeasureWeight = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId);

            if (baseusedMeasureWeight == null)
            {
                throw new SmartException("Primary weight can't be loaded");
            }

            var usedMeasureDimension = _measureService.GetMeasureDimensionBySystemKeyword(MEASUREDIMENSIONSYSTEMKEYWORD);

            if (usedMeasureDimension == null)
            {
                throw new SmartException(string.Format("USPS shipping service. Could not load \"{0}\" measure dimension", MEASUREDIMENSIONSYSTEMKEYWORD));
            }

            var baseusedMeasureDimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId);

            if (usedMeasureDimension == null)
            {
                throw new SmartException("Primary dimension can't be loaded");
            }


            int length = Convert.ToInt32(Math.Ceiling(getShippingOptionRequest.GetTotalLength() / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int height = Convert.ToInt32(Math.Ceiling(getShippingOptionRequest.GetTotalHeight() / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int width  = Convert.ToInt32(Math.Ceiling(getShippingOptionRequest.GetTotalWidth() / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int weight = Convert.ToInt32(Math.Ceiling(_shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items) / baseusedMeasureWeight.Ratio * usedMeasureWeight.Ratio));

            if (length < 1)
            {
                length = 1;
            }
            if (height < 1)
            {
                height = 1;
            }
            if (width < 1)
            {
                width = 1;
            }
            if (weight < 1)
            {
                weight = 1;
            }

            string zipPostalCodeFrom = getShippingOptionRequest.ZipPostalCodeFrom;
            string zipPostalCodeTo   = getShippingOptionRequest.ShippingAddress.ZipPostalCode;

            //valid values for testing. http://testing.shippingapis.com/ShippingAPITest.dll
            //Zip to = "20008"; Zip from ="10022"; weight = 2;

            int pounds  = Convert.ToInt32(weight / 16);
            int ounces  = Convert.ToInt32(weight - (pounds * 16.0M));
            int girth   = height + height + width + width;
            var taxRate = decimal.Zero;
            //Get shopping cart sub-total.  V2 International rates require the package value to be declared.
            decimal subTotal = decimal.Zero;

            foreach (var shoppingCartItem in getShippingOptionRequest.Items)
            {
                if (shoppingCartItem.Item.IsFreeShipping || !shoppingCartItem.Item.IsShipEnabled)
                {
                    continue;
                }

                var itemSubTotal        = _priceCalculationService.GetSubTotal(shoppingCartItem, true);
                var itemSubTotalInclTax = _taxService.GetProductPrice(shoppingCartItem.Item.Product, itemSubTotal, true, getShippingOptionRequest.Customer, out taxRate);
                subTotal += itemSubTotalInclTax;
            }

            string requestString = string.Empty;

            bool isDomestic = IsDomesticRequest(getShippingOptionRequest);

            if (isDomestic)
            {
                #region domestic request
                zipPostalCodeFrom = zipPostalCodeFrom.Truncate(5).EnsureNumericOnly();
                zipPostalCodeTo   = zipPostalCodeTo.Truncate(5).EnsureNumericOnly();

                var sb = new StringBuilder();
                sb.AppendFormat("<RateV4Request USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.Append("<Revision>2</Revision>");

                var xmlStrings = new USPSStrings(); // Create new instance with string array

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    var packageSize = GetPackageSize(length, height, width);
                    // RJH get all XML strings not commented out for USPSStrings.
                    // RJH V3 USPS Service must be Express, Express SH, Express Commercial, Express SH Commercial, First Class, Priority, Priority Commercial, Parcel, Library, BPM, Media, ALL or ONLINE;
                    // AC - Updated to V4 API and made minor improvements to allow First Class Packages (package only - not envelopes).


                    foreach (string element in xmlStrings.Elements) // Loop over elements with property
                    {
                        if ((element == "First Class") && (weight >= 14))
                        {
                            // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                        }
                        else
                        {
                            sb.Append("<Package ID=\"0\">");

                            sb.AppendFormat("<Service>{0}</Service>", element);
                            if (element == "First Class")
                            {
                                sb.Append("<FirstClassMailType>PARCEL</FirstClassMailType>");
                            }

                            sb.AppendFormat("<ZipOrigination>{0}</ZipOrigination>", zipPostalCodeFrom);
                            sb.AppendFormat("<ZipDestination>{0}</ZipDestination>", zipPostalCodeTo);
                            sb.AppendFormat("<Pounds>{0}</Pounds>", pounds);
                            sb.AppendFormat("<Ounces>{0}</Ounces>", ounces);
                            sb.Append("<Container/>");
                            sb.AppendFormat("<Size>{0}</Size>", packageSize);
                            sb.AppendFormat("<Width>{0}</Width>", width);
                            sb.AppendFormat("<Length>{0}</Length>", length);
                            sb.AppendFormat("<Height>{0}</Height>", height);
                            sb.AppendFormat("<Girth>{0}</Girth>", girth);

                            sb.Append("<Machinable>FALSE</Machinable>");

                            sb.Append("</Package>");
                        }
                    }
                }
                else
                {
                    int totalPackages        = 1;
                    int totalPackagesDims    = 1;
                    int totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)pounds / (decimal)MAXPACKAGEWEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                    }
                    totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                    {
                        totalPackages = 1;
                    }

                    int pounds2 = pounds / totalPackages;
                    //we don't use ounces
                    int ounces2 = ounces / totalPackages;
                    int height2 = height / totalPackages;
                    int width2  = width / totalPackages;
                    int length2 = length / totalPackages;

                    if (pounds2 < 1)
                    {
                        pounds2 = 1;
                    }
                    if (height2 < 1)
                    {
                        height2 = 1;
                    }
                    if (width2 < 1)
                    {
                        width2 = 1;
                    }
                    if (length2 < 1)
                    {
                        length2 = 1;
                    }

                    var packageSize = GetPackageSize(length2, height2, width2);

                    int girth2 = height2 + height2 + width2 + width2;

                    for (int i = 0; i < totalPackages; i++)
                    {
                        foreach (string element in xmlStrings.Elements)
                        {
                            if ((element == "First Class") && (weight >= 14))
                            {
                                // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                            }
                            else
                            {
                                sb.AppendFormat("<Package ID=\"{0}\">", i.ToString());
                                sb.AppendFormat("<Service>{0}</Service>", element);
                                if (element == "First Class")
                                {
                                    sb.Append("<FirstClassMailType>PARCEL</FirstClassMailType>");
                                }
                                sb.AppendFormat("<ZipOrigination>{0}</ZipOrigination>", zipPostalCodeFrom);
                                sb.AppendFormat("<ZipDestination>{0}</ZipDestination>", zipPostalCodeTo);
                                sb.AppendFormat("<Pounds>{0}</Pounds>", pounds2);
                                sb.AppendFormat("<Ounces>{0}</Ounces>", ounces2);
                                sb.Append("<Container/>");
                                sb.AppendFormat("<Size>{0}</Size>", packageSize);
                                sb.AppendFormat("<Width>{0}</Width>", width2);
                                sb.AppendFormat("<Length>{0}</Length>", length2);
                                sb.AppendFormat("<Height>{0}</Height>", height2);
                                sb.AppendFormat("<Girth>{0}</Girth>", girth2);
                                sb.Append("<Machinable>FALSE</Machinable>");
                                sb.Append("</Package>");
                            }
                        }
                    }
                }

                sb.Append("</RateV4Request>");

                requestString = "API=RateV4&XML=" + sb.ToString();
                #endregion
            }
            else
            {
                #region international request
                var sb = new StringBuilder();
                // sb.AppendFormat("<IntlRateRequest USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.AppendFormat("<IntlRateV2Request USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);

                //V2 International rates require the package value to be declared.  Max content value for most shipping options is $400 so it is limited here.
                decimal intlSubTotal = decimal.Zero;
                if (subTotal > 400)
                {
                    intlSubTotal = 400;
                }
                else
                {
                    intlSubTotal = subTotal;
                }

                //little hack here for international requests
                length = 12;
                width  = 12;
                height = 12;
                girth  = height + height + width + width;

                string mailType    = "Package"; //Package, Envelope
                var    packageSize = GetPackageSize(length, height, width);

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    sb.Append("<Package ID=\"0\">");
                    sb.AppendFormat("<Pounds>{0}</Pounds>", pounds);
                    sb.AppendFormat("<Ounces>{0}</Ounces>", ounces);
                    sb.Append("<Machinable>FALSE</Machinable>");
                    sb.AppendFormat("<MailType>{0}</MailType>", mailType);
                    sb.Append("<GXG>");
                    sb.Append("<POBoxFlag>N</POBoxFlag>");
                    sb.Append("<GiftFlag>N</GiftFlag>");
                    sb.Append("</GXG>");
                    sb.AppendFormat("<ValueOfContents>{0}</ValueOfContents>", intlSubTotal);
                    sb.AppendFormat("<Country>{0}</Country>", getShippingOptionRequest.ShippingAddress.Country.Name);
                    sb.Append("<Container>RECTANGULAR</Container>");
                    sb.AppendFormat("<Size>{0}</Size>", packageSize);
                    sb.AppendFormat("<Width>{0}</Width>", width);
                    sb.AppendFormat("<Length>{0}</Length>", length);
                    sb.AppendFormat("<Height>{0}</Height>", height);
                    sb.AppendFormat("<Girth>{0}</Girth>", girth);
                    sb.Append("<CommercialFlag>N</CommercialFlag>");
                    sb.Append("</Package>");
                }
                else
                {
                    int totalPackages        = 1;
                    int totalPackagesDims    = 1;
                    int totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)pounds / (decimal)MAXPACKAGEWEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                    }
                    totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                    {
                        totalPackages = 1;
                    }

                    int pounds2 = pounds / totalPackages;
                    //we don't use ounces
                    int ounces2 = ounces / totalPackages;
                    int height2 = height / totalPackages;
                    int width2  = width / totalPackages;
                    int length2 = length / totalPackages;
                    if (pounds2 < 1)
                    {
                        pounds2 = 1;
                    }
                    if (height2 < 1)
                    {
                        height2 = 1;
                    }
                    if (width2 < 1)
                    {
                        width2 = 1;
                    }
                    if (length2 < 1)
                    {
                        length2 = 1;
                    }

                    //little hack here for international requests
                    length2 = 12;
                    width2  = 12;
                    height2 = 12;
                    var packageSize2 = GetPackageSize(length2, height2, width2);
                    int girth2       = height2 + height2 + width2 + width2;

                    for (int i = 0; i < totalPackages; i++)
                    {
                        sb.AppendFormat("<Package ID=\"{0}\">", i.ToString());
                        sb.AppendFormat("<Pounds>{0}</Pounds>", pounds2);
                        sb.AppendFormat("<Ounces>{0}</Ounces>", ounces2);
                        sb.Append("<Machinable>FALSE</Machinable>");
                        sb.AppendFormat("<MailType>{0}</MailType>", mailType);
                        sb.Append("<GXG>");
                        sb.Append("<POBoxFlag>N</POBoxFlag>");
                        sb.Append("<GiftFlag>N</GiftFlag>");
                        sb.Append("</GXG>");
                        sb.AppendFormat("<ValueOfContents>{0}</ValueOfContents>", intlSubTotal);
                        sb.AppendFormat("<Country>{0}</Country>", getShippingOptionRequest.ShippingAddress.Country.Name);
                        sb.Append("<Container>RECTANGULAR</Container>");
                        sb.AppendFormat("<Size>{0}</Size>", packageSize2);
                        sb.AppendFormat("<Width>{0}</Width>", width2);
                        sb.AppendFormat("<Length>{0}</Length>", length2);
                        sb.AppendFormat("<Height>{0}</Height>", height2);
                        sb.AppendFormat("<Girth>{0}</Girth>", girth2);
                        sb.Append("<CommercialFlag>N</CommercialFlag>");
                        sb.Append("</Package>");
                    }
                }

                sb.Append("</IntlRateV2Request>");

                requestString = "API=IntlRateV2&XML=" + sb.ToString();
                #endregion
            }

            return(requestString);
        }
示例#2
0
        private string CreateRequest(string username, string password, GetShippingOptionRequest getShippingOptionRequest)
        {
            var usedMeasureWeight = _measureService.GetMeasureWeightBySystemKeyword(MEASUREWEIGHTSYSTEMKEYWORD);

            if (usedMeasureWeight == null)
            {
                throw new NopException(string.Format("USPS shipping service. Could not load \"{0}\" measure weight", MEASUREWEIGHTSYSTEMKEYWORD));
            }

            var baseusedMeasureWeight = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId);

            if (baseusedMeasureWeight == null)
            {
                throw new NopException("Primary weight can't be loaded");
            }

            var usedMeasureDimension = _measureService.GetMeasureDimensionBySystemKeyword(MEASUREDIMENSIONSYSTEMKEYWORD);

            if (usedMeasureDimension == null)
            {
                throw new NopException(string.Format("USPS shipping service. Could not load \"{0}\" measure dimension", MEASUREDIMENSIONSYSTEMKEYWORD));
            }

            var baseusedMeasureDimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId);

            if (baseusedMeasureDimension == null)
            {
                throw new NopException("Primary dimension can't be loaded");
            }

            decimal lengthTmp, widthTmp, heightTmp;

            _shippingService.GetDimensions(getShippingOptionRequest.Items, out widthTmp, out lengthTmp, out heightTmp);


            int length = Convert.ToInt32(Math.Ceiling(lengthTmp / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int height = Convert.ToInt32(Math.Ceiling(heightTmp / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int width  = Convert.ToInt32(Math.Ceiling(widthTmp / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int weight = Convert.ToInt32(Math.Ceiling(_shippingService.GetTotalWeight(getShippingOptionRequest) / baseusedMeasureWeight.Ratio * usedMeasureWeight.Ratio));


            if (length < 1)
            {
                length = 1;
            }
            if (height < 1)
            {
                height = 1;
            }
            if (width < 1)
            {
                width = 1;
            }
            if (weight < 1)
            {
                weight = 1;
            }


            string zipPostalCodeFrom = getShippingOptionRequest.ZipPostalCodeFrom;
            string zipPostalCodeTo   = getShippingOptionRequest.ShippingAddress.ZipPostalCode;

            //valid values for testing. http://testing.shippingapis.com/ShippingAPITest.dll
            //Zip to = "20008"; Zip from ="10022"; weight = 2;



            int pounds = Convert.ToInt32(weight / 16);
            int ounces = Convert.ToInt32(weight - (pounds * 16.0M));
            int girth  = height + height + width + width;
            //Get shopping cart sub-total.  V2 International rates require the package value to be declared.
            decimal subTotal = decimal.Zero;

            foreach (var packageItem in getShippingOptionRequest.Items)
            {
                //TODO we should use getShippingOptionRequest.Items.GetQuantity() method to get subtotal
                subTotal += _priceCalculationService.GetSubTotal(packageItem.ShoppingCartItem);
            }



            string requestString;

            bool isDomestic = IsDomesticRequest(getShippingOptionRequest);

            if (isDomestic)
            {
                #region domestic request
                zipPostalCodeFrom = CommonHelper.EnsureMaximumLength(CommonHelper.EnsureNumericOnly(zipPostalCodeFrom), 5);
                zipPostalCodeTo   = CommonHelper.EnsureMaximumLength(CommonHelper.EnsureNumericOnly(zipPostalCodeTo), 5);

                var sb = new StringBuilder();
                sb.AppendFormat("<RateV4Request USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.Append("<Revision>2</Revision>");

                var xmlStrings = new USPSStrings(); // Create new instance with string array

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    var packageSize = GetPackageSize(length, height, width);
                    // RJH get all XML strings not commented out for USPSStrings.
                    // RJH V3 USPS Service must be Express, Express SH, Express Commercial, Express SH Commercial, First Class, Priority, Priority Commercial, Parcel, Library, BPM, Media, ALL or ONLINE;
                    // AC - Updated to V4 API and made minor improvements to allow First Class Packages (package only - not envelopes).


                    foreach (string element in xmlStrings.Elements) // Loop over elements with property
                    {
                        if ((element == "First Class") && (weight >= 14))
                        {
                            // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                        }
                        else
                        {
                            sb.Append("<Package ID=\"0\">");

                            sb.AppendFormat("<Service>{0}</Service>", element);
                            if (element == "First Class")
                            {
                                sb.Append("<FirstClassMailType>PARCEL</FirstClassMailType>");
                            }

                            sb.AppendFormat("<ZipOrigination>{0}</ZipOrigination>", zipPostalCodeFrom);
                            sb.AppendFormat("<ZipDestination>{0}</ZipDestination>", zipPostalCodeTo);
                            sb.AppendFormat("<Pounds>{0}</Pounds>", pounds);
                            sb.AppendFormat("<Ounces>{0}</Ounces>", ounces);
                            sb.Append("<Container/>");
                            sb.AppendFormat("<Size>{0}</Size>", packageSize);
                            sb.AppendFormat("<Width>{0}</Width>", width);
                            sb.AppendFormat("<Length>{0}</Length>", length);
                            sb.AppendFormat("<Height>{0}</Height>", height);
                            sb.AppendFormat("<Girth>{0}</Girth>", girth);

                            sb.Append("<Machinable>FALSE</Machinable>");

                            sb.Append("</Package>");
                        }
                    }
                }
                else
                {
                    int totalPackagesDims    = 1;
                    int totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)pounds / (decimal)MAXPACKAGEWEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                    }
                    var totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                    {
                        totalPackages = 1;
                    }

                    int pounds2 = pounds / totalPackages;
                    //we don't use ounces
                    int ounces2 = ounces / totalPackages;
                    int height2 = height / totalPackages;
                    int width2  = width / totalPackages;
                    int length2 = length / totalPackages;
                    if (pounds2 < 1)
                    {
                        pounds2 = 1;
                    }
                    if (height2 < 1)
                    {
                        height2 = 1;
                    }
                    if (width2 < 1)
                    {
                        width2 = 1;
                    }
                    if (length2 < 1)
                    {
                        length2 = 1;
                    }

                    var packageSize = GetPackageSize(length2, height2, width2);

                    int girth2 = height2 + height2 + width2 + width2;

                    for (int i = 0; i < totalPackages; i++)
                    {
                        foreach (string element in xmlStrings.Elements)
                        {
                            if ((element == "First Class") && (weight >= 14))
                            {
                                // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                            }
                            else
                            {
                                sb.AppendFormat("<Package ID=\"{0}\">", i.ToString());
                                sb.AppendFormat("<Service>{0}</Service>", element);
                                if (element == "First Class")
                                {
                                    sb.Append("<FirstClassMailType>PARCEL</FirstClassMailType>");
                                }
                                sb.AppendFormat("<ZipOrigination>{0}</ZipOrigination>", zipPostalCodeFrom);
                                sb.AppendFormat("<ZipDestination>{0}</ZipDestination>", zipPostalCodeTo);
                                sb.AppendFormat("<Pounds>{0}</Pounds>", pounds2);
                                sb.AppendFormat("<Ounces>{0}</Ounces>", ounces2);
                                sb.Append("<Container/>");
                                sb.AppendFormat("<Size>{0}</Size>", packageSize);
                                sb.AppendFormat("<Width>{0}</Width>", width2);
                                sb.AppendFormat("<Length>{0}</Length>", length2);
                                sb.AppendFormat("<Height>{0}</Height>", height2);
                                sb.AppendFormat("<Girth>{0}</Girth>", girth2);
                                sb.Append("<Machinable>FALSE</Machinable>");
                                sb.Append("</Package>");
                            }
                        }
                    }
                }

                sb.Append("</RateV4Request>");

                requestString = "API=RateV4&XML=" + sb.ToString();
                #endregion
            }
            else
            {
                #region international request
                var sb = new StringBuilder();
                // sb.AppendFormat("<IntlRateRequest USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.AppendFormat("<IntlRateV2Request USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.AppendFormat("<Revision>2</Revision>");

                //V2 International rates require the package value to be declared.  Max content value for most shipping options is $400 so it is limited here.
                decimal intlSubTotal = subTotal > 400 ? 400 : subTotal;

                //little hack here for international requests
                length = 12;
                width  = 12;
                height = 12;
                girth  = height + height + width + width;

                string mailType    = "Package"; //Package, Envelope
                var    packageSize = GetPackageSize(length, height, width);

                var countryName = getShippingOptionRequest.ShippingAddress.Country.Name;
                //USPS country hacks
                //The USPS wants the NAME of the country for international shipments rather than one of the ISO codes
                //It requires "Korea, Republic of (South Korea)" rather than "Korea".
                if (countryName == "Korea")
                {
                    countryName = "Korea, Republic of (South Korea)";
                }

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    sb.Append("<Package ID=\"0\">");
                    sb.AppendFormat("<Pounds>{0}</Pounds>", pounds);
                    sb.AppendFormat("<Ounces>{0}</Ounces>", ounces);
                    sb.Append("<Machinable>FALSE</Machinable>");
                    sb.AppendFormat("<MailType>{0}</MailType>", mailType);
                    sb.Append("<GXG>");
                    sb.Append("<POBoxFlag>N</POBoxFlag>");
                    sb.Append("<GiftFlag>N</GiftFlag>");
                    sb.Append("</GXG>");
                    sb.AppendFormat("<ValueOfContents>{0}</ValueOfContents>", intlSubTotal);
                    sb.AppendFormat("<Country>{0}</Country>", countryName);
                    sb.Append("<Container>RECTANGULAR</Container>");
                    sb.AppendFormat("<Size>{0}</Size>", packageSize);
                    sb.AppendFormat("<Width>{0}</Width>", width);
                    sb.AppendFormat("<Length>{0}</Length>", length);
                    sb.AppendFormat("<Height>{0}</Height>", height);
                    sb.AppendFormat("<Girth>{0}</Girth>", girth);
                    sb.AppendFormat("<OriginZip>{0}</OriginZip>", zipPostalCodeFrom);
                    sb.Append("<CommercialFlag>N</CommercialFlag>");
                    sb.Append("</Package>");
                }
                else
                {
                    int totalPackagesDims    = 1;
                    int totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)pounds / (decimal)MAXPACKAGEWEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                    }
                    var totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                    {
                        totalPackages = 1;
                    }

                    int pounds2 = pounds / totalPackages;
                    if (pounds2 < 1)
                    {
                        pounds2 = 1;
                    }
                    //we don't use ounces
                    int ounces2 = ounces / totalPackages;
                    //int height2 = height / totalPackages;
                    //int width2 = width / totalPackages;
                    //int length2 = length / totalPackages;
                    //if (height2 < 1)
                    //    height2 = 1; // Why assign a 1 if it is assigned below 12? Perhaps this is a mistake.
                    //if (width2 < 1)
                    //    width2 = 1; // Similarly
                    //if (length2 < 1)
                    //    length2 = 1; // Similarly

                    //little hack here for international requests (uncomment the code above when fixed)
                    var length2      = 12;
                    var width2       = 12;
                    var height2      = 12;
                    var packageSize2 = GetPackageSize(length2, height2, width2);
                    int girth2       = height2 + height2 + width2 + width2;

                    for (int i = 0; i < totalPackages; i++)
                    {
                        sb.AppendFormat("<Package ID=\"{0}\">", i.ToString());
                        sb.AppendFormat("<Pounds>{0}</Pounds>", pounds2);
                        sb.AppendFormat("<Ounces>{0}</Ounces>", ounces2);
                        sb.Append("<Machinable>FALSE</Machinable>");
                        sb.AppendFormat("<MailType>{0}</MailType>", mailType);
                        sb.Append("<GXG>");
                        sb.Append("<POBoxFlag>N</POBoxFlag>");
                        sb.Append("<GiftFlag>N</GiftFlag>");
                        sb.Append("</GXG>");
                        sb.AppendFormat("<ValueOfContents>{0}</ValueOfContents>", intlSubTotal);
                        sb.AppendFormat("<Country>{0}</Country>", countryName);
                        sb.Append("<Container>RECTANGULAR</Container>");
                        sb.AppendFormat("<Size>{0}</Size>", packageSize2);
                        sb.AppendFormat("<Width>{0}</Width>", width2);
                        sb.AppendFormat("<Length>{0}</Length>", length2);
                        sb.AppendFormat("<Height>{0}</Height>", height2);
                        sb.AppendFormat("<Girth>{0}</Girth>", girth2);
                        sb.AppendFormat("<OriginZip>{0}</OriginZip>", zipPostalCodeFrom);
                        sb.Append("<CommercialFlag>N</CommercialFlag>");
                        sb.Append("</Package>");
                    }
                }

                sb.Append("</IntlRateV2Request>");

                requestString = "API=IntlRateV2&XML=" + sb.ToString();
                #endregion
            }

            return(requestString);
        }
        private string CreateRequest(string username, string password, bool isDomestic, GetShippingOptionRequest getShippingOptionRequest)
        {
            var(width, length, height) = GetDimensions(getShippingOptionRequest.Items);
            var weight = GetWeight(getShippingOptionRequest);

            var zipPostalCodeFrom = getShippingOptionRequest.ZipPostalCodeFrom;
            var zipPostalCodeTo   = getShippingOptionRequest.ShippingAddress.ZipPostalCode;

            //valid values for testing.
            //Zip to = "20008"; Zip from ="10022"; weight = 2;

            var pounds = Convert.ToInt32(weight / 16);
            var ounces = Convert.ToInt32(weight - (pounds * 16.0M));
            var girth  = height + height + width + width;
            //Get shopping cart sub-total.  V2 International rates require the package value to be declared.
            var subTotal = decimal.Zero;

            foreach (var packageItem in getShippingOptionRequest.Items)
            {
                //TODO we should use getShippingOptionRequest.Items.GetQuantity() method to get subtotal
                subTotal += _priceCalculationService.GetSubTotal(packageItem.ShoppingCartItem);
            }

            var rootElementName = isDomestic ? "RateV4Request" : "IntlRateV2Request";

            var rootRequestElement = new XElement(rootElementName,
                                                  new XAttribute("USERID", username),
                                                  new XAttribute("PASSWORD", password),
                                                  new XElement("Revision", 2));

            if (isDomestic)
            {
                #region domestic request

                var xmlStrings = new USPSStrings(); // Create new instance with string array

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    var packageSize = GetPackageSize(length, height, width);
                    // RJH get all XML strings not commented out for USPSStrings.
                    // RJH V3 USPS Service must be Express, Express SH, Express Commercial, Express SH Commercial, First Class, Priority, Priority Commercial, Parcel, Library, BPM, Media, ALL or ONLINE;
                    // AC - Updated to V4 API and made minor improvements to allow First Class Packages (package only - not envelopes).

                    foreach (var element in xmlStrings.Elements) // Loop over elements with property
                    {
                        if ((element == "First Class") && (weight >= 14))
                        {
                            // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                        }
                        else
                        {
                            var packageElement = new XElement("Package", new XAttribute("ID", 0),
                                                              new XElement("Service", element),
                                                              new XElement("ZipOrigination", CommonHelper.EnsureMaximumLength(CommonHelper.EnsureNumericOnly(zipPostalCodeFrom), 5)),
                                                              new XElement("ZipDestination", CommonHelper.EnsureMaximumLength(CommonHelper.EnsureNumericOnly(zipPostalCodeTo), 5)),
                                                              new XElement("Pounds", pounds),
                                                              new XElement("Ounces", ounces),
                                                              new XElement("Container"),
                                                              new XElement("Size", packageSize),
                                                              new XElement("Width", width),
                                                              new XElement("Length", length),
                                                              new XElement("Height", height),
                                                              new XElement("Girth", girth),
                                                              new XElement("Machinable", false));

                            if (element == "First Class")
                            {
                                packageElement.Add(new XElement("FirstClassMailType", "PARCEL"));
                            }

                            rootRequestElement.Add(packageElement);
                        }
                    }
                }
                else
                {
                    var totalPackagesDims    = 1;
                    var totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling(pounds / USPSShippingDefaults.MAX_PACKAGE_WEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / 108M));
                    }
                    var totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                    {
                        totalPackages = 1;
                    }

                    var pounds2 = Math.Max(pounds / totalPackages, 1);
                    //we don't use ounces
                    var ounces2 = Math.Max(ounces / totalPackages, 1);
                    var height2 = Math.Max(height / totalPackages, 1);
                    var width2  = Math.Max(width / totalPackages, 1);
                    var length2 = Math.Max(length / totalPackages, 1);

                    var packageSize = GetPackageSize(length2, height2, width2);

                    var girth2 = height2 + height2 + width2 + width2;

                    for (var i = 0; i < totalPackages; i++)
                    {
                        foreach (var element in xmlStrings.Elements)
                        {
                            if ((element == "First Class") && (weight >= 14))
                            {
                                // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                            }
                            else
                            {
                                var packageElement = new XElement("Package", new XAttribute("ID", i),
                                                                  new XElement("Service", element),
                                                                  new XElement("ZipOrigination", zipPostalCodeFrom),
                                                                  new XElement("ZipDestination", zipPostalCodeTo),
                                                                  new XElement("Pounds", pounds2),
                                                                  new XElement("Ounces", ounces2),
                                                                  new XElement("Container"),
                                                                  new XElement("Size", packageSize),
                                                                  new XElement("Width", width2),
                                                                  new XElement("Length", length2),
                                                                  new XElement("Height", height2),
                                                                  new XElement("Girth", girth2),
                                                                  new XElement("Machinable", false));

                                if (element == "First Class")
                                {
                                    packageElement.Add(new XElement("FirstClassMailType", "PARCEL"));
                                }

                                rootRequestElement.Add(packageElement);
                            }
                        }
                    }
                }

                #endregion
            }
            else
            {
                #region international request

                //V2 International rates require the package value to be declared.  Max content value for most shipping options is $400 so it is limited here.
                var intlSubTotal = subTotal > 400 ? 400 : subTotal;

                //little hack here for international requests
                length = 12;
                width  = 12;
                height = 12;
                girth  = height + height + width + width;

                var mailType    = "Package"; //Package, Envelope
                var packageSize = GetPackageSize(length, height, width);

                var countryName = FormatCountryForIntlRequest(getShippingOptionRequest);

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    var packageElement = new XElement("Package", new XAttribute("ID", 0),
                                                      new XElement("Pounds", pounds),
                                                      new XElement("Ounces", ounces),
                                                      new XElement("Machinable", false),
                                                      new XElement("MailType", mailType),
                                                      new XElement("GXG",
                                                                   new XElement("POBoxFlag", "N"),
                                                                   new XElement("GiftFlag", "N")),
                                                      new XElement("ValueOfContents", intlSubTotal),
                                                      new XElement("Country", countryName),
                                                      new XElement("Container", "RECTANGULAR"),
                                                      new XElement("Size", packageSize),
                                                      new XElement("Width", width),
                                                      new XElement("Length", length),
                                                      new XElement("Height", height),
                                                      new XElement("Girth", girth),
                                                      new XElement("OriginZip", zipPostalCodeFrom),
                                                      new XElement("CommercialFlag", "N"));

                    rootRequestElement.Add(packageElement);
                }
                else
                {
                    var totalPackagesDims    = 1;
                    var totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling(pounds / USPSShippingDefaults.MAX_PACKAGE_WEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / 108M));
                    }

                    var totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                    {
                        totalPackages = 1;
                    }

                    var pounds2 = pounds / totalPackages;
                    if (pounds2 < 1)
                    {
                        pounds2 = 1;
                    }
                    //we don't use ounces
                    var ounces2 = ounces / totalPackages;
                    //int height2 = height / totalPackages;
                    //int width2 = width / totalPackages;
                    //int length2 = length / totalPackages;
                    //if (height2 < 1)
                    //    height2 = 1; // Why assign a 1 if it is assigned below 12? Perhaps this is a mistake.
                    //if (width2 < 1)
                    //    width2 = 1; // Similarly
                    //if (length2 < 1)
                    //    length2 = 1; // Similarly

                    //little hack here for international requests (uncomment the code above when fixed)
                    var length2      = 12;
                    var width2       = 12;
                    var height2      = 12;
                    var packageSize2 = GetPackageSize(length2, height2, width2);
                    var girth2       = height2 + height2 + width2 + width2;

                    for (var i = 0; i < totalPackages; i++)
                    {
                        var packageElement = new XElement("Package", new XAttribute("ID", i),
                                                          new XElement("Pounds", pounds2),
                                                          new XElement("Ounces", ounces2),
                                                          new XElement("Machinable", false),
                                                          new XElement("MailType", mailType),
                                                          new XElement("GXG",
                                                                       new XElement("POBoxFlag", "N"),
                                                                       new XElement("GiftFlag", "N")),
                                                          new XElement("ValueOfContents", intlSubTotal),
                                                          new XElement("Country", countryName),
                                                          new XElement("Container", "RECTANGULAR"),
                                                          new XElement("Size", packageSize2),
                                                          new XElement("Width", width2),
                                                          new XElement("Length", length2),
                                                          new XElement("Height", height2),
                                                          new XElement("Girth", girth2),
                                                          new XElement("OriginZip", zipPostalCodeFrom),
                                                          new XElement("CommercialFlag", "N"));

                        rootRequestElement.Add(packageElement);
                    }
                }

                #endregion
            }

            return(new XDocument(rootRequestElement).ToString());
        }