How to Integrate Avalara Sales Tax in Asp.Net Core

In this article , I will show you how to integrate Avalara sales tax in Asp.net core for calculating product tax in your website.

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
  1. 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));

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories