/// <summary>
        /// Executes the transaction request to SagePay
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <returns></returns>
        public PaymentRequest CreatePaymentRequest(OrderInfo orderInfo)
        {
            var paymentProvider = PaymentProvider.GetPaymentProvider(orderInfo.PaymentInfo.Id);

            var sagePayDirectIntegration = new SagePayDirectIntegration();

            var request = sagePayDirectIntegration.DirectPaymentRequest();

            SetRequestData(request, orderInfo);

            var result = sagePayDirectIntegration.ProcessDirectPaymentRequest(request, SagePaySettings.DirectPaymentUrl);

            if (result.Status == ResponseStatus.OK || (SagePaySettings.DefaultTransactionType == TransactionType.AUTHENTICATE && result.Status == ResponseStatus.REGISTERED))
            {
                orderInfo.PaymentInfo.Parameters = result.Status + "&" + result.StatusDetail;

                PaymentProviderHelper.SetTransactionId(orderInfo, result.VpsTxId);
                //Response.Redirect(string.Format("Result.aspx?vendorTxCode={0}", request.VendorTxCode));
            }
            else if (result.Status == ResponseStatus.THREEDAUTH)
            {
                // todo: not supported yet! code below is work in progress
                //var threeDSecureRequest = new PaymentRequest();

                //threeDSecureRequest.Parameters.Add("paReq", result.PaReq.Replace(" ", "+"));
                //threeDSecureRequest.Parameters.Add("acsUrl", result.AcsUrl);
                //threeDSecureRequest.Parameters.Add("md", result.Md);
                //threeDSecureRequest.Parameters.Add("vendorTxCode", request.VendorTxCode);

                //// Save Order with Order status in 3D Process
                //var threeDAuth = new NameValueCollection
                //{
                //	{"paReq", result.PaReq.Replace(" ", "+")},
                //	{"acsUrl", result.AcsUrl},
                //	{"md", result.Md},
                //	{"vendorTxCode", request.VendorTxCode}
                //};
                //if (HttpContext.Current.Session["USER_3DAUTH"] != null)
                //{
                //	HttpContext.Current.Session["USER_3DAUTH"] = null;
                //}
                //HttpContext.Current.Session.Add("USER_3DAUTH", threeDAuth);

                ////<form action="<%= ACSUrl %>" method="post">
                ////<input type="hidden" name="PaReq" value="<%= PaReq %>" />
                ////<input type="hidden" name="TermUrl" value="<%= TermUrl %>" />
                ////<input type="hidden" name="MD" value="<%= MD %>" />
                ////<input type="submit" value="Go" />
                ////</form>

                //var responseString = _requestSender.SendRequest(result.AcsUrl, threeDSecureRequest.ParametersAsString);


                //var threeDAuthRequest = sagePayDirectIntegration.ThreeDAuthRequest();
                //threeDAuthRequest.Md = Request.Form["MD"];
                //threeDAuthRequest.PaRes = Request.Form["PaRes"];
                //var directPaymentResult = sagePayDirectIntegration.ProcessDirect3D(threeDAuthRequest);

                //if (directPaymentResult.Status == ResponseStatus.OK)
                //{
                //	orderInfo.Paid = true;
                //	orderInfo.Status = OrderStatus.ReadyForDispatch;
                //}
                //else
                //{

                //	Log.Instance.LogError("SagePay Did not return a proper directPaymentResult status: " + directPaymentResult.StatusDetail);
                //	PaymentProviderHelper.AddValidationResult(orderInfo, orderInfo.PaymentInfo.Id, "SagePayReturnedError", directPaymentResult.StatusDetail);
                //}
            }
            else
            {
                Log.Instance.LogError("SagePay Did not return a proper status: " + result.StatusDetail);
                PaymentProviderHelper.AddValidationResult(orderInfo, orderInfo.PaymentInfo.Id, "SagePayReturnedError", result.StatusDetail);
            }


            orderInfo.Save();

            return(new PaymentRequest());
        }
        /// <summary>
        /// Executes the transaction request to SagePay
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <returns></returns>
        public PaymentRequest CreatePaymentRequest(OrderInfo orderInfo)
        {
            // new API Call for easier access to date (but not able to write to)
            var orderAPI = API.Basket.GetBasket(orderInfo.UniqueOrderId);

            var paymentProvider = PaymentProvider.GetPaymentProvider(orderInfo.PaymentInfo.Id);

            #region config helper

            var vendorName = paymentProvider.GetSetting("VendorName");

            var liveUrl = "https://live.sagepay.com/gateway/service/vspdirect-register.vsp";
            var testUrl = "https://test.sagepay.com/Simulator/VSPDirectGateway.asp";

            var configLiveUrl = paymentProvider.GetSetting("Url");
            var configTestUrl = paymentProvider.GetSetting("testUrl");

            if (!string.IsNullOrEmpty(configLiveUrl))
            {
                liveUrl = configLiveUrl;
            }
            if (!string.IsNullOrEmpty(configTestUrl))
            {
                testUrl = configTestUrl;
            }

            #endregion

            var reportUrl = paymentProvider.ReportUrl();

            var request = new PaymentRequest();

            var cardTypeMethod = orderInfo.PaymentInfo.MethodId;

            // Get the fields from the current request, this way they won't be stored in the order or in uWebshop
            var creditCardHolderName = HttpContext.Current.Request["CardHolder"];
            var creditCardNumber     = HttpContext.Current.Request["CardNumber"];
            var creditCardCV2        = HttpContext.Current.Request["CV2"];
            var creditCardExpiryDate = HttpContext.Current.Request["ExpiryDate"];

            if (string.IsNullOrEmpty(creditCardHolderName))
            {
                // if no creditCardHolder field is posted, try to see if the order contains an holder field
                creditCardHolderName = orderAPI.Customer.GetValue <string>("customerCardHolder");

                if (string.IsNullOrEmpty(creditCardHolderName))
                {
                    // if that is not present, use first letter of firstName and full last name
                    creditCardHolderName = orderInfo.CustomerFirstName.Substring(0, 1) + " " +
                                           orderInfo.CustomerLastName;
                }
            }

            if (string.IsNullOrEmpty(creditCardNumber))
            {
                // if no creditCardNumber field is posted, try to see if the order contains an creditcardnumber
                creditCardNumber = orderAPI.Customer.GetValue <string>("customerCardNumber");

                if (cardTypeMethod.ToLowerInvariant() != "paypal" &&
                    (string.IsNullOrEmpty(creditCardNumber) && !paymentProvider.TestMode))
                {
                    Log.Instance.LogError("Sagepay CreatePaymentRequest: No Creditcardnumber Given");

                    PaymentProviderHelper.AddValidationResult(orderInfo, paymentProvider.Id, "CreditCardError", "No Creditcardnumber Entered");

                    return(null);
                }
            }

            if (string.IsNullOrEmpty(creditCardCV2))
            {
                // if no creditCardNumber field is posted, try to see if the order contains an creditcardnumber
                creditCardCV2 = orderAPI.Customer.GetValue <string>("customerCardCV2");

                if (cardTypeMethod.ToLowerInvariant() != "paypal" && string.IsNullOrEmpty(creditCardCV2) && !paymentProvider.TestMode)
                {
                    Log.Instance.LogError("Sagepay CreatePaymentRequest: No CV2 Given");

                    PaymentProviderHelper.AddValidationResult(orderInfo, paymentProvider.Id, "CV2Error", "No CV2 Entered");

                    return(null);
                }
            }

            if (string.IsNullOrEmpty(creditCardExpiryDate))
            {
                // if no ExpiryDate field is posted, try to see if the order contains an expirydate
                creditCardExpiryDate = orderAPI.Customer.GetValue <string>("customerCardExpiryDate");

                if (cardTypeMethod.ToLowerInvariant() != "paypal" && string.IsNullOrEmpty(creditCardExpiryDate) && !paymentProvider.TestMode)
                {
                    Log.Instance.LogError("Sagepay CreatePaymentRequest: No creditCardExpiryDate Given");

                    PaymentProviderHelper.AddValidationResult(orderInfo, paymentProvider.Id, "CardExpiryDateError", "No CardExpiryDate Entered");

                    return(null);
                }
            }

            // Preset Valid test creditcardnumbers for testmode
            if (paymentProvider.TestMode)
            {
                switch (cardTypeMethod.ToUpperInvariant())
                {
                case "VISA":
                    creditCardNumber = "4929000000006";
                    break;

                case "MC":
                    creditCardNumber = "5404000000000001";
                    break;

                case "MCDEBIT":
                    creditCardNumber = "5573470000000001";
                    break;

                case "DELTA":
                    creditCardNumber = "4462000000000003";
                    break;

                case "MAESTRO":
                    creditCardNumber = "5641820000000005";
                    break;

                case "UKE":
                    creditCardNumber = "4917300000000008";
                    break;

                case "AMEX":
                    creditCardNumber = "374200000000004";
                    break;

                case "DINERS":
                    creditCardNumber = "36000000000008";
                    break;

                case "DC":
                    creditCardNumber = "4929000000006";
                    break;

                case "JCB":
                    creditCardNumber = "3569990000000009";
                    break;

                case "LASER":
                    creditCardNumber = "6304990000000000044";
                    break;
                }
            }

            request.Parameters.Add("CardType", cardTypeMethod);
            request.Parameters.Add("CardHolder", paymentProvider.TestMode ? "T.Ester" : creditCardHolderName);
            request.Parameters.Add("CardNumber", creditCardNumber);
            request.Parameters.Add("CV2", paymentProvider.TestMode ? "123" : creditCardCV2);
            request.Parameters.Add("ExpiryDate", paymentProvider.TestMode ? DateTime.Now.AddMonths(6).ToString("MMyy") : creditCardExpiryDate);

            request.Parameters.Add("VPSProtocol", "2.23");
            request.Parameters.Add("TxType", "PAYMENT");
            request.Parameters.Add("Vendor", vendorName);

            var trasactionId = orderInfo.OrderNumber + "x" + DateTime.Now.ToString("hhmmss");

            request.Parameters.Add("VendorTxCode", trasactionId);

            request.Parameters.Add("Amount", orderInfo.ChargedAmount.ToString(new CultureInfo("en-GB").NumberFormat));
            request.Parameters.Add("Currency", new RegionInfo(orderInfo.StoreInfo.Store.CurrencyCultureInfo.LCID).ISOCurrencySymbol);

            request.Parameters.Add("Description", orderInfo.OrderNumber);

            request.Parameters.Add("NotificationURL", reportUrl);

            request.Parameters.Add("BillingSurname", GetSagePaySafeCustomerInfo(orderAPI.Customer.LastName));
            request.Parameters.Add("BillingFirstnames", GetSagePaySafeCustomerInfo(orderAPI.Customer.FirstName));
            request.Parameters.Add("BillingAddress1", GetSagePaySafeCustomerInfo(orderAPI.Customer.Address1));
            request.Parameters.Add("BillingCity", GetSagePaySafeCustomerInfo(orderAPI.Customer.City));
            request.Parameters.Add("BillingPostCode", GetSagePaySafeCustomerInfo(orderAPI.Customer.ZipCode));
            request.Parameters.Add("BillingCountry", GetSagePaySafeCustomerInfo(orderInfo.CustomerInfo.CountryCode));

            var deliverySurName   = string.IsNullOrEmpty(orderAPI.Customer.Shipping.LastName) ? orderAPI.Customer.LastName : orderAPI.Customer.Shipping.LastName;
            var deliveryFirstName = string.IsNullOrEmpty(orderAPI.Customer.Shipping.FirstName) ? orderAPI.Customer.FirstName : orderAPI.Customer.Shipping.FirstName;
            var deliveryAddress1  = string.IsNullOrEmpty(orderAPI.Customer.Shipping.Address1) ? orderAPI.Customer.Address1 : orderAPI.Customer.Shipping.Address1;
            var deliveryPostcode  = string.IsNullOrEmpty(orderAPI.Customer.Shipping.ZipCode) ? orderAPI.Customer.ZipCode : orderAPI.Customer.Shipping.ZipCode;
            var deliveryCity      = string.IsNullOrEmpty(orderAPI.Customer.Shipping.City) ? orderAPI.Customer.City : orderAPI.Customer.Shipping.City;
            var deliveryCountry   = string.IsNullOrEmpty(orderAPI.Customer.Shipping.CountryCode) ? orderAPI.Customer.CountryCode : orderAPI.Customer.Shipping.CountryCode;

            request.Parameters.Add("DeliverySurname", GetSagePaySafeCustomerInfo(deliverySurName));
            request.Parameters.Add("DeliveryFirstnames", GetSagePaySafeCustomerInfo(deliveryFirstName));
            request.Parameters.Add("DeliveryAddress1", GetSagePaySafeCustomerInfo(deliveryAddress1));
            request.Parameters.Add("DeliveryCity", GetSagePaySafeCustomerInfo(deliveryCity));
            request.Parameters.Add("DeliveryPostCode", GetSagePaySafeCustomerInfo(deliveryPostcode));
            request.Parameters.Add("DeliveryCountry", GetSagePaySafeCustomerInfo(deliveryCountry));

            // optionele parameters:
            //request.Parameters.Add("BillingAddress2", "");
            //request.Parameters.Add("BillingState", "");
            //request.Parameters.Add("BillingPhone", "");
            //request.Parameters.Add("DeliveryAddress2", "");
            //request.Parameters.Add("DeliveryState", "");
            //request.Parameters.Add("DeliveryPhone", "");
            //request.Parameters.Add("CustomerEMail", "");
            //request.Parameters.Add("Basket", ""); // optioneel info over basket
            //request.Parameters.Add("AllowGiftAid", "0");
            //request.Parameters.Add("Apply3DSecure", "0");

            var sagePayUrl     = paymentProvider.TestMode ? testUrl : liveUrl;
            var responseString = _requestSender.SendRequest(sagePayUrl, request.ParametersAsString);

            var deserializer = new ResponseSerializer();
            var response     = deserializer.Deserialize <TransactionRegistrationResponse>(responseString);

            if (!string.IsNullOrEmpty(response.VPSTxId) && response.Status == ResponseType.Ok)
            {
                orderInfo.PaymentInfo.Parameters = response.Status + "&" + response.StatusDetail;

                PaymentProviderHelper.SetTransactionId(orderInfo, response.VPSTxId);
            }
            else
            {
                Log.Instance.LogError("SagePay Did not return a proper status: " + response.Status + " detail: " + response.StatusDetail);

                PaymentProviderHelper.AddValidationResult(orderInfo, paymentProvider.Id, "SagePayReturnedError", response.StatusDetail);
            }

            orderInfo.Save();

            return(request);
        }