/// <summary>
        /// Performs the setup for an express checkout.
        /// </summary>
        /// <param name="invoice">
        /// The <see cref="IInvoice"/>.
        /// </param>
        /// <param name="payment">
        /// The <see cref="IPayment"/>
        /// </param>
        /// <param name="returnUrl">
        /// The return URL.
        /// </param>
        /// <param name="cancelUrl">
        /// The cancel URL.
        /// </param>
        /// <returns>
        /// The <see cref="ExpressCheckoutResponse"/>.
        /// </returns>
        protected virtual PayPalExpressTransactionRecord SetExpressCheckout(IInvoice invoice, IPayment payment, string returnUrl, string cancelUrl)
        {
            var record = new PayPalExpressTransactionRecord
            {
                Success = true,
                Data    = { Authorized = false, CurrencyCode = invoice.CurrencyCode }
            };

            var factory = new PayPalPaymentDetailsTypeFactory(new PayPalFactorySettings {
                WebsiteUrl = _websiteUrl
            });
            var paymentDetailsType = factory.Build(invoice, PaymentActionCodeType.ORDER);

            // The API requires this be in a list
            var paymentDetailsList = new List <PaymentDetailsType>()
            {
                paymentDetailsType
            };

            // ExpressCheckout details
            var ecDetails = new SetExpressCheckoutRequestDetailsType()
            {
                ReturnURL       = returnUrl,
                CancelURL       = cancelUrl,
                PaymentDetails  = paymentDetailsList,
                AddressOverride = "1"
            };

            // Trigger the event to allow for overriding ecDetails
            var ecdOverride = new PayPalExpressCheckoutRequestDetailsOverride(invoice, payment, ecDetails);

            SettingCheckoutRequestDetails.RaiseEvent(new ObjectEventArgs <PayPalExpressCheckoutRequestDetailsOverride>(ecdOverride), this);

            // The ExpressCheckoutRequest
            var request = new SetExpressCheckoutRequestType
            {
                Version = Version,
                SetExpressCheckoutRequestDetails = ecdOverride.ExpressCheckoutDetails
            };

            // Crete the wrapper for Express Checkout
            var wrapper = new SetExpressCheckoutReq
            {
                SetExpressCheckoutRequest = request
            };

            try
            {
                var service  = GetPayPalService();
                var response = service.SetExpressCheckout(wrapper);

                record.SetExpressCheckout = _responseFactory.Build(response, response.Token);
                if (record.SetExpressCheckout.Success())
                {
                    record.Data.Token = response.Token;
                    record.SetExpressCheckout.RedirectUrl = GetRedirectUrl(response.Token);
                }
                else
                {
                    foreach (var et in record.SetExpressCheckout.ErrorTypes)
                    {
                        var code = et.ErrorCode;
                        var sm   = et.ShortMessage;
                        var lm   = et.LongMessage;
                        MultiLogHelper.Warn <PayPalExpressCheckoutService>(string.Format("{0} {1} {2}", code, lm, sm));
                    }

                    record.Success = false;
                }
            }
            catch (Exception ex)
            {
                record.Success            = false;
                record.SetExpressCheckout = _responseFactory.Build(ex);
            }

            return(record);
        }
        /// <summary>
        /// Validates a successful response.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="token">
        /// The token.
        /// </param>
        /// <param name="payerId">
        /// The payer id.
        /// </param>
        /// <param name="record">
        /// The record.
        /// </param>
        /// <returns>
        /// The <see cref="ExpressCheckoutResponse"/>.
        /// </returns>
        /// <remarks>
        /// PayPal returns to the success URL even if the payment was declined. e.g.  The success URL represents a successful transaction
        /// not a successful payment so we need to do another request to verify the payment was completed and get additional information
        /// such as the transaction id so we can do refunds etc.
        /// </remarks>
        internal PayPalExpressTransactionRecord Authorize(IInvoice invoice, IPayment payment, string token, string payerId, PayPalExpressTransactionRecord record)
        {
            // Now we have to get the transaction details for the successful payment
            ExpressCheckoutResponse result = null;

            try
            {
                // do authorization
                var service = GetPayPalService();
                var doAuthorizationResponse = service.DoAuthorization(new DoAuthorizationReq
                {
                    DoAuthorizationRequest = new DoAuthorizationRequestType
                    {
                        TransactionID = record.Data.CheckoutPaymentTransactionId,
                        Amount        = new BasicAmountType(PayPalApiHelper.GetPayPalCurrencyCode(record.Data.CurrencyId), record.Data.AuthorizedAmount)
                    }
                });

                result = _responseFactory.Build(doAuthorizationResponse, token);
                if (result.Success())
                {
                    record.Data.Authorized = true;
                    record.Data.AuthorizationTransactionId = doAuthorizationResponse.TransactionID;
                }
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            record.DoAuthorization = result;

            return(record);
        }
        /// <summary>
        /// The do express checkout payment.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="token">
        /// The token.
        /// </param>
        /// <param name="payerId">
        /// The payer id.
        /// </param>
        /// <param name="record">
        /// The record of the transaction.
        /// </param>
        /// <returns>
        /// The <see cref="PayPalExpressTransactionRecord"/>.
        /// </returns>
        internal PayPalExpressTransactionRecord DoExpressCheckoutPayment(IInvoice invoice, IPayment payment, string token, string payerId, PayPalExpressTransactionRecord record)
        {
            var factory = new PayPalPaymentDetailsTypeFactory();

            ExpressCheckoutResponse result = null;

            try
            {
                // do express checkout
                var request = new DoExpressCheckoutPaymentRequestType(
                    new DoExpressCheckoutPaymentRequestDetailsType
                {
                    Token          = token,
                    PayerID        = payerId,
                    PaymentDetails =
                        new List <PaymentDetailsType>
                    {
                        factory.Build(invoice, PaymentActionCodeType.ORDER)
                    }
                });

                var doExpressCheckoutPayment = new DoExpressCheckoutPaymentReq
                {
                    DoExpressCheckoutPaymentRequest = request
                };

                var service  = GetPayPalService();
                var response = service.DoExpressCheckoutPayment(doExpressCheckoutPayment);
                result = _responseFactory.Build(response, token);

                var transactionId = response.DoExpressCheckoutPaymentResponseDetails.PaymentInfo[0].TransactionID;
                var currency      = response.DoExpressCheckoutPaymentResponseDetails.PaymentInfo[0].GrossAmount.currencyID;
                var amount        = response.DoExpressCheckoutPaymentResponseDetails.PaymentInfo[0].GrossAmount.value;

                record.Data.CheckoutPaymentTransactionId = transactionId;
                record.Data.CurrencyId       = currency.ToString();
                record.Data.AuthorizedAmount = amount;
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            record.DoExpressCheckoutPayment = result;
            record.Success = result.Success();

            return(record);
        }
        /// <summary>
        /// Performs the GetExpressCheckoutDetails operation.
        /// </summary>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="token">
        /// The token.
        /// </param>
        /// <param name="record">
        /// The record.
        /// </param>
        /// <returns>
        /// The <see cref="PayPalExpressTransactionRecord"/>.
        /// </returns>
        internal PayPalExpressTransactionRecord GetExpressCheckoutDetails(IPayment payment, string token, PayPalExpressTransactionRecord record)
        {
            record.Success = true;
            ExpressCheckoutResponse result = null;

            try
            {
                var getDetailsRequest = new GetExpressCheckoutDetailsReq
                {
                    GetExpressCheckoutDetailsRequest = new GetExpressCheckoutDetailsRequestType(token)
                };

                var service  = GetPayPalService();
                var response = service.GetExpressCheckoutDetails(getDetailsRequest);
                result = _responseFactory.Build(response, token);

                if (result.Success())
                {
                    record.Data.PayerId = response.GetExpressCheckoutDetailsResponseDetails.PayerInfo.PayerID;
                }
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            record.GetExpressCheckoutDetails = result;
            record.Success = result.Success();
            return(record);
        }
 /// <summary>
 /// Processes the payment.
 /// </summary>
 /// <param name="payment">
 /// The payment.
 /// </param>
 /// <param name="record">
 /// The record.
 /// </param>
 /// <returns>
 /// The <see cref="PayPalExpressTransactionRecord"/>.
 /// </returns>
 private PayPalExpressTransactionRecord Process(IPayment payment, PayPalExpressTransactionRecord record)
 {
     payment.SavePayPalTransactionRecord(record);
     return(record);
 }
        /// <summary>
        /// Performs the setup for an express checkout.
        /// </summary>
        /// <param name="invoice">
        /// The <see cref="IInvoice"/>.
        /// </param>
        /// <param name="payment">
        /// The <see cref="IPayment"/>
        /// </param>
        /// <param name="returnUrl">
        /// The return URL.
        /// </param>
        /// <param name="cancelUrl">
        /// The cancel URL.
        /// </param>
        /// <returns>
        /// The <see cref="ExpressCheckoutResponse"/>.
        /// </returns>
        protected virtual PayPalExpressTransactionRecord SetExpressCheckout(IInvoice invoice, IPayment payment, string returnUrl, string cancelUrl)
        {
            var record = new PayPalExpressTransactionRecord
            {
                Success = true,
                Data    = { Authorized = false, CurrencyCode = invoice.CurrencyCode }
            };

            var factory = new PayPalPaymentDetailsTypeFactory(new PayPalFactorySettings {
                WebsiteUrl = _websiteUrl
            });
            var paymentDetailsType = factory.Build(invoice, PaymentActionCodeType.ORDER);

            // The API requires this be in a list
            var paymentDetailsList = new List <PaymentDetailsType>()
            {
                paymentDetailsType
            };

            // ExpressCheckout details
            //// We do not want the customer to be able to reset their shipping address at PayPal
            //// due to the fact that it could affect shipping charges and in some cases tax rates.
            //// This is the AddressOverride = "0" - NOT WORKING!
            var ecDetails = new SetExpressCheckoutRequestDetailsType()
            {
                ReturnURL       = returnUrl,
                CancelURL       = cancelUrl,
                PaymentDetails  = paymentDetailsList,
                AddressOverride = "0"
            };

            // Trigger the event to allow for overriding ecDetails
            var ecdOverride = new PayPalExpressCheckoutRequestDetailsOverride(invoice, payment, ecDetails);

            SettingCheckoutRequestDetails.RaiseEvent(new ObjectEventArgs <PayPalExpressCheckoutRequestDetailsOverride>(ecdOverride), this);

            // The ExpressCheckoutRequest
            var request = new SetExpressCheckoutRequestType
            {
                Version = Version,
                SetExpressCheckoutRequestDetails = ecdOverride.ExpressCheckoutDetails
            };

            // Crete the wrapper for Express Checkout
            var wrapper = new SetExpressCheckoutReq
            {
                SetExpressCheckoutRequest = request
            };

            try
            {
                var service  = GetPayPalService();
                var response = service.SetExpressCheckout(wrapper);
                record.SetExpressCheckout             = _responseFactory.Build(response, response.Token);
                record.Data.Token                     = response.Token;
                record.SetExpressCheckout.RedirectUrl = GetRedirectUrl(response.Token);
            }
            catch (Exception ex)
            {
                record.Success            = false;
                record.SetExpressCheckout = _responseFactory.Build(ex);
            }

            return(record);
        }