public decimal GetShippingTotal(IList <ShoppingCartItem> cart) { //load all shipping rate computation methods var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer); return(_orderTotalCalculationService.GetShoppingCartShippingTotal(cart, true, shippingRateComputationMethods).GetValueOrDefault()); }
private async Task PrepareShippingInfo(OrderTotalsModel model, GetOrderTotals request) { model.RequiresShipping = request.Cart.RequiresShipping(); if (model.RequiresShipping) { decimal?shoppingCartShippingBase = (await _orderTotalCalculationService.GetShoppingCartShippingTotal(request.Cart)).shoppingCartShippingTotal; if (shoppingCartShippingBase.HasValue) { model.Shipping = _priceFormatter.FormatShippingPrice(shoppingCartShippingBase.Value, true); //selected shipping method var shippingOption = request.Customer.GetAttributeFromEntity <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, request.Store.Id); if (shippingOption != null) { model.SelectedShippingMethod = shippingOption.Name; } } } }
/// <summary> /// Get transaction amount details /// </summary> /// <param name="paymentRequest">Payment info required for an order processing</param> /// <param name="shoppingCart">Shopping cart</param> /// <param name="items">List of PayPal items</param> /// <returns>Amount details object</returns> protected DetailsAmountInfo GetAmountDetails(IList <ShoppingCartItem> shoppingCart, IList <Item> items, out decimal totalAdjust) { //get total discount amount var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(shoppingCart, out decimal discountAmount, out List <DiscountForCaching> _, out List <AppliedGiftCard> _, out int _, out decimal _); //get shipping total var shippingRateComputationMethods = _shippingPluginManager .LoadActivePlugins(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id); var shipping = _orderTotalCalculationService.GetShoppingCartShippingTotal(shoppingCart, shippingRateComputationMethods); var shippingTotal = shipping ?? 0; //get tax total var taxTotal = _orderTotalCalculationService.GetTaxTotal(shoppingCart, shippingRateComputationMethods); //get subtotal decimal subTotal; if (items != null && items.Any()) { //items passed to PayPal, so calculate subtotal based on them subTotal = items.Sum(item => !decimal.TryParse(item.price, out decimal tmpPrice) || !int.TryParse(item.quantity, out int tmpQuantity) ? 0 : tmpPrice * tmpQuantity); } else { subTotal = orderTotal.Value - shippingTotal - taxTotal; } //adjust order total to avoid PayPal payment error: "Transaction amount details (subtotal, tax, shipping) must add up to specified amount total" totalAdjust = Math.Round(shippingTotal, 2) + Math.Round(subTotal, 2) + Math.Round(taxTotal, 2); //create amount details return(new DetailsAmountInfo { shipping = shippingTotal.ToString("N", new CultureInfo("en-US")), subtotal = subTotal.ToString("N", new CultureInfo("en-US")), tax = taxTotal.ToString("N", new CultureInfo("en-US")) }); }
/// <summary> /// Get transaction line items /// </summary> /// <param name="customer">Customer</param> /// <param name="storeId">Store identifier</param> /// <returns>List of transaction items</returns> private List <BasketItem> GetItems(Core.Domain.Customers.Customer customer, int storeId) { var items = new List <BasketItem>(); //get current shopping cart var shoppingCart = _shoppingCartService.GetShoppingCart(customer, ShoppingCartType.ShoppingCart, storeId); //define function to create item BasketItem createItem(decimal price, string productId, string productName, string categoryName, BasketItemType itemType = BasketItemType.PHYSICAL) { return(new BasketItem { Id = productId, Name = productName, Category1 = categoryName, ItemType = itemType.ToString(), Price = Convert.ToDecimal(price, CultureInfo.InvariantCulture).ToString("f8", CultureInfo.InvariantCulture), }); } items.AddRange(shoppingCart.Select(sci => { var product = _productService.GetProductById(sci.ProductId); var shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(product, _shoppingCartService.GetUnitPrice(sci), out var _); var shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency); return(createItem(shoppingCartUnitPriceWithDiscount * sci.Quantity, product.Id.ToString(), product.Name, _categoryService.GetProductCategoriesByProductId(sci.ProductId).Aggregate(",", (all, pc) => { var res = _categoryService.GetCategoryById(pc.CategoryId).Name; res = all == "," ? res : all + ", " + res; return res; }))); })); //shipping without tax var shoppingCartShipping = _orderTotalCalculationService.GetShoppingCartShippingTotal(shoppingCart, false); if (shoppingCartShipping.HasValue && shoppingCartShipping.Value != 0) { items.Add(createItem(shoppingCartShipping ?? 0, Guid.NewGuid().ToString(), "Shipping", "Shipping", BasketItemType.VIRTUAL)); } return(items); }
/// <summary> /// Get transaction line items /// </summary> /// <param name="customer">Customer</param> /// <param name="storeId">Store identifier</param> /// <returns>List of transaction items</returns> private List <BasketItem> GetItems(Core.Domain.Customers.Customer customer, int storeId) { var items = new List <BasketItem>(); //get current shopping cart var shoppingCart = _shoppingCartService.GetShoppingCart(customer, ShoppingCartType.ShoppingCart, storeId); //define function to create item BasketItem createItem(decimal price, string productId, string productName, string categoryName, BasketItemType itemType = BasketItemType.PHYSICAL) { return(new BasketItem { Id = productId, Name = productName, Category1 = categoryName, ItemType = itemType.ToString(), Price = Convert.ToDecimal(price, CultureInfo.InvariantCulture).ToString("f8", CultureInfo.InvariantCulture), }); } items.AddRange(shoppingCart.Where(shoppingCartItem => shoppingCartItem.ProductId != 0).Select(shoppingCartItem => { var product = _productService.GetProductById(shoppingCartItem.ProductId); var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id).FirstOrDefault(); var category = _categoryService.GetCategoryById(productCategories.CategoryId); return(createItem(product.Price * shoppingCartItem.Quantity, product.Id.ToString(), product.Name, category.Name)); })); //LoadAllShippingRateComputationMethods var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id); //shipping without tax decimal taxRate = 0; var shoppingCartShipping = _orderTotalCalculationService.GetShoppingCartShippingTotal(shoppingCart, false, out taxRate /*shippingRateComputationMethods*/); if (shoppingCartShipping.HasValue) { items.Add(createItem(shoppingCartShipping ?? 0, Guid.NewGuid().ToString(), "Shipping", "Shipping", BasketItemType.VIRTUAL)); } return(items); }
public void CanGetShippingTotalWithFixedShippingRateExcludingTax() { var product = _productService.GetProductBySku("FR_451_RB"); product.AdditionalShippingCharge = 21.25M; product.IsFreeShipping = false; _productService.UpdateProduct(product); var shipping = _orderTotalCalcService.GetShoppingCartShippingTotal(ShoppingCart, false, out var taxRate, out var appliedDiscounts); product.AdditionalShippingCharge = 0M; product.IsFreeShipping = true; _productService.UpdateProduct(product); shipping.Should().NotBeNull(); //10 - default fixed shipping rate, 42.5 - additional shipping change shipping.Should().Be(52.5M); appliedDiscounts.Count.Should().Be(0); //10 - default fixed tax rate taxRate.Should().Be(10); }
public PayPalResponse CreatePayment( PayPalApiSettingsBase settings, PayPalSessionData session, List <OrganizedShoppingCartItem> cart, string providerSystemName, string returnUrl, string cancelUrl) { var store = _services.StoreContext.CurrentStore; var customer = _services.WorkContext.CurrentCustomer; var language = _services.WorkContext.WorkingLanguage; var currencyCode = store.PrimaryStoreCurrency.CurrencyCode; var dateOfBirth = customer.GetAttribute <DateTime?>(SystemCustomerAttributeNames.DateOfBirth); Discount orderAppliedDiscount; List <AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints = 0; decimal redeemedRewardPointsAmount; decimal orderDiscountInclTax; decimal totalOrderItems = decimal.Zero; var includingTax = (_services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id) == TaxDisplayType.IncludingTax); var shipping = (_orderTotalCalculationService.GetShoppingCartShippingTotal(cart) ?? decimal.Zero); var paymentFee = _paymentService.GetAdditionalHandlingFee(cart, providerSystemName); var total = (_orderTotalCalculationService.GetShoppingCartTotal(cart, out orderDiscountInclTax, out orderAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount) ?? decimal.Zero); var data = new Dictionary <string, object>(); var redirectUrls = new Dictionary <string, object>(); var payer = new Dictionary <string, object>(); var payerInfo = new Dictionary <string, object>(); var transaction = new Dictionary <string, object>(); var amount = new Dictionary <string, object>(); var amountDetails = new Dictionary <string, object>(); var items = new List <Dictionary <string, object> >(); var itemList = new Dictionary <string, object>(); // "PayPal PLUS only supports transaction type “Sale” (instant settlement)" if (providerSystemName == PayPalPlusProvider.SystemName) { data.Add("intent", "sale"); } else { data.Add("intent", settings.TransactMode == TransactMode.AuthorizeAndCapture ? "sale" : "authorize"); } if (settings.ExperienceProfileId.HasValue()) { data.Add("experience_profile_id", settings.ExperienceProfileId); } // redirect urls if (returnUrl.HasValue()) { redirectUrls.Add("return_url", returnUrl); } if (cancelUrl.HasValue()) { redirectUrls.Add("cancel_url", cancelUrl); } if (redirectUrls.Any()) { data.Add("redirect_urls", redirectUrls); } // payer, payer_info if (dateOfBirth.HasValue) { payerInfo.Add("birth_date", dateOfBirth.Value.ToString("yyyy-MM-dd")); } if (customer.BillingAddress != null) { payerInfo.Add("billing_address", CreateAddress(customer.BillingAddress, false)); } payer.Add("payment_method", "paypal"); payer.Add("payer_info", payerInfo); data.Add("payer", payer); // line items foreach (var item in cart) { decimal unitPriceTaxRate = decimal.Zero; decimal unitPrice = _priceCalculationService.GetUnitPrice(item, true); decimal productPrice = _taxService.GetProductPrice(item.Item.Product, unitPrice, includingTax, customer, out unitPriceTaxRate); var line = new Dictionary <string, object>(); line.Add("quantity", item.Item.Quantity); line.Add("name", item.Item.Product.GetLocalized(x => x.Name, language.Id, true, false).Truncate(127)); line.Add("price", productPrice.FormatInvariant()); line.Add("currency", currencyCode); line.Add("sku", item.Item.Product.Sku.Truncate(50)); items.Add(line); totalOrderItems += (productPrice * item.Item.Quantity); } var itemsPlusMisc = (totalOrderItems + shipping + paymentFee); if (total != itemsPlusMisc) { var line = new Dictionary <string, object>(); line.Add("quantity", "1"); line.Add("name", T("Plugins.SmartStore.PayPal.Other").Text.Truncate(127)); line.Add("price", (total - itemsPlusMisc).FormatInvariant()); line.Add("currency", currencyCode); items.Add(line); totalOrderItems += (total - itemsPlusMisc); } itemList.Add("items", items); if (customer.ShippingAddress != null) { itemList.Add("shipping_address", CreateAddress(customer.ShippingAddress, true)); } // transactions amountDetails.Add("shipping", shipping.FormatInvariant()); amountDetails.Add("subtotal", totalOrderItems.FormatInvariant()); if (!includingTax) { // "To avoid rounding errors we recommend not submitting tax amounts on line item basis. // Calculated tax amounts for the entire shopping basket may be submitted in the amount objects. // In this case the item amounts will be treated as amounts excluding tax. // In a B2C scenario, where taxes are included, no taxes should be submitted to PayPal." SortedDictionary <decimal, decimal> taxRates = null; var taxTotal = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates); amountDetails.Add("tax", taxTotal.FormatInvariant()); } if (paymentFee != decimal.Zero) { amountDetails.Add("handling_fee", paymentFee.FormatInvariant()); } amount.Add("total", total.FormatInvariant()); amount.Add("currency", currencyCode); amount.Add("details", amountDetails); transaction.Add("amount", amount); transaction.Add("item_list", itemList); transaction.Add("invoice_number", session.OrderGuid.ToString()); data.Add("transactions", new List <Dictionary <string, object> > { transaction }); var result = CallApi("POST", "/v1/payments/payment", session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } //Logger.InsertLog(LogLevel.Information, "PayPal PLUS", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + (result.Json != null ? result.Json.ToString() : "")); return(result); }
/// <summary> /// Prepare tax details by Avalara tax service /// </summary> /// <param name="cart">Shopping cart</param> private void PrepareTaxDetails(IList <ShoppingCartItem> cart) { //ensure that Avalara tax provider is active var taxProvider = _taxPluginManager .LoadPluginBySystemName(AvalaraTaxDefaults.SystemName, _workContext.CurrentCustomer, _storeContext.CurrentStore.Id) as AvalaraTaxProvider; if (!_taxPluginManager.IsPluginActive(taxProvider)) { return; } //create dummy order for the tax request var order = new Order { Customer = _workContext.CurrentCustomer }; //addresses order.BillingAddress = _workContext.CurrentCustomer.BillingAddress; order.ShippingAddress = _workContext.CurrentCustomer.ShippingAddress; if (_shippingSettings.AllowPickupInStore) { var pickupPoint = _genericAttributeService.GetAttribute <PickupPoint>(_workContext.CurrentCustomer, NopCustomerDefaults.SelectedPickupPointAttribute, _storeContext.CurrentStore.Id); if (pickupPoint != null) { var country = _countryService.GetCountryByTwoLetterIsoCode(pickupPoint.CountryCode); order.PickupAddress = new Address { Address1 = pickupPoint.Address, City = pickupPoint.City, Country = country, StateProvince = _stateProvinceService.GetStateProvinceByAbbreviation(pickupPoint.StateAbbreviation, country?.Id), ZipPostalCode = pickupPoint.ZipPostalCode, CreatedOnUtc = DateTime.UtcNow, }; } } //checkout attributes order.CheckoutAttributesXml = _genericAttributeService.GetAttribute <string>(_workContext.CurrentCustomer, NopCustomerDefaults.CheckoutAttributes, _storeContext.CurrentStore.Id); //shipping method var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id); order.OrderShippingExclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart, false, shippingRateComputationMethods) ?? 0; order.ShippingMethod = _genericAttributeService.GetAttribute <ShippingOption>(_workContext.CurrentCustomer, NopCustomerDefaults.SelectedShippingOptionAttribute, _storeContext.CurrentStore.Id)?.Name; //payment method var paymentMethod = _genericAttributeService.GetAttribute <string>(_workContext.CurrentCustomer, NopCustomerDefaults.SelectedPaymentMethodAttribute, _storeContext.CurrentStore.Id); var paymentFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethod); order.PaymentMethodAdditionalFeeExclTax = _taxService.GetPaymentMethodAdditionalFee(paymentFee, false, _workContext.CurrentCustomer); order.PaymentMethodSystemName = paymentMethod; //add discount amount _orderTotalCalculationService.GetShoppingCartSubTotal(cart, false, out var orderSubTotalDiscountExclTax, out _, out _, out _); order.OrderSubTotalDiscountExclTax = orderSubTotalDiscountExclTax; //create dummy order items foreach (var cartItem in cart) { var orderItem = new OrderItem { AttributesXml = cartItem.AttributesXml, Product = cartItem.Product, Quantity = cartItem.Quantity }; var itemSubtotal = _priceCalculationService.GetSubTotal(cartItem, true, out _, out _, out _); orderItem.PriceExclTax = _taxService.GetProductPrice(cartItem.Product, itemSubtotal, false, _workContext.CurrentCustomer, out _); order.OrderItems.Add(orderItem); } //get tax details var taxTransaction = taxProvider.CreateOrderTaxTransaction(order, false); if (taxTransaction == null) { return; } //and save it for the further usage var taxDetails = new TaxDetails { TaxTotal = taxTransaction.totalTax }; foreach (var item in taxTransaction.summary) { if (!item.rate.HasValue || !item.tax.HasValue) { continue; } var taxRate = item.rate.Value * 100; var taxValue = item.tax.Value; if (!taxDetails.TaxRates.ContainsKey(taxRate)) { taxDetails.TaxRates.Add(taxRate, taxValue); } else { taxDetails.TaxRates[taxRate] = taxDetails.TaxRates[taxRate] + taxValue; } } _httpContextAccessor.HttpContext.Session.Set(AvalaraTaxDefaults.TaxDetailsSessionValue, taxDetails); }
/// <summary> /// Handle shopping cart changed event /// </summary> /// <param name="cartItem">Shopping cart item</param> public void HandleShoppingCartChangedEvent(ShoppingCartItem cartItem) { //whether marketing automation is enabled if (!_sendInBlueSettings.UseMarketingAutomation) { return; } try { //create API client var client = CreateMarketingAutomationClient(); //first, try to identify current customer client.Identify(new Identify(cartItem.Customer.Email)); //get shopping cart GUID var shoppingCartGuid = _genericAttributeService.GetAttribute <Guid?>(cartItem.Customer, SendinBlueDefaults.ShoppingCartGuidAttribute); //create track event object var trackEvent = new TrackEvent(cartItem.Customer.Email, string.Empty); //get current customer's shopping cart var cart = cartItem.Customer.ShoppingCartItems .Where(item => item.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(_storeContext.CurrentStore.Id).ToList(); if (cart.Any()) { //get URL helper var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext); //get shopping cart amounts _orderTotalCalculationService.GetShoppingCartSubTotal(cart, _workContext.TaxDisplayType == TaxDisplayType.IncludingTax, out var cartDiscount, out _, out var cartSubtotal, out _); var cartTax = _orderTotalCalculationService.GetTaxTotal(cart, false); var cartShipping = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart); var cartTotal = _orderTotalCalculationService.GetShoppingCartTotal(cart, false, false); //get products data by shopping cart items var itemsData = cart.Where(item => item.Product != null).Select(item => { //try to get product attribute combination var combination = _productAttributeParser.FindProductAttributeCombination(item.Product, item.AttributesXml); //get default product picture var picture = _pictureService.GetProductPicture(item.Product, item.AttributesXml); //get product SEO slug name var seName = _urlRecordService.GetSeName(item.Product); //create product data return(new { id = item.Product.Id, name = item.Product.Name, variant_id = combination?.Id ?? item.Product.Id, variant_name = combination?.Sku ?? item.Product.Name, sku = combination?.Sku ?? item.Product.Sku, category = item.Product.ProductCategories.Aggregate(",", (all, category) => { var res = category.Category.Name; res = all == "," ? res : all + ", " + res; return res; }), url = urlHelper.RouteUrl("Product", new { SeName = seName }, _webHelper.CurrentRequestProtocol), image = _pictureService.GetPictureUrl(picture), quantity = item.Quantity, price = _priceCalculationService.GetSubTotal(item) }); }).ToArray(); //prepare cart data var cartData = new { affiliation = _storeContext.CurrentStore.Name, subtotal = cartSubtotal, shipping = cartShipping ?? decimal.Zero, total_before_tax = cartSubtotal + cartShipping ?? decimal.Zero, tax = cartTax, discount = cartDiscount, revenue = cartTotal ?? decimal.Zero, url = urlHelper.RouteUrl("ShoppingCart", null, _webHelper.CurrentRequestProtocol), currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)?.CurrencyCode, //gift_wrapping = string.Empty, //currently we can't get this value items = itemsData }; //if there is a single item in the cart, so the cart is just created if (cart.Count == 1) { shoppingCartGuid = Guid.NewGuid(); } else { //otherwise cart is updated shoppingCartGuid = shoppingCartGuid ?? Guid.NewGuid(); } trackEvent.EventName = SendinBlueDefaults.CartUpdatedEventName; trackEvent.EventData = new { id = $"cart:{shoppingCartGuid}", data = cartData }; } else { //there are no items in the cart, so the cart is deleted shoppingCartGuid = shoppingCartGuid ?? Guid.NewGuid(); trackEvent.EventName = SendinBlueDefaults.CartDeletedEventName; trackEvent.EventData = new { id = $"cart:{shoppingCartGuid}" }; } //track event client.TrackEvent(trackEvent); //update GUID for the current customer's shopping cart _genericAttributeService.SaveAttribute(cartItem.Customer, SendinBlueDefaults.ShoppingCartGuidAttribute, shoppingCartGuid); } catch (Exception exception) { //log full error _logger.Error($"SendinBlue Marketing Automation error: {exception.Message}.", exception, cartItem.Customer); } }
public void Can_get_shipping_total_with_fixed_shipping_rate_excluding_tax() { var product1 = new Product { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, AdditionalShippingCharge = 5.5M, IsShipEnabled = true }; _productService.InsertProduct(product1); var product2 = new Product { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 6.5M, IsShipEnabled = true }; _productService.InsertProduct(product2); var sci1 = new ShoppingCartItem { AttributesXml = string.Empty, Quantity = 3, ProductId = product1.Id }; var sci2 = new ShoppingCartItem { AttributesXml = string.Empty, Quantity = 4, ProductId = product2.Id }; //sci3 is not shippable var product3 = new Product { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 7.5M, IsShipEnabled = false }; _productService.InsertProduct(product3); var sci3 = new ShoppingCartItem { AttributesXml = string.Empty, Quantity = 5, ProductId = product3.Id }; var cart = new List <ShoppingCartItem> { sci1, sci2, sci3 }; var customer = _customerService.GetCustomerById(1); cart.ForEach(sci => sci.CustomerId = customer.Id); var shipping = _orderTotalCalcService.GetShoppingCartShippingTotal(cart, false, out var taxRate, out var appliedDiscounts); shipping.Should().NotBeNull(); //10 - default fixed shipping rate, 42.5 - additional shipping change shipping.Should().Be(52.5M); appliedDiscounts.Count.Should().Be(0); //10 - default fixed tax rate taxRate.Should().Be(10); }
/// <summary> /// Gets tax total /// </summary> /// <param name="taxTotalRequest">Tax total request</param> /// <returns>Tax total</returns> public TaxTotalResult GetTaxTotal(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) _orderTotalCalculationService .GetShoppingCartSubTotal(taxTotalRequest.ShoppingCart, false, out _, out _, out _, out _, out var orderSubTotalTaxRates); 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 = _orderTotalCalculationService .GetShoppingCartShippingTotal(taxTotalRequest.ShoppingCart, false, out _); var shippingInclTax = _orderTotalCalculationService .GetShoppingCartShippingTotal(taxTotalRequest.ShoppingCart, true, out var taxRate); 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 ? _genericAttributeService.GetAttribute <string>(taxTotalRequest.Customer, NopCustomerDefaults.SelectedPaymentMethodAttribute, taxTotalRequest.StoreId) : string.Empty; var paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(taxTotalRequest.ShoppingCart, paymentMethodSystemName); var paymentMethodAdditionalFeeExclTax = _taxService .GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, false, taxTotalRequest.Customer, out _); var paymentMethodAdditionalFeeInclTax = _taxService .GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, true, taxTotalRequest.Customer, out var taxRate); 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); }
public void Can_get_shipping_total_with_fixed_shipping_rate_excluding_tax() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, ProductVariant = new ProductVariant() { Id = 1, Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, AdditionalShippingCharge = 5.5M, IsShipEnabled = true, } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, ProductVariant = new ProductVariant() { Id = 2, Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 6.5M, IsShipEnabled = true, } }; //sci3 is not shippable var sci3 = new ShoppingCartItem() { AttributesXml = "", Quantity = 5, ProductVariant = new ProductVariant() { Id = 3, Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 7.5M, IsShipEnabled = false, } }; var cart = new List <ShoppingCartItem>() { sci1, sci2, sci3 }; var customer = new Customer(); cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); decimal taxRate = decimal.Zero; Discount appliedDiscount = null; decimal? shipping = null; shipping = _orderTotalCalcService.GetShoppingCartShippingTotal(cart, false, out taxRate, out appliedDiscount); shipping.ShouldNotBeNull(); //10 - default fixed shipping rate, 42.5 - additional shipping change shipping.ShouldEqual(52.5); appliedDiscount.ShouldBeNull(); //10 - default fixed tax rate taxRate.ShouldEqual(10); }
public decimal GetShippingTotal(IList <ShoppingCartItem> cart) { return(_orderTotalCalculationService.GetShoppingCartShippingTotal(cart, true).GetValueOrDefault()); }
/// <summary> /// Prepare details to place an order. It also sets some properties to "processPaymentRequest" /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Details</returns> protected override PlaceOrderContainer PreparePlaceOrderDetails(ProcessPaymentRequest processPaymentRequest) { var details = new PlaceOrderContainer { //customer Customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId) }; if (details.Customer == null) { throw new ArgumentException("Customer is not set"); } //affiliate var affiliate = _affiliateService.GetAffiliateById(details.Customer.AffiliateId); if (affiliate != null && affiliate.Active && !affiliate.Deleted) { details.AffiliateId = affiliate.Id; } //check whether customer is guest if (details.Customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed) { throw new QNetException("Anonymous checkout is not allowed"); } //customer currency var currencyTmp = _currencyService.GetCurrencyById( _genericAttributeService.GetAttribute <int>(details.Customer, QNetCustomerDefaults.CurrencyIdAttribute, processPaymentRequest.StoreId)); var customerCurrency = currencyTmp != null && currencyTmp.Published ? currencyTmp : _workContext.WorkingCurrency; var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); details.CustomerCurrencyCode = customerCurrency.CurrencyCode; details.CustomerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate; //customer language details.CustomerLanguage = _languageService.GetLanguageById( _genericAttributeService.GetAttribute <int>(details.Customer, QNetCustomerDefaults.LanguageIdAttribute, processPaymentRequest.StoreId)); if (details.CustomerLanguage == null || !details.CustomerLanguage.Published) { details.CustomerLanguage = _workContext.WorkingLanguage; } //billing address if (details.Customer.BillingAddress == null) { throw new QNetException("Billing address is not provided"); } if (!CommonHelper.IsValidEmail(details.Customer.BillingAddress.Email)) { throw new QNetException("Email is not valid"); } details.BillingAddress = (Address)details.Customer.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) { throw new QNetException($"Country '{details.BillingAddress.Country.Name}' is not allowed for billing"); } //checkout attributes details.CheckoutAttributesXml = _genericAttributeService.GetAttribute <string>(details.Customer, QNetCustomerDefaults.CheckoutAttributes, processPaymentRequest.StoreId); details.CheckoutAttributeDescription = _checkoutAttributeFormatter.FormatAttributes(details.CheckoutAttributesXml, details.Customer); //load shopping cart details.Cart = _shoppingCartService.GetShoppingCart(details.Customer, ShoppingCartType.ShoppingCart, processPaymentRequest.StoreId); if (!details.Cart.Any()) { throw new QNetException("Cart is empty"); } //validate the entire shopping cart var warnings = _shoppingCartService.GetShoppingCartWarnings(details.Cart, details.CheckoutAttributesXml, true); if (warnings.Any()) { throw new QNetException(warnings.Aggregate(string.Empty, (current, next) => $"{current}{next};")); } //validate individual cart items foreach (var sci in details.Cart) { var sciWarnings = _shoppingCartService.GetShoppingCartItemWarnings(details.Customer, sci.ShoppingCartType, sci.Product, processPaymentRequest.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false, sci.Id); if (sciWarnings.Any()) { throw new QNetException(sciWarnings.Aggregate(string.Empty, (current, next) => $"{current}{next};")); } } //min totals validation if (!ValidateMinOrderSubtotalAmount(details.Cart)) { var minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); throw new QNetException(string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false))); } if (!ValidateMinOrderTotalAmount(details.Cart)) { var minOrderTotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderTotalAmount, _workContext.WorkingCurrency); throw new QNetException(string.Format(_localizationService.GetResource("Checkout.MinOrderTotalAmount"), _priceFormatter.FormatPrice(minOrderTotalAmount, true, false))); } //tax display type if (_taxSettings.AllowCustomersToSelectTaxDisplayType) { details.CustomerTaxDisplayType = (TaxDisplayType)_genericAttributeService.GetAttribute <int>(details.Customer, QNetCustomerDefaults.TaxDisplayTypeIdAttribute, processPaymentRequest.StoreId); } else { details.CustomerTaxDisplayType = _taxSettings.TaxDisplayType; } //sub total (incl tax) _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, true, out var orderSubTotalDiscountAmount, out var orderSubTotalAppliedDiscounts, out var subTotalWithoutDiscountBase, out var _); details.OrderSubTotalInclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountInclTax = orderSubTotalDiscountAmount; //discount history foreach (var disc in orderSubTotalAppliedDiscounts) { if (!_discountService.ContainsDiscount(details.AppliedDiscounts, disc)) { details.AppliedDiscounts.Add(disc); } } //sub total (excl tax) _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, false, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out _); details.OrderSubTotalExclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountExclTax = orderSubTotalDiscountAmount; //shipping info if (_shoppingCartService.ShoppingCartRequiresShipping(details.Cart)) { var pickupPoint = _genericAttributeService.GetAttribute <PickupPoint>(details.Customer, QNetCustomerDefaults.SelectedPickupPointAttribute, processPaymentRequest.StoreId); if (_shippingSettings.AllowPickupInStore && pickupPoint != null) { var country = _countryService.GetCountryByTwoLetterIsoCode(pickupPoint.CountryCode); var state = _stateProvinceService.GetStateProvinceByAbbreviation(pickupPoint.StateAbbreviation, country?.Id); details.PickupInStore = true; details.PickupAddress = new Address { Address1 = pickupPoint.Address, City = pickupPoint.City, County = pickupPoint.County, Country = country, StateProvince = state, ZipPostalCode = pickupPoint.ZipPostalCode, CreatedOnUtc = DateTime.UtcNow }; } else { if (details.Customer.ShippingAddress == null) { throw new QNetException("Shipping address is not provided"); } if (!CommonHelper.IsValidEmail(details.Customer.ShippingAddress.Email)) { throw new QNetException("Email is not valid"); } //clone shipping address details.ShippingAddress = (Address)details.Customer.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) { throw new QNetException($"Country '{details.ShippingAddress.Country.Name}' is not allowed for shipping"); } } var shippingOption = _genericAttributeService.GetAttribute <ShippingOption>(details.Customer, QNetCustomerDefaults.SelectedShippingOptionAttribute, processPaymentRequest.StoreId); if (shippingOption != null) { details.ShippingMethodName = shippingOption.Name; details.ShippingRateComputationMethodSystemName = shippingOption.ShippingRateComputationMethodSystemName; } details.ShippingStatus = ShippingStatus.NotYetShipped; } else { details.ShippingStatus = ShippingStatus.ShippingNotRequired; } //LoadAllShippingRateComputationMethods var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id); //shipping total var orderShippingTotalInclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, true, shippingRateComputationMethods, out var _, out var shippingTotalDiscounts); var orderShippingTotalExclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, false, shippingRateComputationMethods); if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue) { throw new QNetException("Shipping total couldn't be calculated"); } details.OrderShippingTotalInclTax = orderShippingTotalInclTax.Value; details.OrderShippingTotalExclTax = orderShippingTotalExclTax.Value; foreach (var disc in shippingTotalDiscounts) { if (!_discountService.ContainsDiscount(details.AppliedDiscounts, disc)) { details.AppliedDiscounts.Add(disc); } } //payment total var paymentAdditionalFee = _paymentService.GetAdditionalHandlingFee(details.Cart, processPaymentRequest.PaymentMethodSystemName); details.PaymentAdditionalFeeInclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, true, details.Customer); details.PaymentAdditionalFeeExclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, false, details.Customer); //tax amount details.OrderTaxTotal = _orderTotalCalculationService.GetTaxTotal(details.Cart, shippingRateComputationMethods, out var taxRatesDictionary); //Avalara plugin changes //get previously saved tax details received from the Avalara tax service var taxDetails = _httpContextAccessor.HttpContext.Session.Get <TaxDetails>(AvalaraTaxDefaults.TaxDetailsSessionValue); if (taxDetails != null) { //adjust tax total according to received value from the Avalara if (taxDetails.TaxTotal.HasValue) { details.OrderTaxTotal = taxDetails.TaxTotal.Value; } if (taxDetails.TaxRates?.Any() ?? false) { taxRatesDictionary = new SortedDictionary <decimal, decimal>(taxDetails.TaxRates); } } //Avalara plugin changes //VAT number var customerVatStatus = (VatNumberStatus)_genericAttributeService.GetAttribute <int>(details.Customer, QNetCustomerDefaults.VatNumberStatusIdAttribute); if (_taxSettings.EuVatEnabled && customerVatStatus == VatNumberStatus.Valid) { details.VatNumber = _genericAttributeService.GetAttribute <string>(details.Customer, QNetCustomerDefaults.VatNumberAttribute); } //tax rates details.TaxRates = taxRatesDictionary.Aggregate(string.Empty, (current, next) => $"{current}{next.Key.ToString(CultureInfo.InvariantCulture)}:{next.Value.ToString(CultureInfo.InvariantCulture)}; "); //order total (and applied discounts, gift cards, reward points) var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(details.Cart, out var orderDiscountAmount, out var orderAppliedDiscounts, out var appliedGiftCards, out var redeemedRewardPoints, out var redeemedRewardPointsAmount); if (!orderTotal.HasValue) { throw new QNetException("Order total couldn't be calculated"); } details.OrderDiscountAmount = orderDiscountAmount; details.RedeemedRewardPoints = redeemedRewardPoints; details.RedeemedRewardPointsAmount = redeemedRewardPointsAmount; details.AppliedGiftCards = appliedGiftCards; details.OrderTotal = orderTotal.Value; //discount history foreach (var disc in orderAppliedDiscounts) { if (!_discountService.ContainsDiscount(details.AppliedDiscounts, disc)) { details.AppliedDiscounts.Add(disc); } } processPaymentRequest.OrderTotal = details.OrderTotal; //Avalara plugin changes //delete custom value _httpContextAccessor.HttpContext.Session.Set <TaxDetails>(AvalaraTaxDefaults.TaxDetailsSessionValue, null); //Avalara plugin changes //recurring or standard shopping cart? details.IsRecurringShoppingCart = _shoppingCartService.ShoppingCartIsRecurring(details.Cart); if (!details.IsRecurringShoppingCart) { return(details); } var recurringCyclesError = _shoppingCartService.GetRecurringCycleInfo(details.Cart, out var recurringCycleLength, out var recurringCyclePeriod, out var recurringTotalCycles); if (!string.IsNullOrEmpty(recurringCyclesError)) { throw new QNetException(recurringCyclesError); } processPaymentRequest.RecurringCycleLength = recurringCycleLength; processPaymentRequest.RecurringCyclePeriod = recurringCyclePeriod; processPaymentRequest.RecurringTotalCycles = recurringTotalCycles; return(details); }
/// <summary> /// Prepare details to place an order. It also sets some properties to "processPaymentRequest" /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Details</returns> protected override PlaceOrderContainter PreparePlaceOrderDetails(ProcessPaymentRequest processPaymentRequest) { var details = new PlaceOrderContainter(); //customer details.Customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); if (details.Customer == null) { throw new ArgumentException("Customer is not set"); } //affiliate var affiliate = _affiliateService.GetAffiliateById(details.Customer.AffiliateId); if (affiliate != null && affiliate.Active && !affiliate.Deleted) { details.AffiliateId = affiliate.Id; } //check whether customer is guest if (details.Customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed) { throw new NopException("Anonymous checkout is not allowed"); } //customer currency var currencyTmp = _currencyService.GetCurrencyById( details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.CurrencyId, processPaymentRequest.StoreId)); var customerCurrency = (currencyTmp != null && currencyTmp.Published) ? currencyTmp : _workContext.WorkingCurrency; var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); details.CustomerCurrencyCode = customerCurrency.CurrencyCode; //START PATCH var coinServiceSettings = EngineContext.Current.ContainerManager.Resolve <CoinServiceSettings>(); string[] Cryptos; if (coinServiceSettings.SupportedCoins != null) { Cryptos = coinServiceSettings.SupportedCoins.Split(','); } else { Cryptos = new string[0]; } if (Cryptos.Contains(details.CustomerCurrencyCode)) { details.CustomerCurrencyRate = CoinMarketCapHelper.GetCoinMarketCapRate(details.CustomerCurrencyCode) / primaryStoreCurrency.Rate; } else { details.CustomerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate; } //END PATCH //customer language details.CustomerLanguage = _languageService.GetLanguageById( details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.LanguageId, processPaymentRequest.StoreId)); if (details.CustomerLanguage == null || !details.CustomerLanguage.Published) { details.CustomerLanguage = _workContext.WorkingLanguage; } //billing address if (details.Customer.BillingAddress == null) { throw new NopException("Billing address is not provided"); } if (!CommonHelper.IsValidEmail(details.Customer.BillingAddress.Email)) { throw new NopException("Email is not valid"); } details.BillingAddress = (Address)details.Customer.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) { throw new NopException(string.Format("Country '{0}' is not allowed for billing", details.BillingAddress.Country.Name)); } //checkout attributes details.CheckoutAttributesXml = details.Customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, processPaymentRequest.StoreId); details.CheckoutAttributeDescription = _checkoutAttributeFormatter.FormatAttributes(details.CheckoutAttributesXml, details.Customer); //load shopping cart details.Cart = details.Customer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(processPaymentRequest.StoreId).ToList(); if (!details.Cart.Any()) { throw new NopException("Cart is empty"); } //validate the entire shopping cart var warnings = _shoppingCartService.GetShoppingCartWarnings(details.Cart, details.CheckoutAttributesXml, true); if (warnings.Any()) { throw new NopException(warnings.Aggregate(string.Empty, (current, next) => string.Format("{0}{1};", current, next))); } //validate individual cart items foreach (var sci in details.Cart) { var sciWarnings = _shoppingCartService.GetShoppingCartItemWarnings(details.Customer, sci.ShoppingCartType, sci.Product, processPaymentRequest.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false); if (sciWarnings.Any()) { throw new NopException(sciWarnings.Aggregate(string.Empty, (current, next) => string.Format("{0}{1};", current, next))); } } //min totals validation if (!ValidateMinOrderSubtotalAmount(details.Cart)) { var minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false))); } if (!ValidateMinOrderTotalAmount(details.Cart)) { var minOrderTotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderTotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderTotalAmount"), _priceFormatter.FormatPrice(minOrderTotalAmount, true, false))); } //tax display type if (_taxSettings.AllowCustomersToSelectTaxDisplayType) { details.CustomerTaxDisplayType = (TaxDisplayType)details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.TaxDisplayTypeId, processPaymentRequest.StoreId); } else { details.CustomerTaxDisplayType = _taxSettings.TaxDisplayType; } //sub total (incl tax) decimal orderSubTotalDiscountAmount; List <DiscountForCaching> orderSubTotalAppliedDiscounts; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, true, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); details.OrderSubTotalInclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountInclTax = orderSubTotalDiscountAmount; //discount history foreach (var disc in orderSubTotalAppliedDiscounts) { if (!details.AppliedDiscounts.ContainsDiscount(disc)) { details.AppliedDiscounts.Add(disc); } } //sub total (excl tax) _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, false, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); details.OrderSubTotalExclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountExclTax = orderSubTotalDiscountAmount; //shipping info if (details.Cart.RequiresShipping()) { var pickupPoint = details.Customer.GetAttribute <PickupPoint>(SystemCustomerAttributeNames.SelectedPickupPoint, processPaymentRequest.StoreId); if (_shippingSettings.AllowPickUpInStore && pickupPoint != null) { var country = _countryService.GetCountryByTwoLetterIsoCode(pickupPoint.CountryCode); var state = _stateProvinceService.GetStateProvinceByAbbreviation(pickupPoint.StateAbbreviation); details.PickUpInStore = true; details.PickupAddress = new Address { Address1 = pickupPoint.Address, City = pickupPoint.City, Country = country, StateProvince = state, ZipPostalCode = pickupPoint.ZipPostalCode, CreatedOnUtc = DateTime.UtcNow, }; } else { if (details.Customer.ShippingAddress == null) { throw new NopException("Shipping address is not provided"); } if (!CommonHelper.IsValidEmail(details.Customer.ShippingAddress.Email)) { throw new NopException("Email is not valid"); } //clone shipping address details.ShippingAddress = (Address)details.Customer.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) { throw new NopException(string.Format("Country '{0}' is not allowed for shipping", details.ShippingAddress.Country.Name)); } } var shippingOption = details.Customer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, processPaymentRequest.StoreId); if (shippingOption != null) { details.ShippingMethodName = shippingOption.Name; details.ShippingRateComputationMethodSystemName = shippingOption.ShippingRateComputationMethodSystemName; } details.ShippingStatus = ShippingStatus.NotYetShipped; } else { details.ShippingStatus = ShippingStatus.ShippingNotRequired; } //shipping total decimal tax; List <DiscountForCaching> shippingTotalDiscounts; var orderShippingTotalInclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, true, out tax, out shippingTotalDiscounts); var orderShippingTotalExclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, false); if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue) { throw new NopException("Shipping total couldn't be calculated"); } details.OrderShippingTotalInclTax = orderShippingTotalInclTax.Value; details.OrderShippingTotalExclTax = orderShippingTotalExclTax.Value; foreach (var disc in shippingTotalDiscounts) { if (!details.AppliedDiscounts.ContainsDiscount(disc)) { details.AppliedDiscounts.Add(disc); } } //payment total var paymentAdditionalFee = _paymentService.GetAdditionalHandlingFee(details.Cart, processPaymentRequest.PaymentMethodSystemName); details.PaymentAdditionalFeeInclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, true, details.Customer); details.PaymentAdditionalFeeExclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, false, details.Customer); //tax amount SortedDictionary <decimal, decimal> taxRatesDictionary; details.OrderTaxTotal = _orderTotalCalculationService.GetTaxTotal(details.Cart, out taxRatesDictionary); //VAT number var customerVatStatus = (VatNumberStatus)details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.VatNumberStatusId); if (_taxSettings.EuVatEnabled && customerVatStatus == VatNumberStatus.Valid) { details.VatNumber = details.Customer.GetAttribute <string>(SystemCustomerAttributeNames.VatNumber); } //tax rates details.TaxRates = taxRatesDictionary.Aggregate(string.Empty, (current, next) => string.Format("{0}{1}:{2}; ", current, next.Key.ToString(CultureInfo.InvariantCulture), next.Value.ToString(CultureInfo.InvariantCulture))); //order total (and applied discounts, gift cards, reward points) List <AppliedGiftCard> appliedGiftCards; List <DiscountForCaching> orderAppliedDiscounts; decimal orderDiscountAmount; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(details.Cart, out orderDiscountAmount, out orderAppliedDiscounts, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); if (!orderTotal.HasValue) { throw new NopException("Order total couldn't be calculated"); } details.OrderDiscountAmount = orderDiscountAmount; details.RedeemedRewardPoints = redeemedRewardPoints; details.RedeemedRewardPointsAmount = redeemedRewardPointsAmount; details.AppliedGiftCards = appliedGiftCards; details.OrderTotal = orderTotal.Value; //discount history foreach (var disc in orderAppliedDiscounts) { if (!details.AppliedDiscounts.ContainsDiscount(disc)) { details.AppliedDiscounts.Add(disc); } } processPaymentRequest.OrderTotal = details.OrderTotal; //recurring or standard shopping cart? details.IsRecurringShoppingCart = details.Cart.IsRecurring(); if (details.IsRecurringShoppingCart) { int recurringCycleLength; RecurringProductCyclePeriod recurringCyclePeriod; int recurringTotalCycles; var recurringCyclesError = details.Cart.GetRecurringCycleInfo(_localizationService, out recurringCycleLength, out recurringCyclePeriod, out recurringTotalCycles); if (!string.IsNullOrEmpty(recurringCyclesError)) { throw new NopException(recurringCyclesError); } processPaymentRequest.RecurringCycleLength = recurringCycleLength; processPaymentRequest.RecurringCyclePeriod = recurringCyclePeriod; processPaymentRequest.RecurringTotalCycles = recurringTotalCycles; } return(details); }
/// <summary> /// Process a payment /// </summary> /// <param name="processPaymentRequest">Payment info required for an order processing</param> /// <returns>Process payment result</returns> public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest) { var result = new ProcessPaymentResult(); decimal subTotal = 0; decimal?shipping = 0; decimal taxTotal = 0; SortedDictionary <decimal, decimal> taxRatesDictionary; var _products = new List <Models.ApiProduct>(); var NotifyUrl = _manualPaymentSettings.MerchantBaseUrl + "PaymentSendSpend/IPNHandler/?order={0}&status={1}"; var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); if (customer == null) { throw new Exception("Customer cannot be loaded"); } var shoppingCart = customer.ShoppingCartItems .Where(shoppingCartItem => shoppingCartItem.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(processPaymentRequest.StoreId).ToList(); shipping = _orderTotalCalculationService.GetShoppingCartShippingTotal(shoppingCart, false); taxTotal = _orderTotalCalculationService.GetTaxTotal(shoppingCart, out taxRatesDictionary); subTotal = shoppingCart.Sum(x => x.Product.Price * x.Quantity); shoppingCart.ForEach(x => { _products.Add(new Models.ApiProduct { merch_productId = x.ProductId.ToString(), merch_productName = x.Product.Name, merch_productQty = x.Quantity, merch_productUnitPrice = _currencyService.ConvertFromPrimaryStoreCurrency(x.Product.Price, _workContext.WorkingCurrency) }); }); var apiPayment = new Models.ApiPaymentRequest { merch_name = _manualPaymentSettings.MerchantName, apiId = _manualPaymentSettings.AppId, merch_uniqueId = _manualPaymentSettings.MerchantUniqueId, merch_baseURL = _manualPaymentSettings.MerchantBaseUrl, merch_orderId = processPaymentRequest.OrderGuid.ToString(), merch_orderDescription = processPaymentRequest.InitialOrderId > 0 ? string.Format("Parent Order Id: {0}", processPaymentRequest.InitialOrderId) : "", merch_subTotal = _currencyService.ConvertFromPrimaryStoreCurrency(subTotal, _workContext.WorkingCurrency), merch_totalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(processPaymentRequest.OrderTotal, _workContext.WorkingCurrency), merch_currency = processPaymentRequest.CustomValues["Currency"].ToString(), merch_orderDateTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")), merch_notifyUrl = NotifyUrl, merch_continueUrl = _manualPaymentSettings.ContinueUrl, merch_Products = _products, customer_firstName = customer.BillingAddress.FirstName, customer_lastName = customer.BillingAddress.LastName, customer_Email = customer.BillingAddress.Email, customer_fmm_UserNameOrMobileNo = processPaymentRequest.CustomValues["PhoneNumber"].ToString(), merch_order_alive = _manualPaymentSettings.MerchantOrderAlive, merch_shortOrderNo = string.Empty, merch_shippingCost = shipping.HasValue ? _currencyService.ConvertFromPrimaryStoreCurrency(shipping.Value, _workContext.WorkingCurrency) : 0, merch_otherCharges = _currencyService.ConvertFromPrimaryStoreCurrency(taxTotal, _workContext.WorkingCurrency), merch_preAuth = _manualPaymentSettings.PreAuth, countryCode = processPaymentRequest.CustomValues["Country"].ToString() }; using (var client = new HttpClient()) { var content = new StringContent(JsonConvert.SerializeObject(apiPayment)); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using (var res = client.PostAsync(String.Format("{0}api/v1/SecurePayment", _manualPaymentSettings.AppUrl), content)) { res.Wait(); if (res.Result.IsSuccessStatusCode) { var data = res.Result.Content.ReadAsStringAsync(); var ret = JsonConvert.DeserializeObject <Models.ApiResponse>(data.Result.ToString()); switch (ret.responseCode.ToUpper()) { case "APPROVED": result.NewPaymentStatus = Core.Domain.Payments.PaymentStatus.Pending; break; default: result.AddError(ret.responseText); break; } } else { result.AddError("Unable to process your request, Please try again later."); } } } return(result); }
private PaymentMessage GetPaymentoMessage(PayPalPlusBrasilPaymentSettings payPalPlusBrasilPaymentSettings, Customer customer) { var cart = _workContext.CurrentCustomer.ShoppingCartItems. Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(_storeContext.CurrentStore.Id) .ToList(); List <AppliedGiftCard> appliedGiftCards; List <Discount> orderAppliedDiscounts; decimal orderDiscountAmount; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(cart, out orderDiscountAmount, out orderAppliedDiscounts, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); decimal tax; List <Discount> shippingTotalDiscounts; var orderShippingTotalInclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart, true, out tax, out shippingTotalDiscounts); decimal orderSubTotalDiscountAmount; List <Discount> orderSubTotalAppliedDiscounts; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; _orderTotalCalculationService.GetShoppingCartSubTotal(cart, true, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); var paymentMessage = new PaymentMessage(); paymentMessage.Intent = "sale"; paymentMessage.Payer.PaymentMethod = "paypal"; paymentMessage.ExperienceProfileId = payPalPlusBrasilPaymentSettings.IdProfileExperience; var transactionList = new List <Models.Message.Request.Transaction>(); var itemTransaction = new Models.Message.Request.Transaction(); itemTransaction.Amount.Currency = "BRL"; itemTransaction.Amount.Total = orderTotal.Value.ToString("N", new CultureInfo("en-US")); itemTransaction.Amount.Details.Shipping = orderShippingTotalInclTax.Value.ToString("N", new CultureInfo("en-US")); itemTransaction.Amount.Details.Subtotal = subTotalWithoutDiscountBase.ToString("N", new CultureInfo("en-US")); itemTransaction.Amount.Details.Discount = (orderDiscountAmount + orderSubTotalDiscountAmount).ToString("N", new CultureInfo("en-US")); itemTransaction.Description = "This is the payment transaction description"; itemTransaction.PaymentOptions.AllowedPaymentMethod = "IMMEDIATE_PAY"; itemTransaction.InvoiceNumber = string.Empty; var number = string.Empty; var complement = string.Empty; new AddressHelper(_addressAttributeParser, _workContext).GetCustomNumberAndComplement(customer.ShippingAddress.CustomAttributes, out number, out complement); itemTransaction.ItemList.ShippingAddress.RecipientName = AddressHelper.GetFullName(customer.ShippingAddress); itemTransaction.ItemList.ShippingAddress.Line1 = customer.ShippingAddress.Address1; itemTransaction.ItemList.ShippingAddress.Line2 = complement; itemTransaction.ItemList.ShippingAddress.City = customer.ShippingAddress.City; itemTransaction.ItemList.ShippingAddress.CountryCode = customer.ShippingAddress.Country.TwoLetterIsoCode; itemTransaction.ItemList.ShippingAddress.PostalCode = customer.ShippingAddress.ZipPostalCode; itemTransaction.ItemList.ShippingAddress.State = customer.ShippingAddress.StateProvince.Name; itemTransaction.ItemList.ShippingAddress.Phone = AddressHelper.FormatarCelular(customer.ShippingAddress.PhoneNumber); var itemList = new List <Models.Message.Request.Item>(); foreach (var itemCart in cart) { var item = new Models.Message.Request.Item(); item.Name = itemCart.Product.Name; item.Description = itemCart.Product.ShortDescription; item.Quantity = itemCart.Quantity; List <Discount> scDiscounts; decimal discountAmount; var scUnitPrice = _priceCalculationService.GetUnitPrice(itemCart, true, out discountAmount, out scDiscounts); item.Price = decimal.Round(scUnitPrice, 2).ToString("N2", new CultureInfo("en-US")); item.Sku = itemCart.Product.Sku; item.Currency = "BRL"; itemList.Add(item); } itemTransaction.ItemList.Items = itemList.ToArray(); transactionList.Add(itemTransaction); paymentMessage.Transactions = transactionList.ToArray(); string returnUrl = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalPlusBrasil/IPNHandler"; string cancelReturnUrl = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalPlusBrasil/IPNHandler"; paymentMessage.RedirectUrls.ReturnUrl = new Uri(returnUrl); paymentMessage.RedirectUrls.CancelUrl = new Uri(cancelReturnUrl); return(paymentMessage); }
/// <summary> /// PrepareOrderTotalsModel: /// </summary> /// <param name="cart"></param> /// <param name="isEditable"></param> /// <returns></returns> public virtual decimal PrepareOrderTotalsModel(IList <ShoppingCartItem> cart, bool isEditable) { var model = new OrderTotalsModel(); model.IsEditable = isEditable; if (cart.Count > 0) { //subtotal decimal orderSubTotalDiscountAmountBase; Discount orderSubTotalAppliedDiscount; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; var subTotalIncludingTax = _workContext.TaxDisplayType == TaxDisplayType.IncludingTax && !_taxSettings.ForceTaxExclusionFromOrderSubtotal; _orderTotalCalculationService.GetShoppingCartSubTotal(cart, subTotalIncludingTax, out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); decimal subtotalBase = subTotalWithoutDiscountBase; decimal subtotal = _currencyService.ConvertFromPrimaryStoreCurrency(subtotalBase, _workContext.WorkingCurrency); model.SubTotal = _priceFormatter.FormatPrice(subtotal, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); if (orderSubTotalDiscountAmountBase > decimal.Zero) { decimal orderSubTotalDiscountAmount = _currencyService.ConvertFromPrimaryStoreCurrency(orderSubTotalDiscountAmountBase, _workContext.WorkingCurrency); model.SubTotalDiscount = _priceFormatter.FormatPrice(-orderSubTotalDiscountAmount, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); model.AllowRemovingSubTotalDiscount = orderSubTotalAppliedDiscount != null && orderSubTotalAppliedDiscount.RequiresCouponCode && !String.IsNullOrEmpty(orderSubTotalAppliedDiscount.CouponCode) && model.IsEditable; } //shipping info model.RequiresShipping = cart.RequiresShipping(); if (model.RequiresShipping) { decimal?shoppingCartShippingBase = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart); if (shoppingCartShippingBase.HasValue) { decimal shoppingCartShipping = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, _workContext.WorkingCurrency); model.Shipping = _priceFormatter.FormatShippingPrice(shoppingCartShipping, true); //selected shipping method var shippingOption = _workContext.CurrentCustomer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (shippingOption != null) { model.SelectedShippingMethod = shippingOption.Name; } } } //payment method fee var paymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute <string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id); decimal paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethodSystemName); decimal paymentMethodAdditionalFeeWithTaxBase = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, _workContext.CurrentCustomer); if (paymentMethodAdditionalFeeWithTaxBase > decimal.Zero) { decimal paymentMethodAdditionalFeeWithTax = _currencyService.ConvertFromPrimaryStoreCurrency(paymentMethodAdditionalFeeWithTaxBase, _workContext.WorkingCurrency); model.PaymentMethodAdditionalFee = _priceFormatter.FormatPaymentMethodAdditionalFee(paymentMethodAdditionalFeeWithTax, true); } //tax bool displayTax = true; bool displayTaxRates = true; if (_taxSettings.HideTaxInOrderSummary && _workContext.TaxDisplayType == TaxDisplayType.IncludingTax) { displayTax = false; displayTaxRates = false; } else { SortedDictionary <decimal, decimal> taxRates; decimal shoppingCartTaxBase = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates); decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, _workContext.WorkingCurrency); if (shoppingCartTaxBase == 0 && _taxSettings.HideZeroTax) { displayTax = false; displayTaxRates = false; } else { displayTaxRates = _taxSettings.DisplayTaxRates && taxRates.Count > 0; displayTax = !displayTaxRates; model.Tax = _priceFormatter.FormatPrice(shoppingCartTax, true, false); foreach (var tr in taxRates) { model.TaxRates.Add(new OrderTotalsModel.TaxRate { Rate = _priceFormatter.FormatTaxRate(tr.Key), Value = _priceFormatter.FormatPrice(_currencyService.ConvertFromPrimaryStoreCurrency(tr.Value, _workContext.WorkingCurrency), true, false), }); } } } model.DisplayTaxRates = displayTaxRates; model.DisplayTax = displayTax; //total decimal orderTotalDiscountAmountBase; Discount orderTotalAppliedDiscount; List <AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; decimal?shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, out orderTotalDiscountAmountBase, out orderTotalAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); return(_currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotalBase.Value, _workContext.WorkingCurrency)); } return(decimal.Zero); }