public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
		{
			context.Payment.PaymentStatus = PaymentStatus.Authorized;
			context.Payment.OuterId = context.Payment.Number;
			context.Payment.CapturedDate = DateTime.UtcNow;
			return new ProcessPaymentResult { IsSuccess = true, NewPaymentStatus = PaymentStatus.Authorized };
		}
		public void ProcessPaymentForOrder()
		{
			var result = _controller.GetById("order1") as OkNegotiatedContentResult<webModel.CustomerOrder>;
			var testOrder = result.Content;

			var payment = testOrder.InPayments.FirstOrDefault();

			var mockPaymentManager = new Mock<IPaymentMethodsService>();
			var gateway = mockPaymentManager.Object.GetAllPaymentMethods().FirstOrDefault(x => x.Code == payment.GatewayCode);

			var paymentEvaluationContext = new ProcessPaymentEvaluationContext();

			var paymentResult = gateway.ProcessPayment(paymentEvaluationContext);

			payment.IsApproved = paymentResult.IsSuccess;

			_controller.Update(testOrder);
		}
		public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			GatewaySettings settings = new GatewaySettings();
			settings.setCredentials(ProfileId, ProfileKey)
				.setVerbose(true)
				.setHostUrl(GatewaySettings.URL_CERT);
			Gateway gateway = new Gateway(settings);

			GatewayRequest request = new GatewayRequest(GatewayRequest.TransactionType.SALE);
			if (string.IsNullOrEmpty(context.Payment.OuterId))
			{
				request.setCardData("4012888812348882", "1216");
			}
			else
			{
				request.setTokenData(context.Payment.OuterId, string.Empty);
			}
			request.setAmount("1.03");
			GatewayResponse response = gateway.run(request);

			var tranId = response.getTransactionId();

			var errorCode = response.getErrorCode();

			if(errorCode.Equals("000"))
			{
				retVal.OuterId = tranId;
				retVal.IsSuccess = true;
				retVal.NewPaymentStatus = PaymentStatus.Pending; //maybe
			}
			else
			{
				retVal.NewPaymentStatus = PaymentStatus.Voided;
				retVal.Error = string.Format("Mes error {0}", errorCode);
			}

			return retVal;
		}
        private DoDirectPaymentReq GetDoDirectPaymentRequest(ProcessPaymentEvaluationContext context)
        {
            var retVal = new DoDirectPaymentReq();

            retVal.DoDirectPaymentRequest = new DoDirectPaymentRequestType();
            retVal.DoDirectPaymentRequest.Version = GetApiVersion();
            var details = new DoDirectPaymentRequestDetailsType();
            retVal.DoDirectPaymentRequest.DoDirectPaymentRequestDetails = details;
            details.PaymentAction = PaymentActionCodeType.SALE;

            //credit card
            details.CreditCard = GetCreditCardDetails(context);


            //order totals
            details.PaymentDetails = new PaymentDetailsType();
            details.PaymentDetails.OrderTotal = new BasicAmountType();
            details.PaymentDetails.OrderTotal.value = FormatMoney(context.Payment.Sum);
            details.PaymentDetails.OrderTotal.currencyID = (CurrencyCodeType)Enum.Parse(typeof(CurrencyCodeType), context.Order.Currency.ToString());
            details.PaymentDetails.Custom = context.Order.Id;
            details.PaymentDetails.ButtonSource = "virtoCommerceManagerCart";

            return retVal;
        }
        public IHttpActionResult ProcessOrderPayments([FromBody]BankCardInfo bankCardInfo, string orderId, string paymentId)
        {
            var order = _customerOrderService.GetById(orderId, coreModel.CustomerOrderResponseGroup.Full);
            if (order == null)
            {
                throw new NullReferenceException("order");
            }
            var payment = order.InPayments.FirstOrDefault(x => x.Id == paymentId);
            if (payment == null)
            {
                throw new NullReferenceException("payment");
            }
            var store = _storeService.GetById(order.StoreId);
            var paymentMethod = store.PaymentMethods.FirstOrDefault(x => x.Code == payment.GatewayCode);
            if (payment == null)
            {
                throw new NullReferenceException("appropriate paymentMethod not found");
            }

            var context = new ProcessPaymentEvaluationContext
            {
                Order = order,
                Payment = payment,
                Store = store,
				BankCardInfo = bankCardInfo
            };

            var result = paymentMethod.ProcessPayment(context);
            if (result.NewPaymentStatus == PaymentStatus.Pending || result.NewPaymentStatus == PaymentStatus.Paid)
            {
                payment.OuterId = result.OuterId;
				payment.IsApproved = result.NewPaymentStatus == PaymentStatus.Paid;
                _customerOrderService.Update(new coreModel.CustomerOrder[] { order });
            }
            var retVal = new webModel.ProcessPaymentResult();
            retVal.InjectFrom(result);
            retVal.PaymentMethodType = paymentMethod.PaymentMethodType;

            return Ok(retVal);
        }
 /// <summary>
 /// Method that contains logic of registration payment in external payment system
 /// </summary>
 /// <param name="context"></param>
 /// <returns>Result of registration payment in external payment system</returns>
 public abstract ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context);
		public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			if (!(context.Store != null && (!string.IsNullOrEmpty(context.Store.SecureUrl) || !string.IsNullOrEmpty(context.Store.Url))))
				throw new NullReferenceException("no store with this id");

			var url = string.Empty;
			if (!string.IsNullOrEmpty(context.Store.SecureUrl))
			{
				url = context.Store.SecureUrl;
			}
			else
			{
				url = context.Store.Url;
			}

			var config = GetConfigMap();

			var service = new AdaptivePaymentsService(config);

			var request = CreatePaypalRequest(context.Order, context.Payment, url);

			var response = service.Pay(request);

			if (response.error != null && response.error.Count > 0)
			{
				var sb = new StringBuilder();
				foreach (var error in response.error)
				{
					sb.AppendLine(error.message);
				}
				retVal.Error = sb.ToString();
				retVal.NewPaymentStatus = PaymentStatus.Voided;
			}
			else
			{
				retVal.OuterId = response.payKey;
				retVal.IsSuccess = true;
				var redirectBaseUrl = GetBaseUrl(Mode);
				retVal.RedirectUrl = string.Format(redirectBaseUrl, retVal.OuterId);
				retVal.NewPaymentStatus = PaymentStatus.Pending;
			}

			return retVal;
		}
		/// <summary>
		/// Method that contains logic of registration payment in external payment system
		/// </summary>
		/// <param name="context"></param>
		/// <returns>Result of registration payment in external payment system</returns>
		public abstract ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context);
		public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			if (!(context.Store != null && !string.IsNullOrEmpty(context.Store.Url)))
				throw new NullReferenceException("no store with this id");

			var config = GetConfigMap(context.Store);

			var url = context.Store.Url;

			var request = CreatePaypalRequest(context.Order, context.Store, context.Payment);

			var service = new PayPalAPIInterfaceServiceService(config);

		    try
			{
				var setEcResponse = service.SetExpressCheckout(request);

				CheckResponse(setEcResponse);

				retVal.IsSuccess = true;
				retVal.NewPaymentStatus = PaymentStatus.Pending;
				retVal.OuterId = setEcResponse.Token;
				var redirectBaseUrl = GetBaseUrl(Mode);
				retVal.RedirectUrl = string.Format(redirectBaseUrl, retVal.OuterId);
			}
			catch (System.Exception ex)
			{
				retVal.Error = ex.Message;
			}

			return retVal;
		}
        public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
        {
            var retVal = new ProcessPaymentResult();

            if (context.Order != null && context.Store != null && context.Payment != null)
            {
                if (!(!string.IsNullOrEmpty(context.Store.SecureUrl) || !string.IsNullOrEmpty(context.Store.Url)))
                    throw new NullReferenceException("store must specify Url or SecureUrl property");

                var baseStoreUrl = string.Empty;
                if (!string.IsNullOrEmpty(context.Store.SecureUrl))
                {
                    baseStoreUrl = context.Store.SecureUrl;
                }
                else
                {
                    baseStoreUrl = context.Store.Url;
                }

                var orderId = context.Order.Number;

                //get md5 hash passing the order number, currency ISO code and order total
                var md5Hash = CalculateMD5Hash(orderId, (int)context.Order.Currency, (int)(context.Order.Sum * 100));

                var reqparm = new NameValueCollection();
                reqparm.Add(acceptUrlFormDataName, AcceptUrl);
                reqparm.Add(callbackUrlFormDataName, CallbackUrl);
                reqparm.Add(cancelUrlFormDataName, AcceptUrl);
                reqparm.Add(merchantIdFormDataName, MerchantId);
                reqparm.Add(orderIdFormDataName, orderId);
                reqparm.Add(orderInternalIdFormDataName, context.Order.Id);
                reqparm.Add(amountFormDataName, ((int)(context.Order.Sum * 100)).ToString());
                reqparm.Add(currencyFormDataName, ((int)context.Order.Currency).ToString());
                reqparm.Add(languageFormDataName, context.Store.DefaultLanguage.Substring(0, 2));
                reqparm.Add(md5KeyFormDataName, md5Hash);
                reqparm.Add(decoratorFormDataName, FormDecoarator);

                if (Mode == "test")
                {
                    reqparm.Add(testModeFormDataName, "1");
                }

                //build form to post to FlexWin
                var checkoutform = string.Empty;
                                
                checkoutform += string.Format("<form name='dibs' action='{0}' method='POST' charset='UTF-8'>", RedirectUrl);
                checkoutform += "<p>You'll be redirected to DIBS payment in a moment. If not, click the 'Procced' button...</p>";

                const string paramTemplateString = "<INPUT TYPE='hidden' name='{0}' value='{1}'>";
                foreach (string key in reqparm)
                    checkoutform += string.Format(paramTemplateString, key, reqparm[key]);
                checkoutform += "<button type='submit'>Proceed</button>";
                checkoutform += "</form>";

                checkoutform += "<script language='javascript'>document.dibs.submit();</script>";
                                
                retVal.HtmlForm = checkoutform;
                retVal.IsSuccess = true;
                retVal.NewPaymentStatus = PaymentStatus.Pending;
            }
            return retVal;
        }
		private ProcessPaymentResult NewCreateKlarnaOrder(KlarnaLocalization localization, ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			var orderLineItems = GetOrderLineItems(context.Order);

			MerchantUrls merchantUrls = new MerchantUrls
			{
				Terms = new System.Uri(
					string.Format("{0}/{1}", context.Store.Url, TermsUrl)),
				Checkout = new System.Uri(
					string.Format("{0}/{1}", context.Store.Url, CheckoutUrl)),
				Confirmation = new System.Uri(
					string.Format("{0}/{1}?sid=123&orderId={2}&", context.Store.Url, ConfirmationUrl, context.Order.Id) + "klarna_order={checkout.order.uri}"),
				Push = new System.Uri(
					string.Format("{0}/{1}?sid=123&orderId={2}&", context.Store.Url, "admin/api/paymentcallback", context.Order.Id) + "klarna_order={checkout.order.uri}")
			};

			CheckoutOrderData orderData = new CheckoutOrderData()
			{
				PurchaseCountry = localization.CountryName,
				PurchaseCurrency = localization.Currency,
				Locale = localization.Locale,
				OrderAmount = (int)(context.Order.Sum * 100),
				OrderTaxAmount = (int)(context.Order.Tax * 100),
				OrderLines = orderLineItems,
				MerchantUrls = merchantUrls
			};

			var connector = ConnectorFactory.Create(
				AppKey,
				AppSecret,
				Client.TestBaseUrl);
			Client client = new Client(connector);

			var checkout = client.NewCheckoutOrder();
			checkout.Create(orderData);

			orderData = checkout.Fetch();
			retVal.IsSuccess = true;
			retVal.NewPaymentStatus = PaymentStatus.Pending;
			retVal.OuterId = orderData.OrderId;
			retVal.HtmlForm = string.Format("<div>{0}</div>", orderData.HtmlSnippet);

			return retVal;
		}
        private CreditCardDetailsType GetCreditCardDetails(ProcessPaymentEvaluationContext context)
        {
            var retVal = new CreditCardDetailsType();

            retVal.CreditCardNumber = context.BankCardInfo.BankCardNumber;
			retVal.CreditCardType = GetPaypalCreditCardType(context.BankCardInfo.BankCardType);
			retVal.ExpMonth = context.BankCardInfo.BankCardMonth;
			retVal.ExpYear = context.BankCardInfo.BankCardYear;
			retVal.CVV2 = context.BankCardInfo.BankCardCVV2;
            retVal.CardOwner = new PayerInfoType();

            if (context.Order.Addresses.Any(x => x.AddressType == VirtoCommerce.Domain.Commerce.Model.AddressType.Billing))
            {
                var billingAddress = context.Order.Addresses.FirstOrDefault(x => x.AddressType == VirtoCommerce.Domain.Commerce.Model.AddressType.Billing);
                retVal.CardOwner.PayerCountry = GetPaypalCountryCodeType(billingAddress.CountryCode);

                retVal.CardOwner.Address = new PayPal.PayPalAPIInterfaceService.Model.AddressType();
                retVal.CardOwner.Address.Street1 = billingAddress.Line1;
                retVal.CardOwner.Address.Street2 = billingAddress.Line2;
                retVal.CardOwner.Address.CityName = billingAddress.City;
                retVal.CardOwner.Address.StateOrProvince = billingAddress.RegionName;

                retVal.CardOwner.Address.Country = GetPaypalCountryCodeType(billingAddress.CountryCode);
                retVal.CardOwner.Address.PostalCode = billingAddress.Zip;
                retVal.CardOwner.Payer = billingAddress.Email;
                retVal.CardOwner.PayerName = new PersonNameType();
                retVal.CardOwner.PayerName.FirstName = billingAddress.FirstName;
                retVal.CardOwner.PayerName.LastName = billingAddress.LastName;
            }
			else if (context.Order.Addresses.Any())
            {
				var billingAddress = context.Order.Addresses.FirstOrDefault();
				retVal.CardOwner.PayerCountry = GetPaypalCountryCodeType(billingAddress.CountryCode);

				retVal.CardOwner.Address = new PayPal.PayPalAPIInterfaceService.Model.AddressType();
				retVal.CardOwner.Address.Street1 = billingAddress.Line1;
				retVal.CardOwner.Address.Street2 = billingAddress.Line2;
				retVal.CardOwner.Address.CityName = billingAddress.City;
				retVal.CardOwner.Address.StateOrProvince = billingAddress.RegionName;

				retVal.CardOwner.Address.Country = GetPaypalCountryCodeType(billingAddress.CountryCode);
				retVal.CardOwner.Address.PostalCode = billingAddress.Zip;
				retVal.CardOwner.Payer = billingAddress.Email;
				retVal.CardOwner.PayerName = new PersonNameType();
				retVal.CardOwner.PayerName.FirstName = billingAddress.FirstName;
				retVal.CardOwner.PayerName.LastName = billingAddress.LastName;
            }
			else
			{
				throw new NullReferenceException("no billing address");
			}

            return retVal;
        }
        public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
        {
            var retVal = new ProcessPaymentResult();

            if (context.Order != null && context.Store != null && context.Payment != null)
            {
                var sequence = new Random().Next(0, 1000).ToString();
                var timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
                var currency = context.Payment.Currency.ToString();

                var fingerprint = HmacMD5(TxnKey, ApiLogin + "^" + sequence + "^" + timeStamp + "^" + context.Payment.Sum.ToString("F", CultureInfo.InvariantCulture) + "^" + currency);

                var confirmationUrl = string.Format("{0}/{1}/{2}", context.Store.Url, ConfirmationRelativeUrl, context.Order.Id);

                var checkoutform = string.Empty;

                checkoutform += string.Format("<form action='{0}' method='POST'>", GetAuthorizeNetUrl());

                //credit cart inputs for user
                checkoutform += string.Format("<p><div style='float:left;width:250px;'><label>Credit Card Number</label><div id = 'CreditCardNumber'>{0}</div></div>", CreateInput(false, "x_card_num", "5555555555554444", 28));
                checkoutform += string.Format("<div style='float:left;width:70px;'><label>Exp.</label><div id='CreditCardExpiration'>{0}</div></div>", CreateInput(false, "x_exp_date", "0216", 5));
                checkoutform += string.Format("<div style='float:left;width:70px;'><label>CCV</label><div id='CCV'>{0}</div></div></p>", CreateInput(false, "x_card_code", "345", 5));

                //
                checkoutform += CreateInput(true, "x_login", ApiLogin);
                checkoutform += CreateInput(true, "x_invoice_num", context.Order.Id);
                checkoutform += CreateInput(true, "x_po_num", context.Order.Number);
                checkoutform += CreateInput(true, "x_relay_response", "TRUE");
                checkoutform += CreateInput(true, "x_relay_url", confirmationUrl);

                ///Fingerprint and params for it
                checkoutform += CreateInput(true, "x_fp_sequence", sequence);
                checkoutform += CreateInput(true, "x_fp_timestamp", timeStamp);
                checkoutform += CreateInput(true, "x_fp_hash", fingerprint);
                checkoutform += CreateInput(true, "x_currency_code", currency);
                checkoutform += CreateInput(true, "x_amount", context.Payment.Sum.ToString("F", CultureInfo.InvariantCulture));

                checkoutform += GetAuthOrCapture();

                // Add a Submit button
                checkoutform += "<div style='clear:both'></div><p><input type='submit' class='submit' value='Order with DPM!' /></p></form>";

                checkoutform = checkoutform + DPMFormGenerator.EndForm();

                retVal.HtmlForm = checkoutform;
                retVal.IsSuccess = true;
                retVal.NewPaymentStatus = PaymentStatus.Pending;
            }

            return retVal;
        }
		private ProcessPaymentResult ProcessKlarnaOrder(KlarnaLocalization localization, ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			var cartItems = CreateKlarnaCartItems(context.Order);

			//Create cart
			var cart = new Dictionary<string, object> { { "items", cartItems } };
			var data = new Dictionary<string, object>
					{
						{ "cart", cart }
					};

			//Create klarna order "http://example.com" context.Store.Url
			var connector = Connector.Create(AppSecret);
			Order order = null;
			var merchant = new Dictionary<string, object>
					{
						{ "id", AppKey },
						{ "terms_uri", string.Format("{0}/{1}", context.Store.Url, TermsUrl) },
						{ "checkout_uri", string.Format("{0}/{1}", context.Store.Url, CheckoutUrl) },
						{ "confirmation_uri", string.Format("{0}/{1}?sid=123&orderId={2}&", context.Store.Url, ConfirmationUrl, context.Order.Id) + "klarna_order={checkout.order.uri}" },
						{ "push_uri", string.Format("{0}/{1}?sid=123&orderId={2}&", context.Store.Url, "admin/api/paymentcallback", context.Order.Id) + "klarna_order={checkout.order.uri}" },
						{ "back_to_store_uri", context.Store.Url }
					};

			var layout = new Dictionary<string, object>
					{
						{ "layout", "desktop" }
					};

			data.Add("purchase_country", localization.CountryName);
			data.Add("purchase_currency", localization.Currency);
			data.Add("locale", localization.Locale);
			data.Add("merchant", merchant);
			data.Add("gui", layout);

			order =
				new Order(connector)
				{
					BaseUri = new Uri(GetCheckoutBaseUrl(localization.Currency)),
					ContentType = _contentType
				};
			order.Create(data);
			order.Fetch();

			//Gets snippet
			var gui = order.GetValue("gui") as JObject;
			var html = gui["snippet"].Value<string>();

			retVal.IsSuccess = true;
			retVal.NewPaymentStatus = context.Payment.PaymentStatus = PaymentStatus.Pending;
			retVal.HtmlForm = html;
			retVal.OuterId = context.Payment.OuterId = order.GetValue("id") as string;

			return retVal;
		}
		public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			if (context.Order != null && context.Store != null && context.Payment != null)
			{
				KlarnaLocalization localization;
				string countryName = null;
				string currency = context.Order.Currency.ToString();

				if (context.Order.Addresses != null && context.Order.Addresses.Count > 0)
				{
					var address = context.Order.Addresses.FirstOrDefault();
					countryName = address.CountryName;
				}

				if (!string.IsNullOrEmpty(countryName))
				{
					localization = GetLocalization(currency, countryName);
				}
				else
				{
					localization = GetLocalization(currency, null);
				}

				if (localization != null)
				{
					retVal = ProcessKlarnaOrder(localization, context);
				}
				else
				{
					retVal.Error = "Klarna is not available for this order";
				}
			}

			return retVal;
		}
        public IHttpActionResult ProcessOrderPayments(string orderId, string paymentId, [SwaggerOptional] BankCardInfo bankCardInfo)
        {
            //search first by order number
            var order = _customerOrderService.GetByOrderNumber(orderId, coreModel.CustomerOrderResponseGroup.Full);

            //if not found by order number search by order id
            if (order == null)
                order = _customerOrderService.GetById(orderId, coreModel.CustomerOrderResponseGroup.Full);

            if (order == null)
            {
                throw new NullReferenceException("order");
            }
            var payment = order.InPayments.FirstOrDefault(x => x.Id == paymentId);
            if (payment == null)
            {
                throw new NullReferenceException("payment");
            }
            var store = _storeService.GetById(order.StoreId);
            var paymentMethod = store.PaymentMethods.FirstOrDefault(x => x.Code == payment.GatewayCode);
            if (paymentMethod == null)
            {
                throw new NullReferenceException("appropriate paymentMethod not found");
            }

            var context = new ProcessPaymentEvaluationContext
            {
                Order = order,
                Payment = payment,
                Store = store,
                BankCardInfo = bankCardInfo
            };

            var result = paymentMethod.ProcessPayment(context);

            _customerOrderService.Update(new[] { order });

            var retVal = new webModel.ProcessPaymentResult();
            retVal.InjectFrom(result);
            retVal.PaymentMethodType = paymentMethod.PaymentMethodType;

            return Ok(retVal);
        }
        private Hashtable PrepareProcessPaymentRequest(ProcessPaymentEvaluationContext context)
        {
            Hashtable request = new Hashtable();
            request.Add("merchantID", MerchantId);
            request.Add("merchantReferenceCode", context.Payment.Number);

            if (IsSeparatePaymentAction())
            {
                request.Add("ccAuthService_run", "true");
            }
            else
            {
                request.Add("ccAuthService_run", "true");
                request.Add("ccCaptureService_run", "true");
            }

            if(IsTest())
                request.Add("sendToProduction", "false");
            else
                request.Add("sendToProduction", "true");

            // Set billing address of payment as address for request
            var address = context.Payment.BillingAddress;
            
            // Set first billing address in order
            if (address == null && context.Order.Addresses != null)
                address = context.Order.Addresses.FirstOrDefault(a => a.AddressType == AddressType.Billing || a.AddressType == AddressType.BillingAndShipping);
            
            // Set any first address in order
            if (address == null)
                address = context.Order.Addresses.FirstOrDefault();

            // Throw exception, is no address
            if (address == null)
                throw new NullReferenceException("No address, payment can't be processed");

            SetBillingAddress(address, request);
            SetCreditCardInfo(context.BankCardInfo, request);

            request.Add("purchaseTotals_currency", context.Payment.Currency.ToString());
            request.Add("item_0_unitPrice", context.Payment.Sum.ToString(CultureInfo.InvariantCulture));
            //request.Add("item_0_quantity", "1");

            return request;
        }
        public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
        {
            var retVal = new ProcessPaymentResult();

            var request = PrepareProcessPaymentRequest(context);

            var reply = NVPClient.RunTransaction(request);
            if (reply != null && reply.ContainsKey("decision") && reply.ContainsKey("reasonCode"))
            {
                var decision = (string)reply["decision"];
                var reasonCode = int.Parse((string)reply["reasonCode"]);
                var isAccept = decision.Equals("ACCEPT", StringComparison.InvariantCultureIgnoreCase);
                var isSuccessReasonCode = reasonCode == 100;
                if (isAccept && isSuccessReasonCode)
                {
                    context.Payment.OuterId = (string)reply["requestID"];
                    if (IsSeparatePaymentAction())
                    {
                        retVal.NewPaymentStatus = context.Payment.PaymentStatus = PaymentStatus.Authorized;
                        context.Payment.AuthorizedDate = DateTime.UtcNow;
                    }
                    else
                    {
                        retVal.NewPaymentStatus = context.Payment.PaymentStatus = PaymentStatus.Paid;
                        context.Payment.AuthorizedDate = context.Payment.CapturedDate = DateTime.UtcNow;
                        context.Payment.IsApproved = true;
                    }
                    retVal.IsSuccess = true;
                    retVal.RedirectUrl = string.Format("{0}/{1}?id={2}", context.Store.Url, ThankYouPageRelativeUrl, context.Order.Id);
                }
                else
                {
                    if (reasonCode == 101)
                        throw new NullReferenceException(string.Format("result from cyber source, not success, decision is {0}, reasonCode is {1}, full info of reason is {2}", decision, reasonCode, EnumerateValues(reply, "missingField")));
                    if (reasonCode == 102)
                        throw new NullReferenceException(string.Format("result from cyber source, not success, decision is {0}, reasonCode is {1}, full info of reason is {2}", decision, reasonCode, EnumerateValues(reply, "invalidField")));
                    if (reasonCode == 204)
                        throw new NullReferenceException(string.Format("result from cyber source, not success, decision is {0}, reasonCode is {1}, full info of reason is not enough funds", decision, reasonCode));

                    throw new NullReferenceException(string.Format("result from cyber source, not success, decision is {0}, reasonCode is {1}", decision, reasonCode));
                }
            }
            else
            {
                throw new NullReferenceException("no reply from cyber source");
            }

            return retVal;
        }
        public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
        {
            var retVal = new ProcessPaymentResult();

            if (!(context.Store != null))
                throw new NullReferenceException("no store with this id");

            var doDirectPaymentRequest = GetDoDirectPaymentRequest(context);

            var service = GetService();
            var response = service.DoDirectPayment(doDirectPaymentRequest);

            string error;
            bool success = CheckResponse(response, out error);


            if (success)
            {
                retVal.OuterId = response.TransactionID;
                retVal.IsSuccess = (response.Ack.Value == AckCodeType.SUCCESS || response.Ack.Value == AckCodeType.SUCCESSWITHWARNING);
                retVal.NewPaymentStatus = retVal.IsSuccess ? PaymentStatus.Paid : PaymentStatus.Voided;
            }
            else
            {
                retVal.Error = error;
            }

            return retVal;
        }
		public override ProcessPaymentResult ProcessPayment(ProcessPaymentEvaluationContext context)
		{
			var retVal = new ProcessPaymentResult();

			if (context.Store == null)
				throw new NullReferenceException("no store with this id");

            if (!(!string.IsNullOrEmpty(context.Store.SecureUrl) || !string.IsNullOrEmpty(context.Store.Url)))
                throw new NullReferenceException("store must specify Url or SecureUrl property");

			var url = string.Empty;
			if (!string.IsNullOrEmpty(context.Store.SecureUrl))
			{
				url = context.Store.SecureUrl;
			}
			else
			{
				url = context.Store.Url;
			}

			var config = GetConfigMap();

			var service = new AdaptivePaymentsService(config);

			var request = CreatePaypalRequest(context.Order, context.Payment, url);

			var payResponse = service.Pay(request);
            var setPaymentOptionsResponse = service.SetPaymentOptions(new SetPaymentOptionsRequest { payKey = payResponse.payKey, senderOptions = new SenderOptions { referrerCode = "Virto_SP" } });
            var executePaymentResponse = service.ExecutePayment(new ExecutePaymentRequest { payKey = payResponse.payKey, actionType = "PAY", requestEnvelope = new RequestEnvelope { errorLanguage = "en_US" } });

			if (executePaymentResponse.error != null && executePaymentResponse.error.Count > 0)
			{
				var sb = new StringBuilder();
				foreach (var error in executePaymentResponse.error)
				{
					sb.AppendLine(error.message);
				}
				retVal.Error = sb.ToString();
				retVal.NewPaymentStatus = PaymentStatus.Voided;
			}
			else
			{
				retVal.OuterId = payResponse.payKey;
				retVal.IsSuccess = true;
				var redirectBaseUrl = GetBaseUrl(Mode);
				retVal.RedirectUrl = string.Format(redirectBaseUrl, retVal.OuterId);
				retVal.NewPaymentStatus = PaymentStatus.Pending;
			}

			return retVal;
		}