public void Get_InvalidRateV4Request_RequestError() { RateV4Response response = _rateService.Get(new RateV4Request { UserId = "kjzsdjbh fgkjashdf jhasdf" }); Assert.That(response.Error, Is.InstanceOf <RequestError>()); }
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); }
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); }
public void Get_RateV4Request_RateV4Response() { RateV4Response response = _rateService.Get(RateServiceTestsData.GetDomesticRequest()); Assert.That(response, Is.InstanceOf <RateV4Response>()); }
public void Get_DomesticWithZipCodeLessThanFiveCharacters_ReturnsPackageError() { RateV4Response response = _rateService.Get(RateServiceTestsData.GetDomesticRequestWithZipDestinationLessThan5CharactersLong()); Assert.That(response.Packages[0].Error, Is.Not.Null); }
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)); } }
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); }
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); }