public Rate GetTaxRateForLocation(string zip, string country, string state, string city, string street) { Rate locationWithRateInfo = null; bool failedVerification = false; Response.StatusCode = BadRequest().StatusCode; if (string.IsNullOrEmpty(zip) || (zip.Length != 5 && zip.Length != 10)) { Response.HttpContext.Features.Get <IHttpResponseFeature>().ReasonPhrase = "Zip code is invalid."; failedVerification = true; } // Threw in this online checker just in case bogus zip if (!failedVerification) { try { using (var client = new WebClient()) { var s = client.DownloadString($"http://api.zippopotam.us/us/{zip}"); } // Of course we can extend this to do actual comparison for Country, state, etc... } catch (WebException wex) { failedVerification = true; Debug.WriteLine( $"Exception thrown when calling zip lookup: {wex.Message}. Response: {wex.Response}"); if (wex.Status == WebExceptionStatus.ProtocolError) { var zipLookupReturnStatusCode = ((HttpWebResponse)wex.Response).StatusCode; var errorDescription = ((HttpWebResponse)wex.Response).StatusDescription; Debug.WriteLine($"Status Code : {zipLookupReturnStatusCode}. Error: {errorDescription}"); Response.HttpContext.Features.Get <IHttpResponseFeature>().ReasonPhrase = "Zip code is invalid."; } } // } if (!failedVerification) { ITaxApiCaller taxApi = _apiChooser.GetAppropriateApi(); locationWithRateInfo = ((ITaxCalculatorApi)taxApi).GetTaxRateForLocation(zip, country, state, city, street); Response.StatusCode = Ok().StatusCode; } return(locationWithRateInfo); }
public ITaxApiCaller GetAppropriateApi(string explicitKey = null) { ITaxApiCaller apiCaller = null; var keyOfApiToLoad = string.IsNullOrEmpty(explicitKey) ? _apiSettings.DefaultTaxApi : explicitKey; try { if (!_taxApiLibraries.ContainsKey(keyOfApiToLoad)) { TaxApiProvider provider = GetExplicitApi(keyOfApiToLoad); var assemblyTypeNameOfApi = provider.AssemblyFQN; string assemblyFileName = provider.Name + ".dll"; string assemblyPath = AppDomain.CurrentDomain.BaseDirectory + provider.Name + "Client.dll"; Assembly apiAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); var exported = apiAssembly.ExportedTypes.FirstOrDefault(t => t.Name == provider.ClrType); if (exported == null) { throw new InvalidOperationException("Configuration of tax api clients is not valid."); } Type taxApiType = apiAssembly.GetType(exported.FullName ?? throw new InvalidOperationException()); object taxApiInstance = Activator.CreateInstance(taxApiType); apiCaller = taxApiInstance as ITaxApiCaller; if (apiCaller == null) { throw new InvalidOperationException($"Could not instantiate tax api library: '{keyOfApiToLoad}'"); } apiCaller.AuthenticationToken = provider.ApiToken; _taxApiLibraries.TryAdd(keyOfApiToLoad, apiCaller); } else { apiCaller = _taxApiLibraries[keyOfApiToLoad]; } } catch (Exception e) { // Do some logging here Debug.WriteLine($"Exception thrown when instantiating taxApi libraries: '{keyOfApiToLoad}'. Exception: {e}"); throw; } return(apiCaller); }
public float CalculateSalesTaxForOrder([FromBody] Order order) { float totalSalesTaxForOrder = 0; try { if (order.ProductLineItems == null || order.ProductLineItems.Count == 0) { // More detailed verification of Order, Customer, Product info can be added here... Response.StatusCode = 400; Response.HttpContext.Features.Get <IHttpResponseFeature>().ReasonPhrase = "Order contains no product line items."; } else { ITaxApiCaller taxApi = _apiChooser.GetAppropriateApi(); totalSalesTaxForOrder = ((ITaxCalculatorApi)taxApi).CalculateSalesTaxForOrder(order); } } catch (InvalidOperationException iox) { // taxApi client did not like something. Let's check further if (iox.Data.Contains("Response")) { HttpResponseMessage apiResponse = (HttpResponseMessage)iox.Data["Response"]; Response.StatusCode = (int)apiResponse.StatusCode; Response.HttpContext.Features.Get <IHttpResponseFeature>().ReasonPhrase = apiResponse.ReasonPhrase; } } catch (Exception) { Response.StatusCode = 500; } return(totalSalesTaxForOrder); }