Example #1
0
    public async Task <Shipment> GetRatesAsync(
        Shipment shipment,
        UspsRateOptions rateOptions,
        CancellationToken cancellationToken = default)
    {
        shipment = shipment.IsDomestic()
            ? await UspsDomesticRate(shipment, rateOptions).ConfigureAwait(false)
            : await UspsInternationalRate(shipment, rateOptions);

        return(shipment);
    }
Example #2
0
    private Shipment ParseInternationalResult(
        Shipment shipment,
        UspsRateOptions rateOptions,
        string response)
    {
        var document = XDocument.Load(new StringReader(response));

        var rates = document
                    .Descendants("Service")
                    .GroupBy(item => (string)item.Element("SvcDescription"))
                    .Select(g => new
        {
            Name         = g.Key,
            DeliveryDate = g.Select(x => (string)x.Element("GuaranteeAvailability")).FirstOrDefault(),
            TotalCharges = g.Sum(x => decimal.Parse((string)x.Element("Postage")))
        });

        foreach (var r in rates)
        {
            var name = Regex.Replace(r.Name, "&lt.*gt;", string.Empty);

            if (rateOptions.ServiceName == name ||
                rateOptions.ServiceName == "ALL")
            {
                if (r.DeliveryDate != null && DateTime.TryParse(r.DeliveryDate, out var deliveryDate))
                {
                    shipment.Rates.Add(new Rate(
                                           $"USPS {name}",
                                           name,
                                           r.TotalCharges,
                                           r.TotalCharges,
                                           (DateTime?)deliveryDate,
                                           false,
                                           shipment.Options.PreferredCurrencyCode));
                }
                else
                {
                    shipment.Rates.Add(new Rate(
                                           $"USPS {name}",
                                           name,
                                           r.TotalCharges,
                                           r.TotalCharges,
                                           rateOptions.DefaultGuaranteedDelivery,
                                           false,
                                           shipment.Options.PreferredCurrencyCode));
                }
            }
        }

        // check for errors
        return(document.Root.ParseErrors(shipment));
    }
Example #3
0
    private async Task <Shipment> UspsInternationalRate(Shipment shipment, UspsRateOptions rateOptions)
    {
        try
        {
            var sb = CreateInternationalRequest(shipment);

            var rateUri  = new Uri(_options.Value.BaseUri, $"?API=IntlRateV2&XML={sb}");
            var response = await _httpClient.GetStringAsync(rateUri).ConfigureAwait(false);

            shipment = ParseInternationalResult(shipment, rateOptions, response);
        }
        catch (Exception ex)
        {
            shipment.InternalErrors.Add($"{nameof(UspsRateProvider)}Domestic exception: {ex?.Message}");
        }

        return(shipment);
    }
Example #4
0
    public async Task Get_First_Class_International_Mail_Successfully(string w, string c)
    {
        var sp       = GetServices();
        var provider = sp.GetRequiredService <IUspsRateProvider>();

        Assert.NotNull(provider);
        var weight      = Convert.ToDecimal(w);
        var charge      = Convert.ToDecimal(c);
        var destination = new Address("1851, BUR JUMAN BUSINESS TOWER,MAKHOOL ", "Dubai", string.Empty, string.Empty, "AE", isResidential: true);

        // CASE: UM606525025US First Class International (R) Large Envelope or Flat $36.56 weight 2 lbs 4 oz
        var packages = new List <Package>
        {
            // weight from 1 oz to 4lbs for First-Class Package International Service
            UspsRateConfigurator.GetIntlBox(weight)
        };

        var shipOptions = new ShipmentOptions
        {
            PackagingType = nameof(IntlPackageType.ALL),
            ShippingDate  = DateTime.Now.AddBusinessDays(1),
        };

        var shipment    = new Shipment(_origin, destination, packages, shipOptions);
        var rateOptions = new UspsRateOptions {
            ServiceName = "First-Class Package International Service"
        };

        var result = await provider.GetRatesAsync(shipment, rateOptions);

        var rate = result.Rates.FirstOrDefault();

        Assert.NotNull(rate);

        // expectable rate for this package due to the weight
        Assert.Equal(charge, rate?.TotalCharges);
        Assert.Null(rate?.GuaranteedDelivery);
        _output.WriteLine($"{rate?.ServiceName} - ${rate?.TotalCharges} - {rate?.GuaranteedDelivery}");
    }
Example #5
0
    public async Task Get_Priority_Mail_International_Package_5lbs_Successfully()
    {
        var sp       = GetServices();
        var provider = sp.GetRequiredService <IUspsRateProvider>();

        Assert.NotNull(provider);

        var destination = new Address("FLAT 22 TOLBUT COURT", "ROMFORD", string.Empty, string.Empty, "GB", isResidential: true);

        var packages = new List <Package>
        {
            // https://www.usps.com/international/priority-mail-international.htm
            // Maximum weight for Priority Mail International Flat Rate Envelopes and small Flat Rate Boxes is 4 lbs.
            // Fast international delivery time: 6–10 business days
            // new Package(11M, 5M, 1M, 5M, 0.0M),
            UspsRateConfigurator.GetIntlBox(5m)
        };

        var shipOptions = new ShipmentOptions
        {
            PackagingType = nameof(IntlPackageType.PACKAGE),
            ShippingDate  = DateTime.Now.AddBusinessDays(1),
        };
        var shipment    = new Shipment(_origin, destination, packages, shipOptions);
        var rateOptions = new UspsRateOptions {
            ServiceName = "Priority Mail International"
        };

        var result = await provider.GetRatesAsync(shipment, rateOptions);

        var rate = result.Rates.FirstOrDefault();

        Assert.NotNull(rate);
        Assert.Equal(77.60m, rate?.TotalCharges);

        _output.WriteLine($"{rate?.ServiceName}- ${rate?.TotalCharges} - {rate?.GuaranteedDelivery}");
    }
Example #6
0
    private async Task <Shipment> UspsDomesticRate(Shipment shipment, UspsRateOptions rateOptions)
    {
        try
        {
            var sb = CreateDometicRequest(shipment, rateOptions);

            var rateUri  = new Uri(_options.Value.BaseUri, $"?API=RateV4&XML={sb}");
            var response = await _httpClient.GetStringAsync(rateUri).ConfigureAwait(false);

            var specialServiceCodes = new List <string>();
            if (shipment.Packages.Any(x => x.SignatureRequiredOnDelivery))
            {
                specialServiceCodes.Add("119"); // 119 represents Adult Signature Requiredgnature Required
            }

            shipment = ParseDomesticResult(shipment, response, rateOptions, specialServiceCodes);
        }
        catch (Exception ex)
        {
            shipment.InternalErrors.Add($"{nameof(UspsRateProvider)}Domestic exception: {ex?.Message}");
        }

        return(shipment);
    }
Example #7
0
    private string CreateDometicRequest(Shipment shipment, UspsRateOptions rateOptions)
    {
        var sb = new StringBuilder();

        // var signatureOnDeliveryRequired = false;
        var settings = new XmlWriterSettings
        {
            Indent             = false,
            OmitXmlDeclaration = true,
            NewLineHandling    = NewLineHandling.None
        };

        using (var writer = XmlWriter.Create(sb, settings))
        {
            writer.WriteStartElement("RateV4Request");
            writer.WriteAttributeString("USERID", _options.Value.UserId);
            if (!rateOptions.BaseRatesOnly)
            {
                writer.WriteElementString("Revision", "2");
            }

            var i = 0;
            foreach (var package in shipment.Packages)
            {
                string size;
                var    container = shipment.Options?.PackagingType?.Replace("_", " ");
                if (package.IsPackageLarge())
                {
                    size = "LARGE";

                    // Container must be RECTANGULAR or NONRECTANGULAR when SIZE is LARGE
                    if (container == null || !string.Equals(container, "NONRECTANGULAR", StringComparison.InvariantCultureIgnoreCase))
                    {
                        container = "RECTANGULAR";
                    }
                }
                else
                {
                    size = "REGULAR";
                    if (string.IsNullOrEmpty(container))
                    {
                        container = string.Empty;
                    }
                }

                writer.WriteStartElement("Package");
                writer.WriteAttributeString("ID", i.ToString());
                writer.WriteElementString("Service", rateOptions.ServiceName);
                if (rateOptions.ServiceName.Contains("First"))
                {
                    writer.WriteElementString("FirstClassMailType", container);
                }

                writer.WriteElementString("ZipOrigination", shipment.OriginAddress.CountryCode == "US" && shipment.OriginAddress.PostalCode.Length > 5 ? shipment.OriginAddress.PostalCode.Substring(0, 5) : shipment.OriginAddress.PostalCode);
                writer.WriteElementString("ZipDestination", shipment.DestinationAddress.CountryCode == "US" && shipment.DestinationAddress.PostalCode.Length > 5 ? shipment.DestinationAddress.PostalCode.Substring(0, 5) : shipment.DestinationAddress.PostalCode);
                writer.WriteElementString("Pounds", package.PoundsAndOunces.Pounds.ToString());
                writer.WriteElementString("Ounces", package.PoundsAndOunces.Ounces.ToString());
                if (rateOptions.ServiceName == "First Class")
                {
                    writer.WriteElementString("Container", string.Empty);
                }
                else
                {
                    writer.WriteElementString("Container", container);
                }

                writer.WriteElementString("Size", size);
                writer.WriteElementString("Width", package.Dimensions.RoundedWidth.ToString());
                writer.WriteElementString("Length", package.Dimensions.RoundedLength.ToString());
                writer.WriteElementString("Height", package.Dimensions.RoundedHeight.ToString());
                writer.WriteElementString("Girth", package.Dimensions.Girth.ToString());
                writer.WriteElementString("Machinable", package.IsPackageMachinable().ToString());
                if (shipment.Options.ShippingDate != null)
                {
                    writer.WriteElementString(
                        "ShipDate",
                        shipment.Options.ShippingDate.Value.AddDays(1).ToString("yyyy-MM-dd"));
                }

                if (package.SignatureRequiredOnDelivery)
                {
                    // signatureOnDeliveryRequired = true;
                }

                writer.WriteEndElement();
                i++;
            }

            writer.WriteEndElement();
            writer.Flush();
        }

        return(sb.ToString());
    }
Example #8
0
    private Shipment ParseDomesticResult(
        Shipment shipment,
        string response,
        UspsRateOptions rateOptions,
        IList <string>?includeSpecialServiceCodes = null)
    {
        var document = XElement.Parse(response, LoadOptions.None);

        var rates = from item in document.Descendants("Postage")
                    group item by(string) item.Element("MailService")
                    into g
                    select new
        {
            Name            = g.Key,
            TotalCharges    = g.Sum(x => decimal.Parse((string)x.Element("Rate"))),
            DeliveryDate    = g.Select(x => (string)x.Element("CommitmentDate")).FirstOrDefault(),
            SpecialServices = g.Select(x => x.Element("SpecialServices")).FirstOrDefault()
        };

        foreach (var r in rates)
        {
            var name = Regex.Replace(r.Name, "&lt.*&gt;", string.Empty);
            var additionalCharges = 0.0m;

            if (includeSpecialServiceCodes?.Count > 0 && r.SpecialServices != null)
            {
                var specialServices = r.SpecialServices.XPathSelectElements("SpecialService").ToList();
                if (specialServices.Count > 0)
                {
                    foreach (var specialService in specialServices)
                    {
                        var serviceId = (string)specialService.Element("ServiceID");
                        var price     = decimal.Parse((string)specialService.Element("Price"));

                        if (includeSpecialServiceCodes.Contains(serviceId))
                        {
                            additionalCharges += price;
                        }
                    }
                }
            }

            var charges = r.TotalCharges + additionalCharges;

            if (r.DeliveryDate != null && DateTime.TryParse(r.DeliveryDate, out var deliveryDate))
            {
                var saturdayDelivery = shipment.Options.SaturdayDelivery && deliveryDate.DayOfWeek == DayOfWeek.Saturday;

                shipment.Rates.Add(new Rate(
                                       $"USPS {name}",
                                       name,
                                       charges,
                                       charges,
                                       (DateTime?)deliveryDate,
                                       saturdayDelivery,
                                       shipment.Options.GetCurrencyCode()));
            }
            else
            {
                shipment.Rates.Add(new Rate(
                                       $"USPS {name}",
                                       name,
                                       charges,
                                       charges,
                                       rateOptions.DefaultGuaranteedDelivery,
                                       false,
                                       shipment.Options.GetCurrencyCode()));
            }
        }

        // check for errors
        return(document.ParseErrors(shipment));
    }