Exemple #1
0
        public ActionResult DirectDebitPaymentInfo()
        {
            var model       = PaymentInfoGet <DirectDebitPaymentInfoModel, DirectDebitPaymentSettings>();
            var paymentData = _httpContext.GetCheckoutState().PaymentData;

            model.DirectDebitAccountHolder = (string)paymentData.Get("DirectDebitAccountHolder");
            model.DirectDebitAccountNumber = (string)paymentData.Get("DirectDebitAccountNumber");
            model.DirectDebitBankCode      = (string)paymentData.Get("DirectDebitBankCode");
            model.DirectDebitBankName      = (string)paymentData.Get("DirectDebitBankName");
            model.DirectDebitBic           = (string)paymentData.Get("DirectDebitBic");
            model.DirectDebitCountry       = (string)paymentData.Get("DirectDebitCountry");
            model.DirectDebitIban          = (string)paymentData.Get("DirectDebitIban");

            return(PartialView(model));
        }
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext == null || filterContext.ActionDescriptor == null || filterContext.HttpContext == null || filterContext.HttpContext.Request == null)
            {
                return;
            }

            var attr = Convert.ToBoolean(filterContext.HttpContext.GetCheckoutState().CustomProperties.Get("PayPalExpressButtonUsed"));

            //verify paypalexpressprovider was used
            if (attr == true)
            {
                var store    = _services.StoreContext.CurrentStore;
                var customer = _services.WorkContext.CurrentCustomer;

                _genericAttributeService.SaveAttribute <string>(customer, SystemCustomerAttributeNames.SelectedPaymentMethod, PayPalExpressProvider.SystemName, store.Id);

                var paymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest;
                if (paymentRequest == null)
                {
                    _httpContext.Session["OrderPaymentInfo"] = new ProcessPaymentRequest();
                }

                //delete property for backward navigation
                _httpContext.GetCheckoutState().CustomProperties.Remove("PayPalExpressButtonUsed");

                filterContext.Result = new RedirectToRouteResult(
                    new RouteValueDictionary
                {
                    { "Controller", "Checkout" },
                    { "Action", "Confirm" },
                    { "area", null }
                });
            }
        }
Exemple #3
0
        protected bool IsPaymentWorkflowRequired(IList <OrganizedShoppingCartItem> cart, bool ignoreRewardPoints = false)
        {
            //check whether order total equals zero
            decimal?shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, ignoreRewardPoints);

            if (shoppingCartTotalBase.HasValue && shoppingCartTotalBase.Value == decimal.Zero)
            {
                return(false);
            }

            if (_httpContext.GetCheckoutState().IsPaymentSelectionSkipped)
            {
                return(false);
            }

            return(true);
        }
Exemple #4
0
        public static AmazonPayCheckoutState GetAmazonPayState(this HttpContextBase httpContext, ILocalizationService localizationService)
        {
            AmazonPayCheckoutState state = null;
            var checkoutState            = httpContext.GetCheckoutState();

            if (checkoutState == null || (state = (AmazonPayCheckoutState)checkoutState.CustomProperties[AmazonPayCore.AmazonPayCheckoutStateKey]) == null)
            {
                throw new SmartException(localizationService.GetResource("Plugins.Payments.AmazonPay.MissingCheckoutSessionState"));
            }

            return(state);
        }
Exemple #5
0
        public static bool HasAmazonPayState(this HttpContextBase httpContext)
        {
            var checkoutState = httpContext.GetCheckoutState();

            if (checkoutState != null && checkoutState.CustomProperties.ContainsKey(AmazonPayCore.AmazonPayCheckoutStateKey))
            {
                var state = checkoutState.CustomProperties[AmazonPayCore.AmazonPayCheckoutStateKey] as AmazonPayCheckoutState;

                return(state != null && state.OrderReferenceId.HasValue());
            }
            return(false);
        }
        public ActionResult PaymentMethod()
        {
            //validation
            var cart = _workContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, _storeContext.CurrentStore.Id);

            if (cart.Count == 0)
                return RedirectToRoute("ShoppingCart");

            if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed))
                return new HttpUnauthorizedResult();

            // Check whether payment workflow is required
            // we ignore reward points during cart total calculation
            bool isPaymentWorkflowRequired = IsPaymentWorkflowRequired(cart, true);

            var model = PreparePaymentMethodModel(cart);
            bool onlyOnePassiveMethod = model.PaymentMethods.Count == 1 && !model.PaymentMethods[0].RequiresInteraction;

            if (!isPaymentWorkflowRequired || (_paymentSettings.BypassPaymentMethodSelectionIfOnlyOne && onlyOnePassiveMethod && !model.DisplayRewardPoints))
            {
                // If there's nothing to pay for OR if we have only one passive payment method and reward points are disabled
                // or the current customer doesn't have any reward points so customer doesn't have to choose a payment method.

                _genericAttributeService.SaveAttribute<string>(
                    _workContext.CurrentCustomer,
                    SystemCustomerAttributeNames.SelectedPaymentMethod,
                    (!isPaymentWorkflowRequired || !model.PaymentMethods.Any()) ? null : model.PaymentMethods[0].PaymentMethodSystemName,
                    _storeContext.CurrentStore.Id);

                _httpContext.GetCheckoutState().IsPaymentSelectionSkipped = true;

                return RedirectToAction("Confirm");
            }

            _httpContext.GetCheckoutState().IsPaymentSelectionSkipped = false;

            return View(model);
        }
Exemple #7
0
        public static PayPalSessionData GetPayPalSessionData(this HttpContextBase httpContext, CheckoutState state = null)
        {
            if (state == null)
            {
                state = httpContext.GetCheckoutState();
            }

            if (!state.CustomProperties.ContainsKey(PayPalPlusProvider.SystemName))
            {
                state.CustomProperties.Add(PayPalPlusProvider.SystemName, new PayPalSessionData());
            }

            return(state.CustomProperties.Get(PayPalPlusProvider.SystemName) as PayPalSessionData);
        }
Exemple #8
0
        internal static bool HasAmazonPayState(this HttpContextBase httpContext)
        {
            var checkoutState    = httpContext.GetCheckoutState();
            var checkoutStateKey = AmazonPayPlugin.SystemName + ".CheckoutState";

            if (checkoutState != null && checkoutState.CustomProperties.ContainsKey(checkoutStateKey))
            {
                var state = checkoutState.CustomProperties[checkoutStateKey] as AmazonPayCheckoutState;

                return(state != null && state.AccessToken.HasValue());
            }

            return(false);
        }
Exemple #9
0
        public static PayPalSessionData GetPayPalState(this HttpContextBase httpContext, string key)
        {
            Guard.NotEmpty(key, nameof(key));

            var state = httpContext.GetCheckoutState();

            if (!state.CustomProperties.ContainsKey(key))
            {
                state.CustomProperties.Add(key, new PayPalSessionData());
            }

            var session = state.CustomProperties.Get(key) as PayPalSessionData;

            return(session);
        }
Exemple #10
0
        public static PayPalSessionData GetPayPalState(this HttpContextBase httpContext, string providerSystemName)
        {
            Guard.NotEmpty(providerSystemName, nameof(providerSystemName));

            var state = httpContext.GetCheckoutState();

            if (!state.CustomProperties.ContainsKey(providerSystemName))
            {
                state.CustomProperties.Add(providerSystemName, new PayPalSessionData {
                    ProviderSystemName = providerSystemName
                });
            }

            var session = state.CustomProperties.Get(providerSystemName) as PayPalSessionData;

            return(session);
        }
Exemple #11
0
        internal static AmazonPayCheckoutState GetAmazonPayState(this HttpContextBase httpContext, ILocalizationService localizationService)
        {
            var checkoutState = httpContext.GetCheckoutState();

            if (checkoutState == null)
            {
                throw new SmartException(localizationService.GetResource("Plugins.Payments.AmazonPay.MissingCheckoutSessionState"));
            }

            var state = checkoutState.CustomProperties.Get(AmazonPayPlugin.SystemName + ".CheckoutState") as AmazonPayCheckoutState;

            if (state == null)
            {
                throw new SmartException(localizationService.GetResource("Plugins.Payments.AmazonPay.MissingCheckoutSessionState"));
            }

            return(state);
        }
        public ActionResult PaymentInfo()
        {
            var model = new PayPalDirectPaymentInfoModel();

            // Credit card types.
            model.CreditCardTypes.Add(new SelectListItem
            {
                Text  = "Visa",
                Value = "Visa",
            });
            model.CreditCardTypes.Add(new SelectListItem
            {
                Text  = "Master card",
                Value = "MasterCard",
            });
            model.CreditCardTypes.Add(new SelectListItem
            {
                Text  = "Discover",
                Value = "Discover",
            });
            model.CreditCardTypes.Add(new SelectListItem
            {
                Text  = "Amex",
                Value = "Amex",
            });

            // Years.
            for (int i = 0; i < 15; i++)
            {
                string year = Convert.ToString(DateTime.Now.Year + i);
                model.ExpireYears.Add(new SelectListItem
                {
                    Text  = year,
                    Value = year,
                });
            }

            // Months.
            for (int i = 1; i <= 12; i++)
            {
                string text = (i < 10) ? "0" + i.ToString() : i.ToString();
                model.ExpireMonths.Add(new SelectListItem
                {
                    Text  = text,
                    Value = i.ToString(),
                });
            }

            // Set postback values.
            var paymentData = _httpContext.GetCheckoutState().PaymentData;

            model.CardholderName = (string)paymentData.Get("CardholderName");
            model.CardNumber     = (string)paymentData.Get("CardNumber");
            model.CardCode       = (string)paymentData.Get("CardCode");

            var creditCardType = (string)paymentData.Get("CreditCardType");
            var selectedCcType = model.CreditCardTypes.Where(x => x.Value.Equals(creditCardType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

            if (selectedCcType != null)
            {
                selectedCcType.Selected = true;
            }

            var expireMonth   = (string)paymentData.Get("ExpireMonth");
            var selectedMonth = model.ExpireMonths.Where(x => x.Value.Equals(expireMonth, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

            if (selectedMonth != null)
            {
                selectedMonth.Selected = true;
            }

            var expireYear   = (string)paymentData.Get("ExpireYear");
            var selectedYear = model.ExpireYears.Where(x => x.Value.Equals(expireYear, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

            if (selectedYear != null)
            {
                selectedYear.Selected = true;
            }

            return(PartialView(model));
        }
Exemple #13
0
        public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentRequest processPaymentRequest, IList <OrganizedShoppingCartItem> cart)
        {
            var result         = new SetExpressCheckoutResponseType();
            var store          = Services.StoreService.GetStoreById(processPaymentRequest.StoreId);
            var customer       = Services.WorkContext.CurrentCustomer;
            var settings       = Services.Settings.LoadSetting <PayPalExpressPaymentSettings>(processPaymentRequest.StoreId);
            var payPalCurrency = GetApiCurrency(store.PrimaryStoreCurrency);
            var excludingTax   = (Services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id) == TaxDisplayType.ExcludingTax);

            var req = new SetExpressCheckoutReq
            {
                SetExpressCheckoutRequest = new SetExpressCheckoutRequestType
                {
                    Version = ApiVersion,
                    SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType()
                }
            };

            var details = new SetExpressCheckoutRequestDetailsType
            {
                PaymentAction          = GetPaymentAction(settings),
                PaymentActionSpecified = true,
                CancelURL = Services.WebHelper.GetStoreLocation(store.SslEnabled) + "cart",
                ReturnURL = Services.WebHelper.GetStoreLocation(store.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/GetDetails",
                //CallbackURL = _webHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/ShippingOptions?CustomerID=" + _workContext.CurrentCustomer.Id.ToString(),
                //CallbackTimeout = _payPalExpressPaymentSettings.CallbackTimeout.ToString()
                ReqConfirmShipping = settings.ConfirmedShipment.ToString(),
                NoShipping         = settings.NoShipmentAddress.ToString()
            };

            // populate cart
            var taxRate          = decimal.Zero;
            var unitPriceTaxRate = decimal.Zero;
            var itemTotal        = decimal.Zero;
            var cartItems        = new List <PaymentDetailsItemType>();

            foreach (var item in cart)
            {
                var product   = item.Item.Product;
                var unitPrice = _priceCalculationService.GetUnitPrice(item, true);
                var shoppingCartUnitPriceWithDiscount = excludingTax
                    ? _taxService.GetProductPrice(product, unitPrice, false, customer, out taxRate)
                    : _taxService.GetProductPrice(product, unitPrice, true, customer, out unitPriceTaxRate);

                cartItems.Add(new PaymentDetailsItemType
                {
                    Name     = product.Name,
                    Number   = product.Sku,
                    Quantity = item.Item.Quantity.ToString(),
                    // this is the per item cost
                    Amount = new BasicAmountType
                    {
                        currencyID = payPalCurrency,
                        Value      = shoppingCartUnitPriceWithDiscount.FormatInvariant()
                    }
                });

                itemTotal += (item.Item.Quantity * shoppingCartUnitPriceWithDiscount);
            }
            ;

            // additional handling fee
            var additionalHandlingFee = GetAdditionalHandlingFee(cart);

            cartItems.Add(new PaymentDetailsItemType
            {
                Name     = T("Plugins.Payments.PayPal.PaymentMethodFee").Text,
                Quantity = "1",
                Amount   = new BasicAmountType()
                {
                    currencyID = payPalCurrency,
                    Value      = additionalHandlingFee.FormatInvariant()
                }
            });

            itemTotal += GetAdditionalHandlingFee(cart);

            //shipping
            var shippingTotal = decimal.Zero;

            if (cart.RequiresShipping())
            {
                decimal?shoppingCartShippingBase = OrderTotalCalculationService.GetShoppingCartShippingTotal(cart);
                if (shoppingCartShippingBase.HasValue && shoppingCartShippingBase > 0)
                {
                    shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, Services.WorkContext.WorkingCurrency);
                }
                else
                {
                    shippingTotal = settings.DefaultShippingPrice;
                }
            }

            //This is the default if the Shipping Callback fails
            //var shippingOptions = new List<ShippingOptionType>();
            //shippingOptions.Add(new ShippingOptionType()
            //{
            //    ShippingOptionIsDefault = "true",
            //    ShippingOptionName = "Standard Shipping",
            //    ShippingOptionAmount = new BasicAmountType()
            //    {
            //        Value = shippingTotal.ToString(), //This is the default value used for shipping if the Instant Update API returns an error or does not answer within the callback time
            //        currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
            //    }
            //});
            //details.FlatRateShippingOptions = shippingOptions.ToArray();
            //details.TotalType = TotalType.EstimatedTotal;

            // get total tax
            //SortedDictionary<decimal, decimal> taxRates = null;
            //decimal shoppingCartTaxBase = OrderTotalCalculationService.GetTaxTotal(cart, out taxRates);
            //decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, CommonServices.WorkContext.WorkingCurrency);

            // discount
            var discount = -processPaymentRequest.Discount;

            if (discount != 0)
            {
                cartItems.Add(new PaymentDetailsItemType
                {
                    Name     = T("Plugins.Payments.PayPal.ThreadrockDiscount").Text,
                    Quantity = "1",
                    Amount   = new BasicAmountType // this is the total discount
                    {
                        currencyID = payPalCurrency,
                        Value      = discount.FormatInvariant()
                    }
                });

                itemTotal += discount;
            }

            if (!cart.IsRecurring())
            {
                //we don't apply gift cards for recurring products
                var giftCards = _giftCardService.GetActiveGiftCardsAppliedByCustomer(customer, Services.StoreContext.CurrentStore.Id);
                if (giftCards != null)
                {
                    foreach (var gc in giftCards)
                    {
                        if (itemTotal > decimal.Zero)
                        {
                            decimal remainingAmount = gc.GetGiftCardRemainingAmount();
                            decimal amountCanBeUsed = decimal.Zero;
                            if (itemTotal > remainingAmount)
                            {
                                amountCanBeUsed = remainingAmount;
                            }
                            else
                            {
                                amountCanBeUsed = itemTotal - .01M;
                            }

                            decimal amountToSubtract = -amountCanBeUsed;

                            cartItems.Add(new PaymentDetailsItemType
                            {
                                Name     = T("Plugins.Payments.PayPal.GiftcardApplied").Text,
                                Quantity = "1",
                                Amount   = new BasicAmountType
                                {
                                    currencyID = payPalCurrency,
                                    Value      = amountToSubtract.FormatInvariant()
                                }
                            });

                            //reduce subtotal
                            itemTotal += amountToSubtract;
                        }
                    }
                }
            }

            // populate payment details
            var paymentDetails = new PaymentDetailsType
            {
                ItemTotal = new BasicAmountType
                {
                    Value      = Math.Round(itemTotal, 2).FormatInvariant(),
                    currencyID = payPalCurrency
                },
                ShippingTotal = new BasicAmountType
                {
                    Value      = Math.Round(shippingTotal, 2).FormatInvariant(),
                    currencyID = payPalCurrency
                },
                //TaxTotal = new BasicAmountType
                //{
                //    Value = Math.Round(shoppingCartTax, 2).ToString("N", new CultureInfo("en-us")),
                //    currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                //},
                OrderTotal = new BasicAmountType
                {
                    Value      = Math.Round(itemTotal + shippingTotal, 2).FormatInvariant(),
                    currencyID = payPalCurrency
                },
                Custom             = processPaymentRequest.OrderGuid.ToString(),
                ButtonSource       = SmartStoreVersion.CurrentFullVersion,
                PaymentAction      = GetPaymentAction(settings),
                PaymentDetailsItem = cartItems.ToArray()
            };

            details.PaymentDetails = new[] { paymentDetails };

            details.ShippingMethodSpecified = true;

            req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails.Custom = processPaymentRequest.OrderGuid.ToString();
            req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails        = details;

            using (var service = GetApiAaService(settings))
            {
                result = service.SetExpressCheckout(req);
            }

            var checkoutState = _httpContext.GetCheckoutState();

            if (checkoutState.CustomProperties.ContainsKey("PayPalExpressButtonUsed"))
            {
                checkoutState.CustomProperties["PayPalExpressButtonUsed"] = true;
            }
            else
            {
                checkoutState.CustomProperties.Add("PayPalExpressButtonUsed", true);
            }

            return(result);
        }
        public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentRequest processPaymentRequest,
                                                                 IList <Core.Domain.Orders.OrganizedShoppingCartItem> cart)
        {
            var result       = new SetExpressCheckoutResponseType();
            var currentStore = CommonServices.StoreContext.CurrentStore;

            var req = new SetExpressCheckoutReq
            {
                SetExpressCheckoutRequest = new SetExpressCheckoutRequestType
                {
                    Version = PayPalHelper.GetApiVersion(),
                    SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType()
                }
            };

            var details = new SetExpressCheckoutRequestDetailsType
            {
                PaymentAction          = PayPalHelper.GetPaymentAction(Settings),
                PaymentActionSpecified = true,
                CancelURL = CommonServices.WebHelper.GetStoreLocation(currentStore.SslEnabled) + "cart",
                ReturnURL = CommonServices.WebHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/GetDetails",
                //CallbackURL = _webHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/ShippingOptions?CustomerID=" + _workContext.CurrentCustomer.Id.ToString(),
                //CallbackTimeout = _payPalExpressPaymentSettings.CallbackTimeout.ToString()
                ReqConfirmShipping = Settings.ConfirmedShipment.ToString(),
                NoShipping         = Settings.NoShipmentAddress.ToString()
            };

            // populate cart
            decimal itemTotal = decimal.Zero;
            var     cartItems = new List <PaymentDetailsItemType>();

            foreach (OrganizedShoppingCartItem item in cart)
            {
                decimal shoppingCartUnitPriceWithDiscountBase = _priceCalculationService.GetUnitPrice(item, true);
                decimal shoppingCartUnitPriceWithDiscount     = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, CommonServices.WorkContext.WorkingCurrency);
                decimal priceIncludingTier = shoppingCartUnitPriceWithDiscount;
                cartItems.Add(new PaymentDetailsItemType()
                {
                    Name     = item.Item.Product.Name,
                    Number   = item.Item.Product.Sku,
                    Quantity = item.Item.Quantity.ToString(),
                    Amount   = new BasicAmountType() // this is the per item cost
                    {
                        currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)),
                        Value      = (priceIncludingTier).ToString("N", new CultureInfo("en-us"))
                    }
                });
                itemTotal += (item.Item.Quantity * priceIncludingTier);
            }
            ;

            decimal shippingTotal = decimal.Zero;

            if (cart.RequiresShipping())
            {
                decimal?shoppingCartShippingBase = OrderTotalCalculationService.GetShoppingCartShippingTotal(cart);
                if (shoppingCartShippingBase.HasValue && shoppingCartShippingBase > 0)
                {
                    shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, CommonServices.WorkContext.WorkingCurrency);
                }
                else
                {
                    shippingTotal = Settings.DefaultShippingPrice;
                }
            }

            //This is the default if the Shipping Callback fails
            //var shippingOptions = new List<ShippingOptionType>();
            //shippingOptions.Add(new ShippingOptionType()
            //{
            //    ShippingOptionIsDefault = "true",
            //    ShippingOptionName = "Standard Shipping",
            //    ShippingOptionAmount = new BasicAmountType()
            //    {
            //        Value = shippingTotal.ToString(), //This is the default value used for shipping if the Instant Update API returns an error or does not answer within the callback time
            //        currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
            //    }
            //});
            //details.FlatRateShippingOptions = shippingOptions.ToArray();
            //details.TotalType = TotalType.EstimatedTotal;

            // get total tax
            SortedDictionary <decimal, decimal> taxRates = null;
            decimal shoppingCartTaxBase = OrderTotalCalculationService.GetTaxTotal(cart, out taxRates);
            decimal shoppingCartTax     = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, CommonServices.WorkContext.WorkingCurrency);
            decimal discount            = -processPaymentRequest.Discount;


            // Add discounts to PayPal order
            if (discount != 0)
            {
                cartItems.Add(new PaymentDetailsItemType()
                {
                    Name     = "Threadrock Discount",
                    Quantity = "1",
                    Amount   = new BasicAmountType() // this is the total discount
                    {
                        currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)),
                        Value      = discount.ToString("N", new CultureInfo("en-us"))
                    }
                });

                itemTotal += discount;
            }

            // get customer
            int customerId = Convert.ToInt32(CommonServices.WorkContext.CurrentCustomer.Id.ToString());
            var customer   = _customerService.GetCustomerById(customerId);

            if (!cart.IsRecurring())
            {
                //we don't apply gift cards for recurring products
                var giftCards = _giftCardService.GetActiveGiftCardsAppliedByCustomer(customer);
                if (giftCards != null)
                {
                    foreach (var gc in giftCards)
                    {
                        if (itemTotal > decimal.Zero)
                        {
                            decimal remainingAmount = gc.GetGiftCardRemainingAmount();
                            decimal amountCanBeUsed = decimal.Zero;
                            if (itemTotal > remainingAmount)
                            {
                                amountCanBeUsed = remainingAmount;
                            }
                            else
                            {
                                amountCanBeUsed = itemTotal - .01M;
                            }

                            decimal amountToSubtract = -amountCanBeUsed;

                            cartItems.Add(new PaymentDetailsItemType()
                            {
                                Name     = "Giftcard Applied",
                                Quantity = "1",
                                Amount   = new BasicAmountType()
                                {
                                    currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)),
                                    Value      = amountToSubtract.ToString("N", new CultureInfo("en-us"))
                                }
                            });

                            //reduce subtotal
                            itemTotal += amountToSubtract;
                        }
                    }
                }
            }

            // populate payment details
            var paymentDetails = new PaymentDetailsType
            {
                ItemTotal = new BasicAmountType
                {
                    Value      = Math.Round(itemTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                ShippingTotal = new BasicAmountType
                {
                    Value      = Math.Round(shippingTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                TaxTotal = new BasicAmountType
                {
                    Value      = Math.Round(shoppingCartTax, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                OrderTotal = new BasicAmountType
                {
                    Value      = Math.Round(itemTotal + shoppingCartTax + shippingTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                Custom             = processPaymentRequest.OrderGuid.ToString(),
                ButtonSource       = SmartStoreVersion.CurrentFullVersion,
                PaymentAction      = PayPalHelper.GetPaymentAction(Settings),
                PaymentDetailsItem = cartItems.ToArray()
            };

            details.PaymentDetails = new[] { paymentDetails };
            //details.MaxAmount = new BasicAmountType()  // this is the per item cost
            //{
            //    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)),
            //    Value = (decimal.Parse(paymentDetails.OrderTotal.Value) + 30).ToString()
            //};

            details.ShippingMethodSpecified = true;

            req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails.Custom = processPaymentRequest.OrderGuid.ToString();
            req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails        = details;

            using (var service = new PayPalAPIAASoapBinding())
            {
                service.Url = PayPalHelper.GetPaypalServiceUrl(Settings);
                service.RequesterCredentials = PayPalHelper.GetPaypalApiCredentials(Settings);
                result = service.SetExpressCheckout(req);
            }

            _httpContext.GetCheckoutState().CustomProperties.Add("PayPalExpressButtonUsed", true);

            return(result);
        }