public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest request)
        {
            // initiate Amazon payment. We do not add errors to request.Errors cause of asynchronous processing.
            var result = new ProcessPaymentResult();
            var errors = new List<string>();
            bool informCustomerAboutErrors = false;
            bool informCustomerAddErrors = false;

            try
            {
                var orderGuid = request.OrderGuid.ToString();
                var store = _storeService.GetStoreById(request.StoreId);
                var currency = _services.WorkContext.WorkingCurrency;
                var settings = _services.Settings.LoadSetting<AmazonPaySettings>(store.Id);
                var state = _httpContext.GetAmazonPayState(_services.Localization);
                var client = new AmazonPayClient(settings);

                informCustomerAboutErrors = settings.InformCustomerAboutErrors;
                informCustomerAddErrors = settings.InformCustomerAddErrors;

                _api.Authorize(client, result, errors, state.OrderReferenceId, request.OrderTotal, currency.CurrencyCode, orderGuid);
            }
            catch (OffAmazonPaymentsServiceException exc)
            {
                LogAmazonError(exc, errors: errors);
            }
            catch (Exception exc)
            {
                LogError(exc, errors: errors);
            }

            if (informCustomerAboutErrors && errors != null && errors.Count > 0)
            {
                // customer needs to be informed of an amazon error here. hooking OrderPlaced.CustomerNotification won't work
                // cause of asynchronous processing. solution: we add a customer order note that is also send as an email.

                var state = new AmazonPayActionState() { OrderGuid = request.OrderGuid };

                if (informCustomerAddErrors)
                {
                    state.Errors = new List<string>();
                    state.Errors.AddRange(errors);
                }

                AsyncRunner.Run((container, x) =>
                {
                    var obj = x as AmazonPayActionState;

                    container.Resolve<IAmazonPayService>().AddCustomerOrderNoteLoop(obj);
                },
                state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
            }

            return result;
        }
        public void AddCustomerOrderNoteLoop(AmazonPayActionState state)
        {
            try
            {
                var sleepMillSec = 4000;
                var loopMillSec = 40000;
                var startTime = DateTime.Now.TimeOfDay;

                for (int i = 0; i < 99 && (DateTime.Now.TimeOfDay.Milliseconds - startTime.Milliseconds) <= loopMillSec; ++i)
                {
                    var order = _orderService.GetOrderByGuid(state.OrderGuid);
                    if (order != null)
                    {
                        var sb = new StringBuilder(T("Plugins.Payments.AmazonPay.AuthorizationHardDeclineMessage"));

                        if (state.Errors != null)
                        {
                            foreach (var error in state.Errors)
                                sb.AppendFormat("<p>{0}</p>", error);
                        }

                        var orderNote = new OrderNote()
                        {
                            DisplayToCustomer = true,
                            Note = sb.ToString(),
                            CreatedOnUtc = DateTime.UtcNow,
                        };

                        order.OrderNotes.Add(orderNote);
                        _orderService.UpdateOrder(order);

                        _workflowMessageService.SendNewOrderNoteAddedCustomerNotification(orderNote, _services.WorkContext.WorkingLanguage.Id);
                        break;
                    }

                    Thread.Sleep(sleepMillSec);
                }
            }
            catch (Exception exc)
            {
                LogError(exc);
            }
        }