public async Task <TrackResponse> TrackPackages(string trackingNumber)
        {
            TrackFieldRequest requestData = new TrackFieldRequest(trackingNumber);

            string Xml = requestData.ToXML();

            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, _serviceUri + Xml);

            HttpResponseMessage response = await _client.SendAsync(requestMessage);

            string responseXml = await response.Content.ReadAsStringAsync();

            return(TrackResponse.LoadFromXMLString(responseXml));
        }
        public async Task <List <TrackInfo> > GetTrackInfoAsync(List <TrackID> input, CancellationToken cancellationToken)
        {
            // limit is 10 tracking numbers per request
            var requestGuid = Guid.NewGuid().ToString();

            _logger.LogInformation("New request for {packageTotal} package(s). {requestGuid}", input.Count, requestGuid);

            List <TrackInfo>  output = new();
            TrackFieldRequest request;
            var index = 0;

            while (index < input.Count)
            {
                request = new TrackFieldRequest
                {
                    USERID   = _options.UserId,
                    Revision = "1",
                    ClientIp = _options.ClientIp,
                    TrackID  = input.Skip(index).Take(10).ToList(),
                    SourceId = _options?.SourceId ?? nameof(UspsTrackingClient)
                };

                index += 10;

                XmlSerializer xsSubmit = new(typeof(TrackFieldRequest));
                var           xml      = string.Empty;

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

                var formData = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair <string, string>("API", "TrackV2"),
                    new KeyValuePair <string, string>("XML", xml)
                });

                var response = await _httpClient.PostAsync(string.Empty, formData, cancellationToken).ConfigureAwait(false);

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

                try
                {
                    XmlSerializer deserializer = new(typeof(TrackResponse));
                    var           ms           = new MemoryStream(Encoding.UTF8.GetBytes(content));
                    var           responseJson = (TrackResponse)deserializer.Deserialize(ms);

                    // todo: save response data to correct input data
                    foreach (var trackInfo in responseJson.TrackInfo)
                    {
                        if (trackInfo.Error != null)
                        {
                            _logger.LogWarning(
                                "USPS Returned Error: {uspsErrorNumber} {uspsErrorDescription} {requestGuid}",
                                trackInfo.Error.Number,
                                trackInfo.Error.Description,
                                requestGuid);
                        }
                        else
                        {
                            output.Add(trackInfo);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "{requestGuid}", requestGuid);
                    throw new UspsTrackingClientException(ex);
                }
            }

            return(output);
        }
Exemple #3
0
        internal static async Task <List <TrackInfo> > TrackAsync(List <TrackID> input)
        {
            // limit is 10 tracking numbers per request
            string requestGuid = Guid.NewGuid().ToString();

            Log.Information("{area}: New request for {packageTotal} package(s). {requestGuid}", "Track()", input.Count, requestGuid);

            List <TrackInfo>  output = new();
            TrackFieldRequest request;
            int index = 0;

            while (index < input.Count)
            {
                request = new TrackFieldRequest
                {
                    USERID   = UspsApiUsername,
                    Revision = "1",
                    ClientIp = "12.174.118.186",
                    TrackID  = input.Skip(index).Take(10).ToList(),
                    SourceId = "MYUSPS"
                };

                index += 10;

                XmlSerializer xsSubmit = new(typeof(TrackFieldRequest));
                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", "TrackV2"),
                    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}", "Track()", 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}", "Track()", 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
                {
                    XmlSerializer deserializer = new(typeof(TrackResponse));
                    var           ms           = new MemoryStream(Encoding.UTF8.GetBytes(content));
                    TrackResponse responseJson = (TrackResponse)deserializer.Deserialize(ms);

                    // todo: save response data to correct input data
                    foreach (TrackInfo trackInfo in responseJson.TrackInfo)
                    {
                        if (trackInfo.Error != null)
                        {
                            Log.Warning("{area}: USPS Returned Error: {uspsErrorNumber} {uspsErrorDescription} {requestGuid}", "Track()", trackInfo.Error.Number, trackInfo.Error.Description, requestGuid);
                        }

                        output.Add(trackInfo);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error("{area}: Exception: {ex} {requestGuid}", "Track()", 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");
                throw new UspsApiException("Counts did not match between input and output");
            }

            return(output);
        }