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); }
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); }
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); }