private AuthorizeResponse AuthorizePayment(
            AmazonPaySettings settings,
            AmazonPayCheckoutState state,
            Store store,
            ProcessPaymentRequest request,
            Client client,
            bool synchronously,
            out AuthorizeRequest authRequest)
        {
            authRequest = new AuthorizeRequest()
                          .WithMerchantId(settings.SellerId)
                          .WithAmazonOrderReferenceId(state.OrderReferenceId)
                          .WithAuthorizationReferenceId(GetRandomId("Authorize"))
                          .WithCaptureNow(settings.TransactionType == AmazonPayTransactionType.AuthorizeAndCapture)
                          .WithCurrencyCode(ConvertCurrency(store.PrimaryStoreCurrency.CurrencyCode))
                          .WithAmount(request.OrderTotal);

            if (synchronously)
            {
                authRequest = authRequest.WithTransactionTimeout(0);
            }

            // See https://pay.amazon.com/de/developer/documentation/lpwa/201956480
            //{"SandboxSimulation": {"State":"Declined", "ReasonCode":"InvalidPaymentMethod", "PaymentMethodUpdateTimeInMins":5}}
            //{"SandboxSimulation": {"State":"Declined", "ReasonCode":"AmazonRejected"}}
            //if (settings.UseSandbox)
            //{
            //	var authNote = _services.Settings.GetSettingByKey<string>("SmartStore.AmazonPay.SellerAuthorizationNote");
            //  authRequest = authRequest.WithSellerAuthorizationNote(authNote);
            //}

            var authResponse = client.Authorize(authRequest);

            return(authResponse);
        }
        public AmazonPayViewModel ProcessPluginRequest(AmazonPayRequestType type, TempDataDictionary tempData, string orderReferenceId = null)
        {
            var model = new AmazonPayViewModel();
            model.Type = type;

            try
            {
                var store = _services.StoreContext.CurrentStore;
                var customer = _services.WorkContext.CurrentCustomer;
                var cart = customer.GetCartItems(ShoppingCartType.ShoppingCart, store.Id);

                if (type == AmazonPayRequestType.LoginHandler)
                {
                    if (string.IsNullOrWhiteSpace(orderReferenceId))
                    {
                        LogError(null, T("Plugins.Payments.AmazonPay.MissingOrderReferenceId"), null, true);
                        model.Result = AmazonPayResultType.Redirect;
                        return model;
                    }

                    if (cart.Count <= 0 || !IsActive(store.Id))
                    {
                        model.Result = AmazonPayResultType.Redirect;
                        return model;
                    }

                    if (customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)
                    {
                        model.Result = AmazonPayResultType.Unauthorized;
                        return model;
                    }

                    var checkoutState = _httpContext.GetCheckoutState();

                    if (checkoutState == null)
                    {
                        Logger.InsertLog(LogLevel.Warning, "Checkout state is null in AmazonPayService.ValidateAndInitiateCheckout!");
                        model.Result = AmazonPayResultType.Redirect;
                        return model;
                    }

                    var state = new AmazonPayCheckoutState()
                    {
                        OrderReferenceId = orderReferenceId
                    };

                    if (checkoutState.CustomProperties.ContainsKey(AmazonPayCore.AmazonPayCheckoutStateKey))
                        checkoutState.CustomProperties[AmazonPayCore.AmazonPayCheckoutStateKey] = state;
                    else
                        checkoutState.CustomProperties.Add(AmazonPayCore.AmazonPayCheckoutStateKey, state);

                    //_httpContext.Session.SafeSet(AmazonPayCore.AmazonPayCheckoutStateKey, state);

                    model.RedirectAction = "Index";
                    model.RedirectController = "Checkout";
                    model.Result = AmazonPayResultType.Redirect;
                    return model;
                }
                else if (type == AmazonPayRequestType.ShoppingCart || type == AmazonPayRequestType.MiniShoppingCart)
                {
                    if (cart.Count <= 0 || !IsActive(store.Id))
                    {
                        model.Result = AmazonPayResultType.None;
                        return model;
                    }

                    string storeLocation = _services.WebHelper.GetStoreLocation(store.SslEnabled);
                    model.LoginHandlerUrl = "{0}Plugins/SmartStore.AmazonPay/AmazonPayShoppingCart/LoginHandler".FormatWith(storeLocation);
                }
                else
                {
                    if (!_httpContext.HasAmazonPayState() || cart.Count <= 0)
                    {
                        model.Result = AmazonPayResultType.Redirect;
                        return model;
                    }

                    if (customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)
                    {
                        model.Result = AmazonPayResultType.Unauthorized;
                        return model;
                    }

                    var state = _httpContext.GetAmazonPayState(_services.Localization);

                    model.OrderReferenceId = state.OrderReferenceId;
                    //model.IsOrderConfirmed = state.IsOrderConfirmed;
                }

                var currency = _services.WorkContext.WorkingCurrency;
                var settings = _services.Settings.LoadSetting<AmazonPaySettings>(store.Id);

                model.SellerId = settings.SellerId;
                model.ClientId = settings.AccessKey;
                model.IsShippable = cart.RequiresShipping();
                model.IsRecurring = cart.IsRecurring();
                model.WidgetUrl = settings.GetWidgetUrl();
                model.ButtonUrl = settings.GetButtonUrl(type);
                model.AddressWidgetWidth = Math.Max(settings.AddressWidgetWidth, 200);
                model.AddressWidgetHeight = Math.Max(settings.AddressWidgetHeight, 228);
                model.PaymentWidgetWidth = Math.Max(settings.PaymentWidgetWidth, 200);
                model.PaymentWidgetHeight = Math.Max(settings.PaymentWidgetHeight, 228);

                if (type == AmazonPayRequestType.MiniShoppingCart)
                {
                    if (!settings.ShowButtonInMiniShoppingCart)
                    {
                        model.Result = AmazonPayResultType.None;
                        return model;
                    }
                }
                else if (type == AmazonPayRequestType.Address)
                {
                    if (!model.IsShippable)
                    {
                        model.RedirectAction = "ShippingMethod";
                        model.RedirectController = "Checkout";
                        model.Result = AmazonPayResultType.Redirect;
                        return model;
                    }

                    var shippingToCountryNotAllowed = tempData[AmazonPayCore.SystemName + "ShippingToCountryNotAllowed"];

                    if (shippingToCountryNotAllowed != null && true == (bool)shippingToCountryNotAllowed)
                        model.Warning = T("Plugins.Payments.AmazonPay.ShippingToCountryNotAllowed");
                }
                else if (type == AmazonPayRequestType.ShippingMethod)
                {
                    model.RedirectAction = model.RedirectController = "";

                    if (model.IsShippable)
                    {
                        var client = new AmazonPayClient(settings);
                        var details = _api.GetOrderReferenceDetails(client, model.OrderReferenceId);

                        if (_api.FindAndApplyAddress(details, customer, model.IsShippable, true))
                        {
                            _customerService.UpdateCustomer(customer);
                            model.Result = AmazonPayResultType.None;
                            return model;
                        }
                        else
                        {
                            tempData[AmazonPayCore.SystemName + "ShippingToCountryNotAllowed"] = true;
                            model.RedirectAction = "ShippingAddress";
                            model.RedirectController = "Checkout";
                            model.Result = AmazonPayResultType.Redirect;
                            return model;
                        }
                    }
                }
                else if (type == AmazonPayRequestType.Payment)
                {
                    if (_rewardPointsSettings.Enabled && !model.IsRecurring)
                    {
                        int rewardPointsBalance = customer.GetRewardPointsBalance();
                        decimal rewardPointsAmountBase = _orderTotalCalculationService.ConvertRewardPointsToAmount(rewardPointsBalance);
                        decimal rewardPointsAmount = _currencyService.ConvertFromPrimaryStoreCurrency(rewardPointsAmountBase, currency);

                        if (rewardPointsAmount > decimal.Zero)
                        {
                            model.DisplayRewardPoints = true;
                            model.RewardPointsAmount = _priceFormatter.FormatPrice(rewardPointsAmount, true, false);
                            model.RewardPointsBalance = rewardPointsBalance;
                        }
                    }

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

                    var client = new AmazonPayClient(settings);
                    var details = _api.SetOrderReferenceDetails(client, model.OrderReferenceId, GetOrderTotal(), currency.CurrencyCode);

                    // this is ugly...
                    var paymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest;
                    if (paymentRequest == null)
                    {
                        _httpContext.Session["OrderPaymentInfo"] = new ProcessPaymentRequest();
                    }
                }
                else if (type == AmazonPayRequestType.OrderReviewData)
                {
                    if (model.IsShippable)
                    {
                        var shippingOption = customer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, store.Id);
                        if (shippingOption != null)
                            model.ShippingMethod = shippingOption.Name;
                    }
                }
            }
            catch (OffAmazonPaymentsServiceException exc)
            {
                LogAmazonError(exc, notify: true);
            }
            catch (Exception exc)
            {
                LogError(exc, notify: true);
            }
            return model;
        }