In this article , I will show you how to integrate Avalara sales tax in Asp.net core for calculating product tax in your website.
- Go to the Avalara sales tax portal https://www.avalara.com/us/en/get-started.html.
- Create sales tax account and login with your creadential.
- Avalara Sales Tax Login Portal URL
- Complete your sales tax profile.
Avalara is a software to get your business tax compliance done right. It’s tax automation for businesses with real-time tax calculation and automatic returns filing.
- create New Asp.net core web API project and open appsettings.json
-
appsettings.json
"AvalaraSalesTax": { "Username": "Your User Name", "Password": "Your Password", "CompanyCode": "DEFAULT",//if company code is not provided then use DEFAULT "DiscardFirstCall": true, "Environment": "https://sandbox-rest.avatax.com", "Lines": 1, "LogExceptionalDelays": false, "SleepBetweenCalls": 0, "Threads": 1 },
2. Create Options.cs
public class Options { [Required] //Username for AvaTax. public string Username { get; set; } [Required] //Password for AvaTax. public string Password { get; set; } [Required] //CompanyCode to use when contacting AvaTax. If not specified, uses 'DEFAULT'. public string CompanyCode { get; set; } //Discard first API call. The first API call includes lots of overhead. public bool? DiscardFirstCall { get; set; } //URL of the AvaTax environment to call. public string Environment { get; set; } //Type of document to create. public DocumentType DocType { get; set; } = DocumentType.SalesOrder; //Number of lines to include in each tax transaction. public int Lines { get; set; } //Log only exceptional delays public bool LogExceptionalDelays { get; set; } //Milliseconds to sleep between calls public int SleepBetweenCalls { get; set; } //Number of threads to create public int Threads { get; set; } //Number of API calls to execute before finishing. Default is forever. public int? Calls { get; set; } public bool IsValid() { return (!String.IsNullOrEmpty(Username) && !String.IsNullOrEmpty(Password)); } }
3) Create Sales Tax Transaction Service
public interface ISalesTaxTransactionService { Task<Result<TaxCalculated>> CreateTransactionModel(); }
public class SalesTaxTransactionService : ISalesTaxTransactionService { public readonly IHostingEnvironment _hostingEnvironment; public static int Count = 0; public static AvaTaxClient SalesTaxClient = null; public static CreateTransactionModel TransactionModel = null; public static long TotalMs = 0; private readonly IOptions<Options> _salesTaxOptions; public static CallDuration TotalDuration = null; public SalesTaxTransactionService(IHostingEnvironment hostingEnvironment, IOptions<Options> salesTaxOptions) { _hostingEnvironment = hostingEnvironment; _salesTaxOptions = salesTaxOptions; } public async Task<Result<TaxCalculated>> CreateTransactionModel() { if (String.IsNullOrEmpty(_salesTaxOptions.Value.Environment) || !_salesTaxOptions.Value.Environment.StartsWith("http")) { var result = new Result<TaxCalculated>() { Success = false, }; return result; } SalesTaxClient = new AvaTaxClient("Your Project Name", "1.0", Environment.MachineName, new Uri(_salesTaxOptions.Value.Environment)) .WithSecurity(_salesTaxOptions.Value.Username, _salesTaxOptions.Value.Password); var ping = new PingResultModel(); ping = SalesTaxClient.Ping(); if (!(bool)ping.authenticated) { var result = new Result<TaxCalculated>() { Success = false, }; return result; } FetchResult<CompanyModel> companies = null; try { companies = await SalesTaxClient.QueryCompaniesAsync(null, $"companyCode eq '{_salesTaxOptions.Value.CompanyCode}'", null, null, null); } catch (Exception ex) { throw ex; } if (companies == null || companies.count != 1) { var result = new Result<TaxCalculated>() { Success = false, }; return result; } if ((companies.value[0].isTest != true) && IsPermanent(_salesTaxOptions.Value.DocType)) { var result = new Result<TaxCalculated>() { Success = false, }; return result; } var customerCode = "0000000" //Default if (customerCode == null) { var result = new Result<TaxCalculated>() { Success = false, }; return result; } var tb = new TransactionBuilder(SalesTaxClient, _salesTaxOptions.Value.CompanyCode, _salesTaxOptions.Value.DocType, customerCode); for (int i = 0; i < _salesTaxOptions.Value.Lines; i++) { tb.WithLine(200) //Your product Price .WithLineAddress(TransactionAddressType.PointOfOrderAcceptance, TestAddress1, TestAddress2, TestAddress3, TestCity, TestState,TestZip, "TestCountry") .WithLineAddress(TransactionAddressType.PointOfOrderOrigin, TestAddress1, TestAddress2, TestAddress3,TestCity, TestState, TestZip, "TestCountry") .WithLineAddress(TransactionAddressType.ShipFrom, TestAddress1, TestAddress2, TestAddress3, TestCity, TestState, TestZip, "TestCountry") .WithLineAddress(TransactionAddressType.ShipTo, "123 Main Street", null, null, "Irvine", "CA", "92615", "US") .WithCurrencyCode("USD") .WithDiscountAmount(30)//Discount .WithEmail(Test@gmail.com)//Customer Email .WithItemDiscount(true)//If discount provided then set WithItemDiscount true .WithDate(DateTime.UtcNow) .WithCommit(); } TransactionModel = tb.GetCreateTransactionModel(); TaxCalculated taxCalculated = new TaxCalculated(); if (_salesTaxOptions.Value.DiscardFirstCall.HasValue && _salesTaxOptions.Value.DiscardFirstCall.Value) { try { var t = SalesTaxClient.CreateTransaction(null, TransactionModel); taxCalculated.TotalTax = t.totalTax; taxCalculated.ProductPrice = t.totalAmount; taxCalculated.TotalDiscount = t.totalDiscount; taxCalculated.TaxCode = t.lines[0].taxCode; taxCalculated.TaxCodeId = t.lines[0].taxCodeId; } catch (Exception ex) { throw ex; } } var resultData = new Result<TaxCalculated>() { Success = true, Data = taxCalculated }; return resultData; } private static bool IsPermanent(DocumentType docType) { switch (docType) { case DocumentType.InventoryTransferInvoice: case DocumentType.PurchaseInvoice: case DocumentType.ReturnInvoice: case DocumentType.ReverseChargeInvoice: case DocumentType.SalesInvoice: return true; } return false; } }
4) Create TaxCalculated.cs
public class TaxCalculated { public decimal? TotalTax { get; set; } public decimal? ProductPrice { get; set; } public string TaxCode { get; set; } public int? TaxCodeId { get; set; } public decimal? TotalDiscount { get; set; } }
5) Configure Avalara Sales Tax Section in startup.cs
services.Configure<Options>(configuration.GetSection(AVALARA_SALS_TAX));