public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest) { var result = new ProcessPaymentResult(); try { var options = IyzicoHelper.GetIyzicoOptions(_iyzicoPaymentSettings); var paymentCard = new PaymentCard() { CardHolderName = processPaymentRequest.CreditCardName, CardNumber = processPaymentRequest.CreditCardNumber, ExpireMonth = processPaymentRequest.CreditCardExpireMonth.ToString(), ExpireYear = processPaymentRequest.CreditCardExpireYear.ToString(), Cvc = processPaymentRequest.CreditCardCvv2 }; var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); var billingAddress = _iyzicoService.PrepareAddress(_customerService.GetCustomerBillingAddress(customer)); var shippingAddress = _customerService.GetCustomerShippingAddress(customer) != null?_iyzicoService.PrepareAddress(_customerService.GetCustomerShippingAddress(customer)) : billingAddress; var installment = GetInstallment(processPaymentRequest, paymentCard, options); var shoppingCart = _shoppingCartService.GetShoppingCart(customer, ShoppingCartType.ShoppingCart); var shoppingCartTotal = _orderTotalCalculationService.GetShoppingCartTotal(shoppingCart, out var orderDiscountAmount, out var orderAppliedDiscounts, out var appliedGiftCards, out var redeemedRewardPoints, out var redeemedRewardPointsAmount, usePaymentMethodAdditionalFee: false); var paymentRequest = new CreatePaymentRequest { Price = _priceCalculationService.RoundPrice(shoppingCartTotal ?? 0).ToString("f8", CultureInfo.InvariantCulture), PaidPrice = installment.TotalPrice, Currency = Currency.TRY.ToString(), Installment = installment.InstallmentNumber, BasketId = processPaymentRequest.OrderGuid.ToString(), PaymentCard = paymentCard, Buyer = _iyzicoService.PrepareBuyer(processPaymentRequest.CustomerId), ShippingAddress = shippingAddress, BillingAddress = billingAddress, BasketItems = GetItems(customer, processPaymentRequest.StoreId) }; paymentRequest.PaymentGroup = PaymentGroup.LISTING.ToString(); var payment = Payment.Create(paymentRequest, options); if (payment.Status != "success") { string errorMessage = _localizationService.GetResource(String.Format("Plugins.Payments.Iyzico.ErrorMessage.{0}", payment.ErrorCode)) ?? payment.ErrorMessage; result.AddError(errorMessage); return(result); } result.NewPaymentStatus = PaymentStatus.Pending; return(result); } catch (Exception ex) { result.AddError(ex.Message); return(result); } }
public virtual IActionResult GetInstallment(string binNumber) { if (String.IsNullOrEmpty(binNumber)) { return(Json(String.Empty)); } var customer = _customerService.GetCustomerById(_workContext.CurrentCustomer.Id); var shoppingCart = _shoppingCartService.GetShoppingCart(customer, ShoppingCartType.ShoppingCart); var shoppingCartTotal = _orderTotalCalculationService.GetShoppingCartTotal(shoppingCart, out var orderDiscountAmount, out var orderAppliedDiscounts, out var appliedGiftCards, out var redeemedRewardPoints, out var redeemedRewardPointsAmount); var options = IyzicoHelper.GetIyzicoOptions(_iyzicoPaymentSettings); var retrieveInstallmentInfoRequest = new RetrieveInstallmentInfoRequest() { BinNumber = binNumber.ToString(), Locale = Locale.TR.ToString(), Price = _priceCalculationService.RoundPrice(shoppingCartTotal.Value).ToString("f8", CultureInfo.InvariantCulture), ConversationId = string.Empty }; var installmentInfo = InstallmentInfo.Retrieve(retrieveInstallmentInfoRequest, options); var subTotalIncludingTax = _workContext.TaxDisplayType == TaxDisplayType.IncludingTax && !_taxSettings.ForceTaxExclusionFromOrderSubtotal; var subtotal = decimal.Zero; var list = new List <Installment>(); if (installmentInfo.Status == "success" && installmentInfo.InstallmentDetails.Count > 0) { foreach (var installmentDetail in installmentInfo.InstallmentDetails.FirstOrDefault().InstallmentPrices) { var installment = new Installment(); installment.DisplayName = _localizationService.GetResource("Plugins.Payments.Iyzico.Installment" + installmentDetail.InstallmentNumber); installment.InstallmentNumber = installmentDetail.InstallmentNumber ?? 0; decimal.TryParse(installmentDetail.Price.Replace(".", ","), out decimal price); installment.Price = _priceFormatter.FormatPrice(price, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage.Id, subTotalIncludingTax); decimal.TryParse(installmentDetail.TotalPrice.Replace(".", ","), out decimal totalPrice); installment.TotalPrice = _priceFormatter.FormatPrice(totalPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage.Id, subTotalIncludingTax); list.Add(installment); } } else { subtotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotal ?? 0, _workContext.WorkingCurrency); list.Add(new Installment() { DisplayName = _localizationService.GetResource("Plugins.Payments.Iyzico.Installment1"), InstallmentNumber = 1, Price = _priceFormatter.FormatPrice(subtotal, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage.Id, subTotalIncludingTax), TotalPrice = _priceFormatter.FormatPrice(subtotal, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage.Id, subTotalIncludingTax) }); } return(Json(list)); }
/// <summary> /// Generate a feed /// </summary> /// <param name="stream">Stream</param> /// <param name="store">Store</param> /// <returns>Generated feed</returns> public void GenerateFeed(Stream stream, Store store) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (store == null) { throw new ArgumentNullException(nameof(store)); } const string googleBaseNamespace = "http://base.google.com/ns/1.0"; var settings = new XmlWriterSettings { Encoding = Encoding.UTF8 }; var googleShoppingSettings = _settingService.LoadSetting <GoogleShoppingSettings>(store.Id); //language var languageId = 0; var languages = _languageService.GetAllLanguages(storeId: store.Id); //if we have only one language, let's use it if (languages.Count == 1) { //let's use the first one var language = languages.FirstOrDefault(); languageId = language != null ? language.Id : 0; } //otherwise, use the current one if (languageId == 0) { languageId = _workContext.WorkingLanguage.Id; } //we load all Google products here using one SQL request (performance optimization) var allGoogleProducts = _googleService.GetAll(); using (var writer = XmlWriter.Create(stream, settings)) { //Generate feed according to the following specs: http://www.google.com/support/merchants/bin/answer.py?answer=188494&expand=GB writer.WriteStartDocument(); writer.WriteStartElement("rss"); writer.WriteAttributeString("version", "2.0"); writer.WriteAttributeString("xmlns", "g", null, googleBaseNamespace); writer.WriteStartElement("channel"); writer.WriteElementString("title", "Google Base feed"); writer.WriteElementString("link", "http://base.google.com/base/"); writer.WriteElementString("description", "Information about products"); var products1 = _productService.SearchProducts(storeId: store.Id, visibleIndividuallyOnly: true); foreach (var product1 in products1) { var productsToProcess = new List <Product>(); switch (product1.ProductType) { case ProductType.SimpleProduct: { //simple product doesn't have child products productsToProcess.Add(product1); } break; case ProductType.GroupedProduct: { //grouped products could have several child products var associatedProducts = _productService.GetAssociatedProducts(product1.Id, store.Id); productsToProcess.AddRange(associatedProducts); } break; default: continue; } foreach (var product in productsToProcess) { writer.WriteStartElement("item"); #region Basic Product Information //id [id]- An identifier of the item writer.WriteElementString("g", "id", googleBaseNamespace, product.Id.ToString()); //title [title] - Title of the item writer.WriteStartElement("title"); var title = _localizationService.GetLocalized(product, x => x.Name, languageId); //title should be not longer than 70 characters if (title.Length > 70) { title = title.Substring(0, 70); } writer.WriteCData(title); writer.WriteEndElement(); // title //description [description] - Description of the item writer.WriteStartElement("description"); var description = _localizationService.GetLocalized(product, x => x.FullDescription, languageId); if (string.IsNullOrEmpty(description)) { description = _localizationService.GetLocalized(product, x => x.ShortDescription, languageId); } if (string.IsNullOrEmpty(description)) { description = _localizationService.GetLocalized(product, x => x.Name, languageId); //description is required } //resolving character encoding issues in your data feed description = StripInvalidChars(description, true); writer.WriteCData(description); writer.WriteEndElement(); // description //google product category [google_product_category] - Google's category of the item //the category of the product according to Google’s product taxonomy. http://www.google.com/support/merchants/bin/answer.py?answer=160081 var googleProductCategory = ""; //var googleProduct = _googleService.GetByProductId(product.Id); var googleProduct = allGoogleProducts.FirstOrDefault(x => x.ProductId == product.Id); if (googleProduct != null) { googleProductCategory = googleProduct.Taxonomy; } if (string.IsNullOrEmpty(googleProductCategory)) { googleProductCategory = googleShoppingSettings.DefaultGoogleCategory; } if (string.IsNullOrEmpty(googleProductCategory)) { throw new NopException("Default Google category is not set"); } writer.WriteStartElement("g", "google_product_category", googleBaseNamespace); writer.WriteCData(googleProductCategory); writer.WriteFullEndElement(); // g:google_product_category //product type [product_type] - Your category of the item var defaultProductCategory = _categoryService .GetProductCategoriesByProductId(product.Id, store.Id) .FirstOrDefault(); if (defaultProductCategory != null) { //TODO localize categories var category = _categoryService.GetFormattedBreadCrumb(defaultProductCategory.Category, separator: ">", languageId: languageId); if (!string.IsNullOrEmpty(category)) { writer.WriteStartElement("g", "product_type", googleBaseNamespace); writer.WriteCData(category); writer.WriteFullEndElement(); // g:product_type } } //link [link] - URL directly linking to your item's page on your website var productUrl = GetUrlHelper().RouteUrl("Product", new { SeName = _urlRecordService.GetSeName(product) }, GetHttpProtocol()); writer.WriteElementString("link", productUrl); //image link [image_link] - URL of an image of the item //additional images [additional_image_link] //up to 10 pictures const int maximumPictures = 10; var storeLocation = _webHelper.GetStoreLocation(_securitySettings.ForceSslForAllPages); var pictures = _pictureService.GetPicturesByProductId(product.Id, maximumPictures); for (var i = 0; i < pictures.Count; i++) { var picture = pictures[i]; var imageUrl = _pictureService.GetPictureUrl(picture, googleShoppingSettings.ProductPictureSize, storeLocation: storeLocation); if (i == 0) { //default image writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl); } else { //additional image writer.WriteElementString("g", "additional_image_link", googleBaseNamespace, imageUrl); } } if (!pictures.Any()) { //no picture? submit a default one var imageUrl = _pictureService.GetDefaultPictureUrl(googleShoppingSettings.ProductPictureSize, storeLocation: storeLocation); writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl); } //condition [condition] - Condition or state of the item writer.WriteElementString("g", "condition", googleBaseNamespace, "new"); writer.WriteElementString("g", "expiration_date", googleBaseNamespace, DateTime.Now.AddDays(googleShoppingSettings.ExpirationNumberOfDays).ToString("yyyy-MM-dd")); #endregion #region Availability & Price //availability [availability] - Availability status of the item var availability = "in stock"; //in stock by default if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && _productService.GetTotalStockQuantity(product) <= 0) { availability = "out of stock"; } //uncomment th code below in order to support "preorder" value for "availability" //if (product.AvailableForPreOrder && // (!product.PreOrderAvailabilityStartDateTimeUtc.HasValue || // product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow)) //{ // availability = "preorder"; //} writer.WriteElementString("g", "availability", googleBaseNamespace, availability); //price [price] - Price of the item var currency = GetUsedCurrency(); decimal finalPriceBase; if (googleShoppingSettings.PricesConsiderPromotions) { var minPossiblePrice = _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer); if (product.HasTierPrices) { //calculate price for the maximum quantity if we have tier prices, and choose minimal minPossiblePrice = Math.Min(minPossiblePrice, _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, quantity: int.MaxValue)); } finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out var _); } else { finalPriceBase = product.Price; } var price = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, currency); //round price now so it matches the product details page price = _priceCalculationService.RoundPrice(price); writer.WriteElementString("g", "price", googleBaseNamespace, price.ToString(new CultureInfo("en-US", false).NumberFormat) + " " + currency.CurrencyCode); #endregion #region Unique Product Identifiers /* Unique product identifiers such as UPC, EAN, JAN or ISBN allow us to show your listing on the appropriate product page. If you don't provide the required unique product identifiers, your store may not appear on product pages, and all your items may be removed from Product Search. * We require unique product identifiers for all products - except for custom made goods. For apparel, you must submit the 'brand' attribute. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute. In all cases, we recommend you submit all three attributes. * You need to submit at least two attributes of 'brand', 'gtin' and 'mpn', but we recommend that you submit all three if available. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute, but we recommend that you include 'brand' and 'mpn' if available. */ //GTIN [gtin] - GTIN var gtin = product.Gtin; if (!string.IsNullOrEmpty(gtin)) { writer.WriteStartElement("g", "gtin", googleBaseNamespace); writer.WriteCData(gtin); writer.WriteFullEndElement(); // g:gtin } //brand [brand] - Brand of the item var defaultManufacturer = _manufacturerService.GetProductManufacturersByProductId(product.Id).FirstOrDefault(); if (defaultManufacturer != null) { writer.WriteStartElement("g", "brand", googleBaseNamespace); writer.WriteCData(defaultManufacturer.Manufacturer.Name); writer.WriteFullEndElement(); // g:brand } //mpn [mpn] - Manufacturer Part Number (MPN) of the item var mpn = product.ManufacturerPartNumber; if (!string.IsNullOrEmpty(mpn)) { writer.WriteStartElement("g", "mpn", googleBaseNamespace); writer.WriteCData(mpn); writer.WriteFullEndElement(); // g:mpn } //identifier exists [identifier_exists] - Submit custom goods if (googleProduct != null && googleProduct.CustomGoods) { writer.WriteElementString("g", "identifier_exists", googleBaseNamespace, "FALSE"); } #endregion #region Apparel Products /* Apparel includes all products that fall under 'Apparel & Accessories' (including all sub-categories) * in Google’s product taxonomy. */ //gender [gender] - Gender of the item if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.Gender)) { writer.WriteStartElement("g", "gender", googleBaseNamespace); writer.WriteCData(googleProduct.Gender); writer.WriteFullEndElement(); // g:gender } //age group [age_group] - Target age group of the item if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.AgeGroup)) { writer.WriteStartElement("g", "age_group", googleBaseNamespace); writer.WriteCData(googleProduct.AgeGroup); writer.WriteFullEndElement(); // g:age_group } //color [color] - Color of the item if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.Color)) { writer.WriteStartElement("g", "color", googleBaseNamespace); writer.WriteCData(googleProduct.Color); writer.WriteFullEndElement(); // g:color } //size [size] - Size of the item if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.Size)) { writer.WriteStartElement("g", "size", googleBaseNamespace); writer.WriteCData(googleProduct.Size); writer.WriteFullEndElement(); // g:size } #endregion #region Tax & Shipping //tax [tax] //The tax attribute is an item-level override for merchant-level tax settings as defined in your Google Merchant Center account. This attribute is only accepted in the US, if your feed targets a country outside of the US, please do not use this attribute. //IMPORTANT NOTE: Set tax in your Google Merchant Center account settings //IMPORTANT NOTE: Set shipping in your Google Merchant Center account settings //shipping weight [shipping_weight] - Weight of the item for shipping //We accept only the following units of weight: lb, oz, g, kg. if (googleShoppingSettings.PassShippingInfoWeight) { string weightName; var shippingWeight = product.Weight; var weightSystemName = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword; switch (weightSystemName) { case "ounce": weightName = "oz"; break; case "lb": weightName = "lb"; break; case "grams": weightName = "g"; break; case "kg": weightName = "kg"; break; default: //unknown weight throw new Exception("Not supported weight. Google accepts the following units: lb, oz, g, kg."); } writer.WriteElementString("g", "shipping_weight", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", shippingWeight.ToString(new CultureInfo("en-US", false).NumberFormat), weightName)); } //shipping length [shipping_length] - Length of the item for shipping //shipping width [shipping_width] - Width of the item for shipping //shipping height [shipping_height] - Height of the item for shipping //We accept only the following units of length: in, cm if (googleShoppingSettings.PassShippingInfoDimensions) { string dimensionName; var length = product.Length; var width = product.Width; var height = product.Height; var dimensionSystemName = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).SystemKeyword; switch (dimensionSystemName) { case "inches": dimensionName = "in"; break; //TODO support other dimensions (convert to cm) default: //unknown dimension throw new Exception("Not supported dimension. Google accepts the following units: in, cm."); } writer.WriteElementString("g", "shipping_length", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", length.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName)); writer.WriteElementString("g", "shipping_width", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", width.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName)); writer.WriteElementString("g", "shipping_height", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", height.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName)); } #endregion writer.WriteEndElement(); // item } } writer.WriteEndElement(); // channel writer.WriteEndElement(); // rss writer.WriteEndDocument(); } }
/// <summary> /// Gets available shipping options /// </summary> /// <param name="cart">Shopping cart</param> /// <param name="shippingAddress">Shipping address</param> /// <param name="customer">Load records allowed only to a specified customer; pass null to ignore ACL permissions</param> /// <param name="allowedShippingRateComputationMethodSystemName">Filter by shipping rate computation method identifier; null to load shipping options of all shipping rate computation methods</param> /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param> /// <returns>Shipping options</returns> public virtual GetShippingOptionResponse GetShippingOptions(IList <ShoppingCartItem> cart, Address shippingAddress, Customer customer = null, string allowedShippingRateComputationMethodSystemName = "", int storeId = 0) { if (cart == null) { throw new ArgumentNullException(nameof(cart)); } var result = new GetShippingOptionResponse(); //create a package var shippingOptionRequests = CreateShippingOptionRequests(cart, shippingAddress, storeId, out var shippingFromMultipleLocations); result.ShippingFromMultipleLocations = shippingFromMultipleLocations; var shippingRateComputationMethods = _shippingPluginManager .LoadActivePlugins(customer, storeId, allowedShippingRateComputationMethodSystemName); if (!shippingRateComputationMethods.Any()) { return(result); } //request shipping options from each shipping rate computation methods foreach (var srcm in shippingRateComputationMethods) { //request shipping options (separately for each package-request) IList <ShippingOption> srcmShippingOptions = null; foreach (var shippingOptionRequest in shippingOptionRequests) { var getShippingOptionResponse = srcm.GetShippingOptions(shippingOptionRequest); if (getShippingOptionResponse.Success) { //success if (srcmShippingOptions == null) { //first shipping option request srcmShippingOptions = getShippingOptionResponse.ShippingOptions; } else { //get shipping options which already exist for prior requested packages for this scrm (i.e. common options) srcmShippingOptions = srcmShippingOptions .Where(existingso => getShippingOptionResponse.ShippingOptions.Any(newso => newso.Name == existingso.Name)) .ToList(); //and sum the rates foreach (var existingso in srcmShippingOptions) { existingso.Rate += getShippingOptionResponse .ShippingOptions .First(newso => newso.Name == existingso.Name) .Rate; } } } else { //errors foreach (var error in getShippingOptionResponse.Errors) { result.AddError(error); _logger.Warning($"Shipping ({srcm.PluginDescriptor.FriendlyName}). {error}"); } //clear the shipping options in this case srcmShippingOptions = new List <ShippingOption>(); break; } } //add this scrm's options to the result if (srcmShippingOptions == null) { continue; } foreach (var so in srcmShippingOptions) { //set system name if not set yet if (string.IsNullOrEmpty(so.ShippingRateComputationMethodSystemName)) { so.ShippingRateComputationMethodSystemName = srcm.PluginDescriptor.SystemName; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { so.Rate = _priceCalculationService.RoundPrice(so.Rate); } result.ShippingOptions.Add(so); } } if (_shippingSettings.ReturnValidOptionsIfThereAreAny) { //return valid options if there are any (no matter of the errors returned by other shipping rate computation methods). if (result.ShippingOptions.Any() && result.Errors.Any()) { result.Errors.Clear(); } } //no shipping options loaded if (!result.ShippingOptions.Any() && !result.Errors.Any()) { result.Errors.Add(_localizationService.GetResource("Checkout.ShippingOptionCouldNotBeLoaded")); } return(result); }
/// <summary> /// Gets shopping cart total /// </summary> /// <param name="cart">Cart</param> /// <param name="appliedGiftCards">Applied gift cards</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscounts">Applied discounts</param> /// <param name="redeemedRewardPoints">Reward points to redeem</param> /// <param name="redeemedRewardPointsAmount">Reward points amount in primary store currency to redeem</param> /// <param name="useRewardPoints">A value indicating reward points should be used; null to detect current choice of the customer</param> /// <param name="usePaymentMethodAdditionalFee">A value indicating whether we should use payment method additional fee when calculating order total</param> /// <returns>Shopping cart total;Null if shopping cart total couldn't be calculated now</returns> public override decimal?GetShoppingCartTotal(IList <ShoppingCartItem> cart, out decimal discountAmount, out List <DiscountForCaching> appliedDiscounts, out List <AppliedGiftCard> appliedGiftCards, out int redeemedRewardPoints, out decimal redeemedRewardPointsAmount, bool?useRewardPoints = null, bool usePaymentMethodAdditionalFee = true) { redeemedRewardPoints = 0; redeemedRewardPointsAmount = decimal.Zero; var customer = cart.FirstOrDefault(item => item.Customer != null)?.Customer; var paymentMethodSystemName = string.Empty; if (customer != null) { paymentMethodSystemName = _genericAttributeService.GetAttribute <string>(customer, NopCustomerDefaults.SelectedPaymentMethodAttribute, _storeContext.CurrentStore.Id); } //subtotal without tax GetShoppingCartSubTotal(cart, false, out _, out _, out _, out var subTotalWithDiscountBase); //subtotal with discount var subtotalBase = subTotalWithDiscountBase; //LoadAllShippingRateComputationMethods var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id); //shipping without tax var shoppingCartShipping = GetShoppingCartShippingTotal(cart, false, shippingRateComputationMethods); //todo override this method again to include the refundable price //refundable price without tax var refundablePrice = cart.Sum(x => x.Product.RefundablePrice * x.Quantity); //payment method additional fee without tax var paymentMethodAdditionalFeeWithoutTax = decimal.Zero; if (usePaymentMethodAdditionalFee && !string.IsNullOrEmpty(paymentMethodSystemName)) { var paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethodSystemName); paymentMethodAdditionalFeeWithoutTax = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, false, customer); } //tax var shoppingCartTax = GetTaxTotal(cart, shippingRateComputationMethods, usePaymentMethodAdditionalFee); //Avalara plugin changes //adjust tax total according to received value from the Avalara shoppingCartTax = _httpContextAccessor.HttpContext.Session .Get <TaxDetails>(AvalaraTaxDefaults.TaxDetailsSessionValue)?.TaxTotal ?? shoppingCartTax; //Avalara plugin changes //order total var resultTemp = decimal.Zero; //refundable price resultTemp += refundablePrice; resultTemp += subtotalBase; if (shoppingCartShipping.HasValue) { resultTemp += shoppingCartShipping.Value; } resultTemp += paymentMethodAdditionalFeeWithoutTax; resultTemp += shoppingCartTax; if (_shoppingCartSettings.RoundPricesDuringCalculation) { resultTemp = _priceCalculationService.RoundPrice(resultTemp); } //order total discount discountAmount = GetOrderTotalDiscount(customer, resultTemp, out appliedDiscounts); //sub totals with discount if (resultTemp < discountAmount) { discountAmount = resultTemp; } //reduce subtotal resultTemp -= discountAmount; if (resultTemp < decimal.Zero) { resultTemp = decimal.Zero; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { resultTemp = _priceCalculationService.RoundPrice(resultTemp); } //let's apply gift cards now (gift cards that can be used) appliedGiftCards = new List <AppliedGiftCard>(); AppliedGiftCards(cart, appliedGiftCards, customer, ref resultTemp); if (resultTemp < decimal.Zero) { resultTemp = decimal.Zero; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { resultTemp = _priceCalculationService.RoundPrice(resultTemp); } if (!shoppingCartShipping.HasValue) { //we have errors return(null); } var orderTotal = resultTemp; //reward points SetRewardPoints(ref redeemedRewardPoints, ref redeemedRewardPointsAmount, useRewardPoints, customer, orderTotal); orderTotal = orderTotal - redeemedRewardPointsAmount; if (_shoppingCartSettings.RoundPricesDuringCalculation) { orderTotal = _priceCalculationService.RoundPrice(orderTotal); } //todo append the refundable price return(orderTotal); }