示例#1
0
        public void Get_InvalidRateV4Request_RequestError()
        {
            RateV4Response response = _rateService.Get(new RateV4Request {
                UserId = "kjzsdjbh fgkjashdf jhasdf"
            });

            Assert.That(response.Error, Is.InstanceOf <RequestError>());
        }
示例#2
0
        public void Get_DomesticOverweightFirstClass_ReturnsPackageError()
        {
            string request =
                string.Format(
                    "<RateV4Request PASSWORD=\"{1}\" USERID=\"{0}\"><Revision>2</Revision><Package ID=\"539720aa4cff99f7\"><Service>First Class</Service><FirstClassMailType>Letter</FirstClassMailType><ZipOrigination>18507</ZipOrigination><ZipDestination>18518</ZipDestination><Pounds>10</Pounds><Ounces>0</Ounces><Container>RECTANGULAR</Container><Size>LARGE</Size><Width>15</Width><Length>15</Length><Height>20</Height><Girth>70</Girth><Value>249.95</Value><Machinable>false</Machinable><ReturnLocations>false</ReturnLocations></Package></RateV4Request>",
                    _userId, _password);
            RateV4Response response = _rateService.Get(request.ToObject <RateV4Request>());

            Assert.That(response.Packages[0].Error, Is.Not.Null);
        }
示例#3
0
        public void Get_DomesticWithZipCodeLongerThanFiveDigits_RateV4ResponseWithNoErrors()
        {
            string request =
                string.Format(
                    "<RateV4Request PASSWORD=\"{1}\" USERID=\"{0}\"><Revision>2</Revision><Package ID=\"2022599e4dfb4687\"><Service>Priority</Service><ZipOrigination>18507</ZipOrigination><ZipDestination>27513-8629</ZipDestination><Pounds>2</Pounds><Ounces>0</Ounces><Container /><Size>REGULAR</Size><Width>1</Width><Length>1</Length><Height>1</Height><Girth>4</Girth><Value>42.95</Value><SpecialServices><SpecialService>1</SpecialService></SpecialServices><Machinable>false</Machinable><ReturnLocations>false</ReturnLocations></Package></RateV4Request>",
                    _userId, _password);
            RateV4Response response = _rateService.Get(request.ToObject <RateV4Request>());

            Assert.That(response.Error, Is.Null);
            Assert.That(response.Packages[0].Error, Is.Null);
        }
示例#4
0
        public void Get_RateV4Request_RateV4Response()
        {
            RateV4Response response = _rateService.Get(RateServiceTestsData.GetDomesticRequest());

            Assert.That(response, Is.InstanceOf <RateV4Response>());
        }
示例#5
0
        public void Get_DomesticWithZipCodeLessThanFiveCharacters_ReturnsPackageError()
        {
            RateV4Response response = _rateService.Get(RateServiceTestsData.GetDomesticRequestWithZipDestinationLessThan5CharactersLong());

            Assert.That(response.Packages[0].Error, Is.Not.Null);
        }
示例#6
0
        public async System.Threading.Tasks.Task <IActionResult> GetAsync()
        {
            var     webRootPath = _hostingEnvironment.WebRootPath;
            Package package     = new Package()
            {
                PackageId      = "0", Service = "ALL", FirstClassMailType = "PACKAGE SERVICE", ZipOrigination = "90001",
                ZipDestination = "10001",
                Pounds         = 0,
                Ounces         = 6,
                Container      = "VARIABLE",
                Size           = "REGULAR",
                Machinable     = "FALSE"
            };
            string userId = _configuration["USPS:UserId"];

            RateV4Request request = new RateV4Request
            {
                Package = package,
                UserId  = userId
            };
            XmlSerializer xsSubmit = new XmlSerializer(typeof(RateV4Request));
            var           xml      = "";

            using (var sww = new StringWriter())
            {
                using (XmlWriter writer = XmlWriter.Create(sww))
                {
                    xsSubmit.Serialize(writer, request);
                    xml = sww.ToString();
                }
            }
            var requestXmlFile = Path.Combine(webRootPath, "request.xml");

            System.IO.File.WriteAllText(requestXmlFile, xml);
            string uspsUrl  = "http://production.shippingapis.com/ShippingAPI.dll";
            var    formData = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair <string, string>("API", "RateV4"),
                new KeyValuePair <string, string>("XML", xml)
            });
            HttpClient httpClient = new HttpClient();
            var        response   = await httpClient.PostAsync(uspsUrl, formData);

            var content = await response.Content.ReadAsStringAsync();

            var responseXmlFile = Path.Combine(webRootPath, "response.xml");

            System.IO.File.WriteAllText(responseXmlFile, content);

            try
            {
                XmlSerializer  deserializer = new XmlSerializer(typeof(RateV4Response));
                var            ms           = new MemoryStream(Encoding.UTF8.GetBytes(content));
                RateV4Response responseJson = (RateV4Response)deserializer.Deserialize(ms);
                return(Ok(responseJson));
            }
            catch (Exception ex)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(Error));
                var           ms         = new MemoryStream(Encoding.UTF8.GetBytes(content));
                Error         error      = (Error)serializer.Deserialize(ms);
                return(NotFound(error));
            }
        }
示例#7
0
        private List <ShippingOption> InterpretShippingOptions(RateV4Response response, decimal minimumShippingRate)
        {
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            if (minimumShippingRate < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(minimumShippingRate), minimumShippingRate, "minimumShippingRate must be greater than zero");
            }

            string[] carrierServicesOffered   = _uspsSettings.DomesticServicesSelected.Split(',');
            decimal  additionalHandlingCharge = _uspsSettings.AdditionalHandlingCharge;
            var      options = new List <ShippingOption>();

            foreach (Package package in response.Packages)
            {
                // indicate a package error if there is one and skip to the next package
                if (package.Error != null)
                {
                    options.Add(new ShippingOption {
                        Name = package.Error.Description
                    });
                    continue;
                }

                foreach (Postage postage in package.Postages)
                {
                    // service doesn't match one that is enabled, move on to the next one
                    if (!carrierServicesOffered.Contains(postage.ClassId))
                    {
                        continue;
                    }

                    string serviceName = GetModifiedServiceName(postage.MailService);

                    SpecialService insurance      = postage.SpecialServices?.FirstOrDefault(s => s.ServiceId == "1" || s.ServiceId == "11");
                    decimal        rate           = postage.Rate + (insurance?.Price ?? 0) + additionalHandlingCharge;
                    ShippingOption shippingOption = options.Find(o => o.Name == serviceName);

                    // Use min shipping amount if rate is less than minimum
                    rate = rate < minimumShippingRate ? minimumShippingRate : rate;

                    if (shippingOption == null)
                    {
                        // service doesn't exist yet, so create a new one
                        shippingOption = new ShippingOption {
                            Name = serviceName,
                            Rate = rate,
                        };

                        options.Add(shippingOption);
                    }
                    else
                    {
                        // service is already in the list, so let's add the current postage rate to it
                        shippingOption.Rate += rate;
                    }
                }
            }

            return(options);
        }
示例#8
0
        internal static async Task <List <UspsApi.Models.RateAPI.Response.Package> > FetchRatesAsync(List <UspsApi.Models.RateAPI.Request.Package> input)
        {
            // limit is 25 packages per request
            string requestGuid = Guid.NewGuid().ToString();

            Log.Information("{area}: New request for {packageTotal} packages. {requestGuid}", "FetchRates()", input.Count, requestGuid);

            List <UspsApi.Models.RateAPI.Response.Package> output = new();
            RateV4Request request;
            int           index = 0;

            while (index < input.Count)
            {
                request = new RateV4Request
                {
                    USERID   = UspsApiUsername,
                    Revision = "2",
                    Package  = input.Skip(index).Take(25).ToList()
                };

                Log.Information("{area}: Fetching rates for {packageCount} package(s). {requestGuid}", "FetchRates()", request.Package.Count, requestGuid);

                XmlSerializer xsSubmit = new(typeof(RateV4Request));
                var           xml      = "";

                using (var sww = new StringWriter())
                {
                    using XmlWriter writer = XmlWriter.Create(sww);
                    xsSubmit.Serialize(writer, request);
                    xml = sww.ToString();
                }

                string uspsUrl  = "https://secure.shippingapis.com/ShippingAPI.dll";
                var    formData = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair <string, string>("API", "RateV4"),
                    new KeyValuePair <string, string>("XML", xml)
                });

                HttpClient httpClient = new()
                {
                    Timeout = TimeSpan.FromSeconds(120)
                };
                HttpResponseMessage response = null;
                int      retryCount          = 0;
                DateTime responseTimer       = DateTime.Now;

retry:
                while (response == null || response.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    if (retryCount > 50)
                    {
                        Log.Error("{area}: USPS Failed to Respond after 50 attempts. {requestGuid}", "FetchRates()", retryCount, requestGuid);
                        throw new UspsApiException("408: After many attempts, the request to the USPS API did not recieve a response. Please try again later.");
                    }

                    if (retryCount > 0)
                    {
                        Log.Warning("{area}: USPS Failed to Respond after " + retryCount + " seconds. Attempt {retryCount}. {requestGuid}", "FetchRates()", retryCount, requestGuid);
                    }

                    try
                    {
                        response = await httpClient.PostAsync(uspsUrl, formData).ConfigureAwait(false);

                        Thread.Sleep(2500 * retryCount);
                        httpClient.CancelPendingRequests();
                        retryCount++;
                    }
                    catch
                    {
                        httpClient.CancelPendingRequests();
                        retryCount++;
                        goto retry;
                    }
                }

                TimeSpan responseTime = DateTime.Now.TimeOfDay.Subtract(responseTimer.TimeOfDay);
                var      content      = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                Log.Information("{area}: USPS response received in {responseTime} ms. {requestGuid}", "FetchRates()", responseTime.Milliseconds, requestGuid);

                try
                {
                    if (content.StartsWith("<Error")) // detect if there was an error
                    {
                        XmlSerializer deserializer = new(typeof(Error));
                        var           ms           = new MemoryStream(Encoding.UTF8.GetBytes(content));
                        Error         responseJson = (Error)deserializer.Deserialize(ms);
                        Log.Warning("{errorNumber}: {errorDescription} {requestGuid}", "FetchRates()", responseJson.Number, responseJson.Description, requestGuid);

                        Package newResponse = new()
                        {
                            ID    = input.First().ID,
                            Error = responseJson
                        };

                        return(new List <Package>()
                        {
                            newResponse
                        });
                    }
                    else
                    {
                        XmlSerializer  deserializer = new(typeof(RateV4Response));
                        var            ms           = new MemoryStream(Encoding.UTF8.GetBytes(content));
                        RateV4Response responseJson = (RateV4Response)deserializer.Deserialize(ms);
                        index += 25;

                        foreach (UspsApi.Models.RateAPI.Response.Package pkg in responseJson.Package)
                        {
                            if (pkg.Error != null)
                            {
                                Log.Warning("{area}: USPS Returned Error: {uspsErrorNumber} {uspsErrorDescription} {requestGuid}", "FetchRates()", pkg.Error.Number, pkg.Error.Description, requestGuid);
                            }

                            output.Add(pkg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error("{area}: Exception: {ex} {requestGuid}", "FetchRates()", ex.ToString(), requestGuid);
                    throw new UspsApiException(ex);
                }
            }

            if (output.Count != input.Count)
            {
                // something went wrong because counts should always match
                Console.WriteLine("Counts did not match between input and output");
                Log.Error("{area}: Counts did not match between input and output. {requestGuid}", "FetchRates()", requestGuid);
                throw new UspsApiException("Counts did not match between input and output");
            }

            return(output);
        }