/// <summary>
        /// Gets tax total
        /// </summary>
        /// <param name="taxTotalRequest">Tax total request</param>
        /// <returns>Tax total</returns>
        public async Task <TaxTotalResult> GetTaxTotalAsync(TaxTotalRequest taxTotalRequest)
        {
            if (!(_httpContextAccessor.HttpContext.Items.TryGetValue("nop.TaxTotal", out var result) && result is TaxTotalResult taxTotalResult))
            {
                var taxRates = new SortedDictionary <decimal, decimal>();

                //order sub total (items + checkout attributes)
                var(_, _, _, _, orderSubTotalTaxRates) = await _orderTotalCalculationService
                                                         .GetShoppingCartSubTotalAsync(taxTotalRequest.ShoppingCart, false);

                var subTotalTaxTotal = decimal.Zero;
                foreach (var kvp in orderSubTotalTaxRates)
                {
                    var taxRate  = kvp.Key;
                    var taxValue = kvp.Value;
                    subTotalTaxTotal += taxValue;

                    if (taxRate > decimal.Zero && taxValue > decimal.Zero)
                    {
                        if (!taxRates.ContainsKey(taxRate))
                        {
                            taxRates.Add(taxRate, taxValue);
                        }
                        else
                        {
                            taxRates[taxRate] = taxRates[taxRate] + taxValue;
                        }
                    }
                }

                //shipping
                var shippingTax = decimal.Zero;
                if (_taxSettings.ShippingIsTaxable)
                {
                    var(shippingExclTax, _, _) = await _orderTotalCalculationService
                                                 .GetShoppingCartShippingTotalAsync(taxTotalRequest.ShoppingCart, false);

                    var(shippingInclTax, taxRate, _) = await _orderTotalCalculationService
                                                       .GetShoppingCartShippingTotalAsync(taxTotalRequest.ShoppingCart, true);

                    if (shippingExclTax.HasValue && shippingInclTax.HasValue)
                    {
                        shippingTax = shippingInclTax.Value - shippingExclTax.Value;
                        if (shippingTax < decimal.Zero)
                        {
                            shippingTax = decimal.Zero;
                        }

                        if (taxRate > decimal.Zero && shippingTax > decimal.Zero)
                        {
                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, shippingTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + shippingTax;
                            }
                        }
                    }
                }

                //add at least one tax rate (0%)
                if (!taxRates.Any())
                {
                    taxRates.Add(decimal.Zero, decimal.Zero);
                }

                var taxTotal = subTotalTaxTotal + shippingTax;

                if (taxTotal < decimal.Zero)
                {
                    taxTotal = decimal.Zero;
                }

                taxTotalResult = new TaxTotalResult {
                    TaxTotal = taxTotal, TaxRates = taxRates
                };
                _httpContextAccessor.HttpContext.Items.TryAdd("nop.TaxTotal", taxTotalResult);
            }

            //payment method additional fee
            if (taxTotalRequest.UsePaymentMethodAdditionalFee && _taxSettings.PaymentMethodAdditionalFeeIsTaxable)
            {
                var paymentMethodSystemName = taxTotalRequest.Customer != null
                    ? await _genericAttributeService.GetAttributeAsync <string>(taxTotalRequest.Customer,
                                                                                NopCustomerDefaults.SelectedPaymentMethodAttribute, taxTotalRequest.StoreId)
                    : string.Empty;

                var paymentMethodAdditionalFee = await _paymentService.GetAdditionalHandlingFeeAsync(taxTotalRequest.ShoppingCart, paymentMethodSystemName);

                var(paymentMethodAdditionalFeeExclTax, _) = await _taxService
                                                            .GetPaymentMethodAdditionalFeeAsync(paymentMethodAdditionalFee, false, taxTotalRequest.Customer);

                var(paymentMethodAdditionalFeeInclTax, taxRate) = await _taxService
                                                                  .GetPaymentMethodAdditionalFeeAsync(paymentMethodAdditionalFee, true, taxTotalRequest.Customer);

                var paymentMethodAdditionalFeeTax = paymentMethodAdditionalFeeInclTax - paymentMethodAdditionalFeeExclTax;

                if (paymentMethodAdditionalFeeTax < decimal.Zero)
                {
                    paymentMethodAdditionalFeeTax = decimal.Zero;
                }

                taxTotalResult.TaxTotal += paymentMethodAdditionalFeeTax;

                if (taxRate > decimal.Zero && paymentMethodAdditionalFeeTax > decimal.Zero)
                {
                    if (!taxTotalResult.TaxRates.ContainsKey(taxRate))
                    {
                        taxTotalResult.TaxRates.Add(taxRate, paymentMethodAdditionalFeeTax);
                    }
                    else
                    {
                        taxTotalResult.TaxRates[taxRate] = taxTotalResult.TaxRates[taxRate] + paymentMethodAdditionalFeeTax;
                    }
                }
            }

            return(taxTotalResult);
        }