Exemplo n.º 1
0
        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            var builder = new StringBuilder();

            builder.Append(GetPaypalUrl());
            var cmd = _paypalStandardPaymentSettings.PassProductNamesAndTotals
                ? "_cart"
                :  "_xclick";

            builder.AppendFormat("?cmd={0}&business={1}", cmd, HttpUtility.UrlEncode(_paypalStandardPaymentSettings.BusinessEmail));
            if (_paypalStandardPaymentSettings.PassProductNamesAndTotals)
            {
                builder.AppendFormat("&upload=1");

                //get the items in the cart
                decimal cartTotal = decimal.Zero;
                var     cartItems = postProcessPaymentRequest.Order.OrderItems;
                int     x         = 1;
                foreach (var item in cartItems)
                {
                    var unitPriceExclTax = item.UnitPriceExclTax;
                    var priceExclTax     = item.PriceExclTax;
                    //round
                    var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(item.Product.Name));
                    builder.AppendFormat("&amount_" + x + "={0}", unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", item.Quantity);
                    x++;
                    cartTotal += priceExclTax;
                }

                //the checkout attributes that have a dollar value and send them to Paypal as items to be paid for
                var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
                foreach (var val in attributeValues)
                {
                    var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                    //round
                    var attPriceRounded = Math.Round(attPrice, 2);
                    if (attPrice > decimal.Zero) //if it has a price
                    {
                        var attribute = val.CheckoutAttribute;
                        if (attribute != null)
                        {
                            var attName = attribute.Name;                                                                                  //set the name
                            builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(attName));                              //name
                            builder.AppendFormat("&amount_" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                            builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity
                            x++;
                            cartTotal += attPrice;
                        }
                    }
                }

                //order totals

                //shipping
                var orderShippingExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
                var orderShippingExclTaxRounded = Math.Round(orderShippingExclTax, 2);
                if (orderShippingExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Shipping fee");
                    builder.AppendFormat("&amount_" + x + "={0}", orderShippingExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal += orderShippingExclTax;
                }

                //payment method additional fee
                var paymentMethodAdditionalFeeExclTax        = postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                var paymentMethodAdditionalFeeExclTaxRounded = Math.Round(paymentMethodAdditionalFeeExclTax, 2);
                if (paymentMethodAdditionalFeeExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Payment method fee");
                    builder.AppendFormat("&amount_" + x + "={0}", paymentMethodAdditionalFeeExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal += paymentMethodAdditionalFeeExclTax;
                }

                //tax
                var orderTax        = postProcessPaymentRequest.Order.OrderTax;
                var orderTaxRounded = Math.Round(orderTax, 2);
                if (orderTax > decimal.Zero)
                {
                    //builder.AppendFormat("&tax_1={0}", orderTax.ToString("0.00", CultureInfo.InvariantCulture));

                    //add tax as item
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode("Sales Tax"));                          //name
                    builder.AppendFormat("&amount_" + x + "={0}", orderTaxRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity

                    cartTotal += orderTax;
                    x++;
                }

                if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
                {
                    /* Take the difference between what the order total is and what it should be and use that as the "discount".
                     * The difference equals the amount of the gift card and/or reward points used.
                     */
                    decimal discountTotal = cartTotal - postProcessPaymentRequest.Order.OrderTotal;
                    discountTotal = Math.Round(discountTotal, 2);
                    //gift card or rewared point amount applied to cart in nopCommerce - shows in Paypal as "discount"
                    builder.AppendFormat("&discount_amount_cart={0}", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
                }
            }
            else
            {
                //pass order total
                builder.AppendFormat("&item_name=Order Number {0}", postProcessPaymentRequest.Order.Id);
                var orderTotal = Math.Round(postProcessPaymentRequest.Order.OrderTotal, 2);
                builder.AppendFormat("&amount={0}", orderTotal.ToString("0.00", CultureInfo.InvariantCulture));
            }

            builder.AppendFormat("&custom={0}", postProcessPaymentRequest.Order.OrderGuid);
            builder.AppendFormat("&charset={0}", "utf-8");
            builder.Append(string.Format("&no_note=1&currency_code={0}", HttpUtility.UrlEncode(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode)));
            builder.AppendFormat("&invoice={0}", postProcessPaymentRequest.Order.Id);
            builder.AppendFormat("&rm=2", new object[0]);
            if (postProcessPaymentRequest.Order.ShippingStatus != ShippingStatus.ShippingNotRequired)
            {
                builder.AppendFormat("&no_shipping=2", new object[0]);
            }
            else
            {
                builder.AppendFormat("&no_shipping=1", new object[0]);
            }

            string returnUrl       = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/PDTHandler";
            string cancelReturnUrl = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/CancelOrder";

            builder.AppendFormat("&return={0}&cancel_return={1}", HttpUtility.UrlEncode(returnUrl), HttpUtility.UrlEncode(cancelReturnUrl));

            //Instant Payment Notification (server to server message)
            if (_paypalStandardPaymentSettings.EnableIpn)
            {
                string ipnUrl;
                if (String.IsNullOrWhiteSpace(_paypalStandardPaymentSettings.IpnUrl))
                {
                    ipnUrl = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/IPNHandler";
                }
                else
                {
                    ipnUrl = _paypalStandardPaymentSettings.IpnUrl;
                }
                builder.AppendFormat("&notify_url={0}", ipnUrl);
            }

            //address
            builder.AppendFormat("&address_override={0}", _paypalStandardPaymentSettings.AddressOverride ? "1" : "0");
            builder.AppendFormat("&first_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.FirstName));
            builder.AppendFormat("&last_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.LastName));
            builder.AppendFormat("&address1={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Address1));
            builder.AppendFormat("&address2={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Address2));
            builder.AppendFormat("&city={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.City));
            //if (!String.IsNullOrEmpty(postProcessPaymentRequest.Order.BillingAddress.PhoneNumber))
            //{
            //    //strip out all non-digit characters from phone number;
            //    string billingPhoneNumber = System.Text.RegularExpressions.Regex.Replace(postProcessPaymentRequest.Order.BillingAddress.PhoneNumber, @"\D", string.Empty);
            //    if (billingPhoneNumber.Length >= 10)
            //    {
            //        builder.AppendFormat("&night_phone_a={0}", HttpUtility.UrlEncode(billingPhoneNumber.Substring(0, 3)));
            //        builder.AppendFormat("&night_phone_b={0}", HttpUtility.UrlEncode(billingPhoneNumber.Substring(3, 3)));
            //        builder.AppendFormat("&night_phone_c={0}", HttpUtility.UrlEncode(billingPhoneNumber.Substring(6, 4)));
            //    }
            //}
            if (postProcessPaymentRequest.Order.BillingAddress.StateProvince != null)
            {
                builder.AppendFormat("&state={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.StateProvince.Abbreviation));
            }
            else
            {
                builder.AppendFormat("&state={0}", "");
            }
            if (postProcessPaymentRequest.Order.BillingAddress.Country != null)
            {
                builder.AppendFormat("&country={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Country.TwoLetterIsoCode));
            }
            else
            {
                builder.AppendFormat("&country={0}", "");
            }
            builder.AppendFormat("&zip={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.ZipPostalCode));
            builder.AppendFormat("&email={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Email));
            _httpContext.Response.Redirect(builder.ToString());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Add order items to the request query parameters
        /// </summary>
        /// <param name="parameters">Query parameters</param>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        private void AddItemsParameters(IDictionary <string, string> parameters, PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //upload order items
            parameters.Add("cmd", "_cart");
            parameters.Add("upload", "1");

            var cartTotal        = decimal.Zero;
            var roundedCartTotal = decimal.Zero;
            var itemCount        = 1;

            //add shopping cart items
            foreach (var item in postProcessPaymentRequest.Order.OrderItems)
            {
                var product = _productService.GetProductById(item.ProductId);

                var roundedItemPrice = Math.Round(item.UnitPriceExclTax, 2);

                //add query parameters
                parameters.Add($"item_name_{itemCount}", product.Name);
                parameters.Add($"amount_{itemCount}", roundedItemPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", item.Quantity.ToString());

                cartTotal        += item.PriceExclTax;
                roundedCartTotal += roundedItemPrice * item.Quantity;
                itemCount++;
            }

            //add checkout attributes as order items
            var checkoutAttributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
            var customer = EngineContext.Current.Resolve <ICustomerService>().GetCustomerById(postProcessPaymentRequest.Order.CustomerId);

            foreach (var attributeValue in checkoutAttributeValues)
            {
                var attributePrice = _taxService.GetCheckoutAttributePrice(attributeValue, false, customer);
                if (attributePrice > 0)
                {
                    var roundedAttributePrice = Math.Round(attributePrice, 2);

                    //add query parameters
                    var attribute = EngineContext.Current.Resolve <ICheckoutAttributeService>().GetCheckoutAttributeById(attributeValue.CheckoutAttributeId);
                    if (attribute != null)
                    {
                        parameters.Add($"item_name_{itemCount}", attribute.Name);
                        parameters.Add($"amount_{itemCount}", roundedAttributePrice.ToString("0.00", CultureInfo.InvariantCulture));
                        parameters.Add($"quantity_{itemCount}", "1");

                        cartTotal        += attributePrice;
                        roundedCartTotal += roundedAttributePrice;
                        itemCount++;
                    }
                }
            }

            //add shipping fee as a separate order item, if it has price
            var roundedShippingPrice = Math.Round(postProcessPaymentRequest.Order.OrderShippingExclTax, 2);

            if (roundedShippingPrice > decimal.Zero)
            {
                parameters.Add($"item_name_{itemCount}", "Shipping fee");
                parameters.Add($"amount_{itemCount}", roundedShippingPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += postProcessPaymentRequest.Order.OrderShippingExclTax;
                roundedCartTotal += roundedShippingPrice;
                itemCount++;
            }

            //add payment method additional fee as a separate order item, if it has price
            var roundedPaymentMethodPrice = Math.Round(postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax, 2);

            if (roundedPaymentMethodPrice > decimal.Zero)
            {
                parameters.Add($"item_name_{itemCount}", "Payment method fee");
                parameters.Add($"amount_{itemCount}", roundedPaymentMethodPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                roundedCartTotal += roundedPaymentMethodPrice;
                itemCount++;
            }

            //add tax as a separate order item, if it has positive amount
            var roundedTaxAmount = Math.Round(postProcessPaymentRequest.Order.OrderTax, 2);

            if (roundedTaxAmount > decimal.Zero)
            {
                parameters.Add($"item_name_{itemCount}", "Tax amount");
                parameters.Add($"amount_{itemCount}", roundedTaxAmount.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += postProcessPaymentRequest.Order.OrderTax;
                roundedCartTotal += roundedTaxAmount;
                itemCount++;
            }

            if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
            {
                //get the difference between what the order total is and what it should be and use that as the "discount"
                var discountTotal = Math.Round(cartTotal - postProcessPaymentRequest.Order.OrderTotal, 2);
                roundedCartTotal -= discountTotal;

                //gift card or rewarded point amount applied to cart in nopCommerce - shows in PayPal as "discount"
                parameters.Add("discount_amount_cart", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
            }

            //save order total that actually sent to PayPal (used for PDT order total validation)
            _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, PaypalHelper.OrderTotalSentToPayPal, roundedCartTotal);
        }
        GetShoppingCartSubTotal(IList <ShoppingCartItem> cart, bool includingTax)
        {
            var discountAmount          = decimal.Zero;
            var appliedDiscounts        = new List <ApplyDiscount>();
            var subTotalWithoutDiscount = decimal.Zero;
            var subTotalWithDiscount    = decimal.Zero;
            var taxRates = new SortedDictionary <decimal, decimal>();

            if (!cart.Any())
            {
                return(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates);
            }

            //get the customer
            Customer customer = _workContext.CurrentCustomer;

            //sub totals
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;

            foreach (var shoppingCartItem in cart)
            {
                var product = await _productService.GetProductById(shoppingCartItem.ProductId);

                if (product == null)
                {
                    continue;
                }

                var subtotal = await _pricingService.GetSubTotal(shoppingCartItem, product);

                decimal sciSubTotal = subtotal.subTotal;

                decimal taxRate;
                var     pricesExcl = await _taxService.GetProductPrice(product, sciSubTotal, false, customer);

                decimal sciExclTax = pricesExcl.productprice;

                var pricesIncl = await _taxService.GetProductPrice(product, sciSubTotal, true, customer);

                decimal sciInclTax = pricesIncl.productprice;
                taxRate = pricesIncl.taxRate;

                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                decimal sciTax = sciInclTax - sciExclTax;
                if (taxRate > decimal.Zero && sciTax > decimal.Zero)
                {
                    if (!taxRates.ContainsKey(taxRate))
                    {
                        taxRates.Add(taxRate, sciTax);
                    }
                    else
                    {
                        taxRates[taxRate] = taxRates[taxRate] + sciTax;
                    }
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var checkoutAttributes = customer.GetUserFieldFromEntity <List <CustomAttribute> >(SystemCustomerFieldNames.CheckoutAttributes, _workContext.CurrentStore.Id);
                var attributeValues    = await _checkoutAttributeParser.ParseCheckoutAttributeValue(checkoutAttributes);

                foreach (var attributeValue in attributeValues)
                {
                    decimal taxRate;
                    var     checkoutAttributePriceExclTax = await _taxService.GetCheckoutAttributePrice(attributeValue.ca, attributeValue.cav, false, customer);

                    decimal caExclTax = await _currencyService.ConvertFromPrimaryStoreCurrency(checkoutAttributePriceExclTax.checkoutPrice, _workContext.WorkingCurrency);

                    var checkoutAttributePriceInclTax = await _taxService.GetCheckoutAttributePrice(attributeValue.ca, attributeValue.cav, true, customer);

                    decimal caInclTax = await _currencyService.ConvertFromPrimaryStoreCurrency(checkoutAttributePriceInclTax.checkoutPrice, _workContext.WorkingCurrency);

                    taxRate = checkoutAttributePriceInclTax.taxRate;

                    subTotalExclTaxWithoutDiscount += caExclTax;
                    subTotalInclTaxWithoutDiscount += caInclTax;

                    //tax rates
                    decimal caTax = caInclTax - caExclTax;
                    if (taxRate > decimal.Zero && caTax > decimal.Zero)
                    {
                        if (!taxRates.ContainsKey(taxRate))
                        {
                            taxRates.Add(taxRate, caTax);
                        }
                        else
                        {
                            taxRates[taxRate] = taxRates[taxRate] + caTax;
                        }
                    }
                }
            }

            //subtotal without discount
            subTotalWithoutDiscount = includingTax ? subTotalInclTaxWithoutDiscount : subTotalExclTaxWithoutDiscount;

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

            if (_shoppingCartSettings.RoundPrices)
            {
                subTotalWithoutDiscount = RoundingHelper.RoundPrice(subTotalWithoutDiscount, _workContext.WorkingCurrency);
            }
            //We calculate discount amount on order subtotal excl tax (discount first)
            //calculate discount amount ('Applied to order subtotal' discount)
            var orderSubtotalDiscount = await GetOrderSubtotalDiscount(customer, _workContext.WorkingCurrency, subTotalExclTaxWithoutDiscount);

            decimal discountAmountExclTax = orderSubtotalDiscount.ordersubtotaldiscount;

            appliedDiscounts = orderSubtotalDiscount.appliedDiscounts;

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            decimal discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            var tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates)
            {
                decimal taxRate  = kvp.Key;
                decimal taxValue = kvp.Value;

                if (taxValue != decimal.Zero)
                {
                    //discount the tax amount that applies to subtotal items
                    if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                    {
                        decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                        discountAmountInclTax += discountTax;
                        taxValue = taxRates[taxRate] - discountTax;
                        if (_shoppingCartSettings.RoundPrices)
                        {
                            taxValue = RoundingHelper.RoundPrice(taxValue, _workContext.WorkingCurrency);
                        }
                        taxRates[taxRate] = taxValue;
                    }

                    //subtotal with discount (incl tax)
                    subTotalInclTaxWithDiscount += taxValue;
                }
            }

            if (_shoppingCartSettings.RoundPrices)
            {
                discountAmountInclTax = RoundingHelper.RoundPrice(discountAmountInclTax, _workContext.WorkingCurrency);
                discountAmountExclTax = RoundingHelper.RoundPrice(discountAmountExclTax, _workContext.WorkingCurrency);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

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

            if (_shoppingCartSettings.RoundPrices)
            {
                subTotalWithDiscount = RoundingHelper.RoundPrice(subTotalWithDiscount, _workContext.WorkingCurrency);
            }

            return(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates);
        }
        private void AddOrderLines(PayexInterface payex, string orderRef, Order order)
        {
            //get the items in the cart
            decimal cartTotal = decimal.Zero;
            var     cartItems = order.OrderItems;
            int     itemIndex = 1;

            foreach (var item in cartItems)
            {
                AddOrderLine(
                    payex, orderRef, item.Product.Sku ?? string.Format("{0}", itemIndex++), item.Product.Name,
                    item.Quantity, item.PriceInclTax)
                .GetAwaiter().GetResult();
                cartTotal += item.PriceInclTax;
            }

            //the checkout attributes that have a value and send them to PayEx as items to be paid for
            var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(order.CheckoutAttributesXml);

            foreach (var val in caValues)
            {
                var caPriceInclTax   = _taxService.GetCheckoutAttributePrice(val, true, order.Customer);
                CheckoutAttribute ca = val.CheckoutAttribute;
                if (caPriceInclTax > decimal.Zero && ca != null) //if it has a price
                {
                    AddOrderLine(payex, orderRef, string.Format("{0}", itemIndex++), ca.Name, 1, caPriceInclTax)
                    .GetAwaiter().GetResult();
                    cartTotal += caPriceInclTax;
                }
            }

            //order totals

            //shipping
            var orderShippingInclTax = order.OrderShippingInclTax;

            if (orderShippingInclTax > decimal.Zero)
            {
                AddOrderLine(
                    payex, orderRef, string.Format("{0}", itemIndex++),
                    _localizationService.GetResource("Order.Shipping"), 1, orderShippingInclTax)
                .GetAwaiter().GetResult();
                cartTotal += orderShippingInclTax;
            }

            //payment method additional fee
            var paymentMethodAdditionalFeeInclTax = order.PaymentMethodAdditionalFeeInclTax;

            if (paymentMethodAdditionalFeeInclTax > decimal.Zero)
            {
                AddOrderLine(
                    payex, orderRef, string.Format("{0}", itemIndex++),
                    _localizationService.GetResource("Order.PaymentMethodAdditionalFee"), 1,
                    paymentMethodAdditionalFeeInclTax)
                .GetAwaiter().GetResult();
                cartTotal += paymentMethodAdditionalFeeInclTax;
            }

            if (cartTotal > order.OrderTotal)
            {
                /* Take the difference between what the order total is and what it should be and use that as the "discount".
                 * The difference equals the amount of the gift card and/or reward points used.
                 */
                decimal discountTotal = cartTotal - order.OrderTotal;
                //gift card or rewared point amount applied to cart in nopCommerce
                AddOrderLine(
                    payex, orderRef, string.Format("{0}", itemIndex++),
                    _localizationService.GetResource("Admin.Orders.Products.Discount"), 1, -discountTotal)
                .GetAwaiter().GetResult();
            }
        }
        /// <summary>
        /// Add order items to the request request metadata
        /// </summary>
        /// <param name="parameters">Query parameters</param>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        private void AddOrderItemsMetaData(TransactionInitializeRequest request, PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //upload order items
            var cartTotal        = decimal.Zero;
            var roundedCartTotal = decimal.Zero;
            var itemCount        = 1;

            //add shopping cart items
            foreach (var item in postProcessPaymentRequest.Order.OrderItems)
            {
                var roundedItemPrice = Math.Round(item.UnitPriceExclTax, 2);

                //add query parameters
                request.MetadataObject[$"item_name_{itemCount}"] = item.Product.Name;
                request.MetadataObject[$"amount_{itemCount}"]    = roundedItemPrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = item.Quantity.ToString();

                cartTotal        += item.PriceExclTax;
                roundedCartTotal += roundedItemPrice * item.Quantity;
                itemCount++;
            }

            //add checkout attributes as order items
            var checkoutAttributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);

            foreach (var attributeValue in checkoutAttributeValues)
            {
                var attributePrice        = _taxService.GetCheckoutAttributePrice(attributeValue, false, postProcessPaymentRequest.Order.Customer);
                var roundedAttributePrice = Math.Round(attributePrice, 2);

                //add query parameters
                if (attributeValue.CheckoutAttribute == null)
                {
                    continue;
                }

                request.MetadataObject[$"item_name_{itemCount}"] = attributeValue.CheckoutAttribute.Name;
                request.MetadataObject[$"amount_{itemCount}"]    = roundedAttributePrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += attributePrice;
                roundedCartTotal += roundedAttributePrice;
                itemCount++;
            }

            //add shipping fee as a separate order item, if it has price
            var roundedShippingPrice = Math.Round(postProcessPaymentRequest.Order.OrderShippingExclTax, 2);

            if (roundedShippingPrice > decimal.Zero)
            {
                request.MetadataObject[$"item_name_{itemCount}"] = "Shipping fee";
                request.MetadataObject[$"amount_{itemCount}"]    = roundedShippingPrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += postProcessPaymentRequest.Order.OrderShippingExclTax;
                roundedCartTotal += roundedShippingPrice;
                itemCount++;
            }

            //add payment method additional fee as a separate order item, if it has price
            var roundedPaymentMethodPrice = Math.Round(postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax, 2);

            if (roundedPaymentMethodPrice > decimal.Zero)
            {
                request.MetadataObject[$"item_name_{itemCount}"] = "Payment method fee";
                request.MetadataObject[$"amount_{itemCount}"]    = roundedPaymentMethodPrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                roundedCartTotal += roundedPaymentMethodPrice;
                itemCount++;
            }

            //add tax as a separate order item, if it has positive amount
            var roundedTaxAmount = Math.Round(postProcessPaymentRequest.Order.OrderTax, 2);

            if (roundedTaxAmount > decimal.Zero)
            {
                request.MetadataObject[$"item_name_{itemCount}"] = "Tax amount";
                request.MetadataObject[$"amount_{itemCount}"]    = roundedTaxAmount.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += postProcessPaymentRequest.Order.OrderTax;
                roundedCartTotal += roundedTaxAmount;
            }

            if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
            {
                //get the difference between what the order total is and what it should be and use that as the "discount"
                var discountTotal = Math.Round(cartTotal - postProcessPaymentRequest.Order.OrderTotal, 2);
                roundedCartTotal -= discountTotal;

                //gift card or rewarded point amount applied to cart in nopCommerce - shows in Paystack as "discount"
                request.MetadataObject["discount_amount_cart"] = discountTotal.ToString("0.00", CultureInfo.InvariantCulture);
            }

            //save order total that actually sent to Paystack (used for PDT order total validation)
            _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, PaystackHelper.OrderTotalSentToPaystack, roundedCartTotal);
        }
        /// <summary>
        /// Formats attributes
        /// </summary>
        /// <param name="attributesXml">Attributes in XML format</param>
        /// <param name="customer">Customer</param>
        /// <param name="separator">Separator</param>
        /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param>
        /// <param name="renderPrices">A value indicating whether to render prices</param>
        /// <param name="allowHyperlinks">A value indicating whether to HTML hyperlink tags could be rendered (if required)</param>
        /// <returns>Attributes</returns>
        public virtual string FormatAttributes(string attributesXml,
                                               Customer customer,
                                               string separator     = "<br />",
                                               bool htmlEncode      = true,
                                               bool renderPrices    = true,
                                               bool allowHyperlinks = true)
        {
            var result = new StringBuilder();

            var attributes = _checkoutAttributeParser.ParseCheckoutAttributes(attributesXml);

            for (var i = 0; i < attributes.Count; i++)
            {
                var attribute = attributes[i];
                var valuesStr = _checkoutAttributeParser.ParseValues(attributesXml, attribute.Id);
                for (var j = 0; j < valuesStr.Count; j++)
                {
                    var valueStr           = valuesStr[j];
                    var formattedAttribute = string.Empty;
                    if (!attribute.ShouldHaveValues())
                    {
                        //no values
                        if (attribute.AttributeControlType == AttributeControlType.MultilineTextbox)
                        {
                            //multiline textbox
                            var attributeName = _localizationService.GetLocalized(attribute, a => a.Name, _workContext.WorkingLanguage.Id);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                attributeName = WebUtility.HtmlEncode(attributeName);
                            }
                            formattedAttribute = $"{attributeName}: {HtmlHelper.FormatText(valueStr, false, true, false, false, false, false)}";
                            //we never encode multiline textbox input
                        }
                        else if (attribute.AttributeControlType == AttributeControlType.FileUpload)
                        {
                            //file upload
                            Guid.TryParse(valueStr, out var downloadGuid);
                            var download = _downloadService.GetDownloadByGuid(downloadGuid);
                            if (download != null)
                            {
                                //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs)
                                string attributeText;
                                var    fileName = $"{download.Filename ?? download.DownloadGuid.ToString()}{download.Extension}";
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    fileName = WebUtility.HtmlEncode(fileName);
                                }
                                if (allowHyperlinks)
                                {
                                    //hyperlinks are allowed
                                    var downloadLink = $"{_webHelper.GetStoreLocation(false)}download/getfileupload/?downloadId={download.DownloadGuid}";
                                    attributeText = $"<a href=\"{downloadLink}\" class=\"fileuploadattribute\">{fileName}</a>";
                                }
                                else
                                {
                                    //hyperlinks aren't allowed
                                    attributeText = fileName;
                                }

                                var attributeName = _localizationService.GetLocalized(attribute, a => a.Name, _workContext.WorkingLanguage.Id);
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    attributeName = WebUtility.HtmlEncode(attributeName);
                                }
                                formattedAttribute = $"{attributeName}: {attributeText}";
                            }
                        }
                        else
                        {
                            //other attributes (textbox, datepicker)
                            formattedAttribute = $"{_localizationService.GetLocalized(attribute, a => a.Name, _workContext.WorkingLanguage.Id)}: {valueStr}";
                            //encode (if required)
                            if (htmlEncode)
                            {
                                formattedAttribute = WebUtility.HtmlEncode(formattedAttribute);
                            }
                        }
                    }
                    else
                    {
                        if (int.TryParse(valueStr, out var attributeValueId))
                        {
                            var attributeValue = _checkoutAttributeService.GetCheckoutAttributeValueById(attributeValueId);

                            if (attributeValue != null)
                            {
                                formattedAttribute = $"{_localizationService.GetLocalized(attribute, a => a.Name, _workContext.WorkingLanguage.Id)}: {_localizationService.GetLocalized(attributeValue, a => a.Name, _workContext.WorkingLanguage.Id)}";
                                if (renderPrices)
                                {
                                    var priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(attribute, attributeValue, customer);
                                    var priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
                                    if (priceAdjustmentBase > 0)
                                    {
                                        formattedAttribute += string.Format(
                                            _localizationService.GetResource("FormattedAttributes.PriceAdjustment"),
                                            "+", _priceFormatter.FormatPrice(priceAdjustment), string.Empty);
                                    }
                                }
                            }

                            //encode (if required)
                            if (htmlEncode)
                            {
                                formattedAttribute = WebUtility.HtmlEncode(formattedAttribute);
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(formattedAttribute))
                    {
                        continue;
                    }

                    if (i != 0 || j != 0)
                    {
                        result.Append(separator);
                    }
                    result.Append(formattedAttribute);
                }
            }

            return(result.ToString());
        }
Exemplo n.º 7
0
        /// <summary>
        /// Gets shopping cart subtotal
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="includingTax">A value indicating whether calculated price should include tax</param>
        /// <param name="discountAmount">Applied discount amount</param>
        /// <param name="appliedDiscount">Applied discount</param>
        /// <param name="subTotalWithoutDiscount">Sub total (without discount)</param>
        /// <param name="subTotalWithDiscount">Sub total (with discount)</param>
        /// <param name="taxRates">Tax rates (of order sub total)</param>
        public virtual void GetShoppingCartSubTotal(IList <ShoppingCartItem> cart,
                                                    bool includingTax,
                                                    out decimal discountAmount, out List <Discount> appliedDiscounts,
                                                    out decimal subTotalWithoutDiscount, out decimal subTotalWithDiscount,
                                                    out SortedDictionary <decimal, decimal> taxRates)
        {
            discountAmount          = decimal.Zero;
            appliedDiscounts        = new List <Discount>();
            subTotalWithoutDiscount = decimal.Zero;
            subTotalWithDiscount    = decimal.Zero;
            taxRates = new SortedDictionary <decimal, decimal>();

            if (!cart.Any())
            {
                return;
            }

            //get the customer
            Customer customer = cart.GetCustomer();

            //sub totals
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;
            var     productService = EngineContextExperimental.Current.Resolve <IProductService>();

            foreach (var shoppingCartItem in cart)
            {
                decimal sciSubTotal = _priceCalculationService.GetSubTotal(shoppingCartItem);
                var     product     = productService.GetProductById(shoppingCartItem.ProductId);
                decimal taxRate;
                decimal sciExclTax = _taxService.GetProductPrice(product, sciSubTotal, false, customer, out taxRate);
                decimal sciInclTax = _taxService.GetProductPrice(product, sciSubTotal, true, customer, out taxRate);
                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                decimal sciTax = sciInclTax - sciExclTax;
                if (taxRate > decimal.Zero && sciTax > decimal.Zero)
                {
                    if (!taxRates.ContainsKey(taxRate))
                    {
                        taxRates.Add(taxRate, sciTax);
                    }
                    else
                    {
                        taxRates[taxRate] = taxRates[taxRate] + sciTax;
                    }
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var checkoutAttributesXml = customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _storeContext.CurrentStore.Id);
                var attributeValues       = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                if (attributeValues != null)
                {
                    foreach (var attributeValue in attributeValues)
                    {
                        decimal taxRate;

                        decimal caExclTax = _taxService.GetCheckoutAttributePrice(attributeValue, false, customer, out taxRate);
                        decimal caInclTax = _taxService.GetCheckoutAttributePrice(attributeValue, true, customer, out taxRate);
                        subTotalExclTaxWithoutDiscount += caExclTax;
                        subTotalInclTaxWithoutDiscount += caInclTax;

                        //tax rates
                        decimal caTax = caInclTax - caExclTax;
                        if (taxRate > decimal.Zero && caTax > decimal.Zero)
                        {
                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, caTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + caTax;
                            }
                        }
                    }
                }
            }

            //subtotal without discount
            subTotalWithoutDiscount = includingTax ? subTotalInclTaxWithoutDiscount : subTotalExclTaxWithoutDiscount;

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

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithoutDiscount = RoundingHelper.RoundPrice(subTotalWithoutDiscount);
            }

            //We calculate discount amount on order subtotal excl tax (discount first)
            //calculate discount amount ('Applied to order subtotal' discount)
            decimal discountAmountExclTax = GetOrderSubtotalDiscount(customer, subTotalExclTaxWithoutDiscount, out appliedDiscounts);

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            decimal discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            var tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates)
            {
                decimal taxRate  = kvp.Key;
                decimal taxValue = kvp.Value;

                if (taxValue != decimal.Zero)
                {
                    //discount the tax amount that applies to subtotal items
                    if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                    {
                        decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                        discountAmountInclTax += discountTax;
                        taxValue = taxRates[taxRate] - discountTax;
                        if (_shoppingCartSettings.RoundPricesDuringCalculation)
                        {
                            taxValue = RoundingHelper.RoundPrice(taxValue);
                        }
                        taxRates[taxRate] = taxValue;
                    }

                    //subtotal with discount (incl tax)
                    subTotalInclTaxWithDiscount += taxValue;
                }
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                discountAmountInclTax = RoundingHelper.RoundPrice(discountAmountInclTax);
                discountAmountExclTax = RoundingHelper.RoundPrice(discountAmountExclTax);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

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

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithDiscount = RoundingHelper.RoundPrice(subTotalWithDiscount);
            }
        }
Exemplo n.º 8
0
        private async Task PrepareCheckoutAttributes(ShoppingCartModel model, GetShoppingCart request)
        {
            #region Checkout attributes

            var checkoutAttributes = await _checkoutAttributeService.GetAllCheckoutAttributes(request.Store.Id, !request.Cart.RequiresShipping());

            foreach (var attribute in checkoutAttributes)
            {
                var attributeModel = new ShoppingCartModel.CheckoutAttributeModel {
                    Id                   = attribute.Id,
                    Name                 = attribute.GetLocalized(x => x.Name, request.Language.Id),
                    TextPrompt           = attribute.GetLocalized(x => x.TextPrompt, request.Language.Id),
                    IsRequired           = attribute.IsRequired,
                    AttributeControlType = attribute.AttributeControlType,
                    DefaultValue         = attribute.DefaultValue
                };
                if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
                {
                    attributeModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions
                                                           .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                           .ToList();
                }

                if (attribute.ShouldHaveValues())
                {
                    //values
                    var attributeValues = attribute.CheckoutAttributeValues;
                    foreach (var attributeValue in attributeValues)
                    {
                        var attributeValueModel = new ShoppingCartModel.CheckoutAttributeValueModel {
                            Id              = attributeValue.Id,
                            Name            = attributeValue.GetLocalized(x => x.Name, request.Language.Id),
                            ColorSquaresRgb = attributeValue.ColorSquaresRgb,
                            IsPreSelected   = attributeValue.IsPreSelected,
                        };
                        attributeModel.Values.Add(attributeValueModel);

                        //display price if allowed
                        if (await _permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            decimal priceAdjustmentBase = (await _taxService.GetCheckoutAttributePrice(attribute, attributeValue)).checkoutPrice;
                            decimal priceAdjustment     = await _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, request.Currency);

                            if (priceAdjustmentBase > decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment);
                            }
                            else if (priceAdjustmentBase < decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment);
                            }
                        }
                    }
                }
                //set already selected attributes
                var selectedCheckoutAttributes = request.Customer.GetAttributeFromEntity <string>(SystemCustomerAttributeNames.CheckoutAttributes, request.Store.Id);
                switch (attribute.AttributeControlType)
                {
                case AttributeControlType.DropdownList:
                case AttributeControlType.RadioList:
                case AttributeControlType.Checkboxes:
                case AttributeControlType.ColorSquares:
                case AttributeControlType.ImageSquares:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        //clear default selection
                        foreach (var item in attributeModel.Values)
                        {
                            item.IsPreSelected = false;
                        }

                        //select new values
                        var selectedValues = await _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes);

                        foreach (var attributeValue in selectedValues)
                        {
                            if (attributeModel.Id == attributeValue.CheckoutAttributeId)
                            {
                                foreach (var item in attributeModel.Values)
                                {
                                    if (attributeValue.Id == item.Id)
                                    {
                                        item.IsPreSelected = true;
                                    }
                                }
                            }
                        }
                    }
                }
                break;

                case AttributeControlType.ReadonlyCheckboxes:
                {
                    //do nothing
                    //values are already pre-set
                }
                break;

                case AttributeControlType.TextBox:
                case AttributeControlType.MultilineTextbox:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                        if (enteredText.Any())
                        {
                            attributeModel.DefaultValue = enteredText[0];
                        }
                    }
                }
                break;

                case AttributeControlType.Datepicker:
                {
                    //keep in mind my that the code below works only in the current culture
                    var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                    if (selectedDateStr.Any())
                    {
                        DateTime selectedDate;
                        if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture,
                                                   DateTimeStyles.None, out selectedDate))
                        {
                            //successfully parsed
                            attributeModel.SelectedDay   = selectedDate.Day;
                            attributeModel.SelectedMonth = selectedDate.Month;
                            attributeModel.SelectedYear  = selectedDate.Year;
                        }
                    }
                }
                break;

                case AttributeControlType.FileUpload:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        var  downloadGuidStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id).FirstOrDefault();
                        Guid downloadGuid;
                        Guid.TryParse(downloadGuidStr, out downloadGuid);
                        var download = await _downloadService.GetDownloadByGuid(downloadGuid);

                        if (download != null)
                        {
                            attributeModel.DefaultValue = download.DownloadGuid.ToString();
                        }
                    }
                }
                break;

                default:
                    break;
                }

                model.CheckoutAttributes.Add(attributeModel);
            }
            #endregion
        }
Exemplo n.º 9
0
        /// <summary>
        /// Generate string (URL) for redirection
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        /// <param name="passProductNamesAndTotals">A value indicating whether to pass product names and totals</param>
        private string GenerationCallBackUrl(PostProcessPaymentRequest postProcessPaymentRequest, bool passProductNamesAndTotals)
        {
            var builder = new StringBuilder();

            builder.Append(_webHelper.GetStoreLocation(false) + "Plugins/PaymentMellatBank/PDTHandler");
            var cmd = passProductNamesAndTotals
                ? "_cart"
                : "_xclick";

            builder.AppendFormat("?cmd={0}", cmd);
            if (passProductNamesAndTotals)
            {
                builder.AppendFormat("&upload=1");

                //get the items in the cart
                decimal cartTotal        = decimal.Zero;
                var     cartTotalRounded = decimal.Zero;
                var     cartItems        = postProcessPaymentRequest.Order.OrderItems;
                int     x = 1;
                foreach (var item in cartItems)
                {
                    var unitPriceExclTax = item.UnitPriceExclTax;
                    var priceExclTax     = item.PriceExclTax;
                    //round
                    var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(item.Product.Name));
                    builder.AppendFormat("&amount_" + x + "={0}", unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", item.Quantity);
                    x++;
                    cartTotal        += priceExclTax;
                    cartTotalRounded += unitPriceExclTaxRounded * item.Quantity;
                }

                //the checkout attributes that have a cost value and send them to MellatBank as items to be paid for
                var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
                foreach (var val in attributeValues)
                {
                    var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                    //round
                    var attPriceRounded = Math.Round(attPrice, 2);
                    if (attPrice > decimal.Zero) //if it has a price
                    {
                        var attribute = val.CheckoutAttribute;
                        if (attribute != null)
                        {
                            var attName = attribute.Name;                                                                                  //set the name
                            builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(attName));                              //name
                            builder.AppendFormat("&amount_" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                            builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity
                            x++;
                            cartTotal        += attPrice;
                            cartTotalRounded += attPriceRounded;
                        }
                    }
                }

                //order totals

                //shipping
                var orderShippingExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
                var orderShippingExclTaxRounded = Math.Round(orderShippingExclTax, 2);
                if (orderShippingExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Shipping fee");
                    builder.AppendFormat("&amount_" + x + "={0}", orderShippingExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal        += orderShippingExclTax;
                    cartTotalRounded += orderShippingExclTaxRounded;
                }

                //payment method additional fee
                var paymentMethodAdditionalFeeExclTax        = postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                var paymentMethodAdditionalFeeExclTaxRounded = Math.Round(paymentMethodAdditionalFeeExclTax, 2);
                if (paymentMethodAdditionalFeeExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Payment method fee");
                    builder.AppendFormat("&amount_" + x + "={0}", paymentMethodAdditionalFeeExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal        += paymentMethodAdditionalFeeExclTax;
                    cartTotalRounded += paymentMethodAdditionalFeeExclTaxRounded;
                }

                //tax
                var orderTax        = postProcessPaymentRequest.Order.OrderTax;
                var orderTaxRounded = Math.Round(orderTax, 2);
                if (orderTax > decimal.Zero)
                {
                    //builder.AppendFormat("&tax_1={0}", orderTax.ToString("0.00", CultureInfo.InvariantCulture));

                    //add tax as item
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode("Sales Tax"));                          //name
                    builder.AppendFormat("&amount_" + x + "={0}", orderTaxRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity

                    cartTotal        += orderTax;
                    cartTotalRounded += orderTaxRounded;
                    x++;
                }

                if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
                {
                    /* Take the difference between what the order total is and what it should be and use that as the "discount".
                     * The difference equals the amount of the gift card and/or reward points used.
                     */
                    decimal discountTotal = cartTotal - postProcessPaymentRequest.Order.OrderTotal;
                    discountTotal     = Math.Round(discountTotal, 2);
                    cartTotalRounded -= discountTotal;
                    //gift card or rewared point amount applied to cart in nopCommerce - shows in MellatBank as "discount"
                    builder.AppendFormat("&discount_amount_cart={0}", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
                }

                //save order total that actually sent to MellatBank (used for PDT order total validation)
                _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, "OrderMellatBankSaleReferenceId", cartTotalRounded);
            }
            else
            {
                //pass order total
                builder.AppendFormat("&item_name=Order Number {0}", postProcessPaymentRequest.Order.Id);
                var orderTotal = Math.Round(postProcessPaymentRequest.Order.OrderTotal, 2);
                builder.AppendFormat("&amount={0}", orderTotal.ToString("0.00", CultureInfo.InvariantCulture));

                //save order total that actually sent to MellatBank (used for PDT order total validation)
                _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, "OrderMellatBankSaleReferenceId", orderTotal);
            }

            builder.AppendFormat("&custom={0}", postProcessPaymentRequest.Order.OrderGuid);
            builder.AppendFormat("&charset={0}", "utf-8");
            builder.AppendFormat("&bn={0}", BN_CODE);
            builder.Append(string.Format("&no_note=1&currency_code={0}", HttpUtility.UrlEncode(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode)));
            builder.AppendFormat("&invoice={0}", postProcessPaymentRequest.Order.Id);
            builder.AppendFormat("&rm=2", new object[0]);
            if (postProcessPaymentRequest.Order.ShippingStatus != ShippingStatus.ShippingNotRequired)
            {
                builder.AppendFormat("&no_shipping=2", new object[0]);
            }
            else
            {
                builder.AppendFormat("&no_shipping=1", new object[0]);
            }

            return(builder.ToString());
        }
        public virtual void PrepareShoppingCartModel(ShoppingCartModel model,
                                                     IList <ShoppingCartItem> cart, bool isEditable = true,
                                                     bool validateCheckoutAttributes       = false,
                                                     bool prepareEstimateShippingIfEnabled = true, bool setEstimateShippingDefaultAddress = true,
                                                     bool prepareAndDisplayOrderReviewData = false)
        {
            if (cart == null)
            {
                throw new ArgumentNullException("cart");
            }

            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            model.OnePageCheckoutEnabled = _orderSettings.OnePageCheckoutEnabled;

            if (cart.Count == 0)
            {
                return;
            }

            #region Simple properties

            model.IsEditable        = isEditable;
            model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart;
            model.ShowSku           = _catalogSettings.ShowProductSku;
            var checkoutAttributesXml = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
            model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(checkoutAttributesXml, _workContext.CurrentCustomer);
            bool minOrderSubtotalAmountOk = _orderProcessingService.ValidateMinOrderSubtotalAmount(cart);
            if (!minOrderSubtotalAmountOk)
            {
                decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency);
                model.MinOrderSubtotalWarning = string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false));
            }
            model.TermsOfServiceOnShoppingCartPage = _orderSettings.TermsOfServiceOnShoppingCartPage;
            model.TermsOfServiceOnOrderConfirmPage = _orderSettings.TermsOfServiceOnOrderConfirmPage;

            //gift card and gift card boxes
            model.DiscountBox.Display = _shoppingCartSettings.ShowDiscountBox;
            var discountCouponCode = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.DiscountCouponCode);
            var discount           = _discountService.GetDiscountByCouponCode(discountCouponCode);
            if (discount != null &&
                discount.RequiresCouponCode &&
                _discountService.IsDiscountValid(discount, _workContext.CurrentCustomer))
            {
                model.DiscountBox.CurrentCode = discount.CouponCode;
            }
            model.GiftCardBox.Display = _shoppingCartSettings.ShowGiftCardBox;

            //cart warnings
            var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, checkoutAttributesXml, validateCheckoutAttributes);
            foreach (var warning in cartWarnings)
            {
                model.Warnings.Add(warning);
            }

            #endregion

            #region Checkout attributes

            var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(_storeContext.CurrentStore.Id, !cart.RequiresShipping());
            foreach (var attribute in checkoutAttributes)
            {
                var attributeModel = new ShoppingCartModel.CheckoutAttributeModel
                {
                    Id                   = attribute.Id,
                    Name                 = attribute.GetLocalized(x => x.Name),
                    TextPrompt           = attribute.GetLocalized(x => x.TextPrompt),
                    IsRequired           = attribute.IsRequired,
                    AttributeControlType = attribute.AttributeControlType,
                    DefaultValue         = attribute.DefaultValue
                };
                if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
                {
                    attributeModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions
                                                           .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                           .ToList();
                }

                if (attribute.ShouldHaveValues())
                {
                    //values
                    var attributeValues = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id);
                    foreach (var attributeValue in attributeValues)
                    {
                        var attributeValueModel = new ShoppingCartModel.CheckoutAttributeValueModel
                        {
                            Id              = attributeValue.Id,
                            Name            = attributeValue.GetLocalized(x => x.Name),
                            ColorSquaresRgb = attributeValue.ColorSquaresRgb,
                            IsPreSelected   = attributeValue.IsPreSelected,
                        };
                        attributeModel.Values.Add(attributeValueModel);

                        //display price if allowed
                        if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(attributeValue);
                            decimal priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
                            if (priceAdjustmentBase > decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment);
                            }
                            else if (priceAdjustmentBase < decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment);
                            }
                        }
                    }
                }



                //set already selected attributes
                var selectedCheckoutAttributes = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
                switch (attribute.AttributeControlType)
                {
                case AttributeControlType.DropdownList:
                case AttributeControlType.RadioList:
                case AttributeControlType.Checkboxes:
                case AttributeControlType.ColorSquares:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        //clear default selection
                        foreach (var item in attributeModel.Values)
                        {
                            item.IsPreSelected = false;
                        }

                        //select new values
                        var selectedValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes);
                        foreach (var attributeValue in selectedValues)
                        {
                            foreach (var item in attributeModel.Values)
                            {
                                if (attributeValue.Id == item.Id)
                                {
                                    item.IsPreSelected = true;
                                }
                            }
                        }
                    }
                }
                break;

                case AttributeControlType.ReadonlyCheckboxes:
                {
                    //do nothing
                    //values are already pre-set
                }
                break;

                case AttributeControlType.TextBox:
                case AttributeControlType.MultilineTextbox:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                        if (enteredText.Count > 0)
                        {
                            attributeModel.DefaultValue = enteredText[0];
                        }
                    }
                }
                break;

                case AttributeControlType.Datepicker:
                {
                    //keep in mind my that the code below works only in the current culture
                    var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                    if (selectedDateStr.Count > 0)
                    {
                        DateTime selectedDate;
                        if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture,
                                                   DateTimeStyles.None, out selectedDate))
                        {
                            //successfully parsed
                            attributeModel.SelectedDay   = selectedDate.Day;
                            attributeModel.SelectedMonth = selectedDate.Month;
                            attributeModel.SelectedYear  = selectedDate.Year;
                        }
                    }
                }
                break;

                default:
                    break;
                }

                model.CheckoutAttributes.Add(attributeModel);
            }

            #endregion

            #region Estimate shipping

            if (prepareEstimateShippingIfEnabled)
            {
                model.EstimateShipping.Enabled = cart.Count > 0 && cart.RequiresShipping() && _shippingSettings.EstimateShippingEnabled;
                if (model.EstimateShipping.Enabled)
                {
                    //countries
                    int?defaultEstimateCountryId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.CountryId : model.EstimateShipping.CountryId;
                    model.EstimateShipping.AvailableCountries.Add(new SelectListItem {
                        Text = _localizationService.GetResource("Address.SelectCountry"), Value = "0"
                    });
                    foreach (var c in _countryService.GetAllCountriesForShipping())
                    {
                        model.EstimateShipping.AvailableCountries.Add(new SelectListItem
                        {
                            Text     = c.GetLocalized(x => x.Name),
                            Value    = c.Id.ToString(),
                            Selected = c.Id == defaultEstimateCountryId
                        });
                    }
                    //states
                    int?defaultEstimateStateId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.StateProvinceId : model.EstimateShipping.StateProvinceId;
                    var states = defaultEstimateCountryId.HasValue ? _stateProvinceService.GetStateProvincesByCountryId(defaultEstimateCountryId.Value).ToList() : new List <StateProvince>();
                    if (states.Count > 0)
                    {
                        foreach (var s in states)
                        {
                            model.EstimateShipping.AvailableStates.Add(new SelectListItem
                            {
                                Text     = s.GetLocalized(x => x.Name),
                                Value    = s.Id.ToString(),
                                Selected = s.Id == defaultEstimateStateId
                            });
                        }
                    }
                    else
                    {
                        model.EstimateShipping.AvailableStates.Add(new SelectListItem {
                            Text = _localizationService.GetResource("Address.OtherNonUS"), Value = "0"
                        });
                    }

                    if (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null)
                    {
                        model.EstimateShipping.ZipPostalCode = _workContext.CurrentCustomer.ShippingAddress.ZipPostalCode;
                    }
                }
            }

            #endregion

            #region Cart items

            foreach (var sci in cart)
            {
                var cartItemModel = new ShoppingCartModel.ShoppingCartItemModel
                {
                    Id            = sci.Id,
                    Sku           = sci.Product.FormatSku(sci.AttributesXml, _productAttributeParser),
                    ProductId     = sci.Product.Id,
                    ProductName   = sci.Product.GetLocalized(x => x.Name),
                    ProductSeName = sci.Product.GetSeName(),
                    Quantity      = sci.Quantity,
                    AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.Product, sci.AttributesXml),
                };

                //allow editing?
                //1. setting enabled?
                //2. simple product?
                //3. has attribute or gift card?
                //4. visible individually?
                cartItemModel.AllowItemEditing = _shoppingCartSettings.AllowCartItemEditing &&
                                                 sci.Product.ProductType == ProductType.SimpleProduct &&
                                                 (!String.IsNullOrEmpty(cartItemModel.AttributeInfo) || sci.Product.IsGiftCard) &&
                                                 sci.Product.VisibleIndividually;

                //allowed quantities
                var allowedQuantities = sci.Product.ParseAllowedQuatities();
                foreach (var qty in allowedQuantities)
                {
                    cartItemModel.AllowedQuantities.Add(new SelectListItem
                    {
                        Text     = qty.ToString(),
                        Value    = qty.ToString(),
                        Selected = sci.Quantity == qty
                    });
                }

                //recurring info
                if (sci.Product.IsRecurring)
                {
                    cartItemModel.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"), sci.Product.RecurringCycleLength, sci.Product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext));
                }

                //rental info
                if (sci.Product.IsRental)
                {
                    var rentalStartDate = sci.RentalStartDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalStartDateUtc.Value) : "";
                    var rentalEndDate   = sci.RentalEndDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalEndDateUtc.Value) : "";
                    cartItemModel.RentalInfo = string.Format(_localizationService.GetResource("ShoppingCart.Rental.FormattedDate"),
                                                             rentalStartDate, rentalEndDate);
                }

                //unit prices
                if (sci.Product.CallForPrice)
                {
                    cartItemModel.UnitPrice = _localizationService.GetResource("Products.CallForPrice");
                }
                else
                {
                    decimal taxRate;
                    decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci), out taxRate);
                    decimal shoppingCartUnitPriceWithDiscount     = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency);
                    cartItemModel.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount);
                }
                //subtotal, discount
                if (sci.Product.CallForPrice)
                {
                    cartItemModel.SubTotal = _localizationService.GetResource("Products.CallForPrice");
                }
                else
                {
                    //sub total
                    Discount scDiscount;
                    decimal  shoppingCartItemDiscountBase;
                    decimal  taxRate;
                    decimal  shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, true, out shoppingCartItemDiscountBase, out scDiscount), out taxRate);
                    decimal  shoppingCartItemSubTotalWithDiscount     = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);
                    cartItemModel.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount);

                    //display an applied discount amount
                    if (scDiscount != null)
                    {
                        shoppingCartItemDiscountBase = _taxService.GetProductPrice(sci.Product, shoppingCartItemDiscountBase, out taxRate);
                        if (shoppingCartItemDiscountBase > decimal.Zero)
                        {
                            decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency);
                            cartItemModel.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount);
                        }
                    }
                }



                //item warnings
                var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings(
                    _workContext.CurrentCustomer,
                    sci.ShoppingCartType,
                    sci.Product,
                    sci.StoreId,
                    sci.AttributesXml,
                    sci.CustomerEnteredPrice,
                    sci.RentalStartDateUtc,
                    sci.RentalEndDateUtc,
                    sci.Quantity,
                    false);
                foreach (var warning in itemWarnings)
                {
                    cartItemModel.Warnings.Add(warning);
                }

                model.Items.Add(cartItemModel);
            }

            #endregion

            #region Button payment methods

            var paymentMethods = _paymentService
                                 .LoadActivePaymentMethods(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id)
                                 .Where(pm => pm.PaymentMethodType == PaymentMethodType.Button)
                                 .Where(pm => !pm.HidePaymentMethod(cart))
                                 .ToList();
            foreach (var pm in paymentMethods)
            {
                if (cart.IsRecurring() && pm.RecurringPaymentType == RecurringPaymentType.NotSupported)
                {
                    continue;
                }

                string actionName;
                string controllerName;
                RouteValueDictionary routeValues;
                pm.GetPaymentInfoRoute(out actionName, out controllerName, out routeValues);

                model.ButtonPaymentMethodActionNames.Add(actionName);
                model.ButtonPaymentMethodControllerNames.Add(controllerName);
                model.ButtonPaymentMethodRouteValues.Add(routeValues);
            }

            #endregion

            #region Order review data

            if (prepareAndDisplayOrderReviewData)
            {
                model.OrderReviewData.Display = true;

                //billing info
                var billingAddress = _workContext.CurrentCustomer.BillingAddress;
                if (billingAddress != null)
                {
                    model.OrderReviewData.BillingAddress.PrepareModel(
                        address: billingAddress,
                        excludeProperties: false,
                        addressSettings: _addressSettings,
                        addressAttributeFormatter: _addressAttributeFormatter);
                }

                //shipping info
                if (cart.RequiresShipping())
                {
                    model.OrderReviewData.IsShippable = true;

                    if (_shippingSettings.AllowPickUpInStore)
                    {
                        model.OrderReviewData.SelectedPickUpInStore = _workContext.CurrentCustomer.GetAttribute <bool>(SystemCustomerAttributeNames.SelectedPickUpInStore, _storeContext.CurrentStore.Id);
                    }

                    if (!model.OrderReviewData.SelectedPickUpInStore)
                    {
                        var shippingAddress = _workContext.CurrentCustomer.ShippingAddress;
                        if (shippingAddress != null)
                        {
                            model.OrderReviewData.ShippingAddress.PrepareModel(
                                address: shippingAddress,
                                excludeProperties: false,
                                addressSettings: _addressSettings,
                                addressAttributeFormatter: _addressAttributeFormatter);
                        }
                    }


                    //selected shipping method
                    var shippingOption = _workContext.CurrentCustomer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id);
                    if (shippingOption != null)
                    {
                        model.OrderReviewData.ShippingMethod = shippingOption.Name;
                    }
                }
                //payment info
                var selectedPaymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute <string>(
                    SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id);
                var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(selectedPaymentMethodSystemName);
                model.OrderReviewData.PaymentMethod = paymentMethod != null?paymentMethod.GetLocalizedFriendlyName(_localizationService, _workContext.WorkingLanguage.Id) : "";
            }
            #endregion
        }
Exemplo n.º 11
0
 /// <summary>
 /// Gets checkout attribute value price
 /// </summary>
 /// <param name="cav">Checkout attribute value</param>
 /// <returns>Price</returns>
 public decimal GetCheckoutAttributePrice([FromBody] CheckoutAttributeValue cav)
 {
     return(_taxService.GetCheckoutAttributePrice(cav));
 }
Exemplo n.º 12
0
        /// <summary>
        /// Formats attributes
        /// </summary>
        /// <param name="attributes">Attributes</param>
        /// <param name="customer">Customer</param>
        /// <param name="serapator">Serapator</param>
        /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param>
        /// <param name="renderPrices">A value indicating whether to render prices</param>
        /// <returns>Attributes</returns>
        public string FormatAttributes(string attributes,
                                       Customer customer,
                                       string serapator  = "<br />",
                                       bool htmlEncode   = true,
                                       bool renderPrices = true)
        {
            var result = new StringBuilder();

            var caCollection = _checkoutAttributeParser.ParseCheckoutAttributes(attributes);

            for (int i = 0; i < caCollection.Count; i++)
            {
                var ca        = caCollection[i];
                var valuesStr = _checkoutAttributeParser.ParseValues(attributes, ca.Id);
                for (int j = 0; j < valuesStr.Count; j++)
                {
                    string valueStr    = valuesStr[j];
                    string caAttribute = string.Empty;
                    if (!ca.ShouldHaveValues())
                    {
                        if (ca.AttributeControlType == AttributeControlType.MultilineTextbox)
                        {
                            caAttribute = string.Format("{0}: {1}", ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), HtmlHelper.FormatText(valueStr, false, true, true, false, false, false));
                        }
                        else
                        {
                            caAttribute = string.Format("{0}: {1}", ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), valueStr);
                        }
                    }
                    else
                    {
                        int caId = 0;
                        if (int.TryParse(valueStr, out caId))
                        {
                            var caValue = _checkoutAttributeService.GetCheckoutAttributeValueById(caId);
                            if (caValue != null)
                            {
                                caAttribute = string.Format("{0}: {1}", ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), caValue.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id));
                                if (renderPrices)
                                {
                                    decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(caValue, customer);
                                    decimal priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
                                    if (priceAdjustmentBase > 0)
                                    {
                                        string priceAdjustmentStr = _priceFormatter.FormatPrice(priceAdjustment);
                                        caAttribute += string.Format(" [+{0}]", priceAdjustmentStr);
                                    }
                                }
                            }
                        }
                    }

                    if (!String.IsNullOrEmpty(caAttribute))
                    {
                        if (i != 0 || j != 0)
                        {
                            result.Append(serapator);
                        }

                        //we don't encode multiline textbox input
                        if (htmlEncode &&
                            ca.AttributeControlType != AttributeControlType.MultilineTextbox)
                        {
                            result.Append(HttpUtility.HtmlEncode(caAttribute));
                        }
                        else
                        {
                            result.Append(caAttribute);
                        }
                    }
                }
            }

            return(result.ToString());
        }
Exemplo n.º 13
0
        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //Base URL
            var builder = new StringBuilder();

            builder.Append(GetMonerisUrl());

            //Store Id and security token
            builder.AppendFormat("?ps_store_id={0}&hpp_key={1}", HttpUtility.UrlEncode(_monerisStandardPaymentSettings.StoreId), HttpUtility.UrlEncode(_monerisStandardPaymentSettings.PdtToken));

            //OrderId
            builder.AppendFormat("&order_id={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.Id.ToString()));

            //Email
            builder.AppendFormat("&email={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.Customer.Email));

            //UserName
            builder.AppendFormat("&cust_id={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.Customer.Username));

            //Language
            string lang = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;

            if (lang.Contains("fr"))
            {
                lang = "fr-ca";
            }
            builder.AppendFormat("&lang={0}", HttpUtility.UrlEncode(lang));

            //Billing address
            if (!(postProcessPaymentRequest.Order.BillingAddress == null))
            {
                builder.AppendFormat("&bill_first_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.FirstName));
                builder.AppendFormat("&bill_last_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.LastName));
                builder.AppendFormat("&bill_address_one={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Address1 + " " + postProcessPaymentRequest.Order.BillingAddress.Address2));
                builder.AppendFormat("&bill_city={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.City));
                builder.AppendFormat("&bill_state_or_province={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.StateProvince.Abbreviation));
                builder.AppendFormat("&bill_postal_code={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.ZipPostalCode));
                builder.AppendFormat("&bill_country={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Country.TwoLetterIsoCode));
                builder.AppendFormat("&bill_phone={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.PhoneNumber));
            }

            //Shipping address
            if (!(postProcessPaymentRequest.Order.ShippingAddress == null))
            {
                builder.AppendFormat("&ship_first_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.FirstName));
                builder.AppendFormat("&ship_last_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.LastName));
                builder.AppendFormat("&ship_address_one={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.Address1 + " " + postProcessPaymentRequest.Order.ShippingAddress.Address2));
                builder.AppendFormat("&ship_city={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.City));
                builder.AppendFormat("&ship_state_or_province={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.StateProvince.Abbreviation));
                builder.AppendFormat("&ship_postal_code={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.ZipPostalCode));
                builder.AppendFormat("&ship_country={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.Country.TwoLetterIsoCode));
                builder.AppendFormat("&ship_phone={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.PhoneNumber));
            }

            //Shipping
            var shippingPriceExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
            var shippingPriceExclTaxRounded = Math.Round(shippingPriceExclTax, 2);

            builder.AppendFormat("&shipping_cost={0}", shippingPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

            //Send items detail
            if (_monerisStandardPaymentSettings.PassProductNamesAndTotals)
            {
                //Yes

                //get the items in the cart
                var cartItems = postProcessPaymentRequest.Order.OrderItems;
                int x         = 1;
                foreach (var item in cartItems)
                {
                    //round unit price
                    var unitPriceExclTax        = item.UnitPriceExclTax;
                    var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);

                    //round subtotal
                    var priceExclTax        = item.PriceExclTax;
                    var priceExclTaxRounded = Math.Round(priceExclTax, 2);

                    //id
                    builder.AppendFormat("&id" + x + "={0}", HttpUtility.UrlEncode(item.Product.Sku));

                    //description
                    builder.AppendFormat("&description" + x + "={0}", HttpUtility.UrlEncode(item.Product.Name));

                    //quantity
                    builder.AppendFormat("&quantity" + x + "={0}", item.Quantity);

                    //unitprice
                    builder.AppendFormat("&price" + x + "={0}", unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

                    //subtotal
                    builder.AppendFormat("&subtotal" + x + "={0}", priceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

                    //Video project participation
                    if (item.Product.Sku == CameleoEventProducts.PRODUCT_VIDEO_PROJECT)
                    {
                        //Yes
                        //_genericAttributeService.SaveAttribute<ShippingOption>(customer, SystemCustomerAttributeNames.DiscountCouponCode, null);
                    }

                    x++;
                }

                //the checkout attributes that have a dollar value and send them to Moneris as items to be paid for
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
                foreach (var val in caValues)
                {
                    var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                    //round
                    var attPriceRounded = Math.Round(attPrice, 2);
                    if (attPrice > decimal.Zero) //if it has a price
                    {
                        var ca = val.CheckoutAttribute;
                        if (ca != null)
                        {
                            var attName = ca.Name; //set the name

                            //id
                            builder.AppendFormat("&id" + x + "={0}", HttpUtility.UrlEncode(attName));

                            //description
                            builder.AppendFormat("&description" + x + "={0}", HttpUtility.UrlEncode(attName));

                            //quantity
                            builder.AppendFormat("&quantity" + x + "={0}", 1);

                            //unitprice
                            builder.AppendFormat("&price" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture));

                            //subtotal
                            builder.AppendFormat("&subtotal" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture));


                            x++;
                        }
                    }
                }
            }
            else
            {
                //pass order total only
            }

            //Charge Total
            var totalPriceInclTax        = postProcessPaymentRequest.Order.OrderTotal;
            var totalPriceInclTaxRounded = Math.Round(totalPriceInclTax, 2);

            builder.AppendFormat("&charge_total={0}", totalPriceInclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

            var totalPriceExclTax        = postProcessPaymentRequest.Order.OrderTotal - postProcessPaymentRequest.Order.OrderTax;
            var totalPriceExclTaxRounded = Math.Round(totalPriceExclTax, 2);


            string provinceAbbrev = postProcessPaymentRequest.Order.BillingAddress.StateProvince.Abbreviation;

            if (provinceAbbrev.Contains("QC"))
            {
                //Quebec
                //GST
                var totalGST        = totalPriceExclTax * (decimal)0.05;
                var totalGSTRounded = Math.Round(totalGST, 2);
                builder.AppendFormat("&gst={0}", totalGSTRounded.ToString("0.00", CultureInfo.InvariantCulture));

                //PST
                var totalPST        = totalPriceExclTax * (decimal)0.09975;
                var totalPSTRounded = Math.Round(totalPST, 2);
                builder.AppendFormat("&pst={0}", totalPSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("ON") || provinceAbbrev.Contains("NL") || provinceAbbrev.Contains("TNL") || provinceAbbrev.Contains("NB"))
            {
                //HST 13
                var totalHST        = totalPriceExclTax * (decimal)0.13;
                var totalHSTRounded = Math.Round(totalHST, 2);
                builder.AppendFormat("&hst={0}", totalHSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("NS") || provinceAbbrev.Contains("NE"))
            {
                //HST 15
                var totalHST        = totalPriceExclTax * (decimal)0.15;
                var totalHSTRounded = Math.Round(totalHST, 2);
                builder.AppendFormat("&hst={0}", totalHSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("PE") || provinceAbbrev.Contains("PEI") || provinceAbbrev.Contains("IPE"))
            {
                //HST 14
                var totalHST        = totalPriceExclTax * (decimal)0.14;
                var totalHSTRounded = Math.Round(totalHST, 2);
                builder.AppendFormat("&hst={0}", totalHSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("BC") || provinceAbbrev.Contains("CB") || provinceAbbrev.Contains("AB") || provinceAbbrev.Contains("SK") || provinceAbbrev.Contains("MB") || provinceAbbrev.Contains("NT") || provinceAbbrev.Contains("TNO") || provinceAbbrev.Contains("NU") || provinceAbbrev.Contains("YT") || provinceAbbrev.Contains("YU"))
            {
                //GST only
                var totalGST        = totalPriceExclTax * (decimal)0.05;
                var totalGSTRounded = Math.Round(totalGST, 2);
                builder.AppendFormat("&gst={0}", totalGSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }

            //Redirect
            _httpContext.Response.Redirect(builder.ToString());
        }
Exemplo n.º 14
0
        private void AddInvoiceVars(Dictionary <string, string> vars, PostProcessPaymentRequest postProcessPaymentRequest)
        {
            // article for invoice vars:  http://kb.cardcom.co.il/article/AA-00244/0
            var customer  = _workContext.CurrentCustomer;
            var firstName = customer.GetAttribute <string>(SystemCustomerAttributeNames.FirstName);
            var lastName  = customer.GetAttribute <string>(SystemCustomerAttributeNames.LastName);

            // customer info :
            vars["InvoiceHead.CustName"]        = firstName + " " + lastName; // customer name
            vars["InvoiceHead.SendByEmail"]     = "true";                     // will the invoice be send by email to the customer
            vars["InvoiceHead.Language"]        = GetLanguageNameInvoice(_workContext.WorkingLanguage.UniqueSeoCode);
            vars["InvoiceHead.CoinID"]          = GetCurrencyIdByCurrencyName(_currencyService.GetCurrencyById(_workContext.WorkingCurrency.Id).CurrencyCode).ToString();
            vars["InvoiceHead.Email"]           = postProcessPaymentRequest.Order.BillingAddress.Email; // value that will be return and save in CardCom system
            vars["InvoiceHead.CustAddresLine1"] = postProcessPaymentRequest.Order.BillingAddress.Address1;
            vars["InvoiceHead.CustAddresLine2"] = postProcessPaymentRequest.Order.BillingAddress.Address2;
            vars["InvoiceHead.CustCity"]        = postProcessPaymentRequest.Order.BillingAddress.City;
            vars["InvoiceHead.CustLinePH"]      = postProcessPaymentRequest.Order.BillingAddress.PhoneNumber;

            //get the items in the cart
            decimal cartTotal  = decimal.Zero;
            var     cartItems  = postProcessPaymentRequest.Order.OrderItems;
            int     itemsCount = 1;

            foreach (var item in cartItems) //50 chars limit
            {
                var unitPriceExclTax = item.UnitPriceExclTax;
                var priceExclTax     = item.PriceExclTax;
                //round
                var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);
                if (item.Product.WeightProduct)
                {
                    if (item.Product.ByUnit.HasValue && item.Product.ByUnit.Value == true)
                    {
                        vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"] = HttpUtility.UrlEncode((item.Quantity).ToString() + " " + "יחידות");
                        vars["InvoiceLines" + itemsCount.ToString() + ".Price"]    = Math.Round(item.Product.UnitPrice.Value).ToString("0.00", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"] = HttpUtility.UrlEncode((item.Quantity * item.Product.BaseWeight.Value).ToString() + " " + item.Product.WeightUnit);
                        vars["InvoiceLines" + itemsCount.ToString() + ".Price"]    = unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"] = HttpUtility.UrlEncode(item.Quantity.ToString());
                    vars["InvoiceLines" + itemsCount.ToString() + ".Price"]    = unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                }

                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = HttpUtility.UrlEncode(item.Product.Name);
                vars["InvoiceLines" + itemsCount.ToString() + ".ProductID"]   = (String.IsNullOrWhiteSpace(item.Product.Sku)) ? item.Product.Sku : "";

                itemsCount++;
                cartTotal += priceExclTax;
            }
            //the checkout attributes that have a dollar value and send them to CardCom as items to be paid for
            var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);

            foreach (var val in caValues)
            {
                var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                //round
                var attPriceRounded = Math.Round(attPrice, 2);
                if (attPrice > decimal.Zero) //if it has a price
                {
                    var ca = val.CheckoutAttribute;
                    if (ca != null)
                    {
                        var attName = ca.Name;                                                                                                          //set the name
                        vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = HttpUtility.UrlEncode(attName);
                        vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture); //amount
                        vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1";                                                            //quantity
                        itemsCount++;
                        cartTotal += attPrice;
                    }
                }
            }
            //order totals

            //shipping
            var orderShippingExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
            var orderShippingExclTaxRounded = Math.Round(orderShippingExclTax, 2);

            if (orderShippingExclTax > decimal.Zero)
            {
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.ShippingFee");
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = orderShippingExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1"; //quantity
                itemsCount++;
                cartTotal += orderShippingExclTax;
            }

            //payment method additional fee
            var paymentMethodAdditionalFeeExclTax        = postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
            var paymentMethodAdditionalFeeExclTaxRounded = Math.Round(paymentMethodAdditionalFeeExclTax, 2);

            if (paymentMethodAdditionalFeeExclTax > decimal.Zero)
            {
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.PaymentMethodFee");
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = paymentMethodAdditionalFeeExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1"; //quantity
                itemsCount++;
                cartTotal += paymentMethodAdditionalFeeExclTax;
            }
            //tax
            var orderTax        = postProcessPaymentRequest.Order.OrderTax;
            var orderTaxRounded = Math.Round(orderTax, 2);

            if (orderTax > decimal.Zero)
            {
                //add tax as item
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.SalesTax"); //name
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = orderTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);        //amount
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1";                                                                   //quantity

                cartTotal += orderTax;
                itemsCount++;
            }

            if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
            {
                /* Take the difference between what the order total is and what it should be and use that as the "discount".
                 * The difference equals the amount of the gift card and/or reward points used.
                 */
                decimal discountTotal = cartTotal - postProcessPaymentRequest.Order.OrderTotal;
                discountTotal = Math.Round(discountTotal, 2) * (-1);
                //gift card or rewared point amount applied to cart in nopCommerce - shows in Paypal as "discount"
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.Discount"); //name
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = discountTotal.ToString("0.00", CultureInfo.InvariantCulture);
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1";                                                                   //quantity
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Formats attributes
        /// </summary>
        /// <param name="attributes">Attributes</param>
        /// <param name="customer">Customer</param>
        /// <param name="serapator">Serapator</param>
        /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param>
        /// <param name="renderPrices">A value indicating whether to render prices</param>
        /// <param name="allowHyperlinks">A value indicating whether to HTML hyperink tags could be rendered (if required)</param>
        /// <returns>Attributes</returns>
        public string FormatAttributes(string attributes,
                                       Customer customer,
                                       string serapator     = "<br />",
                                       bool htmlEncode      = true,
                                       bool renderPrices    = true,
                                       bool allowHyperlinks = true)
        {
            var result = new StringBuilder();

            var caCollection = _checkoutAttributeParser.ParseCheckoutAttributes(attributes);

            if (caCollection.Count <= 0)
            {
                return(null);
            }
            for (int i = 0; i < caCollection.Count; i++)
            {
                var ca        = caCollection[i];
                var valuesStr = _checkoutAttributeParser.ParseValues(attributes, ca.Id);
                for (int j = 0; j < valuesStr.Count; j++)
                {
                    string valueStr    = valuesStr[j];
                    string caAttribute = "";
                    if (!ca.ShouldHaveValues())
                    {
                        //no values
                        if (ca.AttributeControlType == AttributeControlType.MultilineTextbox)
                        {
                            //multiline textbox
                            string attributeName = ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                attributeName = HttpUtility.HtmlEncode(attributeName);
                            }

                            caAttribute = string.Format("{0}: {1}", attributeName,
                                                        HtmlUtils.ConvertPlainTextToHtml(valueStr.EmptyNull().Replace(":", "").HtmlEncode()));

                            //we never encode multiline textbox input
                        }
                        else if (ca.AttributeControlType == AttributeControlType.FileUpload)
                        {
                            //file upload
                            Guid downloadGuid;
                            Guid.TryParse(valueStr, out downloadGuid);
                            var download = _downloadService.GetDownloadByGuid(downloadGuid);
                            if (download?.MediaFile != null)
                            {
                                //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs)
                                string attributeText = "";
                                var    fileName      = download.MediaFile.Name;
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    fileName = HttpUtility.HtmlEncode(fileName);
                                }
                                if (allowHyperlinks)
                                {
                                    //hyperlinks are allowed
                                    var downloadLink = string.Format("{0}download/getfileupload/?downloadId={1}", _webHelper.GetStoreLocation(false), download.DownloadGuid);
                                    attributeText = string.Format("<a href=\"{0}\" class=\"fileuploadattribute\">{1}</a>", downloadLink, fileName);
                                }
                                else
                                {
                                    //hyperlinks aren't allowed
                                    attributeText = fileName;
                                }
                                string attributeName = ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage);
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    attributeName = HttpUtility.HtmlEncode(attributeName);
                                }
                                caAttribute = string.Format("{0}: {1}", attributeName, attributeText);
                            }
                        }
                        else
                        {
                            //other attributes (textbox, datepicker)
                            caAttribute = string.Format("{0}: {1}", ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage), valueStr);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                caAttribute = HttpUtility.HtmlEncode(caAttribute);
                            }
                        }
                    }
                    else
                    {
                        int caId = 0;
                        if (int.TryParse(valueStr, out caId))
                        {
                            var caValue = _checkoutAttributeService.GetCheckoutAttributeValueById(caId);
                            if (caValue != null)
                            {
                                caAttribute = string.Format("{0}: {1}", ca.GetLocalized(a => a.Name, _workContext.WorkingLanguage), caValue.GetLocalized(a => a.Name, _workContext.WorkingLanguage));
                                if (renderPrices)
                                {
                                    decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(caValue, customer);
                                    decimal priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
                                    if (priceAdjustmentBase > 0)
                                    {
                                        string priceAdjustmentStr = _priceFormatter.FormatPrice(priceAdjustment);
                                        caAttribute += string.Format(" [+{0}]", priceAdjustmentStr);
                                    }
                                }
                            }
                            //encode (if required)
                            if (htmlEncode)
                            {
                                caAttribute = HttpUtility.HtmlEncode(caAttribute);
                            }
                        }
                    }

                    if (!String.IsNullOrEmpty(caAttribute))
                    {
                        if (i != 0 || j != 0)
                        {
                            result.Append(serapator);
                        }
                        result.Append(caAttribute);
                    }
                }
            }

            return(result.ToString());
        }
Exemplo n.º 16
0
        /// <summary>
        /// Gets shopping cart subtotal
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="includingTax">A value indicating whether calculated price should include tax</param>
        /// <param name="discountAmount">Applied discount amount</param>
        /// <param name="appliedDiscount">Applied discount</param>
        /// <param name="subTotalWithoutDiscount">Sub total (without discount)</param>
        /// <param name="subTotalWithDiscount">Sub total (with discount)</param>
        /// <param name="taxRates">Tax rates (of order sub total)</param>
        public virtual void GetShoppingCartSubTotal(IList <ShoppingCartItem> cart,
                                                    bool includingTax,
                                                    out decimal discountAmount, out Discount appliedDiscount,
                                                    out decimal subTotalWithoutDiscount, out decimal subTotalWithDiscount,
                                                    out SortedDictionary <decimal, decimal> taxRates)
        {
            discountAmount          = decimal.Zero;
            appliedDiscount         = null;
            subTotalWithoutDiscount = decimal.Zero;
            subTotalWithDiscount    = decimal.Zero;
            taxRates = new SortedDictionary <decimal, decimal>();

            if (cart.Count == 0)
            {
                return;
            }

            //get the customer
            Customer customer = cart.GetCustomer();

            //sub totals
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;

            foreach (var shoppingCartItem in cart)
            {
                decimal taxRate     = decimal.Zero;
                decimal sciSubTotal = _priceCalculationService.GetSubTotal(shoppingCartItem, true);

                decimal sciExclTax = _taxService.GetProductPrice(shoppingCartItem.ProductVariant, sciSubTotal, false, customer, out taxRate);
                decimal sciInclTax = _taxService.GetProductPrice(shoppingCartItem.ProductVariant, sciSubTotal, true, customer, out taxRate);
                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                decimal sciTax = sciInclTax - sciExclTax;
                if (taxRate > decimal.Zero && sciTax > decimal.Zero)
                {
                    if (!taxRates.ContainsKey(taxRate))
                    {
                        taxRates.Add(taxRate, sciTax);
                    }
                    else
                    {
                        taxRates[taxRate] = taxRates[taxRate] + sciTax;
                    }
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var checkoutAttributesXml = customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService);
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                if (caValues != null)
                {
                    foreach (var caValue in caValues)
                    {
                        decimal taxRate = decimal.Zero;

                        decimal caExclTax = _taxService.GetCheckoutAttributePrice(caValue, false, customer, out taxRate);
                        decimal caInclTax = _taxService.GetCheckoutAttributePrice(caValue, true, customer, out taxRate);
                        subTotalExclTaxWithoutDiscount += caExclTax;
                        subTotalInclTaxWithoutDiscount += caInclTax;

                        //tax rates
                        decimal caTax = caInclTax - caExclTax;
                        if (taxRate > decimal.Zero && caTax > decimal.Zero)
                        {
                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, caTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + caTax;
                            }
                        }
                    }
                }
            }

            //subtotal without discount
            if (includingTax)
            {
                subTotalWithoutDiscount = subTotalInclTaxWithoutDiscount;
            }
            else
            {
                subTotalWithoutDiscount = subTotalExclTaxWithoutDiscount;
            }
            if (subTotalWithoutDiscount < decimal.Zero)
            {
                subTotalWithoutDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithoutDiscount = Math.Round(subTotalWithoutDiscount, 2);
            }

            /*We calculate discount amount on order subtotal excl tax (discount first)*/
            //calculate discount amount ('Applied to order subtotal' discount)
            decimal discountAmountExclTax = GetOrderSubtotalDiscount(customer, subTotalExclTaxWithoutDiscount, out appliedDiscount);

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            decimal discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            Dictionary <decimal, decimal> tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates)
            {
                decimal taxRate  = kvp.Key;
                decimal taxValue = kvp.Value;

                if (taxValue != decimal.Zero)
                {
                    //discount the tax amount that applies to subtotal items
                    if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                    {
                        decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                        discountAmountInclTax += discountTax;
                        taxValue = taxRates[taxRate] - discountTax;
                        if (_shoppingCartSettings.RoundPricesDuringCalculation)
                        {
                            taxValue = Math.Round(taxValue, 2);
                        }
                        taxRates[taxRate] = taxValue;
                    }

                    //subtotal with discount (incl tax)
                    subTotalInclTaxWithDiscount += taxValue;
                }
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                discountAmountInclTax = Math.Round(discountAmountInclTax, 2);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

            //round
            if (subTotalWithDiscount < decimal.Zero)
            {
                subTotalWithDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithDiscount = Math.Round(subTotalWithDiscount, 2);
            }
        }
        /// <summary>
        /// Add order items to the request query parameters
        /// </summary>
        /// <param name="parameters">Query parameters</param>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        private async Task AddItemsParameters(IDictionary <string, string> parameters, Order order)
        {
            //upload order items
            parameters.Add("cmd", "_cart");
            parameters.Add("upload", "1");

            double cartTotal        = 0;
            double roundedCartTotal = 0;
            var    itemCount        = 1;

            //add shopping cart items
            foreach (var item in order.OrderItems)
            {
                var product = await _productService.GetProductById(item.ProductId);

                var roundedItemPrice = Math.Round(item.UnitPriceExclTax, 2);

                //add query parameters
                parameters.Add($"item_name_{itemCount}", product.Name);
                parameters.Add($"amount_{itemCount}", roundedItemPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", item.Quantity.ToString());

                cartTotal        += (item.PriceExclTax);
                roundedCartTotal += roundedItemPrice * item.Quantity;
                itemCount++;
            }

            //add checkout attributes as order items
            var checkoutAttributeValues = await _checkoutAttributeParser.ParseCheckoutAttributeValue(order.CheckoutAttributes);

            var currencyService = _serviceProvider.GetRequiredService <ICurrencyService>();
            var workContext     = _serviceProvider.GetRequiredService <IWorkContext>();
            var customer        = await _serviceProvider.GetRequiredService <ICustomerService>().GetCustomerById(order.CustomerId);

            foreach (var attributeValue in checkoutAttributeValues)
            {
                var attributePrice = await _taxService.GetCheckoutAttributePrice(attributeValue.ca, attributeValue.cav, false, customer);

                if (attributePrice.checkoutPrice > 0)
                {
                    double roundedAttributePrice = Math.Round(await currencyService.ConvertFromPrimaryStoreCurrency(attributePrice.checkoutPrice, workContext.WorkingCurrency), 2);
                    //add query parameters
                    if (attributeValue.ca != null)
                    {
                        parameters.Add($"item_name_{itemCount}", attributeValue.ca.Name);
                        parameters.Add($"amount_{itemCount}", roundedAttributePrice.ToString("0.00", CultureInfo.InvariantCulture));
                        parameters.Add($"quantity_{itemCount}", "1");

                        cartTotal        += attributePrice.checkoutPrice;
                        roundedCartTotal += roundedAttributePrice;
                        itemCount++;
                    }
                }
            }

            //add shipping fee as a separate order item, if it has price
            var roundedShippingPrice = Math.Round(order.OrderShippingExclTax, 2);

            if (roundedShippingPrice > 0)
            {
                parameters.Add($"item_name_{itemCount}", "Shipping fee");
                parameters.Add($"amount_{itemCount}", roundedShippingPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += (order.OrderShippingExclTax);
                roundedCartTotal += roundedShippingPrice;
                itemCount++;
            }

            //add payment method additional fee as a separate order item, if it has price
            var roundedPaymentMethodPrice = Math.Round(order.PaymentMethodAdditionalFeeExclTax, 2);

            if (roundedPaymentMethodPrice > 0)
            {
                parameters.Add($"item_name_{itemCount}", "Payment method fee");
                parameters.Add($"amount_{itemCount}", roundedPaymentMethodPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += (order.PaymentMethodAdditionalFeeExclTax);
                roundedCartTotal += roundedPaymentMethodPrice;
                itemCount++;
            }

            //add tax as a separate order item, if it has positive amount
            var roundedTaxAmount = Math.Round(order.OrderTax, 2);

            if (roundedTaxAmount > 0)
            {
                parameters.Add($"item_name_{itemCount}", "Tax amount");
                parameters.Add($"amount_{itemCount}", roundedTaxAmount.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += (order.OrderTax);
                roundedCartTotal += roundedTaxAmount;
                itemCount++;
            }

            if (cartTotal > order.OrderTotal)
            {
                //get the difference between what the order total is and what it should be and use that as the "discount"
                var discountTotal = Math.Round(cartTotal - (order.OrderTotal), 2);
                roundedCartTotal -= discountTotal;

                //gift voucher or loyalty points amount applied to cart in nopCommerce - shows in PayPal as "discount"
                parameters.Add("discount_amount_cart", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
            }

            //save order total that actually sent to PayPal (used for PDT order total validation)
            await _userFieldService.SaveField(order, PaypalHelper.OrderTotalSentToPayPal, roundedCartTotal);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Formats attributes
        /// </summary>
        /// <param name="attributesXml">Attributes in XML format</param>
        /// <param name="customer">Customer</param>
        /// <param name="serapator">Serapator</param>
        /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param>
        /// <param name="renderPrices">A value indicating whether to render prices</param>
        /// <param name="allowHyperlinks">A value indicating whether to HTML hyperink tags could be rendered (if required)</param>
        /// <returns>Attributes</returns>
        public virtual string FormatAttributes(string attributesXml,
                                               Customer customer,
                                               string serapator     = "<br />",
                                               bool htmlEncode      = true,
                                               bool renderPrices    = true,
                                               bool allowHyperlinks = true)
        {
            var result = new StringBuilder();

            var attributes = _checkoutAttributeParser.ParseCheckoutAttributes(attributesXml);

            for (int i = 0; i < attributes.Count; i++)
            {
                var attribute = attributes[i];
                var valuesStr = _checkoutAttributeParser.ParseValues(attributesXml, attribute.Id);
                for (int j = 0; j < valuesStr.Count; j++)
                {
                    string valueStr           = valuesStr[j];
                    string formattedAttribute = "";
                    if (!attribute.ShouldHaveValues())
                    {
                        //no values
                        if (attribute.AttributeControlType == AttributeControlType.MultilineTextbox)
                        {
                            //multiline textbox
                            var attributeName = attribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                attributeName = HttpUtility.HtmlEncode(attributeName);
                            }
                            formattedAttribute = string.Format("{0}: {1}", attributeName, HtmlHelper.FormatText(valueStr, false, true, false, false, false, false));
                            //we never encode multiline textbox input
                        }
                        else if (attribute.AttributeControlType == AttributeControlType.FileUpload)
                        {
                            //file upload
                            Guid downloadGuid;
                            Guid.TryParse(valueStr, out downloadGuid);
                            var download = _downloadService.GetDownloadByGuid(downloadGuid);
                            if (download != null)
                            {
                                //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs)
                                string attributeText = "";
                                var    fileName      = string.Format("{0}{1}",
                                                                     download.Filename ?? download.DownloadGuid.ToString(),
                                                                     download.Extension);
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    fileName = HttpUtility.HtmlEncode(fileName);
                                }
                                if (allowHyperlinks)
                                {
                                    //hyperlinks are allowed
                                    var downloadLink = string.Format("{0}download/getfileupload/?downloadId={1}", _webHelper.GetStoreLocation(false), download.DownloadGuid);
                                    attributeText = string.Format("<a href=\"{0}\" class=\"fileuploadattribute\">{1}</a>", downloadLink, fileName);
                                }
                                else
                                {
                                    //hyperlinks aren't allowed
                                    attributeText = fileName;
                                }
                                var attributeName = attribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id);
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    attributeName = HttpUtility.HtmlEncode(attributeName);
                                }
                                formattedAttribute = string.Format("{0}: {1}", attributeName, attributeText);
                            }
                        }
                        else
                        {
                            //other attributes (textbox, datepicker)
                            formattedAttribute = string.Format("{0}: {1}", attribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), valueStr);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                formattedAttribute = HttpUtility.HtmlEncode(formattedAttribute);
                            }
                        }
                    }
                    else
                    {
                        int attributeValueId;
                        if (int.TryParse(valueStr, out attributeValueId))
                        {
                            var attributeValue = attribute.CheckoutAttributeValues.Where(x => x.Id == attributeValueId).FirstOrDefault(); //checkoutAttributeService.GetCheckoutAttributeValueById(attributeValueId);
                            if (attributeValue != null)
                            {
                                formattedAttribute = string.Format("{0}: {1}", attribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), attributeValue.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id));
                                if (renderPrices)
                                {
                                    decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(attributeValue, customer);
                                    decimal priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
                                    if (priceAdjustmentBase > 0)
                                    {
                                        string priceAdjustmentStr = _priceFormatter.FormatPrice(priceAdjustment);
                                        formattedAttribute += string.Format(" [+{0}]", priceAdjustmentStr);
                                    }
                                }
                            }
                            //encode (if required)
                            if (htmlEncode)
                            {
                                formattedAttribute = HttpUtility.HtmlEncode(formattedAttribute);
                            }
                        }
                    }

                    if (!String.IsNullOrEmpty(formattedAttribute))
                    {
                        if (i != 0 || j != 0)
                        {
                            result.Append(serapator);
                        }
                        result.Append(formattedAttribute);
                    }
                }
            }

            return(result.ToString());
        }
Exemplo n.º 19
0
        /// <summary>
        /// Formats attributes
        /// </summary>
        /// <param name="customAttributes">Attributes</param>
        /// <param name="customer">Customer</param>
        /// <param name="serapator">Serapator</param>
        /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param>
        /// <param name="renderPrices">A value indicating whether to render prices</param>
        /// <param name="allowHyperlinks">A value indicating whether to HTML hyperink tags could be rendered (if required)</param>
        /// <returns>Attributes</returns>
        public virtual async Task <string> FormatAttributes(IList <CustomAttribute> customAttributes,
                                                            Customer customer,
                                                            string serapator     = "<br />",
                                                            bool htmlEncode      = true,
                                                            bool renderPrices    = true,
                                                            bool allowHyperlinks = true)
        {
            var result = new StringBuilder();

            if (customAttributes == null || !customAttributes.Any())
            {
                return(result.ToString());
            }

            var attributes = await _checkoutAttributeParser.ParseCheckoutAttributes(customAttributes);

            for (int i = 0; i < attributes.Count; i++)
            {
                var attribute = attributes[i];
                var valuesStr = customAttributes.Where(x => x.Key == attribute.Id).Select(x => x.Value).ToList();
                for (var j = 0; j < valuesStr.Count; j++)
                {
                    var valueStr           = valuesStr[j];
                    var formattedAttribute = "";
                    if (!attribute.ShouldHaveValues())
                    {
                        //no values
                        if (attribute.AttributeControlTypeId == AttributeControlType.MultilineTextbox)
                        {
                            //multiline textbox
                            var attributeName = attribute.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                attributeName = WebUtility.HtmlEncode(attributeName);
                            }
                            formattedAttribute = string.Format("{0}: {1}", attributeName, FormatText.ConvertText(valueStr));
                            //we never encode multiline textbox input
                        }
                        else if (attribute.AttributeControlTypeId == AttributeControlType.FileUpload)
                        {
                            //file upload
                            Guid downloadGuid;
                            Guid.TryParse(valueStr, out downloadGuid);
                            var download = await _downloadService.GetDownloadByGuid(downloadGuid);

                            if (download != null)
                            {
                                string attributeText = "";
                                var    fileName      = string.Format("{0}{1}",
                                                                     download.Filename ?? download.DownloadGuid.ToString(),
                                                                     download.Extension);
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    fileName = WebUtility.HtmlEncode(fileName);
                                }
                                if (allowHyperlinks)
                                {
                                    //hyperlinks are allowed
                                    var downloadLink = string.Format("{0}/download/getfileupload/?downloadId={1}", _workContext.CurrentStore.Url.TrimEnd('/'), download.DownloadGuid);
                                    attributeText = string.Format("<a href=\"{0}\" class=\"fileuploadattribute\">{1}</a>", downloadLink, fileName);
                                }
                                else
                                {
                                    //hyperlinks aren't allowed
                                    attributeText = fileName;
                                }
                                var attributeName = attribute.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id);
                                //encode (if required)
                                if (htmlEncode)
                                {
                                    attributeName = WebUtility.HtmlEncode(attributeName);
                                }
                                formattedAttribute = string.Format("{0}: {1}", attributeName, attributeText);
                            }
                        }
                        else
                        {
                            //other attributes (textbox, datepicker)
                            formattedAttribute = string.Format("{0}: {1}", attribute.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id), valueStr);
                            //encode (if required)
                            if (htmlEncode)
                            {
                                formattedAttribute = WebUtility.HtmlEncode(formattedAttribute);
                            }
                        }
                    }
                    else
                    {
                        var attributeValue = attribute.CheckoutAttributeValues.Where(x => x.Id == valueStr).FirstOrDefault();
                        if (attributeValue != null)
                        {
                            formattedAttribute = string.Format("{0}: {1}", attribute.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id), attributeValue.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id));
                            if (renderPrices)
                            {
                                decimal priceAdjustmentBase = (await _taxService.GetCheckoutAttributePrice(attribute, attributeValue, customer)).checkoutPrice;
                                decimal priceAdjustment     = await _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);

                                if (priceAdjustmentBase > 0)
                                {
                                    string priceAdjustmentStr = _priceFormatter.FormatPrice(priceAdjustment);
                                    formattedAttribute += string.Format(" [+{0}]", priceAdjustmentStr);
                                }
                            }
                        }
                        //encode (if required)
                        if (htmlEncode)
                        {
                            formattedAttribute = WebUtility.HtmlEncode(formattedAttribute);
                        }
                    }

                    if (!String.IsNullOrEmpty(formattedAttribute))
                    {
                        if (i != 0 || j != 0)
                        {
                            result.Append(serapator);
                        }
                        result.Append(formattedAttribute);
                    }
                }
            }

            return(result.ToString());
        }