/// <summary>
        /// Verifies the authorization of a success return.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <returns>
        /// The <see cref="PayPalExpressTransactionRecord"/>.
        /// </returns>
        public PayPalExpressTransactionRecord VerifySuccessAuthorziation(IInvoice invoice, IPayment payment)
        {
            // We need to process several transactions in a row to get all the data we need to record the
            // transaction with enough information to do refunds / partial refunds
            var record = payment.GetPayPalTransactionRecord();

            if (record == null || record.SetExpressCheckout == null || record.Data.Token.IsNullOrWhiteSpace())
            {
                throw new NullReferenceException("PayPal ExPress Checkout must be setup");
            }

            record = _service.GetExpressCheckoutDetails(payment, record.Data.Token, record);
            if (!record.Success)
            {
                return(record);
            }

            record = Process(payment, _service.DoExpressCheckoutPayment(invoice, payment, record.Data.Token, record.Data.PayerId, record));
            if (!record.Success)
            {
                return(record);
            }

            record = Process(payment, _service.Authorize(invoice, payment, record.Data.Token, record.Data.PayerId, record));
            return(record);
        }
        /// <summary>
        /// Refunds or partially refunds a payment.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="amount">
        /// The amount of the refund.
        /// </param>
        /// <returns>
        /// The <see cref="PayPalExpressTransactionRecord"/>.
        /// </returns>
        public ExpressCheckoutResponse Refund(IInvoice invoice, IPayment payment, decimal amount)
        {
            var record = payment.GetPayPalTransactionRecord();

            // Ensure the currency code
            if (record.Data.CurrencyCode.IsNullOrWhiteSpace())
            {
                var ex = new PayPalApiException("CurrencyCode was not found in payment extended data PayPal transaction data record.  Cannot perform refund.");
                return(_responseFactory.Build(ex));
            }

            // Ensure the transaction id
            if (record.Data.CaptureTransactionId.IsNullOrWhiteSpace())
            {
                var ex = new PayPalApiException("CaptureTransactionId was not found in payment extended data PayPal transaction data record.  Cannot perform refund.");
                return(_responseFactory.Build(ex));
            }

            // Get the decimal configuration for the current currency
            var currencyCodeType   = PayPalApiHelper.GetPayPalCurrencyCode(record.Data.CurrencyCode);
            var basicAmountFactory = new PayPalBasicAmountTypeFactory(currencyCodeType);

            ExpressCheckoutResponse result = null;

            if (amount > payment.Amount)
            {
                amount = payment.Amount;
            }

            try
            {
                var request = new RefundTransactionRequestType
                {
                    InvoiceID     = invoice.PrefixedInvoiceNumber(),
                    PayerID       = record.Data.PayerId,
                    RefundSource  = RefundSourceCodeType.DEFAULT,
                    Version       = record.DoCapture.Version,
                    TransactionID = record.Data.CaptureTransactionId,
                    Amount        = basicAmountFactory.Build(amount)
                };

                var wrapper = new RefundTransactionReq {
                    RefundTransactionRequest = request
                };

                var refundTransactionResponse = GetPayPalService().RefundTransaction(wrapper);

                result = _responseFactory.Build(refundTransactionResponse, record.Data.Token);
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            return(result);
        }
Exemple #3
0
        /// <summary>
        /// Performs a refund or a partial refund.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="amount">
        /// The amount.
        /// </param>
        /// <param name="args">
        /// The processor arguments.
        /// </param>
        /// <returns>
        /// The <see cref="IPaymentResult"/>.
        /// </returns>
        protected override IPaymentResult PerformRefundPayment(IInvoice invoice, IPayment payment, decimal amount, ProcessorArgumentCollection args)
        {
            var record = payment.GetPayPalTransactionRecord();

            if (StringExtensions.IsNullOrWhiteSpace(record.Data.CaptureTransactionId))
            {
                var error = new NullReferenceException("PayPal transaction could not be found and/or deserialized from payment extended data collection");
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, error), invoice, false));
            }

            var attempt = _paypalApiService.ExpressCheckout.Refund(invoice, payment, amount);

            // store the transaction
            var refundTransActions = record.RefundTransactions.ToList();

            refundTransActions.Add(attempt);
            record.RefundTransactions = refundTransActions;

            if (!attempt.Success())
            {
                // In the case of a failure, package up the exception so we can bubble it up.
                var ex = new PayPalApiException("PayPal Checkout Express refund response ACK was not Success");
                if (record.SetExpressCheckout.ErrorTypes.Any())
                {
                    ex.ErrorTypes = record.SetExpressCheckout.ErrorTypes;
                }

                // ensure that transaction is stored in the payment
                payment.SavePayPalTransactionRecord(record);
                GatewayProviderService.Save(payment);

                return(new PaymentResult(Attempt <IPayment> .Fail(payment, ex), invoice, false));
            }

            foreach (var applied in payment.AppliedPayments())
            {
                applied.TransactionType = AppliedPaymentType.Refund;
                applied.Amount          = 0;
                applied.Description    += " - Refunded";
                this.GatewayProviderService.Save(applied);
            }

            payment.Amount = payment.Amount - amount;

            if (payment.Amount != 0)
            {
                this.GatewayProviderService.ApplyPaymentToInvoice(payment.Key, invoice.Key, AppliedPaymentType.Debit, "To show partial payment remaining after refund", payment.Amount);
            }

            this.GatewayProviderService.Save(payment);

            return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, false));
        }
        /// <summary>
        /// The capture success.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="amount">
        /// The amount.
        /// </param>
        /// <param name="isPartialPayment">
        /// The is partial payment.
        /// </param>
        /// <returns>
        /// The <see cref="ExpressCheckoutResponse"/>.
        /// </returns>
        public PayPalExpressTransactionRecord Capture(IInvoice invoice, IPayment payment, decimal amount, bool isPartialPayment)
        {
            // Get the transaction record
            var record = payment.GetPayPalTransactionRecord();

            ExpressCheckoutResponse result = null;

            try
            {
                var amountFactory = new PayPalBasicAmountTypeFactory(PayPalApiHelper.GetPayPalCurrencyCode(invoice.CurrencyCode));

                var authorizationId = record.Data.AuthorizationTransactionId;

                // do express checkout
                var request = new DoCaptureRequestType()
                {
                    AuthorizationID = authorizationId,
                    Amount          = amountFactory.Build(amount),
                    CompleteType    = isPartialPayment ? CompleteCodeType.NOTCOMPLETE : CompleteCodeType.COMPLETE
                };

                var doCaptureReq = new DoCaptureReq()
                {
                    DoCaptureRequest = request
                };

                var service           = GetPayPalService();
                var doCaptureResponse = service.DoCapture(doCaptureReq);
                result = _responseFactory.Build(doCaptureResponse, record.Data.Token);

                if (result.Success())
                {
                    var transactionId = doCaptureResponse.DoCaptureResponseDetails.PaymentInfo.TransactionID;
                    record.Data.CaptureTransactionId = transactionId;
                }
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            record.DoCapture = result;
            record.Success   = result.Success();
            return(record);
        }
        /// <summary>
        /// Verifies the authorization of a success return.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <returns>
        /// The <see cref="PayPalExpressTransactionRecord"/>.
        /// </returns>
        public PayPalExpressTransactionRecord VerifySuccessAuthorziation(IInvoice invoice, IPayment payment)
        {
            // We need to process several transactions in a row to get all the data we need to record the
            // transaction with enough information to do refunds / partial refunds
            var record = payment.GetPayPalTransactionRecord();
            if (record == null || record.SetExpressCheckout == null || record.Data.Token.IsNullOrWhiteSpace())
            {
                throw new NullReferenceException("PayPal ExPress Checkout must be setup");
            }

            record = _service.GetExpressCheckoutDetails(payment, record.Data.Token, record);
            if (!record.Success) return record;

            record = Process(payment, _service.DoExpressCheckoutPayment(invoice, payment, record.Data.Token, record.Data.PayerId, record));
            if (!record.Success) return record;

            record = Process(payment, _service.Authorize(invoice, payment, record.Data.Token, record.Data.PayerId, record));
            return record;
        }
        /// <summary>
        /// Performs a refund or a partial refund.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="amount">
        /// The amount.
        /// </param>
        /// <param name="args">
        /// The processor arguments.
        /// </param>
        /// <returns>
        /// The <see cref="IPaymentResult"/>.
        /// </returns>
        protected override IPaymentResult PerformRefundPayment(IInvoice invoice, IPayment payment, decimal amount, ProcessorArgumentCollection args)
        {
            var record = payment.GetPayPalTransactionRecord();

            if (StringExtensions.IsNullOrWhiteSpace(record.Data.CaptureTransactionId))
            {
                var error = new NullReferenceException("PayPal transaction could not be found and/or deserialized from payment extended data collection");
                return new PaymentResult(Attempt<IPayment>.Fail(payment, error), invoice, false);
            }

            var attempt = _paypalApiService.ExpressCheckout.Refund(invoice, payment, amount);

            // store the transaction
            var refundTransActions = record.RefundTransactions.ToList();
            refundTransActions.Add(attempt);
            record.RefundTransactions = refundTransActions;

            if (!attempt.Success())
            {
                // In the case of a failure, package up the exception so we can bubble it up.
                var ex = new PayPalApiException("PayPal Checkout Express refund response ACK was not Success");
                if (record.SetExpressCheckout.ErrorTypes.Any()) ex.ErrorTypes = record.SetExpressCheckout.ErrorTypes;

                // ensure that transaction is stored in the payment
                payment.SavePayPalTransactionRecord(record);
                GatewayProviderService.Save(payment);

                return new PaymentResult(Attempt<IPayment>.Fail(payment, ex), invoice, false);
            }

            foreach (var applied in payment.AppliedPayments())
            {
                applied.TransactionType = AppliedPaymentType.Refund;
                applied.Amount = 0;
                applied.Description += " - Refunded";
                this.GatewayProviderService.Save(applied);
            }

            payment.Amount = payment.Amount - amount;

            if (payment.Amount != 0)
            {
                this.GatewayProviderService.ApplyPaymentToInvoice(payment.Key, invoice.Key, AppliedPaymentType.Debit, "To show partial payment remaining after refund", payment.Amount);
            }

            this.GatewayProviderService.Save(payment);

            return new PaymentResult(Attempt<IPayment>.Succeed(payment), invoice, false);
        }
        /// <summary>
        /// Refunds or partially refunds a payment.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="amount">
        /// The amount of the refund.
        /// </param>
        /// <returns>
        /// The <see cref="PayPalExpressTransactionRecord"/>.
        /// </returns>
        public ExpressCheckoutResponse Refund(IInvoice invoice, IPayment payment, decimal amount)
        {
            var record = payment.GetPayPalTransactionRecord();

            // Ensure the currency code
            if (record.Data.CurrencyCode.IsNullOrWhiteSpace())
            {
                var ex = new PayPalApiException("CurrencyCode was not found in payment extended data PayPal transaction data record.  Cannot perform refund.");
                return _responseFactory.Build(ex);
            }

            // Ensure the transaction id
            if (record.Data.CaptureTransactionId.IsNullOrWhiteSpace())
            {
                var ex = new PayPalApiException("CaptureTransactionId was not found in payment extended data PayPal transaction data record.  Cannot perform refund.");
                return _responseFactory.Build(ex);
            }

            // Get the decimal configuration for the current currency
            var currencyCodeType = PayPalApiHelper.GetPayPalCurrencyCode(record.Data.CurrencyCode);
            var basicAmountFactory = new PayPalBasicAmountTypeFactory(currencyCodeType);

            ExpressCheckoutResponse result = null;

            if (amount > payment.Amount) amount = payment.Amount;

            try
            {
                var request = new RefundTransactionRequestType
                    {
                        InvoiceID = invoice.PrefixedInvoiceNumber(),
                        PayerID = record.Data.PayerId,
                        RefundSource = RefundSourceCodeType.DEFAULT,
                        Version = record.DoCapture.Version,
                        TransactionID = record.Data.CaptureTransactionId,
                        Amount = basicAmountFactory.Build(amount)
                    };

                var wrapper = new RefundTransactionReq { RefundTransactionRequest = request };

                var refundTransactionResponse = GetPayPalService().RefundTransaction(wrapper);

                result = _responseFactory.Build(refundTransactionResponse, record.Data.Token);
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            return result;
        }
        /// <summary>
        /// The capture success.
        /// </summary>
        /// <param name="invoice">
        /// The invoice.
        /// </param>
        /// <param name="payment">
        /// The payment.
        /// </param>
        /// <param name="amount">
        /// The amount.
        /// </param>
        /// <param name="isPartialPayment">
        /// The is partial payment.
        /// </param>
        /// <returns>
        /// The <see cref="ExpressCheckoutResponse"/>.
        /// </returns>
        public PayPalExpressTransactionRecord Capture(IInvoice invoice, IPayment payment, decimal amount, bool isPartialPayment)
        {
            // Get the transaction record
            var record = payment.GetPayPalTransactionRecord();

            ExpressCheckoutResponse result = null;

            try
            {
                var amountFactory = new PayPalBasicAmountTypeFactory(PayPalApiHelper.GetPayPalCurrencyCode(invoice.CurrencyCode));

                var authorizationId = record.Data.AuthorizationTransactionId;

                // do express checkout
                var request = new DoCaptureRequestType()
                {
                    AuthorizationID = authorizationId,
                    Amount = amountFactory.Build(amount),
                    CompleteType = isPartialPayment ? CompleteCodeType.NOTCOMPLETE : CompleteCodeType.COMPLETE
                };

                var doCaptureReq = new DoCaptureReq() { DoCaptureRequest = request };

                var service = GetPayPalService();
                var doCaptureResponse = service.DoCapture(doCaptureReq);
                result = _responseFactory.Build(doCaptureResponse, record.Data.Token);

                if (result.Success())
                {
                    var transactionId = doCaptureResponse.DoCaptureResponseDetails.PaymentInfo.TransactionID;
                    record.Data.CaptureTransactionId = transactionId;
                }
            }
            catch (Exception ex)
            {
                result = _responseFactory.Build(ex);
            }

            record.DoCapture = result;
            record.Success = result.Success();
            return record;
        }