예제 #1
0
        private void InvoicePaymentFailed(DateTime?created, StripeInvoice invoice)
        {
            var charge = _paymentProcessorService.GetCharge(invoice.Charge);
            var notes  = "No Stripe Failure Code";

            if (charge != null)
            {
                notes = $"{charge.FailureCode ?? "No Stripe Failure Code"}: {charge.FailureMessage ?? "No Stripe Failure Message"}";
            }
            _mpDonorRepository.ProcessRecurringGiftDecline(invoice.Subscription, notes);
            var gift = _mpDonorRepository.GetRecurringGiftForSubscription(invoice.Subscription);

            if (gift.ConsecutiveFailureCount > 2)
            {
                var subscription = _paymentProcessorService.CancelSubscription(gift.StripeCustomerId, gift.SubscriptionId);
                _paymentProcessorService.CancelPlan(subscription.Plan.Id);
                _mpDonorRepository.CancelRecurringGift(gift.RecurringGiftId.Value);
            }
        }
        private DonationDTO HandleDonationNotFoundException(StripeTransfer transfer, StripeRefund refund, string paymentId, DonationNotFoundException e, StripeCharge charge)
        {
            DonationDTO donation;

            if (refund != null)
            {
                _logger.Warn($"Payment not found for refund {paymentId} on transfer {transfer.Id} - may be a refund due to a bank account error");
                // If this is a refund that doesn't exist in MP, create it, assuming it is a refund due to a bank account error (NSF, etc)
                if (_donationService.CreateDonationForBankAccountErrorRefund(refund) != null)
                {
                    donation = _donationService.GetDonationByProcessorPaymentId(paymentId);
                    _logger.Debug($"Updating charge id {charge.Id} to Declined status");
                    _donationService.UpdateDonationStatus(refund.Data[0].ChargeId, _donationStatusDeclined, refund.Data[0].BalanceTransaction.Created);
                }
                else
                {
                    _logger.Error($"Payment not found for refund {paymentId} on transfer {transfer.Id}, probably not a bank account error", e);
                    // ReSharper disable once PossibleIntendedRethrow
                    throw e;
                }
            }
            else
            {
                _logger.Warn($"Payment not found for charge {paymentId} on transfer {transfer.Id} - may be an ACH recurring gift that has not yet processed");
                var stripeCharge = _paymentProcessorService.GetCharge(charge.Id);
                if (stripeCharge?.Source != null && "bank_account".Equals(stripeCharge.Source.Object) && stripeCharge.HasInvoice())
                {
                    // We're making an assumption that if an ACH payment is included in a transfer,
                    // and if we don't have the corresponding Donation in our system yet, that
                    // this is a mistake.  For instance, events delivered out of order from Stripe, and
                    // we received the transfer.paid before the invoice.payment_succeeded.
                    // In this scenario, we will go ahead and create the donation.
                    if (_donationService.CreateDonationForInvoice(stripeCharge.Invoice) != null)
                    {
                        _logger.Debug($"Creating donation for recurring gift payment {charge.Id}");
                        donation = _donationService.GetDonationByProcessorPaymentId(paymentId);
                    }
                    else
                    {
                        _logger.Error($"Donation not found for charge {charge.Id} on transfer {transfer.Id}, and failed to create a donation", e);
                        // ReSharper disable once PossibleIntendedRethrow
                        throw e;
                    }
                }
                else
                {
                    _logger.Error($"Donation not found for charge {charge.Id} on transfer {transfer.Id}, charge does not appear to be related to an ACH recurring gift");
                    // ReSharper disable once PossibleIntendedRethrow
                    throw e;
                }
            }
            return(donation);
        }
예제 #3
0
        private StripeCharge GetStripeCharge(DonationDTO donation)
        {
            if (string.IsNullOrWhiteSpace(donation.Source.PaymentProcessorId))
            {
                return(null);
            }

            // If it is a positive amount, it means it's a Charge, otherwise it's a Refund
            if (donation.Amount >= 0)
            {
                return(_paymentService.GetCharge(donation.Source.PaymentProcessorId));
            }

            var refund = _paymentService.GetRefund(donation.Source.PaymentProcessorId);

            if (refund != null && refund.Charge != null)
            {
                return(refund.Charge);
            }

            return(null);
        }
예제 #4
0
        public PaymentDetailDTO GetPaymentDetails(int paymentId, int invoiceId, string token, bool useInvoiceContact = false)
        {
            var invoice = _invoiceRepository.GetInvoice(invoiceId);
            var me      = new MpMyContact();

            if (useInvoiceContact)
            {
                me = _contactRepository.GetContactById(invoice.PurchaserContactId);
            }
            else
            {
                me = _contactRepository.GetMyProfile(token);
            }

            var payments = _paymentRepository.GetPaymentsForInvoice(invoiceId);

            var currentPayment = payments.Where(p => p.PaymentId == paymentId && p.ContactId == me.Contact_ID).ToList();

            if (currentPayment.Any() || paymentId == 0)
            {
                var          totalPaymentsMade = payments.Sum(p => p.PaymentTotal);
                var          leftToPay         = invoice.InvoiceTotal - totalPaymentsMade;
                StripeCharge charge            = null;
                if (payments.Count > 0)
                {
                    charge = _paymentProcessorService.GetCharge(payments.First().TransactionCode);
                }
                return(new PaymentDetailDTO()
                {
                    PaymentAmount = currentPayment.Any() ? currentPayment.First().PaymentTotal : 0M,
                    RecipientEmail = me.Email_Address,
                    TotalToPay = leftToPay,
                    InvoiceTotal = invoice.InvoiceTotal,
                    RecentPaymentId = payments.Any() ? payments.First().PaymentId : 0,
                    RecentPaymentAmount = payments.Any() ? payments.First().PaymentTotal : 0,
                    RecentPaymentLastFour = charge != null ? charge.Source?.AccountNumberLast4 : ""
                });
            }
            throw new Exception("No Payment found for " + me.Email_Address + " with id " + paymentId);
        }