public decimal GetTax(IList <ShoppingCartItem> cart) { //load all shipping rate computation methods var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer); return(_orderTotalCalculationService.GetTaxTotal(cart, shippingRateComputationMethods)); }
/// <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")) }); }
private async Task PrepareTax(OrderTotalsModel model, GetOrderTotals request) { bool displayTax = true; bool displayTaxRates = true; if (_taxSettings.HideTaxInOrderSummary && request.TaxDisplayType == TaxDisplayType.IncludingTax) { displayTax = false; displayTaxRates = false; } else { var taxtotal = await _orderTotalCalculationService.GetTaxTotal(request.Cart); SortedDictionary <decimal, decimal> taxRates = taxtotal.taxRates; decimal shoppingCartTaxBase = taxtotal.taxtotal; decimal shoppingCartTax = await _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, request.Currency); if (shoppingCartTaxBase == 0 && _taxSettings.HideZeroTax) { displayTax = false; displayTaxRates = false; } else { displayTaxRates = _taxSettings.DisplayTaxRates && taxRates.Any(); 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(await _currencyService.ConvertFromPrimaryStoreCurrency(tr.Value, request.Currency), true, false), }); } } } model.DisplayTaxRates = displayTaxRates; model.DisplayTax = displayTax; }
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> /// 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); } }
/// <summary> /// Prepare the order totals model /// </summary> /// <param name="cart">List of the shopping cart item</param> /// <param name="isEditable">Whether model is editable</param> /// <returns>Order totals model</returns> public override OrderTotalsModel PrepareOrderTotalsModel(IList <ShoppingCartItem> cart, bool isEditable) { var model = new OrderTotalsModel { IsEditable = isEditable }; if (cart.Any()) { //Avalara plugin changes PrepareTaxDetails(cart); //Avalara plugin changes //subtotal var subTotalIncludingTax = _workContext.TaxDisplayType == TaxDisplayType.IncludingTax && !_taxSettings.ForceTaxExclusionFromOrderSubtotal; _orderTotalCalculationService.GetShoppingCartSubTotal(cart, subTotalIncludingTax, out var orderSubTotalDiscountAmountBase, out var _, out var subTotalWithoutDiscountBase, out var _); var subtotalBase = subTotalWithoutDiscountBase; var subtotal = _currencyService.ConvertFromPrimaryStoreCurrency(subtotalBase, _workContext.WorkingCurrency); model.SubTotal = _priceFormatter.FormatPrice(subtotal, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); if (orderSubTotalDiscountAmountBase > decimal.Zero) { var orderSubTotalDiscountAmount = _currencyService.ConvertFromPrimaryStoreCurrency(orderSubTotalDiscountAmountBase, _workContext.WorkingCurrency); model.SubTotalDiscount = _priceFormatter.FormatPrice(-orderSubTotalDiscountAmount, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); } //LoadAllShippingRateComputationMethods var shippingRateComputationMethods = _shippingPluginManager.LoadActivePlugins(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id); //shipping info model.RequiresShipping = _shoppingCartService.ShoppingCartRequiresShipping(cart); if (model.RequiresShipping) { var shoppingCartShippingBase = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart, shippingRateComputationMethods); if (shoppingCartShippingBase.HasValue) { var shoppingCartShipping = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, _workContext.WorkingCurrency); model.Shipping = _priceFormatter.FormatShippingPrice(shoppingCartShipping, true); //selected shipping method var shippingOption = _genericAttributeService.GetAttribute <ShippingOption>(_workContext.CurrentCustomer, NopCustomerDefaults.SelectedShippingOptionAttribute, _storeContext.CurrentStore.Id); if (shippingOption != null) { model.SelectedShippingMethod = shippingOption.Name; } } } else { model.HideShippingTotal = _shippingSettings.HideShippingTotal; } //payment method fee var paymentMethodSystemName = _genericAttributeService.GetAttribute <string>(_workContext.CurrentCustomer, NopCustomerDefaults.SelectedPaymentMethodAttribute, _storeContext.CurrentStore.Id); var paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethodSystemName); var paymentMethodAdditionalFeeWithTaxBase = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, _workContext.CurrentCustomer); if (paymentMethodAdditionalFeeWithTaxBase > decimal.Zero) { var paymentMethodAdditionalFeeWithTax = _currencyService.ConvertFromPrimaryStoreCurrency(paymentMethodAdditionalFeeWithTaxBase, _workContext.WorkingCurrency); model.PaymentMethodAdditionalFee = _priceFormatter.FormatPaymentMethodAdditionalFee(paymentMethodAdditionalFeeWithTax, true); } //tax var displayTax = true; var displayTaxRates = true; if (_taxSettings.HideTaxInOrderSummary && _workContext.TaxDisplayType == TaxDisplayType.IncludingTax) { displayTax = false; displayTaxRates = false; } else { var shoppingCartTaxBase = _orderTotalCalculationService.GetTaxTotal(cart, shippingRateComputationMethods, out var taxRates); //Avalara plugin changes //get tax details from the Avalara tax service, it may slightly differ from the original calculated tax 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) { shoppingCartTaxBase = taxDetails.TaxTotal.Value; } if (taxDetails.TaxRates?.Any() ?? false) { taxRates = new SortedDictionary <decimal, decimal>(taxDetails.TaxRates); } } //Avalara plugin changes var shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, _workContext.WorkingCurrency); if (shoppingCartTaxBase == 0 && _taxSettings.HideZeroTax) { displayTax = false; displayTaxRates = false; } else { displayTaxRates = _taxSettings.DisplayTaxRates && taxRates.Any(); 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 var shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, out var orderTotalDiscountAmountBase, out var _, out var appliedGiftCards, out var redeemedRewardPoints, out var redeemedRewardPointsAmount); if (shoppingCartTotalBase.HasValue) { var shoppingCartTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotalBase.Value, _workContext.WorkingCurrency); model.OrderTotal = _priceFormatter.FormatPrice(shoppingCartTotal, true, false); } //discount if (orderTotalDiscountAmountBase > decimal.Zero) { var orderTotalDiscountAmount = _currencyService.ConvertFromPrimaryStoreCurrency(orderTotalDiscountAmountBase, _workContext.WorkingCurrency); model.OrderTotalDiscount = _priceFormatter.FormatPrice(-orderTotalDiscountAmount, true, false); } //gift cards if (appliedGiftCards != null && appliedGiftCards.Any()) { foreach (var appliedGiftCard in appliedGiftCards) { var gcModel = new OrderTotalsModel.GiftCard { Id = appliedGiftCard.GiftCard.Id, CouponCode = appliedGiftCard.GiftCard.GiftCardCouponCode, }; var amountCanBeUsed = _currencyService.ConvertFromPrimaryStoreCurrency(appliedGiftCard.AmountCanBeUsed, _workContext.WorkingCurrency); gcModel.Amount = _priceFormatter.FormatPrice(-amountCanBeUsed, true, false); var remainingAmountBase = _giftCardService.GetGiftCardRemainingAmount(appliedGiftCard.GiftCard) - appliedGiftCard.AmountCanBeUsed; var remainingAmount = _currencyService.ConvertFromPrimaryStoreCurrency(remainingAmountBase, _workContext.WorkingCurrency); gcModel.Remaining = _priceFormatter.FormatPrice(remainingAmount, true, false); model.GiftCards.Add(gcModel); } } //reward points to be spent (redeemed) if (redeemedRewardPointsAmount > decimal.Zero) { var redeemedRewardPointsAmountInCustomerCurrency = _currencyService.ConvertFromPrimaryStoreCurrency(redeemedRewardPointsAmount, _workContext.WorkingCurrency); model.RedeemedRewardPoints = redeemedRewardPoints; model.RedeemedRewardPointsAmount = _priceFormatter.FormatPrice(-redeemedRewardPointsAmountInCustomerCurrency, true, false); } //reward points to be earned if (_rewardPointsSettings.Enabled && _rewardPointsSettings.DisplayHowMuchWillBeEarned && shoppingCartTotalBase.HasValue) { //get shipping total var shippingBaseInclTax = !model.RequiresShipping ? 0 : _orderTotalCalculationService.GetShoppingCartShippingTotal(cart, true, shippingRateComputationMethods) ?? 0; //get total for reward points var totalForRewardPoints = _orderTotalCalculationService .CalculateApplicableOrderTotalForRewardPoints(shippingBaseInclTax, shoppingCartTotalBase.Value); if (totalForRewardPoints > decimal.Zero) { model.WillEarnRewardPoints = _orderTotalCalculationService.CalculateRewardPoints(_workContext.CurrentCustomer, totalForRewardPoints); } } } return(model); }
public decimal GetTax(IList <ShoppingCartItem> cart) { return(_orderTotalCalculationService.GetTaxTotal(cart)); }
/// <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> /// 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); }
/// <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); }
/// <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(); var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); try { PrepareGBS(); //var creditCard = new creditCardType //{ // cardNumber = processPaymentRequest.CreditCardNumber, // expirationDate = // processPaymentRequest.CreditCardExpireMonth.ToString("D2") + processPaymentRequest.CreditCardExpireYear, // cardCode = processPaymentRequest.CreditCardCvv2 //}; ////standard api call to retrieve response //var paymentType = new paymentType { Item = creditCard }; //transactionTypeEnum transactionType; //switch (_authorizeNetPaymentSettings.TransactMode) //{ // case TransactMode.Authorize: // transactionType = transactionTypeEnum.authOnlyTransaction; // break; // case TransactMode.AuthorizeAndCapture: // transactionType = transactionTypeEnum.authCaptureTransaction; // break; // default: // throw new NopException("Not supported transaction mode"); //} //var billTo = new customerAddressType //{ // firstName = customer.BillingAddress.FirstName, // lastName = customer.BillingAddress.LastName, // email = customer.BillingAddress.Email, // address = customer.BillingAddress.Address1, // city = customer.BillingAddress.City, // zip = customer.BillingAddress.ZipPostalCode //}; //if (!string.IsNullOrEmpty(customer.BillingAddress.Company)) // billTo.company = customer.BillingAddress.Company; //if (customer.BillingAddress.StateProvince != null) // billTo.state = customer.BillingAddress.StateProvince.Abbreviation; //if (customer.BillingAddress.Country != null) // billTo.country = customer.BillingAddress.Country.TwoLetterIsoCode; //var transactionRequest = new transactionRequestType //{ // transactionType = transactionType.ToString(), // amount = Math.Round(processPaymentRequest.OrderTotal, 2), // payment = paymentType, // currencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode, // billTo = billTo, // customerIP = _webHelper.GetCurrentIpAddress(), // order = new orderType // { // //x_invoice_num is 20 chars maximum. hece we also pass x_description // invoiceNumber = processPaymentRequest.OrderGuid.ToString().Substring(0, 20), // description = string.Format("Full order #{0}", processPaymentRequest.OrderGuid) // } //}; //var request = new createTransactionRequest { transactionRequest = transactionRequest }; //// instantiate the contoller that will call the service //var controller = new createTransactionController(request); //controller.Execute(); //// get the response from the service (errors contained if any) //NOP WEB SERVICE CALL START HERE -------------------------------------------------------------------------------------------------------------------- //create nop payment object from user data PaymentTransactionModel payment = new PaymentTransactionModel(); payment.firstName = customer.BillingAddress.FirstName; payment.lastName = customer.BillingAddress.LastName; payment.streetAddress = customer.BillingAddress.Address1; payment.billingCity = customer.BillingAddress.City; payment.postalCode = customer.BillingAddress.ZipPostalCode; payment.countryCode = customer.BillingAddress.Country.Name; if (payment.countryCode == "United States") { payment.countryCode = "US"; } else { payment.countryCode = "US"; } payment.cardExpireMonth = processPaymentRequest.CreditCardExpireMonth.ToString().Length == 1 ? "0" + processPaymentRequest.CreditCardExpireMonth.ToString() : processPaymentRequest.CreditCardExpireMonth.ToString(); //prepend 0 for single digit months payment.cardExpireYear = processPaymentRequest.CreditCardExpireYear.ToString(); payment.cardNum = processPaymentRequest.CreditCardNumber; payment.orderAmount = processPaymentRequest.OrderTotal.ToString(); payment.pcDestZip = (customer.ShippingAddress != null && customer.ShippingAddress.ZipPostalCode != null) ? customer.ShippingAddress.ZipPostalCode : String.Empty; Object value = null; NopResourceDisplayNameAttribute orderNumberKeyGBS = new NopResourceDisplayNameAttribute(("Account.CustomerOrders.OrderNumber")); if (processPaymentRequest.CustomValues.TryGetValue(orderNumberKeyGBS.DisplayName, out value)) { payment.orderID = processPaymentRequest.CustomValues[orderNumberKeyGBS.DisplayName].ToString(); payment.pcOrderID = processPaymentRequest.CustomValues[orderNumberKeyGBS.DisplayName].ToString(); } else { payment.orderID = "NA"; payment.pcOrderID = "NA"; } payment.state = customer.BillingAddress.StateProvince.Abbreviation; payment.tax = _orderTotalCalculationService.GetTaxTotal((IList <ShoppingCartItem>)customer.ShoppingCartItems, false).ToString(); payment.sandBox = _gbsPaymentSettings.UseSandbox; if (Convert.ToBoolean(processPaymentRequest.CustomValues["SavedProfile"]) == true) { payment.createProfile = false; payment.useProfile = true; payment.profileID = processPaymentRequest.CustomValues["ProfileID"].ToString(); } else { payment.createProfile = true; payment.useProfile = false; payment.profileID = ""; } //will need to be able to switch between sand and production version string address = _gbsPaymentSettings.GBSPaymentWebServiceAddress; GBSPaymentServiceClient gateway = new GBSPaymentServiceClient(); //calls to GBSPaymentGateway function var response = gateway.AuthorizeAndCapture(payment, address, _gbsPaymentSettings.LoginId, _gbsPaymentSettings.Password); //use returned GBSTransactionResponse to tell nop what occured in submit switch (response.responseCode) { case GBSTransactionResponse.ResponseCodeType.Approved: result.NewPaymentStatus = PaymentStatus.Authorized; break; case GBSTransactionResponse.ResponseCodeType.Declined: case GBSTransactionResponse.ResponseCodeType.Error: result.NewPaymentStatus = PaymentStatus.Voided; break; default: result.NewPaymentStatus = PaymentStatus.Voided; break; } //validate if (GetErrors(response, result.Errors)) { return(result); } if (_gbsPaymentSettings.TransactMode == TransactMode.Authorize) { result.AuthorizationTransactionCode = string.Format("{0},{1}", response.transactId, response.authCode); } //if (_authorizeNetPaymentSettings.TransactMode == TransactMode.AuthorizeAndCapture) // result.CaptureTransactionId = string.Format("{0},{1}", response.transactionResponse.transId, response.transactionResponse.authCode); result.AuthorizationTransactionResult = string.Format("Approved ({0}: {1})", response.responseCode, response.authCode); //result.AvsResult = response.transactionResponse.avsResultCode; //result.NewPaymentStatus = _authorizeNetPaymentSettings.TransactMode == TransactMode.Authorize ? PaymentStatus.Authorized : PaymentStatus.Paid; //var congrats = "Congrats the payment was successful, now insert profile id into DB"; bool storeProfile = Convert.ToBoolean(processPaymentRequest.CustomValues["StoreProfile"]); if (payment.createProfile == true && storeProfile == true) { string nickName = String.IsNullOrEmpty(processPaymentRequest.CustomValues["NickName"].ToString()) ? "" : processPaymentRequest.CustomValues["NickName"].ToString(); nickName = nickName.Replace("'", "''"); string last4Digits = response.accountNum.ToString(); last4Digits = last4Digits.Substring(last4Digits.Length - 4); DBManager manager = new DBManager(); Dictionary <string, string> paramDic = new Dictionary <string, string>(); paramDic.Add("@CustomerID", customer.Id.ToString()); paramDic.Add("@ProfileID", response.customerRefNum.ToString()); paramDic.Add("@NickName", nickName); paramDic.Add("@Last4Digits", last4Digits); paramDic.Add("@CardType", response.cardBrand.ToString()); paramDic.Add("@ExpMonth", payment.cardExpireMonth); paramDic.Add("@ExpYear", payment.cardExpireYear); string insert = "INSERT INTO Profiles (CustomerID, ProfileID, NickName, Last4Digits, CardType, ExpMonth, ExpYear) "; insert += "VALUES ('" + customer.Id + "', '" + response.customerRefNum + "', '" + nickName + "', '" + last4Digits + "', '" + response.cardBrand + "', '" + payment.cardExpireMonth + "', '" + payment.cardExpireYear + "')"; try { manager.SetParameterizedQueryNoData(insert, paramDic); } catch (Exception ex) { try { _logger.Error("Payment Plugin Error inserting profile on auth : " + ex.Message + ": query = " + insert, ex, null); } catch (Exception ex1) { _logger.Error("Payment Plugin Error inserting profile on auth with additional failure to log the sql statement : " + ex.Message, ex, null); } } } } catch (Exception ex) { _logger.Error("Payment Plugin Error : " + ex.Message, ex, null); throw new Exception("Payment Plugin Exception: " + ex.Message, ex); } return(result); }
public void Can_get_tax_total() { //customer Customer customer = new Customer(); //shopping cart var productVariant1 = new ProductVariant { Id = 1, Name = "Product variant name 1", Price = 10M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 1, Name = "Product name 1", Published = true } }; var sci1 = new ShoppingCartItem() { ProductVariant = productVariant1, ProductVariantId = productVariant1.Id, Quantity = 2, }; var productVariant2 = new ProductVariant { Id = 2, Name = "Product variant name 2", Price = 12M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 2, Name = "Product name 2", Published = true } }; var sci2 = new ShoppingCartItem() { ProductVariant = productVariant2, ProductVariantId = productVariant2.Id, Quantity = 3 }; var cart = new List <ShoppingCartItem>() { sci1, sci2 }; cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); SortedDictionary <decimal, decimal> taxRates; customer.SelectedPaymentMethodSystemName = "test1"; _paymentService.Expect(ps => ps.GetAdditionalHandlingFee("test1")).Return(20); //56 - items, 10 - shipping (fixed), 20 - payment fee //1. shipping is taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(8.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(8.6); //2. shipping is taxable, payment fee is not taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = false; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(6.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(6.6); //3. shipping is not taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = false; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(7.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(7.6); //3. shipping is not taxable, payment fee is not taxable _taxSettings.ShippingIsTaxable = false; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = false; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(5.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(5.6); }
public void Can_get_tax_total() { //customer var customer = _customerService.GetCustomerById(1); //shopping cart var product1 = new Product { Name = "Product name 1", Price = 10M, Published = true, IsShipEnabled = true }; _productService.InsertProduct(product1); var sci1 = new ShoppingCartItem { ProductId = product1.Id, Quantity = 2 }; var product2 = new Product { Name = "Product name 2", Price = 12M, Published = true, IsShipEnabled = true }; _productService.InsertProduct(product2); var sci2 = new ShoppingCartItem { ProductId = product2.Id, Quantity = 3 }; var cart = new List <ShoppingCartItem> { sci1, sci2 }; cart.ForEach(sci => sci.CustomerId = customer.Id); //56 - items, 10 - shipping (fixed), 20 - payment fee //1. shipping is taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; _orderTotalCalcService.GetTaxTotal(cart, out var taxRates).Should().Be(8.6M); taxRates.Should().NotBeNull(); taxRates.Count.Should().Be(1); taxRates.ContainsKey(10).Should().BeTrue(); taxRates[10].Should().Be(8.6M); //2. shipping is taxable, payment fee is not taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = false; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).Should().Be(6.6M); taxRates.Should().NotBeNull(); taxRates.Count.Should().Be(1); taxRates.ContainsKey(10).Should().BeTrue(); taxRates[10].Should().Be(6.6M); //3. shipping is not taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = false; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).Should().Be(7.6M); taxRates.Should().NotBeNull(); taxRates.Count.Should().Be(1); taxRates.ContainsKey(10).Should().BeTrue(); taxRates[10].Should().Be(7.6M); //3. shipping is not taxable, payment fee is not taxable _taxSettings.ShippingIsTaxable = false; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = false; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).Should().Be(5.6M); taxRates.Should().NotBeNull(); taxRates.Count.Should().Be(1); taxRates.ContainsKey(10).Should().BeTrue(); taxRates[10].Should().Be(5.6M); }