Ejemplo n.º 1
0
        public virtual async Task ProcessNextRecurringPaymentAsync(RecurringPayment recurringPayment)
        {
            Guard.NotNull(recurringPayment, nameof(recurringPayment));

            try
            {
                if (!recurringPayment.IsActive)
                {
                    throw new SmartException(T("Payment.RecurringPaymentNotActive"));
                }

                var initialOrder = recurringPayment.InitialOrder;
                if (initialOrder == null)
                {
                    throw new SmartException(T("Order.InitialOrderDoesNotExistForRecurringPayment"));
                }

                var customer = initialOrder.Customer;
                if (customer == null)
                {
                    throw new SmartException(T("Customer.DoesNotExist"));
                }

                var nextPaymentDate = recurringPayment.NextPaymentDate;
                if (!nextPaymentDate.HasValue)
                {
                    throw new SmartException(T("Payment.CannotCalculateNextPaymentDate"));
                }

                var paymentInfo = new ProcessPaymentRequest
                {
                    StoreId              = initialOrder.StoreId,
                    CustomerId           = customer.Id,
                    OrderGuid            = Guid.NewGuid(),
                    IsRecurringPayment   = true,
                    InitialOrderId       = initialOrder.Id,
                    RecurringCycleLength = recurringPayment.CycleLength,
                    RecurringCyclePeriod = recurringPayment.CyclePeriod,
                    RecurringTotalCycles = recurringPayment.TotalCycles,
                };

                var result = await PlaceOrderAsync(paymentInfo, new());

                if (result.Success)
                {
                    if (result.PlacedOrder == null)
                    {
                        throw new SmartException(T("Order.NotFound", "".NaIfEmpty()));
                    }

                    recurringPayment.RecurringPaymentHistory.Add(new RecurringPaymentHistory
                    {
                        RecurringPayment = recurringPayment,
                        CreatedOnUtc     = DateTime.UtcNow,
                        OrderId          = result.PlacedOrder.Id
                    });

                    await _db.SaveChangesAsync();
                }
                else if (result.Errors.Count > 0)
                {
                    throw new SmartException(string.Join(" ", result.Errors));
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorsAll(ex);
                throw;
            }
        }
Ejemplo n.º 2
0
        private void Save_button_Click(object sender, EventArgs e)
        {
            Log.Debug(TAG, nameof(Save_button_Click));

            try
            {
                // earnings cant have category
                int cId = ((JavaLangObjectWrapper <Category>)category_button.Tag).Value.Id;
                int oId = ((JavaLangObjectWrapper <Owner>)owner_button.Tag).Value.Id;
                int pId = ((JavaLangObjectWrapper <PaymentType>)paymentType_button.Tag).Value.Id;
                int iId = ((JavaLangObjectWrapper <Interval>)interval_button.Tag).Value.Id;

                int warranty;
                if (!int.TryParse(warranty_editText.Text, out warranty))
                {
                    warranty = 0;
                }

                float cost = float.Parse(this.cost_editText.Text);

                RecurringPayment item = new RecurringPayment()
                {
                    CategoryId    = cId,
                    Cost          = this.earnings_checkBox.Checked ? cost : 0f - cost,
                    EndDate       = ((JavaLangObjectWrapper <DateTime>) this.endDate_button.Tag).Value,
                    LastUpdate    = ((JavaLangObjectWrapper <Interval>)interval_button.Tag).Value.BeforeDateTime(((JavaLangObjectWrapper <DateTime>) this.startDate_button.Tag).Value),
                    Description   = this.description_editText.Text,
                    OwnerId       = oId,
                    PaymentTypeId = pId,
                    IntervalId    = iId,
                    Warranty      = warranty,
                    Earnings      = this.earnings_checkBox.Checked,
                    Tag           = this.tags_editText.Text,
                    //DateCreated = new Java.Sql.Timestamp(Tools.ConvertToTimestamp(DateTime.Now))
                    IsActive = this.isActive_checkBox.Checked,
                };

                #region Ask for permission
                //https://github.com/xamarin/monodroid-samples/blob/master/android-m/RuntimePermissions/MainActivity.cs
                const int    REQUEST_CODE_ASK_PERMISSIONS = 123;
                const string permission = Android.Manifest.Permission.WriteExternalStorage;

                var hasWriteContactsPermission = ActivityCompat.CheckSelfPermission(this.Activity, permission);

                if (hasWriteContactsPermission != Android.Content.PM.Permission.Granted)
                {
                    RequestPermissions(new string[] { Android.Manifest.Permission.WriteExternalStorage },
                                       REQUEST_CODE_ASK_PERMISSIONS);
                    return;
                }
                #endregion

                if (SelectedItem != null) // update existing item
                {
                    item.Id = SelectedItem.Id;
                    if (db.Update(item).Result)
                    {
                        Toast.MakeText(this.Activity, Resources.GetString(Resource.String.Saved), ToastLength.Short).Show();

                        if (onContinueWithHandler != null)
                        {
                            onContinueWithHandler();
                        }
                        Dismiss();
                    }
                }
                else if (db.Insert(item).Result) // inser new item
                {
                    Toast.MakeText(this.Activity, Resources.GetString(Resource.String.Saved), ToastLength.Short).Show();

                    if (onContinueWithHandler != null)
                    {
                        onContinueWithHandler();
                    }
                    Dismiss();
                }
                else
                {
                    Toast.MakeText(this.Activity, Resources.GetString(Resource.String.WasntSaved), ToastLength.Short).Show();
                }
            }
            catch (NullReferenceException ex)
            {
                Log.Error(TAG, nameof(Save_button_Click), ex.Message);
                Toast.MakeText(this.Activity, Resources.GetString(Resource.String.SomethingMissing), ToastLength.Short).Show();
            }
            catch (Exception ex)
            {
                Log.Error(TAG, nameof(Save_button_Click), ex.Message);
                Toast.MakeText(this.Activity, ex.Message, ToastLength.Short).Show();
            }
        }
        /// <summary>
        /// Gets a value indicating whether a customer can cancel recurring payment
        /// </summary>
        /// <param name="customerToValidate">Customer</param>
        /// <param name="recurringPayment">Recurring Payment</param>
        /// <returns>value indicating whether a customer can cancel recurring payment</returns>
        public virtual async Task <bool> CanCancelRecurringPayment(Customer customerToValidate, RecurringPayment recurringPayment)
        {
            if (recurringPayment == null)
            {
                return(false);
            }

            if (customerToValidate == null)
            {
                return(false);
            }

            var initialOrder = recurringPayment.InitialOrder;

            if (initialOrder == null)
            {
                return(false);
            }

            var customer = await _customerService.GetCustomerById(recurringPayment.InitialOrder.CustomerId);

            if (customer == null)
            {
                return(false);
            }

            if (initialOrder.OrderStatus == OrderStatus.Cancelled)
            {
                return(false);
            }

            if (!customerToValidate.IsAdmin())
            {
                if (customer.Id != customerToValidate.Id)
                {
                    return(false);
                }
            }

            if (!recurringPayment.NextPaymentDate.HasValue)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Updates the recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 /// <returns>A task that represents the asynchronous operation</returns>
 public virtual async Task UpdateRecurringPaymentAsync(RecurringPayment recurringPayment)
 {
     await _recurringPaymentRepository.UpdateAsync(recurringPayment);
 }
Ejemplo n.º 5
0
        private static bool CheckQuarterly(RecurringPayment recurringPayment)
        {
            TimeSpan dateDiff = DateTime.Now - recurringPayment.LastRecurrenceCreated.Date;

            return(dateDiff.TotalDays >= QUARTERLY_RECURRENCE_DAYS);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Deletes a recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 public virtual void DeleteRecurringPayment(RecurringPayment recurringPayment)
 {
     _recurringPaymentRepository.Delete(recurringPayment);
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Updates the recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 public virtual void UpdateRecurringPayment(RecurringPayment recurringPayment)
 {
     _recurringPaymentRepository.Update(recurringPayment);
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Sends a "Recurring payment cancelled" notification to a store owner
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 /// <param name="languageId">Message language identifier</param>
 /// <returns>Queued email identifier</returns>
 public int SendRecurringPaymentCancelledStoreOwnerNotification(RecurringPayment recurringPayment, int languageId)
 {
     return(_workflowMessageService.SendRecurringPaymentCancelledStoreOwnerNotification(recurringPayment, languageId));
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Sends a "Recurring payment failed" notification to a customer
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 /// <param name="languageId">Message language identifier</param>
 /// <returns>Queued email identifier</returns>
 public int SendRecurringPaymentFailedCustomerNotification(RecurringPayment recurringPayment, int languageId)
 {
     return(_workflowMessageService.SendRecurringPaymentFailedCustomerNotification(recurringPayment, languageId));
 }
Ejemplo n.º 10
0
 public LiquidRecurringPayment(RecurringPayment recurringPayment)
 {
     _recurringPayment = recurringPayment;
     AdditionalTokens  = new Dictionary <string, string>();
 }
        /// <summary>
        /// Sends a "Recurring payment cancelled" notification to a store owner
        /// </summary>
        public static CreateMessageResult SendRecurringPaymentCancelledStoreOwnerNotification(this IMessageFactory factory, RecurringPayment recurringPayment, int languageId = 0)
        {
            Guard.NotNull(recurringPayment, nameof(recurringPayment));

            var order = recurringPayment.InitialOrder;

            return(factory.CreateMessage(MessageContext.Create(MessageTemplateNames.RecurringPaymentCancelledStoreOwner, languageId, order?.StoreId, order?.Customer), true,
                                         recurringPayment, order));
        }
Ejemplo n.º 12
0
        public RecurringPaymentRequest()
        {
            RecurringPayment oRecurringPayment = new RecurringPayment();

            oRecurringPayment.StoreId  = "120995000";
            oRecurringPayment.Function = Function.install;

            RecurringPaymentInformation oRecurringPaymentInformation = new RecurringPaymentInformation();

            oRecurringPaymentInformation.InstallmentCount           = "12";
            oRecurringPaymentInformation.InstallmentFrequency       = "1";
            oRecurringPaymentInformation.InstallmentPeriod          = RecurringPaymentInformationInstallmentPeriod.month;
            oRecurringPaymentInformation.InstallmentPeriodSpecified = true;
            DateTime dateNow = DateTime.Now.AddDays(5);

            oRecurringPaymentInformation.RecurringStartDate = dateNow.ToString("yyyyMMdd");
            oRecurringPaymentInformation.MaximumFailures    = "3";

            oRecurringPayment.RecurringPaymentInformation = oRecurringPaymentInformation;

            CreditCardData oCreditCardData = new CreditCardData();

            oCreditCardData.Brand            = CreditCardDataBrand.VISA;
            oCreditCardData.BrandSpecified   = true;
            oCreditCardData.ItemsElementName = new ItemsChoiceType[] { ItemsChoiceType.CardNumber, ItemsChoiceType.ExpMonth, ItemsChoiceType.ExpYear, ItemsChoiceType.CardCodeValue };
            oCreditCardData.Items            = new Object[] { "4035874000424977", "12", "18", "977" };

            oRecurringPayment.CreditCardData = oCreditCardData;

            Payment oPayment = new Payment();

            oPayment.SubTotal    = 13;
            oPayment.ChargeTotal = 13;
            oPayment.Currency    = "978";

            oRecurringPayment.Payment = oPayment;

            Billing oBilling = new Billing();

            oBilling.Name     = "Name";
            oBilling.Address1 = "Address";
            oBilling.City     = "City";
            oBilling.State    = "State";
            oBilling.Zip      = "Zip";
            oBilling.Country  = "Country";

            oRecurringPayment.Billing = oBilling;

            ClientLocale oClientLocale = new ClientLocale();

            oClientLocale.Country  = "UK";
            oClientLocale.Language = "en";

            WSIPGClient.WebReference.Action oAction;
            oAction              = new WSIPGClient.WebReference.Action();
            oAction.Item         = oRecurringPayment;
            oAction.ClientLocale = oClientLocale;

            RecurringPaymentActionRequest      = new IPGApiActionRequest();
            RecurringPaymentActionRequest.Item = oAction;
        }
Ejemplo n.º 13
0
        protected RecurringPayment Save()
        {
            RecurringPayment recurringPayment = ctrlRecurringPaymentInfo.SaveInfo();

            return(recurringPayment);
        }
        /// <summary>
        /// Process next recurring psayment
        /// </summary>
        /// <param name="recurringPayment">Recurring payment</param>
        public virtual async Task ProcessNextRecurringPayment(RecurringPayment recurringPayment)
        {
            if (recurringPayment == null)
            {
                throw new ArgumentNullException("recurringPayment");
            }
            try
            {
                if (!recurringPayment.IsActive)
                {
                    throw new GrandException("Recurring payment is not active");
                }

                var initialOrder = recurringPayment.InitialOrder;
                if (initialOrder == null)
                {
                    throw new GrandException("Initial order could not be loaded");
                }

                var customer = await _customerService.GetCustomerById(initialOrder.CustomerId);

                if (customer == null)
                {
                    throw new GrandException("Customer could not be loaded");
                }

                var nextPaymentDate = recurringPayment.NextPaymentDate;
                if (!nextPaymentDate.HasValue)
                {
                    throw new GrandException("Next payment date could not be calculated");
                }

                //payment info
                var paymentInfo = new ProcessPaymentRequest {
                    StoreId              = initialOrder.StoreId,
                    CustomerId           = customer.Id,
                    OrderGuid            = Guid.NewGuid(),
                    IsRecurringPayment   = true,
                    InitialOrderId       = initialOrder.Id,
                    RecurringCycleLength = recurringPayment.CycleLength,
                    RecurringCyclePeriod = recurringPayment.CyclePeriod,
                    RecurringTotalCycles = recurringPayment.TotalCycles,
                };

                //place a new order
                var orderConfirmationService = _serviceProvider.GetRequiredService <IOrderConfirmationService>();
                var result = await orderConfirmationService.PlaceOrder(paymentInfo);

                if (result.Success)
                {
                    if (result.PlacedOrder == null)
                    {
                        throw new GrandException("Placed order could not be loaded");
                    }

                    var rph = new RecurringPaymentHistory {
                        RecurringPaymentId = recurringPayment.Id,
                        CreatedOnUtc       = DateTime.UtcNow,
                        OrderId            = result.PlacedOrder.Id,
                    };
                    recurringPayment.RecurringPaymentHistory.Add(rph);
                    await _orderService.UpdateRecurringPayment(recurringPayment);
                }
                else
                {
                    string error = "";
                    for (int i = 0; i < result.Errors.Count; i++)
                    {
                        error += string.Format("Error {0}: {1}", i, result.Errors[i]);
                        if (i != result.Errors.Count - 1)
                        {
                            error += ". ";
                        }
                    }
                    throw new GrandException(error);
                }
            }
            catch (Exception exc)
            {
                _logger.Error(string.Format("Error while processing recurring order. {0}", exc.Message), exc);
                throw;
            }
        }
 /// <summary>
 ///     Default constructor. Will create a new <see cref="RecurringPayment" />
 /// </summary>
 public RecurringPaymentViewModel()
 {
     RecurringPayment = new RecurringPayment();
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Gets a value indicating whether a customer can retry last failed recurring payment
 /// </summary>
 /// <param name="customer">Customer</param>
 /// <param name="recurringPayment">Recurring Payment</param>
 /// <returns>True if a customer can retry payment; otherwise false</returns>
 public bool CanRetryLastRecurringPayment(Customer customer, RecurringPayment recurringPayment)
 {
     return(_orderProcessingService.CanRetryLastRecurringPayment(customer, recurringPayment));
 }
 /// <summary>
 ///     Constructor. Assignes the passed recurring payment to the wrapped payment field.
 /// </summary>
 /// <param name="recurringPayment">RecurringPayment to use for further operations.</param>
 public RecurringPaymentViewModel(RecurringPayment recurringPayment)
 {
     RecurringPayment = recurringPayment;
 }
Ejemplo n.º 18
0
 /// <summary>
 /// Process next recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 /// <param name="paymentResult">Process payment result (info about last payment for automatic recurring payments)</param>
 /// <returns>Collection of errors</returns>
 public IEnumerable <string> ProcessNextRecurringPayment(RecurringPayment recurringPayment, ProcessPaymentResult paymentResult = null)
 {
     return(_orderProcessingService.ProcessNextRecurringPayment(recurringPayment, paymentResult));
 }
Ejemplo n.º 19
0
 /// <summary>
 /// Inserts a recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 public virtual void InsertRecurringPayment(RecurringPayment recurringPayment)
 {
     _recurringPaymentRepository.Insert(recurringPayment);
 }
Ejemplo n.º 20
0
 /// <summary>
 /// Cancels a recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 public IList <string> CancelRecurringPayment(RecurringPayment recurringPayment)
 {
     return(_orderProcessingService.CancelRecurringPayment(recurringPayment));
 }
Ejemplo n.º 21
0
 /// <summary>
 /// Inserts a recurring payment
 /// </summary>
 /// <param name="recurringPayment">Recurring payment</param>
 /// <returns>A task that represents the asynchronous operation</returns>
 public virtual async Task InsertRecurringPaymentAsync(RecurringPayment recurringPayment)
 {
     await _recurringPaymentRepository.InsertAsync(recurringPayment);
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Gets a value indicating whether a customer can cancel recurring payment
 /// </summary>
 /// <param name="customerToValidate">Customer</param>
 /// <param name="recurringPayment">Recurring Payment</param>
 /// <returns>value indicating whether a customer can cancel recurring payment</returns>
 public bool CanCancelRecurringPayment(Customer customerToValidate, RecurringPayment recurringPayment)
 {
     return(_orderProcessingService.CanCancelRecurringPayment(customerToValidate, recurringPayment));
 }
Ejemplo n.º 23
0
        /// <summary>
        /// Gets a recurring payment history
        /// </summary>
        /// <param name="recurringPayment">The recurring payment</param>
        /// <returns>
        /// A task that represents the asynchronous operation
        /// The task result contains the result
        /// </returns>
        public virtual async Task <IList <RecurringPaymentHistory> > GetRecurringPaymentHistoryAsync(RecurringPayment recurringPayment)
        {
            if (recurringPayment is null)
            {
                throw new ArgumentNullException(nameof(recurringPayment));
            }

            return(await _recurringPaymentHistoryRepository.Table
                   .Where(rph => rph.RecurringPaymentId == recurringPayment.Id)
                   .ToListAsync());
        }
        /// <summary>
        /// Prepare paged recurring payment history list model
        /// </summary>
        /// <param name="searchModel">Recurring payment history search model</param>
        /// <param name="recurringPayment">Recurring payment</param>
        /// <returns>Recurring payment history list model</returns>
        public virtual RecurringPaymentHistoryListModel PrepareRecurringPaymentHistoryListModel(RecurringPaymentHistorySearchModel searchModel,
                                                                                                RecurringPayment recurringPayment)
        {
            if (searchModel == null)
            {
                throw new ArgumentNullException(nameof(searchModel));
            }

            if (recurringPayment == null)
            {
                throw new ArgumentNullException(nameof(recurringPayment));
            }

            //get recurring payments history
            var recurringPayments = recurringPayment.RecurringPaymentHistory.OrderBy(historyEntry => historyEntry.CreatedOnUtc).ToList();

            //prepare list model
            var model = new RecurringPaymentHistoryListModel
            {
                Data = recurringPayments.PaginationByRequestModel(searchModel).Select(historyEntry =>
                {
                    //fill in model values from the entity
                    var historyModel = historyEntry.ToModel <RecurringPaymentHistoryModel>();

                    //convert dates to the user time
                    historyModel.CreatedOn = _dateTimeHelper.ConvertToUserTime(historyEntry.CreatedOnUtc, DateTimeKind.Utc);

                    //fill in additional values (not existing in the entity)
                    var order = _orderService.GetOrderById(historyEntry.OrderId);
                    if (order == null)
                    {
                        return(historyModel);
                    }

                    historyModel.OrderStatus       = _localizationService.GetLocalizedEnum(order.OrderStatus);
                    historyModel.PaymentStatus     = _localizationService.GetLocalizedEnum(order.PaymentStatus);
                    historyModel.ShippingStatus    = _localizationService.GetLocalizedEnum(order.ShippingStatus);
                    historyModel.CustomOrderNumber = order.CustomOrderNumber;

                    return(historyModel);
                }),
                Total = recurringPayments.Count
            };

            return(model);
        }
Ejemplo n.º 25
0
        private static bool CheckBiannually(RecurringPayment recurringPayment)
        {
            TimeSpan dateDiff = DateTime.Now - recurringPayment.LastRecurrenceCreated.Date;

            return(dateDiff.TotalDays >= BIANNUALLY_RECURRENCE_DAYS);
        }
        /// <summary>
        /// Prepare recurring payment history search model
        /// </summary>
        /// <param name="searchModel">Recurring payment history search model</param>
        /// <param name="recurringPayment">Recurring payment</param>
        /// <returns>Recurring payment history search model</returns>
        protected virtual RecurringPaymentHistorySearchModel PrepareRecurringPaymentHistorySearchModel(RecurringPaymentHistorySearchModel searchModel,
                                                                                                       RecurringPayment recurringPayment)
        {
            if (searchModel == null)
            {
                throw new ArgumentNullException(nameof(searchModel));
            }

            if (recurringPayment == null)
            {
                throw new ArgumentNullException(nameof(recurringPayment));
            }

            searchModel.RecurringPaymentId = recurringPayment.Id;

            //prepare page parameters
            searchModel.SetGridPageSize();

            return(searchModel);
        }
        /// <summary>
        /// Places an order
        /// </summary>
        /// <param name="processPaymentRequest">Process payment request</param>
        /// <returns>Place order result</returns>
        public override PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest)
        {
            //think about moving functionality of processing recurring orders (after the initial order was placed) to ProcessNextRecurringPayment() method
            if (processPaymentRequest == null)
                throw new ArgumentNullException("processPaymentRequest");

            var result = new PlaceOrderResult();
            try
            {
                if (processPaymentRequest.OrderGuid == Guid.Empty)
                    processPaymentRequest.OrderGuid = Guid.NewGuid();

                //prepare order details
                var details = PreparePlaceOrderDetails(processPaymentRequest);

                #region Payment workflow


                //process payment
                ProcessPaymentResult processPaymentResult = null;
                //skip payment workflow if order total equals zero
                var skipPaymentWorkflow = details.OrderTotal == decimal.Zero;
                if (!skipPaymentWorkflow)
                {
                    var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(processPaymentRequest.PaymentMethodSystemName);
                    if (paymentMethod == null)
                        throw new NopException("Payment method couldn't be loaded");

                    //ensure that payment method is active
                    if (!paymentMethod.IsPaymentMethodActive(_paymentSettings))
                        throw new NopException("Payment method is not active");

                    if (!processPaymentRequest.IsRecurringPayment)
                    {
                        if (details.IsRecurringShoppingCart)
                        {
                            //recurring cart
                            var recurringPaymentType = _paymentService.GetRecurringPaymentType(processPaymentRequest.PaymentMethodSystemName);
                            switch (recurringPaymentType)
                            {
                                case RecurringPaymentType.NotSupported:
                                    throw new NopException("Recurring payments are not supported by selected payment method");
                                case RecurringPaymentType.Manual:
                                case RecurringPaymentType.Automatic:
                                    processPaymentResult = _paymentService.ProcessRecurringPayment(processPaymentRequest);
                                    break;
                                default:
                                    throw new NopException("Not supported recurring payment type");
                            }
                        }
                        else
                        {
                            //standard cart
                            processPaymentResult = _paymentService.ProcessPayment(processPaymentRequest);
                        }
                    }
                    else
                    {
                        if (details.IsRecurringShoppingCart)
                        {
                            //Old credit card info
                            processPaymentRequest.CreditCardType = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardType) : "";
                            processPaymentRequest.CreditCardName = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardName) : "";
                            processPaymentRequest.CreditCardNumber = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardNumber) : "";
                            processPaymentRequest.CreditCardCvv2 = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardCvv2) : "";
                            try
                            {
                                processPaymentRequest.CreditCardExpireMonth = details.InitialOrder.AllowStoringCreditCardNumber ? Convert.ToInt32(_encryptionService.DecryptText(details.InitialOrder.CardExpirationMonth)) : 0;
                                processPaymentRequest.CreditCardExpireYear = details.InitialOrder.AllowStoringCreditCardNumber ? Convert.ToInt32(_encryptionService.DecryptText(details.InitialOrder.CardExpirationYear)) : 0;
                            }
                            catch { }

                            var recurringPaymentType = _paymentService.GetRecurringPaymentType(processPaymentRequest.PaymentMethodSystemName);
                            switch (recurringPaymentType)
                            {
                                case RecurringPaymentType.NotSupported:
                                    throw new NopException("Recurring payments are not supported by selected payment method");
                                case RecurringPaymentType.Manual:
                                    processPaymentResult = _paymentService.ProcessRecurringPayment(processPaymentRequest);
                                    break;
                                case RecurringPaymentType.Automatic:
                                    //payment is processed on payment gateway site
                                    processPaymentResult = new ProcessPaymentResult();
                                    break;
                                default:
                                    throw new NopException("Not supported recurring payment type");
                            }
                        }
                        else
                        {
                            throw new NopException("No recurring products");
                        }
                    }
                }
                else
                {
                    //payment is not required
                    if (processPaymentResult == null)
                        processPaymentResult = new ProcessPaymentResult();
                    processPaymentResult.NewPaymentStatus = PaymentStatus.Paid;
                }

                if (processPaymentResult == null)
                    throw new NopException("processPaymentResult is not available");

                #endregion

                if (processPaymentResult.Success)
                {
                    #region Save order details

                    var order = new Order
                    {
                        StoreId = processPaymentRequest.StoreId,
                        OrderGuid = processPaymentRequest.OrderGuid,
                        CustomerId = details.Customer.Id,
                        CustomerLanguageId = details.CustomerLanguage.Id,
                        CustomerTaxDisplayType = details.CustomerTaxDisplayType,
                        CustomerIp = _webHelper.GetCurrentIpAddress(),
                        OrderSubtotalInclTax = details.OrderSubTotalInclTax,
                        OrderSubtotalExclTax = details.OrderSubTotalExclTax,
                        OrderSubTotalDiscountInclTax = details.OrderSubTotalDiscountInclTax,
                        OrderSubTotalDiscountExclTax = details.OrderSubTotalDiscountExclTax,
                        OrderShippingInclTax = details.OrderShippingTotalInclTax,
                        OrderShippingExclTax = details.OrderShippingTotalExclTax,
                        PaymentMethodAdditionalFeeInclTax = details.PaymentAdditionalFeeInclTax,
                        PaymentMethodAdditionalFeeExclTax = details.PaymentAdditionalFeeExclTax,
                        TaxRates = details.TaxRates,
                        OrderTax = details.OrderTaxTotal,
                        OrderTotal = details.OrderTotal,
                        RefundedAmount = decimal.Zero,
                        OrderDiscount = details.OrderDiscountAmount,
                        CheckoutAttributeDescription = details.CheckoutAttributeDescription,
                        CheckoutAttributesXml = details.CheckoutAttributesXml,
                        CustomerCurrencyCode = details.CustomerCurrencyCode,
                        CurrencyRate = details.CustomerCurrencyRate,
                        AffiliateId = details.AffiliateId,
                        OrderStatus = OrderStatus.Pending,
                        AllowStoringCreditCardNumber = processPaymentResult.AllowStoringCreditCardNumber,
                        CardType = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardType) : string.Empty,
                        CardName = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardName) : string.Empty,
                        CardNumber = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardNumber) : string.Empty,
                        MaskedCreditCardNumber = _encryptionService.EncryptText(_paymentService.GetMaskedCreditCardNumber(processPaymentRequest.CreditCardNumber)),
                        CardCvv2 = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardCvv2) : string.Empty,
                        CardExpirationMonth = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardExpireMonth.ToString()) : string.Empty,
                        CardExpirationYear = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardExpireYear.ToString()) : string.Empty,
                        PaymentMethodSystemName = processPaymentRequest.PaymentMethodSystemName,
                        AuthorizationTransactionId = processPaymentResult.AuthorizationTransactionId,
                        AuthorizationTransactionCode = processPaymentResult.AuthorizationTransactionCode,
                        AuthorizationTransactionResult = processPaymentResult.AuthorizationTransactionResult,
                        CaptureTransactionId = processPaymentResult.CaptureTransactionId,
                        CaptureTransactionResult = processPaymentResult.CaptureTransactionResult,
                        SubscriptionTransactionId = processPaymentResult.SubscriptionTransactionId,
                        PaymentStatus = processPaymentResult.NewPaymentStatus,
                        PaidDateUtc = null,
                        BillingAddress = details.BillingAddress,
                        ShippingAddress = details.ShippingAddress,
                        ShippingStatus = details.ShippingStatus,
                        ShippingMethod = details.ShippingMethodName,
                        PickUpInStore = details.PickUpInStore,
                        ShippingRateComputationMethodSystemName = details.ShippingRateComputationMethodSystemName,
                        CustomValuesXml = processPaymentRequest.SerializeCustomValues(),
                        VatNumber = details.VatNumber,
                        CreatedOnUtc = DateTime.UtcNow
                    };
                    _orderService.InsertOrder(order);

                    #region Promo

                    _promoService.SendConfirmedBasket(order);

                    BasketResponse basketResponse = _promoUtilities.GetBasketResponse();

                    if (basketResponse == null)
                    {
                        throw new NopException(string.Format("Failed to create PromoOrder for order: {0}", order.Id));
                    }
                    else
                    {

                        PromoOrder promoOrder = new PromoOrder()
                        {
                            RequestXml = _workContext.CurrentCustomer.GetAttribute<string>(PromoCustomerAttributeNames.PromoBasketRequest, _genericAttributeService, _storeContext.CurrentStore.Id),
                            ResponseXml = basketResponse.ToXml(),
                            OrderId = order.Id,
                            DeliveryOriginalPrice = basketResponse.DeliveryOriginalPrice
                        };

                        _promoOrderService.InsertPromoOrder(promoOrder);

                        basketResponse.Items.ForEach(bi =>
                        {
                            PromoOrderItem promoOrderItem = new PromoOrderItem()
                            {
                                LineAmount = bi.LineAmount,
                                OrderId = order.Id,
                                PromoOrderId = promoOrder.Id,
                                IsDelivery = bi.IsDelivery,
                                ProductCode = bi.ProductCode,
                                VariantCode = bi.VariantCode,
                                LinePromotionDiscount = bi.LinePromotionDiscount,
                                Barcode = bi.Barcode,
                                Generated = bi.Generated,
                                ManualDiscount = bi.ManualDiscount,
                                OriginalAmount = bi.OriginalAmount,
                                OriginalPrice = bi.OriginalPrice,
                                OriginalQuantity = bi.OriginalQuantity,
                                Price = bi.Price,
                                ProductDescription = bi.ProductDescription,
                                Quantity = bi.Quantity,
                                SplitFromLineId = bi.SplitFromLineId,
                                TotalDiscount = bi.TotalDiscount,
                                TotalIssuedPoints = bi.TotalIssuedPoints
                            };

                            promoOrder.PromoOrderItems.Add(promoOrderItem);
                            _promoOrderService.UpdatePromoOrder(promoOrder);

                            bi.AppliedPromotions.ForEach(ap =>
                            {
                                string promotionTypeDisplay = string.Empty;
                                string promotionType = string.Empty;
                                string promotionName = string.Empty;
                                string promotionDisplayText = string.Empty;
                                var appliedPromo = (from sap in basketResponse.Summary.AppliedPromotions where sap.PromotionId == ap.PromotionId select sap).FirstOrDefault();
                                if (appliedPromo != null)
                                {
                                    promotionName = appliedPromo.PromotionName;
                                    promotionType = appliedPromo.PromotionType;
                                    promotionTypeDisplay = appliedPromo.PromotionTypeDisplay;
                                    promotionDisplayText = appliedPromo.DisplayText;
                                }

                                PromoOrderItemPromotion promoOrderItemPromotion = new PromoOrderItemPromotion()
                                {
                                    BasketLevel = ap.BasketLevelPromotion,
                                    DeliveryLevel = ap.DeliveryLevelPromotion,
                                    DiscountAmount = ap.DiscountAmount,
                                    ForLineId = ap.AssociatedLine,
                                    Instance = ap.InstanceId,
                                    PointsIssued = ap.PointsIssued,
                                    PromotionId = ap.PromotionId,
                                    DisplayText = promotionDisplayText,
                                    PromotionTypeDisplay = promotionTypeDisplay,
                                    PromotionName = promotionName,
                                    PromotionType = promotionType,
                                    ExternalIdentifier = ap.ExternalIdentifier,
                                    ReportingGroupCode = ap.ReportingGroupCode
                                };
                                promoOrderItem.PromoOrderItemPromotions.Add(promoOrderItemPromotion);
                                _promoOrderService.UpdatePromoOrder(promoOrder);
                            });
                        });

                        basketResponse.Coupons.ForEach(c =>
                            {
                                PromoOrderCoupon promoOrderCoupon = new PromoOrderCoupon()
                                {
                                    CouponCode = c.CouponCode,
                                    Issued = c.Issued,
                                    OrderId = order.Id,
                                    PromoOrderId = promoOrder.Id,
                                    CouponName = c.CouponName,
                                    IssuedConfirmed = c.IssuedConfirmed,
                                    DisplayText = c.DisplayText
                                };
                                promoOrder.PromoOrderCoupons.Add(promoOrderCoupon);
                                _promoOrderService.UpdatePromoOrder(promoOrder);
                            });
                    }

                    #region clean up

                    Customer customer = _workContext.CurrentCustomer;

                    // basket guid
                    _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketUniqueReference, null, _storeContext.CurrentStore.Id);

                    // basket response
                    _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketResponse, null, _storeContext.CurrentStore.Id);

                    // basket request
                    _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketRequest, null, _storeContext.CurrentStore.Id);

                    // coupon code
                    _genericAttributeService.SaveAttribute<string>(customer, SystemCustomerAttributeNames.DiscountCouponCode, null);

                    #endregion

                    #endregion

                    result.PlacedOrder = order;

                    if (!processPaymentRequest.IsRecurringPayment)
                    {
                        //move shopping cart items to order items
                        foreach (var sc in details.Cart)
                        {
                            var basketResponseItems = basketResponse.FindBasketResponseItems(sc);

                            if (basketResponseItems == null)
                            {
                                // TODO: handle this error
                            }
                            else
                            {
                                //prices
                                decimal taxRate;
                                decimal discountAmount = basketResponseItems.Sum(i => i.LinePromotionDiscount);
                                decimal scUnitPrice = _priceCalculationService.GetUnitPrice(sc);
                                decimal scSubTotal = basketResponseItems.Sum(i => i.LineAmount);
                                decimal scUnitPriceInclTax = _taxService.GetProductPrice(sc.Product, scUnitPrice, true, details.Customer, out taxRate);
                                decimal scUnitPriceExclTax = _taxService.GetProductPrice(sc.Product, scUnitPrice, false, details.Customer, out taxRate);
                                decimal scSubTotalInclTax = _taxService.GetProductPrice(sc.Product, scSubTotal, true, details.Customer, out taxRate);
                                decimal scSubTotalExclTax = _taxService.GetProductPrice(sc.Product, scSubTotal, false, details.Customer, out taxRate);

                                decimal discountAmountInclTax = _taxService.GetProductPrice(sc.Product, discountAmount, true, details.Customer, out taxRate);
                                decimal discountAmountExclTax = _taxService.GetProductPrice(sc.Product, discountAmount, false, details.Customer, out taxRate);

                                //attributes
                                string attributeDescription = _productAttributeFormatter.FormatAttributes(sc.Product, sc.AttributesXml, details.Customer);

                                var itemWeight = _shippingService.GetShoppingCartItemWeight(sc);

                                //save order item
                                var orderItem = new OrderItem
                                {
                                    OrderItemGuid = Guid.NewGuid(),
                                    Order = order,
                                    ProductId = sc.ProductId,
                                    UnitPriceInclTax = scUnitPriceInclTax,
                                    UnitPriceExclTax = scUnitPriceExclTax,
                                    PriceInclTax = scSubTotalInclTax,
                                    PriceExclTax = scSubTotalExclTax,
                                    OriginalProductCost = _priceCalculationService.GetProductCost(sc.Product, sc.AttributesXml),
                                    AttributeDescription = attributeDescription,
                                    AttributesXml = sc.AttributesXml,
                                    Quantity = sc.Quantity,
                                    DiscountAmountInclTax = discountAmountInclTax,
                                    DiscountAmountExclTax = discountAmountExclTax,
                                    DownloadCount = 0,
                                    IsDownloadActivated = false,
                                    LicenseDownloadId = 0,
                                    ItemWeight = itemWeight,
                                    RentalStartDateUtc = sc.RentalStartDateUtc,
                                    RentalEndDateUtc = sc.RentalEndDateUtc
                                };
                                order.OrderItems.Add(orderItem);
                                _orderService.UpdateOrder(order);

                                //gift cards
                                if (sc.Product.IsGiftCard)
                                {
                                    string giftCardRecipientName, giftCardRecipientEmail,
                                        giftCardSenderName, giftCardSenderEmail, giftCardMessage;
                                    _productAttributeParser.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
                                        {
                                            GiftCardType = sc.Product.GiftCardType,
                                            PurchasedWithOrderItem = orderItem,
                                            Amount = scUnitPriceExclTax,
                                            IsGiftCardActivated = false,
                                            GiftCardCouponCode = _giftCardService.GenerateGiftCardCode(),
                                            RecipientName = giftCardRecipientName,
                                            RecipientEmail = giftCardRecipientEmail,
                                            SenderName = giftCardSenderName,
                                            SenderEmail = giftCardSenderEmail,
                                            Message = giftCardMessage,
                                            IsRecipientNotified = false,
                                            CreatedOnUtc = DateTime.UtcNow
                                        };
                                        _giftCardService.InsertGiftCard(gc);
                                    }
                                }

                                //inventory
                                _productService.AdjustInventory(sc.Product, -sc.Quantity, sc.AttributesXml);
                            }
                        }

                        //clear shopping cart
                        details.Cart.ToList().ForEach(sci => _shoppingCartService.DeleteShoppingCartItem(sci, false));
                    }
                    else
                    {
                        //recurring payment
                        var initialOrderItems = details.InitialOrder.OrderItems;
                        foreach (var orderItem in initialOrderItems)
                        {
                            //save item
                            var newOrderItem = new OrderItem
                            {
                                OrderItemGuid = Guid.NewGuid(),
                                Order = order,
                                ProductId = orderItem.ProductId,
                                UnitPriceInclTax = orderItem.UnitPriceInclTax,
                                UnitPriceExclTax = orderItem.UnitPriceExclTax,
                                PriceInclTax = orderItem.PriceInclTax,
                                PriceExclTax = orderItem.PriceExclTax,
                                OriginalProductCost = orderItem.OriginalProductCost,
                                AttributeDescription = orderItem.AttributeDescription,
                                AttributesXml = orderItem.AttributesXml,
                                Quantity = orderItem.Quantity,
                                DiscountAmountInclTax = orderItem.DiscountAmountInclTax,
                                DiscountAmountExclTax = orderItem.DiscountAmountExclTax,
                                DownloadCount = 0,
                                IsDownloadActivated = false,
                                LicenseDownloadId = 0,
                                ItemWeight = orderItem.ItemWeight,
                                RentalStartDateUtc = orderItem.RentalStartDateUtc,
                                RentalEndDateUtc = orderItem.RentalEndDateUtc
                            };
                            order.OrderItems.Add(newOrderItem);
                            _orderService.UpdateOrder(order);

                            //gift cards
                            if (orderItem.Product.IsGiftCard)
                            {
                                string giftCardRecipientName, giftCardRecipientEmail,
                                    giftCardSenderName, giftCardSenderEmail, giftCardMessage;
                                _productAttributeParser.GetGiftCardAttribute(orderItem.AttributesXml,
                                    out giftCardRecipientName, out giftCardRecipientEmail,
                                    out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);

                                for (int i = 0; i < orderItem.Quantity; i++)
                                {
                                    var gc = new GiftCard
                                    {
                                        GiftCardType = orderItem.Product.GiftCardType,
                                        PurchasedWithOrderItem = newOrderItem,
                                        Amount = orderItem.UnitPriceExclTax,
                                        IsGiftCardActivated = false,
                                        GiftCardCouponCode = _giftCardService.GenerateGiftCardCode(),
                                        RecipientName = giftCardRecipientName,
                                        RecipientEmail = giftCardRecipientEmail,
                                        SenderName = giftCardSenderName,
                                        SenderEmail = giftCardSenderEmail,
                                        Message = giftCardMessage,
                                        IsRecipientNotified = false,
                                        CreatedOnUtc = DateTime.UtcNow
                                    };
                                    _giftCardService.InsertGiftCard(gc);
                                }
                            }

                            //inventory
                            _productService.AdjustInventory(orderItem.Product, -orderItem.Quantity, orderItem.AttributesXml);
                        }
                    }

                    //discount usage history
                    // TODO: replace with Promo discount usage history?

                    //gift card usage history
                    if (!processPaymentRequest.IsRecurringPayment)
                        if (details.AppliedGiftCards != null)
                            foreach (var agc in details.AppliedGiftCards)
                            {
                                decimal amountUsed = agc.AmountCanBeUsed;
                                var gcuh = new GiftCardUsageHistory
                                {
                                    GiftCard = agc.GiftCard,
                                    UsedWithOrder = order,
                                    UsedValue = amountUsed,
                                    CreatedOnUtc = DateTime.UtcNow
                                };
                                agc.GiftCard.GiftCardUsageHistory.Add(gcuh);
                                _giftCardService.UpdateGiftCard(agc.GiftCard);
                            }

                    //reward points history
                    if (details.RedeemedRewardPointsAmount > decimal.Zero)
                    {
                        details.Customer.AddRewardPointsHistoryEntry(-details.RedeemedRewardPoints,
                            string.Format(_localizationService.GetResource("RewardPoints.Message.RedeemedForOrder", order.CustomerLanguageId), order.Id),
                            order,
                            details.RedeemedRewardPointsAmount);
                        _customerService.UpdateCustomer(details.Customer);
                    }

                    //recurring orders
                    if (!processPaymentRequest.IsRecurringPayment && details.IsRecurringShoppingCart)
                    {
                        //create recurring payment (the first payment)
                        var rp = new RecurringPayment
                        {
                            CycleLength = processPaymentRequest.RecurringCycleLength,
                            CyclePeriod = processPaymentRequest.RecurringCyclePeriod,
                            TotalCycles = processPaymentRequest.RecurringTotalCycles,
                            StartDateUtc = DateTime.UtcNow,
                            IsActive = true,
                            CreatedOnUtc = DateTime.UtcNow,
                            InitialOrder = order,
                        };
                        _orderService.InsertRecurringPayment(rp);


                        var recurringPaymentType = _paymentService.GetRecurringPaymentType(processPaymentRequest.PaymentMethodSystemName);
                        switch (recurringPaymentType)
                        {
                            case RecurringPaymentType.NotSupported:
                                {
                                    //not supported
                                }
                                break;
                            case RecurringPaymentType.Manual:
                                {
                                    //first payment
                                    var rph = new RecurringPaymentHistory
                                    {
                                        RecurringPayment = rp,
                                        CreatedOnUtc = DateTime.UtcNow,
                                        OrderId = order.Id,
                                    };
                                    rp.RecurringPaymentHistory.Add(rph);
                                    _orderService.UpdateRecurringPayment(rp);
                                }
                                break;
                            case RecurringPaymentType.Automatic:
                                {
                                    //will be created later (process is automated)
                                }
                                break;
                            default:
                                break;
                        }
                    }

                    #endregion

                    #region Notifications & notes

                    //notes, messages
                    if (_workContext.OriginalCustomerIfImpersonated != null)
                    {
                        //this order is placed by a store administrator impersonating a customer
                        order.OrderNotes.Add(new OrderNote
                        {
                            Note = string.Format("Order placed by a store owner ('{0}'. ID = {1}) impersonating the customer.",
                                _workContext.OriginalCustomerIfImpersonated.Email, _workContext.OriginalCustomerIfImpersonated.Id),
                            DisplayToCustomer = false,
                            CreatedOnUtc = DateTime.UtcNow
                        });
                        _orderService.UpdateOrder(order);
                    }
                    else
                    {
                        order.OrderNotes.Add(new OrderNote
                        {
                            Note = "Order placed",
                            DisplayToCustomer = false,
                            CreatedOnUtc = DateTime.UtcNow
                        });
                        _orderService.UpdateOrder(order);
                    }

                    //send email notifications
                    int orderPlacedStoreOwnerNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedStoreOwnerNotification(order, _localizationSettings.DefaultAdminLanguageId);
                    if (orderPlacedStoreOwnerNotificationQueuedEmailId > 0)
                    {
                        order.OrderNotes.Add(new OrderNote
                        {
                            Note = string.Format("\"Order placed\" email (to store owner) has been queued. Queued email identifier: {0}.", orderPlacedStoreOwnerNotificationQueuedEmailId),
                            DisplayToCustomer = false,
                            CreatedOnUtc = DateTime.UtcNow
                        });
                        _orderService.UpdateOrder(order);
                    }

                    var orderPlacedAttachmentFilePath = _orderSettings.AttachPdfInvoiceToOrderPlacedEmail ?
                        _pdfService.PrintOrderToPdf(order, order.CustomerLanguageId) : null;
                    var orderPlacedAttachmentFileName = _orderSettings.AttachPdfInvoiceToOrderPlacedEmail ?
                        "order.pdf" : null;
                    int orderPlacedCustomerNotificationQueuedEmailId = _workflowMessageService
                        .SendOrderPlacedCustomerNotification(order, order.CustomerLanguageId, orderPlacedAttachmentFilePath, orderPlacedAttachmentFileName);
                    if (orderPlacedCustomerNotificationQueuedEmailId > 0)
                    {
                        order.OrderNotes.Add(new OrderNote
                        {
                            Note = string.Format("\"Order placed\" email (to customer) has been queued. Queued email identifier: {0}.", orderPlacedCustomerNotificationQueuedEmailId),
                            DisplayToCustomer = false,
                            CreatedOnUtc = DateTime.UtcNow
                        });
                        _orderService.UpdateOrder(order);
                    }

                    var vendors = GetVendorsInOrder(order);
                    foreach (var vendor in vendors)
                    {
                        int orderPlacedVendorNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedVendorNotification(order, vendor, order.CustomerLanguageId);
                        if (orderPlacedVendorNotificationQueuedEmailId > 0)
                        {
                            order.OrderNotes.Add(new OrderNote
                            {
                                Note = string.Format("\"Order placed\" email (to vendor) has been queued. Queued email identifier: {0}.", orderPlacedVendorNotificationQueuedEmailId),
                                DisplayToCustomer = false,
                                CreatedOnUtc = DateTime.UtcNow
                            });
                            _orderService.UpdateOrder(order);
                        }
                    }

                    //check order status
                    CheckOrderStatus(order);

                    //reset checkout data
                    if (!processPaymentRequest.IsRecurringPayment)
                        _customerService.ResetCheckoutData(details.Customer, processPaymentRequest.StoreId, clearCouponCodes: true, clearCheckoutAttributes: true);

                    if (!processPaymentRequest.IsRecurringPayment)
                    {
                        _customerActivityService.InsertActivity(
                            "PublicStore.PlaceOrder",
                            _localizationService.GetResource("ActivityLog.PublicStore.PlaceOrder"),
                            order.Id);
                    }

                    //raise event       
                    _eventPublisher.Publish(new OrderPlacedEvent(order));

                    if (order.PaymentStatus == PaymentStatus.Paid)
                    {
                        ProcessOrderPaid(order);
                    }
                    #endregion
                }
                else
                {
                    foreach (var paymentError in processPaymentResult.Errors)
                        result.AddError(string.Format(_localizationService.GetResource("Checkout.PaymentError"), paymentError));
                }
            }
            catch (Exception exc)
            {
                _logger.Error(exc.Message, exc);
                result.AddError(exc.Message);
            }

            #region Process errors

            string error = "";
            for (int i = 0; i < result.Errors.Count; i++)
            {
                error += string.Format("Error {0}: {1}", i + 1, result.Errors[i]);
                if (i != result.Errors.Count - 1)
                    error += ". ";
            }
            if (!String.IsNullOrEmpty(error))
            {
                //log it
                string logError = string.Format("Error while placing order. {0}", error);
                _logger.Error(logError);
            }

            #endregion

            return result;
        }
        /// <summary>
        /// Cancels a recurring payment
        /// </summary>
        /// <param name="recurringPayment">Recurring payment</param>
        public virtual async Task <IList <string> > CancelRecurringPayment(RecurringPayment recurringPayment)
        {
            if (recurringPayment == null)
            {
                throw new ArgumentNullException("recurringPayment");
            }

            var initialOrder = recurringPayment.InitialOrder;

            if (initialOrder == null)
            {
                return new List <string> {
                           "Initial order could not be loaded"
                }
            }
            ;


            var request = new CancelRecurringPaymentRequest();
            CancelRecurringPaymentResult result = null;

            try
            {
                request.Order = initialOrder;

                result = await _paymentService.CancelRecurringPayment(request);

                if (result.Success)
                {
                    //update recurring payment
                    recurringPayment.IsActive = false;
                    await _orderService.UpdateRecurringPayment(recurringPayment);

                    //add a note
                    await _orderService.InsertOrderNote(new OrderNote {
                        Note = "Recurring payment has been cancelled",
                        DisplayToCustomer = false,
                        CreatedOnUtc      = DateTime.UtcNow,
                        OrderId           = initialOrder.Id,
                    });

                    //notify a store owner
                    await _workflowMessageService
                    .SendRecurringPaymentCancelledStoreOwnerNotification(recurringPayment,
                                                                         _localizationSettings.DefaultAdminLanguageId);
                }
            }
            catch (Exception exc)
            {
                if (result == null)
                {
                    result = new CancelRecurringPaymentResult();
                }
                result.AddError(string.Format("Error: {0}. Full exception: {1}", exc.Message, exc));
            }


            //process errors
            string error = "";

            for (int i = 0; i < result.Errors.Count; i++)
            {
                error += string.Format("Error {0}: {1}", i, result.Errors[i]);
                if (i != result.Errors.Count - 1)
                {
                    error += ". ";
                }
            }
            if (!String.IsNullOrEmpty(error))
            {
                //add a note
                await _orderService.InsertOrderNote(new OrderNote {
                    Note = string.Format("Unable to cancel recurring payment. {0}", error),
                    DisplayToCustomer = false,
                    CreatedOnUtc      = DateTime.UtcNow,
                    OrderId           = initialOrder.Id,
                });

                //log it
                string logError = string.Format("Error cancelling recurring payment. Order #{0}. Error: {1}", initialOrder.Id, error);
                await _logger.InsertLog(LogLevel.Error, logError, logError);
            }
            return(result.Errors);
        }