Example #1
0
        /// <summary>
        /// Updates the recurring payment history
        /// </summary>
        /// <param name="recurringPaymentHistory">Recurring payment history</param>
        public void UpdateRecurringPaymentHistory(RecurringPaymentHistory recurringPaymentHistory)
        {
            if (recurringPaymentHistory == null)
                throw new ArgumentNullException("recurringPaymentHistory");

            if (!_context.IsAttached(recurringPaymentHistory))
                _context.RecurringPaymentHistory.Attach(recurringPaymentHistory);

            _context.SaveChanges();
        }
Example #2
0
        /// <summary>
        /// Process next recurring psayment
        /// </summary>
        /// <param name="recurringPaymentId">Recurring payment identifier</param>
        public void ProcessNextRecurringPayment(int recurringPaymentId)
        {
            try
            {
                var rp = GetRecurringPaymentById(recurringPaymentId);
                if (rp == null)
                    throw new NopException("Recurring payment could not be loaded");

                if (!rp.IsActive)
                    throw new NopException("Recurring payment is not active");

                var initialOrder = rp.InitialOrder;
                if (initialOrder == null)
                    throw new NopException("Initial order could not be loaded");

                var customer = initialOrder.Customer;
                if (customer == null)
                    throw new NopException("Customer could not be loaded");

                var nextPaymentDate = rp.NextPaymentDate;
                if (!nextPaymentDate.HasValue)
                    throw new NopException("Next payment date could not be calculated");

                //payment info
                var paymentInfo = new PaymentInfo();
                paymentInfo.IsRecurringPayment = true;
                paymentInfo.InitialOrderId = initialOrder.OrderId;
                paymentInfo.RecurringCycleLength = rp.CycleLength;
                paymentInfo.RecurringCyclePeriod = rp.CyclePeriod;
                paymentInfo.RecurringTotalCycles = rp.TotalCycles;

                //place new order
                int newOrderId = 0;
                string result = this.PlaceOrder(paymentInfo, customer,
                    Guid.NewGuid(), out newOrderId);
                if (!String.IsNullOrEmpty(result))
                {
                    throw new NopException(result);
                }
                else
                {
                    var rph = new RecurringPaymentHistory()
                    {
                        RecurringPaymentId = rp.RecurringPaymentId,
                        OrderId = newOrderId,
                        CreatedOn = DateTime.UtcNow
                    };
                    InsertRecurringPaymentHistory(rph);
                }
            }
            catch (Exception exc)
            {
                IoC.Resolve<ILogService>().InsertLog(LogTypeEnum.OrderError, string.Format("Error while processing recurring order. {0}", exc.Message), exc);
                throw;
            }
        }
Example #3
0
        /// <summary>
        /// Inserts a recurring payment history
        /// </summary>
        /// <param name="recurringPaymentHistory">Recurring payment history</param>
        public void InsertRecurringPaymentHistory(RecurringPaymentHistory recurringPaymentHistory)
        {
            if (recurringPaymentHistory == null)
                throw new ArgumentNullException("recurringPaymentHistory");

            _context.RecurringPaymentHistory.AddObject(recurringPaymentHistory);
            _context.SaveChanges();
        }
Example #4
0
        /// <summary>
        /// Places an order
        /// </summary>
        /// <param name="paymentInfo">Payment info</param>
        /// <param name="customer">Customer</param>
        /// <param name="orderGuid">Order GUID to use</param>
        /// <param name="orderId">Order identifier</param>
        /// <returns>The error status, or String.Empty if no errors</returns>
        public string PlaceOrder(PaymentInfo paymentInfo, Customer customer, 
            Guid orderGuid, out int orderId)
        {
            orderId = 0;
            var processPaymentResult = new ProcessPaymentResult();

            var customerService = IoC.Resolve<ICustomerService>();
            var shoppingCartService = IoC.Resolve<IShoppingCartService>();
            var taxService = IoC.Resolve<ITaxService>();
            var currencyService = IoC.Resolve<ICurrencyService>();
            var shippingService= IoC.Resolve<IShippingService>();
            var paymentService = IoC.Resolve<IPaymentService>();
            var productService = IoC.Resolve<IProductService>();
            var discountService = IoC.Resolve<IDiscountService>();
            var localizationManager = IoC.Resolve<ILocalizationManager>();
            var messageService = IoC.Resolve<IMessageService>();
            var customerActivityService = IoC.Resolve<ICustomerActivityService>();
            var smsService = IoC.Resolve<ISMSService>();
            var logService = IoC.Resolve<ILogService>();

            try
            {
                if (customer == null)
                    throw new ArgumentNullException("customer");

                if (customer.IsGuest && !customerService.AnonymousCheckoutAllowed)
                    throw new NopException("Anonymous checkout is not allowed");

                // This is a check to customer email address which is important to be valid.
                if (!CommonHelper.IsValidEmail(customer.Email)) {
                    throw new NopException("Email is not valid");
                }

                if (paymentInfo == null)
                    throw new ArgumentNullException("paymentInfo");

                Order initialOrder = null;
                if (paymentInfo.IsRecurringPayment)
                {
                    initialOrder = GetOrderById(paymentInfo.InitialOrderId);
                    if (initialOrder == null)
                        throw new NopException("Initial order could not be loaded");
                }

                if (!paymentInfo.IsRecurringPayment)
                {
                    if (paymentInfo.BillingAddress == null)
                        throw new NopException("Billing address not provided");

                    // Billing address email is never asked in the first place, so system must not check its validity
                    //if (!CommonHelper.IsValidEmail(paymentInfo.BillingAddress.Email))
                    //{
                    //    throw new NopException("Email is not valid");
                    //}
                }

                if (paymentInfo.IsRecurringPayment)
                {
                    paymentInfo.PaymentMethodId = initialOrder.PaymentMethodId;
                }

                paymentInfo.CreditCardType = CommonHelper.EnsureNotNull(paymentInfo.CreditCardType);
                paymentInfo.CreditCardName = CommonHelper.EnsureNotNull(paymentInfo.CreditCardName);
                paymentInfo.CreditCardName = CommonHelper.EnsureMaximumLength(paymentInfo.CreditCardName, 100);
                paymentInfo.CreditCardName = paymentInfo.CreditCardName.Trim();
                paymentInfo.CreditCardNumber = CommonHelper.EnsureNotNull(paymentInfo.CreditCardNumber);
                paymentInfo.CreditCardNumber = paymentInfo.CreditCardNumber.Trim();
                paymentInfo.CreditCardCvv2 = CommonHelper.EnsureNotNull(paymentInfo.CreditCardCvv2);
                paymentInfo.CreditCardCvv2 = paymentInfo.CreditCardCvv2.Trim();
                paymentInfo.PaypalToken = CommonHelper.EnsureNotNull(paymentInfo.PaypalToken);
                paymentInfo.PaypalPayerId = CommonHelper.EnsureNotNull(paymentInfo.PaypalPayerId);
                paymentInfo.GoogleOrderNumber = CommonHelper.EnsureNotNull(paymentInfo.GoogleOrderNumber);
                paymentInfo.PurchaseOrderNumber = CommonHelper.EnsureNotNull(paymentInfo.PurchaseOrderNumber);

                ShoppingCart cart = null;
                if (!paymentInfo.IsRecurringPayment)
                {
                    cart = shoppingCartService.GetCustomerShoppingCart(customer.CustomerId, ShoppingCartTypeEnum.ShoppingCart);

                    //validate cart
                    var warnings = shoppingCartService.GetShoppingCartWarnings(cart, customer.CheckoutAttributes, true);
                    if (warnings.Count > 0)
                    {
                        StringBuilder warningsSb = new StringBuilder();
                        foreach (string warning in warnings)
                        {
                            warningsSb.Append(warning);
                            warningsSb.Append(";");
                        }
                        throw new NopException(warningsSb.ToString());
                    }

                    //validate individual cart items
                    foreach (var sci in cart)
                    {
                        var sciWarnings = shoppingCartService.GetShoppingCartItemWarnings(sci.ShoppingCartType,
                            sci.ProductVariantId, sci.AttributesXml,
                            sci.CustomerEnteredPrice, sci.Quantity);

                        if (sciWarnings.Count > 0)
                        {
                            var warningsSb = new StringBuilder();
                            foreach (string warning in sciWarnings)
                            {
                                warningsSb.Append(warning);
                                warningsSb.Append(";");
                            }
                            throw new NopException(warningsSb.ToString());
                        }
                    }
                }

                //tax type
                var customerTaxDisplayType = TaxDisplayTypeEnum.IncludingTax;
                if (!paymentInfo.IsRecurringPayment)
                {
                    if (taxService.AllowCustomersToSelectTaxDisplayType)
                        customerTaxDisplayType = customer.TaxDisplayType;
                    else
                        customerTaxDisplayType = taxService.TaxDisplayType;
                }
                else
                {
                    customerTaxDisplayType = initialOrder.CustomerTaxDisplayType;
                }

                //discount usage history
                var appliedDiscounts = new List<Discount>();

                //checkout attributes
                string checkoutAttributeDescription = string.Empty;
                string checkoutAttributesXml = string.Empty;
                if (!paymentInfo.IsRecurringPayment)
                {
                    checkoutAttributeDescription = CheckoutAttributeHelper.FormatAttributes(customer.CheckoutAttributes, customer, "<br />");
                    checkoutAttributesXml = customer.CheckoutAttributes;
                }
                else
                {
                    checkoutAttributeDescription = initialOrder.CheckoutAttributeDescription;
                    checkoutAttributesXml = initialOrder.CheckoutAttributesXml;
                }

                //sub total
                decimal orderSubTotalInclTax = decimal.Zero;
                decimal orderSubTotalExclTax = decimal.Zero;
                decimal orderSubtotalInclTaxInCustomerCurrency = decimal.Zero;
                decimal orderSubtotalExclTaxInCustomerCurrency = decimal.Zero;
                decimal orderSubTotalDiscountInclTax = decimal.Zero;
                decimal orderSubTotalDiscountExclTax = decimal.Zero;
                decimal orderSubTotalDiscountInclTaxInCustomerCurrency = decimal.Zero;
                decimal orderSubTotalDiscountExclTaxInCustomerCurrency = decimal.Zero;
                if (!paymentInfo.IsRecurringPayment)
                {
                    //sub total (incl tax)
                    decimal orderSubTotalDiscountAmount1 = decimal.Zero;
                    Discount orderSubTotalAppliedDiscount1 = null;
                    decimal subTotalWithoutDiscountBase1 = decimal.Zero;
                    decimal subTotalWithDiscountBase1 = decimal.Zero;
                    string subTotalError1 = shoppingCartService.GetShoppingCartSubTotal(cart, customer,
                        true, out orderSubTotalDiscountAmount1, out orderSubTotalAppliedDiscount1,
                        out subTotalWithoutDiscountBase1, out subTotalWithDiscountBase1);
                    orderSubTotalInclTax = subTotalWithoutDiscountBase1;
                    orderSubTotalDiscountInclTax =orderSubTotalDiscountAmount1;

                    //discount history
                    if (orderSubTotalAppliedDiscount1 != null && !appliedDiscounts.ContainsDiscount(orderSubTotalAppliedDiscount1.Name))
                        appliedDiscounts.Add(orderSubTotalAppliedDiscount1);

                    //sub total (excl tax)
                    decimal orderSubTotalDiscountAmount2 = decimal.Zero;
                    Discount orderSubTotalAppliedDiscount2 = null;
                    decimal subTotalWithoutDiscountBase2 = decimal.Zero;
                    decimal subTotalWithDiscountBase2 = decimal.Zero;
                    string subTotalError2 = shoppingCartService.GetShoppingCartSubTotal(cart, customer,
                        false, out orderSubTotalDiscountAmount2, out orderSubTotalAppliedDiscount2,
                        out subTotalWithoutDiscountBase2, out subTotalWithDiscountBase2);
                    orderSubTotalExclTax = subTotalWithoutDiscountBase2;
                    orderSubTotalDiscountExclTax = orderSubTotalDiscountAmount2;

                    if (!String.IsNullOrEmpty(subTotalError1) || !String.IsNullOrEmpty(subTotalError2))
                        throw new NopException("Sub total couldn't be calculated");

                    //in customer currency
                    orderSubtotalInclTaxInCustomerCurrency = currencyService.ConvertCurrency(orderSubTotalInclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                    orderSubtotalExclTaxInCustomerCurrency = currencyService.ConvertCurrency(orderSubTotalExclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                    orderSubTotalDiscountInclTaxInCustomerCurrency = currencyService.ConvertCurrency(orderSubTotalDiscountInclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                    orderSubTotalDiscountExclTaxInCustomerCurrency = currencyService.ConvertCurrency(orderSubTotalDiscountExclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                }
                else
                {
                    orderSubTotalInclTax = initialOrder.OrderSubtotalInclTax;
                    orderSubTotalExclTax = initialOrder.OrderSubtotalExclTax;

                    //in customer currency
                    orderSubtotalInclTaxInCustomerCurrency = initialOrder.OrderSubtotalInclTaxInCustomerCurrency;
                    orderSubtotalExclTaxInCustomerCurrency = initialOrder.OrderSubtotalExclTaxInCustomerCurrency;
                }

                //shipping info
                decimal orderWeight = decimal.Zero;
                bool shoppingCartRequiresShipping = false;
                if (!paymentInfo.IsRecurringPayment)
                {
                    orderWeight = shippingService.GetShoppingCartTotalWeight(cart, customer);
                    shoppingCartRequiresShipping = shippingService.ShoppingCartRequiresShipping(cart);
                    if (shoppingCartRequiresShipping)
                    {
                        if (paymentInfo.ShippingAddress == null)
                            throw new NopException("Shipping address is not provided");

                        // Billing address email is never asked in the first place, so system must not check its validity
                        //if (!CommonHelper.IsValidEmail(paymentInfo.ShippingAddress.Email))
                        //{
                        //    throw new NopException("Email is not valid");
                        //}
                    }
                }
                else
                {
                    orderWeight = initialOrder.OrderWeight;
                    if (initialOrder.ShippingStatus != ShippingStatusEnum.ShippingNotRequired)
                        shoppingCartRequiresShipping = true;
                }

                //shipping total
                decimal? orderShippingTotalInclTax = null;
                decimal? orderShippingTotalExclTax = null;
                decimal orderShippingInclTaxInCustomerCurrency = decimal.Zero;
                decimal orderShippingExclTaxInCustomerCurrency = decimal.Zero;
                if (!paymentInfo.IsRecurringPayment)
                {
                    decimal taxRate = decimal.Zero;
                    string shippingTotalError1 = string.Empty;
                    string shippingTotalError2 = string.Empty;
                    Discount shippingTotalDiscount = null;
                    orderShippingTotalInclTax = shippingService.GetShoppingCartShippingTotal(cart, customer, true, out taxRate, out shippingTotalDiscount, ref shippingTotalError1);
                    orderShippingTotalExclTax = shippingService.GetShoppingCartShippingTotal(cart, customer, false, ref shippingTotalError2);
                    if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue)
                        throw new NopException("Shipping total couldn't be calculated");
                    if (shippingTotalDiscount != null && !appliedDiscounts.ContainsDiscount(shippingTotalDiscount.Name))
                        appliedDiscounts.Add(shippingTotalDiscount);

                    //in customer currency
                    orderShippingInclTaxInCustomerCurrency = currencyService.ConvertCurrency(orderShippingTotalInclTax.Value, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                    orderShippingExclTaxInCustomerCurrency = currencyService.ConvertCurrency(orderShippingTotalExclTax.Value, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);

                }
                else
                {
                    orderShippingTotalInclTax = initialOrder.OrderShippingInclTax;
                    orderShippingTotalExclTax = initialOrder.OrderShippingExclTax;
                    orderShippingInclTaxInCustomerCurrency = initialOrder.OrderShippingInclTaxInCustomerCurrency;
                    orderShippingExclTaxInCustomerCurrency = initialOrder.OrderShippingExclTaxInCustomerCurrency;
                }

                //payment total
                decimal paymentAdditionalFeeInclTax = decimal.Zero;
                decimal paymentAdditionalFeeExclTax = decimal.Zero;
                decimal paymentAdditionalFeeInclTaxInCustomerCurrency = decimal.Zero;
                decimal paymentAdditionalFeeExclTaxInCustomerCurrency = decimal.Zero;
                if (!paymentInfo.IsRecurringPayment)
                {
                    string paymentAdditionalFeeError1 = string.Empty;
                    string paymentAdditionalFeeError2 = string.Empty;
                    decimal paymentAdditionalFee = paymentService.GetAdditionalHandlingFee(paymentInfo.PaymentMethodId);
                    paymentAdditionalFeeInclTax = taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, true, customer, ref paymentAdditionalFeeError1);
                    paymentAdditionalFeeExclTax = taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, false, customer, ref paymentAdditionalFeeError2);
                    if (!String.IsNullOrEmpty(paymentAdditionalFeeError1))
                        throw new NopException("Payment method fee couldn't be calculated");
                    if (!String.IsNullOrEmpty(paymentAdditionalFeeError2))
                        throw new NopException("Payment method fee couldn't be calculated");

                    //in customer currency
                    paymentAdditionalFeeInclTaxInCustomerCurrency = currencyService.ConvertCurrency(paymentAdditionalFeeInclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                    paymentAdditionalFeeExclTaxInCustomerCurrency = currencyService.ConvertCurrency(paymentAdditionalFeeExclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                }
                else
                {
                    paymentAdditionalFeeInclTax = initialOrder.PaymentMethodAdditionalFeeInclTax;
                    paymentAdditionalFeeExclTax = initialOrder.PaymentMethodAdditionalFeeExclTax;
                    paymentAdditionalFeeInclTaxInCustomerCurrency = initialOrder.PaymentMethodAdditionalFeeInclTaxInCustomerCurrency;
                    paymentAdditionalFeeExclTaxInCustomerCurrency = initialOrder.PaymentMethodAdditionalFeeExclTaxInCustomerCurrency;
                }

                //tax total
                decimal orderTaxTotal = decimal.Zero;
                decimal orderTaxInCustomerCurrency = decimal.Zero;
                string vatNumber = string.Empty;
                string taxRates = string.Empty;
                string taxRatesInCustomerCurrency = string.Empty;
                if (!paymentInfo.IsRecurringPayment)
                {
                    //tax amount
                    SortedDictionary<decimal, decimal> taxRatesDictionary = null;
                    string taxError = string.Empty;
                    orderTaxTotal = taxService.GetTaxTotal(cart,
                        paymentInfo.PaymentMethodId, customer, out taxRatesDictionary, ref taxError);
                    if (!String.IsNullOrEmpty(taxError))
                        throw new NopException("Tax total couldn't be calculated");

                    //in customer currency
                    orderTaxInCustomerCurrency = currencyService.ConvertCurrency(orderTaxTotal, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);

                    //VAT number
                    if (taxService.EUVatEnabled && customer.VatNumberStatus == VatNumberStatusEnum.Valid)
                    {
                        vatNumber = customer.VatNumber;
                    }

                    //tax rates
                    foreach (var kvp in taxRatesDictionary)
                    {
                        var taxRate = kvp.Key;
                        var taxValue = kvp.Value;

                        var taxValueInCustomerCurrency = currencyService.ConvertCurrency(taxValue, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);

                        taxRates += string.Format("{0}:{1};   ", taxRate.ToString(new CultureInfo("en-US")), taxValue.ToString(new CultureInfo("en-US")));
                        taxRatesInCustomerCurrency += string.Format("{0}:{1};   ", taxRate.ToString(new CultureInfo("en-US")), taxValueInCustomerCurrency.ToString(new CultureInfo("en-US")));
                    }
                }
                else
                {
                    orderTaxTotal = initialOrder.OrderTax;
                    orderTaxInCustomerCurrency = initialOrder.OrderTaxInCustomerCurrency;

                    //VAT number
                    //TODO: Possible BUG: VAT number status may have changed since original order was placed, probably best to recalculate tax or do some checks?
                    vatNumber = initialOrder.VatNumber;
                }

                //order total (and applied discounts, gift cards, reward points)
                decimal? orderTotal = null;
                decimal orderTotalInCustomerCurrency = decimal.Zero;
                decimal orderDiscountAmount = decimal.Zero;
                decimal orderDiscountInCustomerCurrency = decimal.Zero;
                List<AppliedGiftCard> appliedGiftCards = null;
                int redeemedRewardPoints = 0;
                decimal redeemedRewardPointsAmount = decimal.Zero;
                if (!paymentInfo.IsRecurringPayment)
                {
                    Discount orderAppliedDiscount = null;

                    bool useRewardPoints = customer.UseRewardPointsDuringCheckout;

                    orderTotal = shoppingCartService.GetShoppingCartTotal(cart,
                        paymentInfo.PaymentMethodId, customer,
                        out orderDiscountAmount, out orderAppliedDiscount,
                        out appliedGiftCards, useRewardPoints,
                        out redeemedRewardPoints, out redeemedRewardPointsAmount);
                    if (!orderTotal.HasValue)
                        throw new NopException("Order total couldn't be calculated");

                    //discount history
                    if (orderAppliedDiscount != null && !appliedDiscounts.ContainsDiscount(orderAppliedDiscount.Name))
                        appliedDiscounts.Add(orderAppliedDiscount);

                    //in customer currency
                    orderDiscountInCustomerCurrency = currencyService.ConvertCurrency(orderDiscountAmount, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                    orderTotalInCustomerCurrency = currencyService.ConvertCurrency(orderTotal.Value, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                }
                else
                {
                    orderDiscountAmount = initialOrder.OrderDiscount;
                    orderTotal = initialOrder.OrderTotal;

                    orderDiscountInCustomerCurrency = initialOrder.OrderDiscountInCustomerCurrency;
                    orderTotalInCustomerCurrency = initialOrder.OrderTotalInCustomerCurrency;
                }
                paymentInfo.OrderTotal = orderTotal.Value;

                //skip payment workflow if order total equals zero
                bool skipPaymentWorkflow = false;
                if (orderTotal.Value == decimal.Zero)
                {
                    skipPaymentWorkflow = true;
                }
                PaymentMethod paymentMethod = null;
                string paymentMethodName = string.Empty;
                if (!skipPaymentWorkflow)
                {
                    paymentMethod = paymentService.GetPaymentMethodById(paymentInfo.PaymentMethodId);
                    if (paymentMethod == null)
                        throw new NopException("Payment method couldn't be loaded");

                    if (!paymentMethod.IsActive)
                        throw new NopException("Payment method is not active");

                    paymentMethodName = paymentMethod.Name;
                }
                else
                {
                    paymentInfo.PaymentMethodId = 0;
                }

                string customerCurrencyCode = string.Empty;
                if (!paymentInfo.IsRecurringPayment)
                {
                    customerCurrencyCode = paymentInfo.CustomerCurrency.CurrencyCode;
                }
                else
                {
                    customerCurrencyCode = initialOrder.CustomerCurrencyCode;
                }

                //billing info
                string billingFirstName = string.Empty;
                string billingLastName = string.Empty;
                string billingPhoneNumber = string.Empty;
                string billingEmail = string.Empty;
                string billingFaxNumber = string.Empty;
                string billingCompany = string.Empty;
                string billingAddress1 = string.Empty;
                string billingAddress2 = string.Empty;
                string billingCity = string.Empty;
                string billingStateProvince = string.Empty;
                int billingStateProvinceId = 0;
                string billingZipPostalCode = string.Empty;
                string billingCountry = string.Empty;
                int billingCountryId = 0;
                if (!paymentInfo.IsRecurringPayment)
                {
                    var billingAddress = paymentInfo.BillingAddress;
                    billingFirstName = billingAddress.FirstName;
                    billingLastName = billingAddress.LastName;
                    billingPhoneNumber = billingAddress.PhoneNumber;
                    billingEmail = billingAddress.Email;
                    billingFaxNumber = billingAddress.FaxNumber;
                    billingCompany = billingAddress.Company;
                    billingAddress1 = billingAddress.Address1;
                    billingAddress2 = billingAddress.Address2;
                    billingCity = billingAddress.City;
                    if (billingAddress.StateProvince != null)
                    {
                        billingStateProvince = billingAddress.StateProvince.Name;
                        billingStateProvinceId = billingAddress.StateProvince.StateProvinceId;
                    }
                    billingZipPostalCode = billingAddress.ZipPostalCode;
                    if (billingAddress.Country != null)
                    {
                        billingCountry = billingAddress.Country.Name;
                        billingCountryId = billingAddress.Country.CountryId;

                        if (!billingAddress.Country.AllowsBilling)
                        {
                            throw new NopException(string.Format("{0} is not allowed for billing", billingCountry));
                        }
                    }
                }
                else
                {
                    billingFirstName = initialOrder.BillingFirstName;
                    billingLastName = initialOrder.BillingLastName;
                    billingPhoneNumber = initialOrder.BillingPhoneNumber;
                    billingEmail = initialOrder.BillingEmail;
                    billingFaxNumber = initialOrder.BillingFaxNumber;
                    billingCompany = initialOrder.BillingCompany;
                    billingAddress1 = initialOrder.BillingAddress1;
                    billingAddress2 = initialOrder.BillingAddress2;
                    billingCity = initialOrder.BillingCity;
                    billingStateProvince = initialOrder.BillingStateProvince;
                    billingStateProvinceId = initialOrder.BillingStateProvinceId;
                    billingZipPostalCode = initialOrder.BillingZipPostalCode;
                    billingCountry = initialOrder.BillingCountry;
                    billingCountryId = initialOrder.BillingCountryId;
                }

                //shipping info
                string shippingFirstName = string.Empty;
                string shippingLastName = string.Empty;
                string shippingPhoneNumber = string.Empty;
                string shippingEmail = string.Empty;
                string shippingFaxNumber = string.Empty;
                string shippingCompany = string.Empty;
                string shippingAddress1 = string.Empty;
                string shippingAddress2 = string.Empty;
                string shippingCity = string.Empty;
                string shippingStateProvince = string.Empty;
                int shippingStateProvinceId = 0;
                string shippingZipPostalCode = string.Empty;
                string shippingCountry = string.Empty;
                int shippingCountryId = 0;
                string shippingMethodName = string.Empty;
                int shippingRateComputationMethodId = 0;
                if (shoppingCartRequiresShipping)
                {
                    if (!paymentInfo.IsRecurringPayment)
                    {
                        var shippingAddress = paymentInfo.ShippingAddress;
                        if (shippingAddress != null)
                        {
                            shippingFirstName = shippingAddress.FirstName;
                            shippingLastName = shippingAddress.LastName;
                            shippingPhoneNumber = shippingAddress.PhoneNumber;
                            shippingEmail = shippingAddress.Email;
                            shippingFaxNumber = shippingAddress.FaxNumber;
                            shippingCompany = shippingAddress.Company;
                            shippingAddress1 = shippingAddress.Address1;
                            shippingAddress2 = shippingAddress.Address2;
                            shippingCity = shippingAddress.City;
                            if (shippingAddress.StateProvince != null)
                            {
                                shippingStateProvince = shippingAddress.StateProvince.Name;
                                shippingStateProvinceId = shippingAddress.StateProvince.StateProvinceId;
                            }
                            shippingZipPostalCode = shippingAddress.ZipPostalCode;
                            if (shippingAddress.Country != null)
                            {
                                shippingCountry = shippingAddress.Country.Name;
                                shippingCountryId = shippingAddress.Country.CountryId;

                                if (!shippingAddress.Country.AllowsShipping)
                                {
                                    throw new NopException(string.Format("{0} is not allowed for shipping", shippingCountry));
                                }
                            }
                            shippingMethodName = string.Empty;
                            var shippingOption = customer.LastShippingOption;
                            if (shippingOption != null)
                            {
                                shippingMethodName = shippingOption.Name;
                                shippingRateComputationMethodId = shippingOption.ShippingRateComputationMethodId;
                            }
                        }
                    }
                    else
                    {
                        shippingFirstName = initialOrder.ShippingFirstName;
                        shippingLastName = initialOrder.ShippingLastName;
                        shippingPhoneNumber = initialOrder.ShippingPhoneNumber;
                        shippingEmail = initialOrder.ShippingEmail;
                        shippingFaxNumber = initialOrder.ShippingFaxNumber;
                        shippingCompany = initialOrder.ShippingCompany;
                        shippingAddress1 = initialOrder.ShippingAddress1;
                        shippingAddress2 = initialOrder.ShippingAddress2;
                        shippingCity = initialOrder.ShippingCity;
                        shippingStateProvince = initialOrder.ShippingStateProvince;
                        shippingStateProvinceId = initialOrder.ShippingStateProvinceId;
                        shippingZipPostalCode = initialOrder.ShippingZipPostalCode;
                        shippingCountry = initialOrder.ShippingCountry;
                        shippingCountryId = initialOrder.ShippingCountryId;
                        shippingMethodName = initialOrder.ShippingMethod;
                        shippingRateComputationMethodId = initialOrder.ShippingRateComputationMethodId;
                    }
                }

                //customer language
                int customerLanguageId = 0;
                if (!paymentInfo.IsRecurringPayment)
                {
                    customerLanguageId = paymentInfo.CustomerLanguage.LanguageId;
                }
                else
                {
                    customerLanguageId = initialOrder.CustomerLanguageId;
                }

                //recurring or standard shopping cart
                bool isRecurringShoppingCart = false;
                if (!paymentInfo.IsRecurringPayment)
                {
                    isRecurringShoppingCart = cart.IsRecurring;
                    if (isRecurringShoppingCart)
                    {
                        int recurringCycleLength = 0;
                        int recurringCyclePeriod = 0;
                        int recurringTotalCycles = 0;
                        string recurringCyclesError = shoppingCartService.GetReccuringCycleInfo(cart, out recurringCycleLength, out recurringCyclePeriod, out recurringTotalCycles);
                        if (!string.IsNullOrEmpty(recurringCyclesError))
                        {
                            throw new NopException(recurringCyclesError);
                        }
                        paymentInfo.RecurringCycleLength = recurringCycleLength;
                        paymentInfo.RecurringCyclePeriod = recurringCyclePeriod;
                        paymentInfo.RecurringTotalCycles = recurringTotalCycles;
                    }
                }
                else
                {
                    isRecurringShoppingCart = true;
                }

                if (!skipPaymentWorkflow)
                {
                    //process payment
                    if (!paymentInfo.IsRecurringPayment)
                    {
                        if (isRecurringShoppingCart)
                        {
                            //recurring cart
                            var recurringPaymentType = paymentService.SupportRecurringPayments(paymentInfo.PaymentMethodId);
                            switch (recurringPaymentType)
                            {
                                case RecurringPaymentTypeEnum.NotSupported:
                                    throw new NopException("Recurring payments are not supported by selected payment method");
                                case RecurringPaymentTypeEnum.Manual:
                                case RecurringPaymentTypeEnum.Automatic:
                                    paymentService.ProcessRecurringPayment(paymentInfo, customer, orderGuid, ref processPaymentResult);
                                    break;
                                default:
                                    throw new NopException("Not supported recurring payment type");
                            }
                        }
                        else
                        {
                            //standard cart
                            paymentService.ProcessPayment(paymentInfo, customer, orderGuid, ref processPaymentResult);
                        }
                    }
                    else
                    {
                        if (isRecurringShoppingCart)
                        {
                            var recurringPaymentType = paymentService.SupportRecurringPayments(paymentInfo.PaymentMethodId);
                            switch (recurringPaymentType)
                            {
                                case RecurringPaymentTypeEnum.NotSupported:
                                    throw new NopException("Recurring payments are not supported by selected payment method");
                                case RecurringPaymentTypeEnum.Manual:
                                    paymentService.ProcessRecurringPayment(paymentInfo, customer, orderGuid, ref processPaymentResult);
                                    break;
                                case RecurringPaymentTypeEnum.Automatic:
                                    //payment is processed on payment gateway site
                                    break;
                                default:
                                    throw new NopException("Not supported recurring payment type");
                            }
                        }
                        else
                        {
                            throw new NopException("No recurring products");
                        }
                    }
                }
                else
                {
                    processPaymentResult.PaymentStatus = PaymentStatusEnum.Paid;
                }

                //process order
                if (String.IsNullOrEmpty(processPaymentResult.Error))
                {
                    var shippingStatusEnum = ShippingStatusEnum.NotYetShipped;
                    if (!shoppingCartRequiresShipping)
                        shippingStatusEnum = ShippingStatusEnum.ShippingNotRequired;

                    //save order in data storage
                    //uncomment this line to support transactions
                    //using (var scope = new System.Transactions.TransactionScope())
                    {
                        var order = new Order()
                        {
                            OrderGuid = orderGuid,
                            CustomerId = customer.CustomerId,
                            CustomerLanguageId = customerLanguageId,
                            CustomerTaxDisplayTypeId = (int)customerTaxDisplayType,
                            CustomerIP = NopContext.Current.UserHostAddress,
                            OrderSubtotalInclTax = orderSubTotalInclTax,
                            OrderSubtotalExclTax = orderSubTotalExclTax,
                            OrderSubTotalDiscountInclTax = orderSubTotalDiscountInclTax,
                            OrderSubTotalDiscountExclTax = orderSubTotalDiscountExclTax,
                            OrderShippingInclTax = orderShippingTotalInclTax.Value,
                            OrderShippingExclTax = orderShippingTotalExclTax.Value,
                            PaymentMethodAdditionalFeeInclTax = paymentAdditionalFeeInclTax,
                            PaymentMethodAdditionalFeeExclTax = paymentAdditionalFeeExclTax,
                            TaxRates = taxRates,
                            OrderTax = orderTaxTotal,
                            OrderTotal = orderTotal.Value,
                            RefundedAmount = decimal.Zero,
                            OrderDiscount = orderDiscountAmount,
                            OrderSubtotalInclTaxInCustomerCurrency = orderSubtotalInclTaxInCustomerCurrency,
                            OrderSubtotalExclTaxInCustomerCurrency = orderSubtotalExclTaxInCustomerCurrency,
                            OrderSubTotalDiscountInclTaxInCustomerCurrency = orderSubTotalDiscountInclTaxInCustomerCurrency,
                            OrderSubTotalDiscountExclTaxInCustomerCurrency = orderSubTotalDiscountExclTaxInCustomerCurrency,
                            OrderShippingInclTaxInCustomerCurrency = orderShippingInclTaxInCustomerCurrency,
                            OrderShippingExclTaxInCustomerCurrency = orderShippingExclTaxInCustomerCurrency,
                            PaymentMethodAdditionalFeeInclTaxInCustomerCurrency = paymentAdditionalFeeInclTaxInCustomerCurrency,
                            PaymentMethodAdditionalFeeExclTaxInCustomerCurrency = paymentAdditionalFeeExclTaxInCustomerCurrency,
                            TaxRatesInCustomerCurrency = taxRatesInCustomerCurrency,
                            OrderTaxInCustomerCurrency = orderTaxInCustomerCurrency,
                            OrderTotalInCustomerCurrency = orderTotalInCustomerCurrency,
                            OrderDiscountInCustomerCurrency = orderDiscountInCustomerCurrency,
                            CheckoutAttributeDescription = checkoutAttributeDescription,
                            CheckoutAttributesXml = checkoutAttributesXml,
                            CustomerCurrencyCode = customerCurrencyCode,
                            OrderWeight = orderWeight,
                            AffiliateId = customer.AffiliateId,
                            OrderStatusId = (int)OrderStatusEnum.Pending,
                            AllowStoringCreditCardNumber = processPaymentResult.AllowStoringCreditCardNumber,
                            CardType = processPaymentResult.AllowStoringCreditCardNumber ? SecurityHelper.Encrypt(paymentInfo.CreditCardType) : string.Empty,
                            CardName = processPaymentResult.AllowStoringCreditCardNumber ? SecurityHelper.Encrypt(paymentInfo.CreditCardName) : string.Empty,
                            CardNumber = processPaymentResult.AllowStoringCreditCardNumber ? SecurityHelper.Encrypt(paymentInfo.CreditCardNumber) : string.Empty,
                            MaskedCreditCardNumber = SecurityHelper.Encrypt(paymentService.GetMaskedCreditCardNumber(paymentInfo.CreditCardNumber)),
                            CardCvv2 = processPaymentResult.AllowStoringCreditCardNumber ? SecurityHelper.Encrypt(paymentInfo.CreditCardCvv2) : string.Empty,
                            CardExpirationMonth = processPaymentResult.AllowStoringCreditCardNumber ? SecurityHelper.Encrypt(paymentInfo.CreditCardExpireMonth.ToString()) : string.Empty,
                            CardExpirationYear = processPaymentResult.AllowStoringCreditCardNumber ? SecurityHelper.Encrypt(paymentInfo.CreditCardExpireYear.ToString()) : string.Empty,
                            PaymentMethodId = paymentInfo.PaymentMethodId,
                            PaymentMethodName = paymentMethodName,
                            AuthorizationTransactionId = processPaymentResult.AuthorizationTransactionId,
                            AuthorizationTransactionCode = processPaymentResult.AuthorizationTransactionCode,
                            AuthorizationTransactionResult = processPaymentResult.AuthorizationTransactionResult,
                            CaptureTransactionId = processPaymentResult.CaptureTransactionId,
                            CaptureTransactionResult = processPaymentResult.CaptureTransactionResult,
                            SubscriptionTransactionId = processPaymentResult.SubscriptionTransactionId,
                            PurchaseOrderNumber = paymentInfo.PurchaseOrderNumber,
                            PaymentStatusId = (int)processPaymentResult.PaymentStatus,
                            PaidDate = null,
                            BillingFirstName = billingFirstName,
                            BillingLastName = billingLastName,
                            BillingPhoneNumber = billingPhoneNumber,
                            BillingEmail = billingEmail,
                            BillingFaxNumber = billingFaxNumber,
                            BillingCompany = billingCompany,
                            BillingAddress1 = billingAddress1,
                            BillingAddress2 = billingAddress2,
                            BillingCity = billingCity,
                            BillingStateProvince = billingStateProvince,
                            BillingStateProvinceId = billingStateProvinceId,
                            BillingZipPostalCode = billingZipPostalCode,
                            BillingCountry = billingCountry,
                            BillingCountryId = billingCountryId,
                            ShippingStatusId = (int)shippingStatusEnum,
                            ShippingFirstName = shippingFirstName,
                            ShippingLastName = shippingLastName,
                            ShippingPhoneNumber = shippingPhoneNumber,
                            ShippingEmail = shippingEmail,
                            ShippingFaxNumber = shippingFaxNumber,
                            ShippingCompany = shippingCompany,
                            ShippingAddress1 = shippingAddress1,
                            ShippingAddress2 = shippingAddress2,
                            ShippingCity = shippingCity,
                            ShippingStateProvince = shippingStateProvince,
                            ShippingStateProvinceId = shippingStateProvinceId,
                            ShippingZipPostalCode = shippingZipPostalCode,
                            ShippingCountry = shippingCountry,
                            ShippingCountryId = shippingCountryId,
                            ShippingMethod = shippingMethodName,
                            ShippingRateComputationMethodId = shippingRateComputationMethodId,
                            ShippedDate = null,
                            DeliveryDate = null,
                            TrackingNumber = string.Empty,
                            VatNumber = vatNumber,
                            Deleted = false,
                            CreatedOn = DateTime.UtcNow
                        };
                        InsertOrder(order);

                        orderId = order.OrderId;

                        if (!paymentInfo.IsRecurringPayment)
                        {
                            //move shopping cart items to order product variants
                            foreach (var sc in cart)
                            {
                                //prices
                                decimal taxRate = decimal.Zero;
                                decimal scUnitPrice = PriceHelper.GetUnitPrice(sc, customer, true);
                                decimal scSubTotal = PriceHelper.GetSubTotal(sc, customer, true);
                                decimal scUnitPriceInclTax = taxService.GetPrice(sc.ProductVariant, scUnitPrice, true, customer, out taxRate);
                                decimal scUnitPriceExclTax = taxService.GetPrice(sc.ProductVariant, scUnitPrice, false, customer, out taxRate);
                                decimal scSubTotalInclTax = taxService.GetPrice(sc.ProductVariant, scSubTotal, true, customer, out taxRate);
                                decimal scSubTotalExclTax = taxService.GetPrice(sc.ProductVariant, scSubTotal, false, customer, out taxRate);
                                decimal scUnitPriceInclTaxInCustomerCurrency = currencyService.ConvertCurrency(scUnitPriceInclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                                decimal scUnitPriceExclTaxInCustomerCurrency = currencyService.ConvertCurrency(scUnitPriceExclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                                decimal scSubTotalInclTaxInCustomerCurrency = currencyService.ConvertCurrency(scSubTotalInclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                                decimal scSubTotalExclTaxInCustomerCurrency = currencyService.ConvertCurrency(scSubTotalExclTax, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);

                                //discounts
                                Discount scDiscount = null;
                                decimal discountAmount = PriceHelper.GetDiscountAmount(sc, customer, out scDiscount);
                                decimal discountAmountInclTax = taxService.GetPrice(sc.ProductVariant, discountAmount, true, customer, out taxRate);
                                decimal discountAmountExclTax = taxService.GetPrice(sc.ProductVariant, discountAmount, false, customer, out taxRate);
                                if (scDiscount != null && !appliedDiscounts.ContainsDiscount(scDiscount.Name))
                                    appliedDiscounts.Add(scDiscount);

                                //attributes
                                string attributeDescription = ProductAttributeHelper.FormatAttributes(sc.ProductVariant, sc.AttributesXml, customer, "<br />");

                                //save item
                                var opv = new OrderProductVariant()
                                {
                                    OrderProductVariantGuid = Guid.NewGuid(),
                                    OrderId = order.OrderId,
                                    ProductVariantId = sc.ProductVariantId,
                                    UnitPriceInclTax = scUnitPriceInclTax,
                                    UnitPriceExclTax = scUnitPriceExclTax,
                                    PriceInclTax = scSubTotalInclTax,
                                    PriceExclTax = scSubTotalExclTax,
                                    UnitPriceInclTaxInCustomerCurrency = scUnitPriceInclTaxInCustomerCurrency,
                                    UnitPriceExclTaxInCustomerCurrency = scUnitPriceExclTaxInCustomerCurrency,
                                    PriceInclTaxInCustomerCurrency = scSubTotalInclTaxInCustomerCurrency,
                                    PriceExclTaxInCustomerCurrency = scSubTotalExclTaxInCustomerCurrency,
                                    AttributeDescription = attributeDescription,
                                    AttributesXml = sc.AttributesXml,
                                    Quantity = sc.Quantity,
                                    DiscountAmountInclTax = discountAmountInclTax,
                                    DiscountAmountExclTax = discountAmountExclTax,
                                    DownloadCount = 0,
                                    IsDownloadActivated = false,
                                    LicenseDownloadId = 0
                                };
                                InsertOrderProductVariant(opv);

                                //gift cards
                                if (sc.ProductVariant.IsGiftCard)
                                {
                                    string giftCardRecipientName = string.Empty;
                                    string giftCardRecipientEmail = string.Empty;
                                    string giftCardSenderName = string.Empty;
                                    string giftCardSenderEmail = string.Empty;
                                    string giftCardMessage = string.Empty;
                                    ProductAttributeHelper.GetGiftCardAttribute(sc.AttributesXml,
                                        out giftCardRecipientName, out giftCardRecipientEmail,
                                        out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);

                                    for (int i = 0; i < sc.Quantity; i++)
                                    {
                                        var gc = new GiftCard()
                                        {
                                            PurchasedOrderProductVariantId = opv.OrderProductVariantId,
                                            Amount = scUnitPriceExclTax,
                                            IsGiftCardActivated = false,
                                            GiftCardCouponCode = GiftCardHelper.GenerateGiftCardCode(),
                                            RecipientName = giftCardRecipientName,
                                            RecipientEmail = giftCardRecipientEmail,
                                            SenderName = giftCardSenderName,
                                            SenderEmail = giftCardSenderEmail,
                                            Message = giftCardMessage,
                                            IsRecipientNotified = false,
                                            CreatedOn = DateTime.UtcNow
                                        };
                                        InsertGiftCard(gc);
                                    }
                                }

                                //inventory
                                productService.AdjustInventory(sc.ProductVariantId, true, sc.Quantity, sc.AttributesXml);
                            }

                            //clear shopping cart
                            foreach (var sc in cart)
                            {
                                shoppingCartService.DeleteShoppingCartItem(sc.ShoppingCartItemId, false);
                            }
                        }
                        else
                        {
                            var initialOrderProductVariants = initialOrder.OrderProductVariants;
                            foreach (var opv in initialOrderProductVariants)
                            {
                                //save item
                                var newOpv = new OrderProductVariant()
                                {
                                    OrderProductVariantGuid = Guid.NewGuid(),
                                    OrderId = order.OrderId,
                                    ProductVariantId = opv.ProductVariantId,
                                    UnitPriceInclTax = opv.UnitPriceInclTax,
                                    UnitPriceExclTax = opv.UnitPriceExclTax,
                                    PriceInclTax = opv.PriceInclTax,
                                    PriceExclTax = opv.PriceExclTax,
                                    UnitPriceInclTaxInCustomerCurrency = opv.UnitPriceInclTaxInCustomerCurrency,
                                    UnitPriceExclTaxInCustomerCurrency = opv.UnitPriceExclTaxInCustomerCurrency,
                                    PriceInclTaxInCustomerCurrency =  opv.PriceInclTaxInCustomerCurrency,
                                    PriceExclTaxInCustomerCurrency = opv.PriceExclTaxInCustomerCurrency,
                                    AttributeDescription = opv.AttributeDescription,
                                    AttributesXml = opv.AttributesXml,
                                    Quantity = opv.Quantity,
                                    DiscountAmountInclTax = opv.DiscountAmountInclTax,
                                    DiscountAmountExclTax =  opv.DiscountAmountExclTax,
                                    DownloadCount = 0,
                                    IsDownloadActivated = false,
                                    LicenseDownloadId = 0
                                };

                                InsertOrderProductVariant(newOpv);

                                //gift cards
                                if (opv.ProductVariant.IsGiftCard)
                                {
                                    string giftCardRecipientName = string.Empty;
                                    string giftCardRecipientEmail = string.Empty;
                                    string giftCardSenderName = string.Empty;
                                    string giftCardSenderEmail = string.Empty;
                                    string giftCardMessage = string.Empty;
                                    ProductAttributeHelper.GetGiftCardAttribute(opv.AttributesXml,
                                        out giftCardRecipientName, out giftCardRecipientEmail,
                                        out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);

                                    for (int i = 0; i < opv.Quantity; i++)
                                    {
                                        var gc = new GiftCard()
                                        {
                                            PurchasedOrderProductVariantId = newOpv.OrderProductVariantId,
                                            Amount = opv.UnitPriceExclTax,
                                            IsGiftCardActivated = false,
                                            GiftCardCouponCode = GiftCardHelper.GenerateGiftCardCode(),
                                            RecipientName = giftCardRecipientName,
                                            RecipientEmail = giftCardRecipientEmail,
                                            SenderName = giftCardSenderName,
                                            SenderEmail = giftCardSenderEmail,
                                            Message = giftCardMessage,
                                            IsRecipientNotified = false,
                                            CreatedOn = DateTime.UtcNow
                                        };
                                        InsertGiftCard(gc);
                                    }
                                }

                                //inventory
                                productService.AdjustInventory(opv.ProductVariantId, true, opv.Quantity, opv.AttributesXml);
                            }
                        }

                        //discount usage history
                        if (!paymentInfo.IsRecurringPayment)
                        {
                            foreach (var discount in appliedDiscounts)
                            {
                                var duh = new DiscountUsageHistory()
                                {
                                    DiscountId = discount.DiscountId,
                                    CustomerId = customer.CustomerId,
                                    OrderId = order.OrderId,
                                    CreatedOn = DateTime.UtcNow
                                };
                                discountService.InsertDiscountUsageHistory(duh);
                            }
                        }

                        //gift card usage history
                        if (!paymentInfo.IsRecurringPayment)
                        {
                            if (appliedGiftCards != null)
                            {
                                foreach (var agc in appliedGiftCards)
                                {
                                    decimal amountUsed = agc.AmountCanBeUsed;
                                    decimal amountUsedInCustomerCurrency = currencyService.ConvertCurrency(amountUsed, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                                    var gcuh = new GiftCardUsageHistory()
                                    {
                                        GiftCardId = agc.GiftCardId,
                                        CustomerId = customer.CustomerId,
                                        OrderId = order.OrderId,
                                        UsedValue = amountUsed,
                                        UsedValueInCustomerCurrency = amountUsedInCustomerCurrency,
                                        CreatedOn = DateTime.UtcNow
                                    };
                                    InsertGiftCardUsageHistory(gcuh);
                                }
                            }
                        }

                        //reward points history
                        if (redeemedRewardPointsAmount > decimal.Zero)
                        {
                            decimal redeemedRewardPointsAmountInCustomerCurrency = currencyService.ConvertCurrency(redeemedRewardPointsAmount, currencyService.PrimaryStoreCurrency, paymentInfo.CustomerCurrency);
                            string message = string.Format(localizationManager.GetLocaleResourceString("RewardPoints.Message.RedeemedForOrder", order.CustomerLanguageId), order.OrderId);

                            RewardPointsHistory rph = this.InsertRewardPointsHistory(customer.CustomerId,
                                order.OrderId, -redeemedRewardPoints,
                                redeemedRewardPointsAmount,
                                redeemedRewardPointsAmountInCustomerCurrency,
                                customerCurrencyCode,
                                message,
                                DateTime.UtcNow);
                        }

                        //recurring orders
                        if (!paymentInfo.IsRecurringPayment)
                        {
                            if (isRecurringShoppingCart)
                            {
                                //create recurring payment
                                var rp = new RecurringPayment()
                                {
                                    InitialOrderId = order.OrderId,
                                    CycleLength = paymentInfo.RecurringCycleLength,
                                    CyclePeriod = paymentInfo.RecurringCyclePeriod,
                                    TotalCycles = paymentInfo.RecurringTotalCycles,
                                    StartDate = DateTime.UtcNow,
                                    IsActive = true,
                                    Deleted = false,
                                    CreatedOn = DateTime.UtcNow
                                };
                                InsertRecurringPayment(rp);

                                var recurringPaymentType = paymentService.SupportRecurringPayments(paymentInfo.PaymentMethodId);
                                switch (recurringPaymentType)
                                {
                                    case RecurringPaymentTypeEnum.NotSupported:
                                        {
                                            //not supported
                                        }
                                        break;
                                    case RecurringPaymentTypeEnum.Manual:
                                        {
                                            //first payment
                                            var rph = new RecurringPaymentHistory()
                                            {
                                                RecurringPaymentId = rp.RecurringPaymentId,
                                                OrderId = order.OrderId,
                                                CreatedOn = DateTime.UtcNow
                                            };
                                            InsertRecurringPaymentHistory(rph);
                                        }
                                        break;
                                    case RecurringPaymentTypeEnum.Automatic:
                                        {
                                            //will be created later (process is automated)
                                        }
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }

                        //notes, messages
                        InsertOrderNote(order.OrderId, string.Format("Order placed"), false, DateTime.UtcNow);

                        int orderPlacedStoreOwnerNotificationQueuedEmailId = messageService.SendOrderPlacedStoreOwnerNotification(order, localizationManager.DefaultAdminLanguage.LanguageId);
                        if (orderPlacedStoreOwnerNotificationQueuedEmailId > 0)
                        {
                            InsertOrderNote(order.OrderId, string.Format("\"Order placed\" email (to store owner) has been queued. Queued email identifier: {0}.", orderPlacedStoreOwnerNotificationQueuedEmailId), false, DateTime.UtcNow);
                        }

                        int orderPlacedCustomerNotificationQueuedEmailId = messageService.SendOrderPlacedCustomerNotification(order, order.CustomerLanguageId);
                        if (orderPlacedCustomerNotificationQueuedEmailId > 0)
                        {
                            InsertOrderNote(order.OrderId, string.Format("\"Order placed\" email (to customer) has been queued. Queued email identifier: {0}.", orderPlacedCustomerNotificationQueuedEmailId), false, DateTime.UtcNow);
                        }

                        smsService.SendOrderPlacedNotification(order);

                        //order status
                        order = CheckOrderStatus(order.OrderId);

                        //reset checkout data
                        if (!paymentInfo.IsRecurringPayment)
                        {
                            customerService.ResetCheckoutData(customer.CustomerId, true);
                        }

                        //log
                        if (!paymentInfo.IsRecurringPayment)
                        {
                            customerActivityService.InsertActivity(
                                "PlaceOrder",
                                localizationManager.GetLocaleResourceString("ActivityLog.PlaceOrder"),
                                order.OrderId);
                        }

                        //uncomment this line to support transactions
                        //scope.Complete();

                        //raise event
                        EventContext.Current.OnOrderPlaced(null,
                            new OrderEventArgs() { Order = order });

                        //raise event
                        if (order.PaymentStatus == PaymentStatusEnum.Paid)
                        {
                            EventContext.Current.OnOrderPaid(null,
                                new OrderEventArgs() { Order = order });
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                processPaymentResult.Error = exc.Message;
                processPaymentResult.FullError = exc.ToString();
            }

            if (!String.IsNullOrEmpty(processPaymentResult.Error))
            {
                logService.InsertLog(LogTypeEnum.OrderError, string.Format("Error while placing order. {0}", processPaymentResult.Error), processPaymentResult.FullError);
            }
            return processPaymentResult.Error;
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            CommonHelper.SetResponseNoCache(Response);

            if (!Page.IsPostBack)
            {
                byte[] param = Request.BinaryRead(Request.ContentLength);
                string strRequest = Encoding.ASCII.GetString(param);
                Dictionary<string, string> values;

                PayPalSewbiePaymentProcessor processor = new PayPalSewbiePaymentProcessor();
                if (processor.VerifyIPN(strRequest, out values))
                {
                    #region values
                    decimal total = decimal.Zero;
                    try
                    {
                        total = decimal.Parse(values["mc_gross"], new CultureInfo("en-US"));
                    }
                    catch { }

                    string payer_status = string.Empty;
                    values.TryGetValue("payer_status", out payer_status);
                    string payment_status = string.Empty;
                    values.TryGetValue("payment_status", out payment_status);
                    string pending_reason = string.Empty;
                    values.TryGetValue("pending_reason", out pending_reason);
                    string mc_currency = string.Empty;
                    values.TryGetValue("mc_currency", out mc_currency);
                    string txn_id = string.Empty;
                    values.TryGetValue("txn_id", out txn_id);
                    string txn_type = string.Empty;
                    values.TryGetValue("txn_type", out txn_type);
                    string rp_invoice_id = string.Empty;
                    values.TryGetValue("rp_invoice_id", out rp_invoice_id);
                    string payment_type = string.Empty;
                    values.TryGetValue("payment_type", out payment_type);
                    string payer_id = string.Empty;
                    values.TryGetValue("payer_id", out payer_id);
                    string receiver_id = string.Empty;
                    values.TryGetValue("receiver_id", out receiver_id);
                    string invoice = string.Empty;
                    values.TryGetValue("invoice", out invoice);
                    string payment_fee = string.Empty;
                    values.TryGetValue("payment_fee", out payment_fee);

                    #endregion

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("Paypal IPN:");
                    foreach (KeyValuePair<string, string> kvp in values)
                    {
                        sb.AppendLine(kvp.Key + ": " + kvp.Value);
                    }

                    PaymentStatusEnum newPaymentStatus = PaypalHelper.GetPaymentStatus(payment_status, pending_reason);
                    sb.AppendLine("New payment status: " + newPaymentStatus.GetPaymentStatusName());

                    switch (txn_type)
                    {
                        case "recurring_payment_profile_created":
                            //do nothing here
                            break;
                        case "recurring_payment":
                            #region Recurring payment
                            {
                                Guid orderNumberGuid = Guid.Empty;
                                try
                                {
                                    orderNumberGuid = new Guid(rp_invoice_id);
                                }
                                catch
                                {
                                }

                                Order initialOrder = this.OrderService.GetOrderByGuid(orderNumberGuid);
                                if (initialOrder != null)
                                {
                                    var recurringPayments = this.OrderService.SearchRecurringPayments(0, initialOrder.OrderId, null);
                                    foreach (var rp in recurringPayments)
                                    {
                                        switch (newPaymentStatus)
                                        {
                                            case PaymentStatusEnum.Authorized:
                                            case PaymentStatusEnum.Paid:
                                                {
                                                    var recurringPaymentHistory = rp.RecurringPaymentHistory;
                                                    if (recurringPaymentHistory.Count == 0)
                                                    {
                                                        //first payment
                                                        var rph = new RecurringPaymentHistory()
                                                        {
                                                            RecurringPaymentId = rp.RecurringPaymentId,
                                                            OrderId = initialOrder.OrderId,
                                                            CreatedOn = DateTime.UtcNow
                                                        };
                                                        this.OrderService.InsertRecurringPaymentHistory(rph);
                                                    }
                                                    else
                                                    {
                                                        //next payments
                                                        this.OrderService.ProcessNextRecurringPayment(rp.RecurringPaymentId);
                                                        //UNDONE change new order status according to newPaymentStatus
                                                        //UNDONE refund/void is not supported
                                                    }
                                                }
                                                break;
                                        }
                                    }

                                    //this.OrderService.InsertOrderNote(newOrder.OrderId, sb.ToString(), DateTime.UtcNow);
                                    this.LogService.InsertLog(LogTypeEnum.Unknown, "PayPal IPN. Recurring info", new NopException(sb.ToString()));
                                }
                                else
                                {
                                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order is not found", new NopException(sb.ToString()));
                                }
                            }
                            #endregion
                            break;
                        default:
                            #region Standard payment
                            {
                                string orderNumber = string.Empty;
                                values.TryGetValue("custom", out orderNumber);
                                Guid orderNumberGuid = Guid.Empty;
                                try
                                {
                                    orderNumberGuid = new Guid(orderNumber);
                                }
                                catch
                                {
                                }

                                Order order = this.OrderService.GetOrderByGuid(orderNumberGuid);
                                if (order != null)
                                {
                                    this.OrderService.InsertOrderNote(order.OrderId, sb.ToString(), false, DateTime.UtcNow);
                                    switch (newPaymentStatus)
                                    {
                                        case PaymentStatusEnum.Pending:
                                            {
                                                this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order Pending", new NopException(sb.ToString()));
                                            }
                                            break;
                                        case PaymentStatusEnum.Authorized:
                                            {
                                                this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " is Authorized", new NopException(sb.ToString()));
                                                if (this.OrderService.CanMarkOrderAsAuthorized(order))
                                                {
                                                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " can be Authorized", new NopException(sb.ToString()));
                                                    this.OrderService.MarkAsAuthorized(order.OrderId);
                                                }
                                            }
                                            break;
                                        case PaymentStatusEnum.Paid:
                                            {
                                                this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " is Paid", new NopException(sb.ToString()));
                                                if (this.OrderService.CanMarkOrderAsPaid(order))
                                                {
                                                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " can be Paid", new NopException(sb.ToString()));
                                                    this.OrderService.MarkOrderAsPaid(order.OrderId);
                                                }
                                            }
                                            break;
                                        case PaymentStatusEnum.Refunded:
                                            {
                                                this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " is Refunded", new NopException(sb.ToString()));
                                                if (this.OrderService.CanRefundOffline(order))
                                                {
                                                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " has been refunded offline.", new NopException(sb.ToString()));
                                                    this.OrderService.RefundOffline(order.OrderId);
                                                }
                                            }
                                            break;
                                        case PaymentStatusEnum.Voided:
                                            {
                                                this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " is void", new NopException(sb.ToString()));
                                                if (this.OrderService.CanVoidOffline(order))
                                                {
                                                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order " + order.OrderId.ToString() + " has been voided offline.", new NopException(sb.ToString()));
                                                    this.OrderService.VoidOffline(order.OrderId);
                                                }
                                            }
                                            break;
                                        default:
                                            break;
                                    }
                                }
                                else
                                {
                                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order is not found", new NopException(sb.ToString()));
                                }
                            }
                            #endregion
                            break;
                    }
                }
                else
                {
                    this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN failed.", strRequest);
                }
            }
        }