static StripeTransaction StripeRefundToStripeTransaction(StripeRefund r) { var trans = new StripeTransaction() { APITransactionId = r.Id, TransactionType = r.Object, Description = r.Description, CreatedTime = r.Created.ToUniversalTime(), Amount = (-1) * r.Amount / 100m, Currency = r.Currency, FeeAmount = r.BalanceTransaction?.Fee / 100m, FeeDetails = JsonConvert.SerializeObject(r.BalanceTransaction?.FeeDetails), TaxAmount = r.Charge?.Invoice?.Tax / 100m, LiveMode = r.Charge?.LiveMode, Status = r.Status, CustomerStripeId = r.Charge?.CustomerId, Captured = r.Charge?.Captured, Card = JsonConvert.SerializeObject(r.Charge?.Source?.Card), InvoiceId = r.Charge?.InvoiceId, CardBrand = r.Charge?.Source?.Card?.Brand, DestinationAccountId = r.Charge?.Destination?.Id, TransferId = r.Charge?.TransferId, TransferGroup = r.Charge?.TransferGroup, Metadata = JsonConvert.SerializeObject(r.Metadata), RefundChargeId = r.ChargeId }; return(trans); }
private async Task PerformTest(string apiKey) { this.apiKeyRepository.Setup(v => v.GetApiKey(UserType.StandardUser)).Returns(apiKey); var expectedOptions = new StripeRefundCreateOptions { Amount = TotalRefundAmount.Value, Reason = "requested_by_customer", Metadata = new Dictionary <string, string> { { CreateStripeRefund.EnactingUserIdMetadataKey, UserId.ToString() }, } }; var stripeRefund = new StripeRefund { Id = CustomerId }; this.stripeService.Setup(v => v.RefundChargeAsync( StripeChargeId, It.Is <StripeRefundCreateOptions>( x => JsonConvert.SerializeObject(x, Formatting.None) == JsonConvert.SerializeObject(expectedOptions, Formatting.None)), apiKey)) .ReturnsAsync(stripeRefund) .Verifiable(); await this.target.ExecuteAsync(UserId, StripeChargeId, TotalRefundAmount, RefundCreditReason.RequestedByCustomer, UserType.StandardUser); this.stripeService.Verify(); }
private PaymentDTO HandlePaymentNotFoundException(StripeTransfer transfer, StripeRefund refund, string paymentId, PaymentNotFoundException e, StripeCharge charge) { PaymentDTO payment; 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 (_paymentService.CreatePaymentForBankAccountErrorRefund(refund) != null) { payment = _paymentService.GetPaymentByTransactionCode(paymentId); payment.Status = DonationStatus.Declined; // make sure to set the correct status. _logger.Debug($"Updating charge id {charge.Id} to Declined status"); _paymentService.UpdatePaymentStatus(payment.PaymentId, _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"); _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(payment); }
static StripeRefundTransaction StripeRefundToStripeTransaction(StripeRefund r) { var trans = new StripeRefundTransaction() { RefundId = r.Id, TransactionType = r.Object, Amount = (-1) * r.Amount / 100m, Reason = r.Reason, Status = r.Status, BalanceTransactionId = r.BalanceTransactionId, BalanceTransaction = JsonConvert.SerializeObject(r.BalanceTransaction), FailureBalanceTransactionId = r.FailureBalanceTransactionId, FailureBalanceTransaction = processNull(JsonConvert.SerializeObject(r.FailureBalanceTransaction)), FailureReason = r.FailureReason, ChargeID = r.ChargeId, Charge = JsonConvert.SerializeObject(r.Charge), CreatedTime = r.Created.ToUniversalTime(), Currency = r.Currency, Description = r.Description, Metadata = JsonConvert.SerializeObject(r.Metadata), ReceiptNumber = r.ReceiptNumber }; return(trans); }
public static string RefundToUser(string chargeId, bool isFullRefund, int specificAmount) { try { string stripekey = ConfigurationManager.AppSettings["AdminStripeApiKey"]; StripeConfiguration.SetApiKey(stripekey); StripeRefundCreateOptions refundOptions; if (isFullRefund == true) { refundOptions = new StripeRefundCreateOptions() { Reason = StripeRefundReasons.RequestedByCustomer, //RefundApplicationFee = true }; } else { refundOptions = new StripeRefundCreateOptions() { Reason = StripeRefundReasons.RequestedByCustomer, //RefundApplicationFee = true, Amount = specificAmount * 100 }; } var refundService = new StripeRefundService(); StripeRefund refund = refundService.Create(chargeId, refundOptions); return(refund.Id); } catch (Exception ex) { Common.ExcepLog(ex); return(null); } }
public RefundResponse CreateResponse(StripeRefund refundResp) { return(_refundResponseBuilder .Create() .RefundId(refundResp.Id) .ChargeId(refundResp.ChargeId) .Amount(refundResp.Amount) .Status(refundResp.Status) .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 StripeRefund CallStripeRefund(string stripeChargeId, double diffPrice) { var refundService = new StripeRefundService(); StripeRefund refund = refundService.Create(stripeChargeId, new StripeRefundCreateOptions() { Amount = Convert.ToInt32(diffPrice * 100), Reason = StripeRefundReasons.RequestedByCustomer }); return(refund); }
public int?CreatePaymentForBankAccountErrorRefund(StripeRefund refund) { if (refund.Data[0].BalanceTransaction == null || !"payment_failure_refund".Equals(refund.Data[0].BalanceTransaction.Type)) { _logger.Error($"Balance transaction was not set, or was not a payment_failure_refund for refund ID {refund.Data[0].Id}"); return(null); } if (string.IsNullOrWhiteSpace(refund.Data[0].Charge?.Id)) { _logger.Error($"No associated Charge for Refund {refund.Data[0].Id}"); return(null); } MpPayment payment; try { payment = _paymentRepository.GetPaymentByTransactionCode(refund.Data[0].Charge.Id); } catch (PaymentNotFoundException) { _logger.Error($"No Payment with payment processor ID {refund.Data[0].Charge.Id} in MP for Refund {refund.Data[0].Id}"); return(null); } _paymentRepository.UpdatePaymentStatus(payment.PaymentId, (int)DonationStatus.Declined); // update the original payment to declined var paymentReverse = new MpPayment { InvoiceNumber = payment.InvoiceNumber, PaymentDate = DateTime.Now, PaymentStatus = (int)DonationStatus.Declined, ContactId = _bankErrorRefundContactId, ProcessorFeeAmount = refund.Data[0].BalanceTransaction.Fee / Constants.StripeDecimalConversionValue, Notes = $"Reversed from PaymentID {payment.PaymentId}", PaymentTypeId = payment.PaymentTypeId, TransactionCode = refund.Data[0].Id, PaymentTotal = -(int.Parse(refund.Data[0].Amount) / Constants.StripeDecimalConversionValue), BatchId = payment.BatchId }; var invoicedetail = _invoiceRepository.GetInvoiceDetailForInvoice(Convert.ToInt32(payment.InvoiceNumber)); var detail = new MpPaymentDetail { PaymentAmount = -(int.Parse(refund.Data[0].Amount) / Constants.StripeDecimalConversionValue), InvoiceDetailId = invoicedetail.InvoiceDetailId, Payment = paymentReverse, CongregationId = _contactRepository.GetContactById(invoicedetail.RecipientContactId).Congregation_ID ?? _configWrapper.GetConfigIntValue("Congregation_Default_ID") }; return(_paymentRepository.CreatePaymentAndDetail(detail).Value.PaymentId); }
public static StripeRefund RefundCharge(string chargeId) { try { var refundService = new StripeRefundService(); StripeRefund refund = refundService.Create(chargeId); return(refund); } catch (Exception ex) { var exp = ex.Message.ToString(); return(null); } }
public static StripeRefund RefundCharge(string token, int amount) { // Set your secret key: remember to change this to your live secret key in production // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.SetApiKey(MasterStrings.StripeSecretKey); var refundOptions = new StripeRefundCreateOptions() { Amount = amount, Reason = "requested_by_customer" }; var refundService = new StripeRefundService(); StripeRefund refund = refundService.Create(token, refundOptions); return(refund); }
private DonationBatchDTO CreateBatchDTOFromCharges(List <StripeCharge> charges, string batchName, DateTime?eventTimestamp, StripeTransfer transfer, ref TransferPaidResponseDTO response) { var now = DateTime.Now; var batch = new DonationBatchDTO() { BatchName = batchName, SetupDateTime = now, BatchTotalAmount = 0, ItemCount = 0, BatchEntryType = _batchEntryTypePaymentProcessor, FinalizedDateTime = now, DepositId = null, ProcessorTransferId = transfer.Id }; response.TotalTransactionCount += charges.Count; // Sort charges so we process refunds for payments in the same transfer after the actual payment is processed var sortedCharges = charges.OrderBy(charge => charge.Type); foreach (var charge in sortedCharges) { try { var paymentId = charge.Id; StripeRefund refund = null; if ("refund".Equals(charge.Type)) // Credit Card Refund { refund = _paymentProcessorService.GetChargeRefund(charge.Id); paymentId = refund.Data[0].Id; } else if ("payment_refund".Equals(charge.Type)) // Bank Account Refund { var refundData = _paymentProcessorService.GetRefund(charge.Id); refund = new StripeRefund { Data = new List <StripeRefundData> { refundData } }; } //TODO: Pull these out into methods? if (charge.Metadata != null && charge.Metadata.ContainsKey("crossroads_transaction_type") && charge.Metadata["crossroads_transaction_type"].ToString() == "payment") { PaymentDTO payment; try { payment = _paymentService.GetPaymentByTransactionCode(paymentId); } catch (PaymentNotFoundException e) { payment = HandlePaymentNotFoundException(transfer, refund, paymentId, e, charge); } if (payment.BatchId != null) { var b = _paymentService.GetPaymentBatch(payment.BatchId.Value); if (string.IsNullOrWhiteSpace(b.ProcessorTransferId)) { // If this payment exists on another batch that does not have a Stripe transfer ID, we'll move it to our batch instead var msg = $"Charge {charge.Id} already exists on batch {b.Id}, moving to new batch"; _logger.Debug(msg); } else { // If this payment exists on another batch that has a Stripe transfer ID, skip it var msg = $"Charge {charge.Id} already exists on batch {b.Id} with transfer id {b.ProcessorTransferId}"; _logger.Debug(msg); response.FailedUpdates.Add(new KeyValuePair <string, string>(charge.Id, msg)); continue; } } if (payment.Status != DonationStatus.Declined && payment.Status != DonationStatus.Refunded) { _logger.Debug($"Updating charge id {charge.Id} to Deposited status"); _paymentService.UpdatePaymentStatus(payment.PaymentId, _donationStatusDeposited, eventTimestamp); } else { _logger.Debug($"Not updating charge id {charge.Id} to Deposited status - it was already {System.Enum.GetName(typeof(DonationStatus), payment.Status)}"); } response.SuccessfulUpdates.Add(charge.Id); batch.ItemCount++; batch.BatchTotalAmount += (charge.Amount / Constants.StripeDecimalConversionValue); batch.Payments.Add(new PaymentDTO { PaymentId = payment.PaymentId, Amount = charge.Amount, ProcessorFee = charge.Fee, BatchId = payment.BatchId, ContactId = payment.ContactId, InvoiceId = payment.InvoiceId, StripeTransactionId = payment.StripeTransactionId }); batch.BatchFeeTotal = batch.Payments.Sum(f => f.ProcessorFee); } else { DonationDTO donation; try { donation = _donationService.GetDonationByProcessorPaymentId(paymentId); } catch (DonationNotFoundException e) { donation = HandleDonationNotFoundException(transfer, refund, paymentId, e, charge); } if (donation.BatchId != null) { var b = _donationService.GetDonationBatch(donation.BatchId.Value); if (string.IsNullOrWhiteSpace(b.ProcessorTransferId)) { // If this donation exists on another batch that does not have a Stripe transfer ID, we'll move it to our batch instead var msg = $"Charge {charge.Id} already exists on batch {b.Id}, moving to new batch"; _logger.Debug(msg); } else { // If this donation exists on another batch that has a Stripe transfer ID, skip it var msg = $"Charge {charge.Id} already exists on batch {b.Id} with transfer id {b.ProcessorTransferId}"; _logger.Debug(msg); response.FailedUpdates.Add(new KeyValuePair <string, string>(charge.Id, msg)); continue; } } if (donation.Status != DonationStatus.Declined && donation.Status != DonationStatus.Refunded) { _logger.Debug($"Updating charge id {charge.Id} to Deposited status"); _donationService.UpdateDonationStatus(int.Parse(donation.Id), _donationStatusDeposited, eventTimestamp); } else { _logger.Debug($"Not updating charge id {charge.Id} to Deposited status - it was already {System.Enum.GetName(typeof(DonationStatus), donation.Status)}"); } response.SuccessfulUpdates.Add(charge.Id); batch.ItemCount++; batch.BatchTotalAmount += (charge.Amount / Constants.StripeDecimalConversionValue); batch.Donations.Add(new DonationDTO { Id = donation.Id, Amount = charge.Amount, Fee = charge.Fee }); batch.BatchFeeTotal = batch.Donations.Sum(f => f.Fee); } } catch (Exception e) { _logger.Warn("Error updating charge " + charge, e); response.FailedUpdates.Add(new KeyValuePair <string, string>(charge.Id, e.Message)); } } if (response.FailedUpdates.Count > 0) { response.Exception = new ApplicationException("Could not update all charges to 'deposited' status, see message for details"); } return(batch); }
public int Add(AddSubscriptionBookingParams param) { try { using (var transaction = new TransactionScope()) { var bookingCode = Helper.RandomString(Constant.BookingCodeLength); while (IsBookingCodeExists(bookingCode)) { bookingCode = Helper.RandomString(Constant.BookingCodeLength); } param.SubscriptionBookingsObject.BookingCode = bookingCode; // Insert New Bookings DayaxeDbContext.SubscriptionBookings.InsertOnSubmit(param.SubscriptionBookingsObject); Commit(); if (param.SubscriptionBookingDiscounts != null && param.SubscriptionBookingDiscounts.Id > 0) { var subscriptionDiscount = new SubscriptionBookingDiscounts { DiscountId = param.SubscriptionBookingDiscounts.Id, SubscriptionBookingId = param.SubscriptionBookingsObject.Id, SubscriptionId = param.SubscriptionBookingsObject.SubscriptionId }; DayaxeDbContext.SubscriptionBookingDiscounts.InsertOnSubmit(subscriptionDiscount); } // Insert to History for First Cycle var cycle = new SubscriptionCycles { SubscriptionBookingId = param.SubscriptionBookingsObject.Id, StartDate = param.SubscriptionBookingsObject.StartDate, EndDate = param.SubscriptionBookingsObject.EndDate, CancelDate = param.SubscriptionBookingsObject.CancelDate, LastUpdatedBy = param.SubscriptionBookingsObject.LastUpdatedBy, LastUpdatedDate = param.SubscriptionBookingsObject.LastUpdatedDate, Status = param.SubscriptionBookingsObject.Status, Price = param.ActualPrice, MerchantPrice = param.MerchantPrice, PayByCredit = param.PayByCredit, TotalPrice = param.TotalPrice, Quantity = param.SubscriptionBookingsObject.Quantity, StripeChargeId = string.Empty, StripeCouponId = param.SubscriptionBookingsObject.StripeCouponId, StripeInvoiceId = string.Empty, CycleNumber = 1 }; DayaxeDbContext.SubscriptionCycles.InsertOnSubmit(cycle); // Insert Discount for Current Customer active Subscription var discount = new Discounts { DiscountName = string.Format("{0} - {1} {2}", param.SubscriptionName, param.FirstName, param.LastName), Code = string.Format("SUP{0}", Helper.RandomString(8)), StartDate = param.SubscriptionBookingsObject.StartDate, EndDate = param.SubscriptionBookingsObject.EndDate, CodeRequired = true, PercentOff = 100, PromoType = (byte)Enums.PromoType.SubscriptionPromo, MinAmount = 0, IsAllProducts = true, MaxPurchases = (byte)param.MaxPurchases }; DayaxeDbContext.Discounts.InsertOnSubmit(discount); Commit(); // Add Invoices var subscriptionInvoice = new SubscriptionInvoices { SubscriptionCyclesId = cycle.Id, BookingStatus = cycle.Status, Quantity = cycle.Quantity, Price = cycle.Price, MerchantPrice = cycle.MerchantPrice, PayByCredit = cycle.PayByCredit, TotalPrice = cycle.TotalPrice, InvoiceStatus = (int)Enums.InvoiceStatus.Charge, StripeChargeId = cycle.StripeChargeId, ChargeAmount = cycle.Price, StripeRefundId = string.Empty, RefundAmount = 0, RefundCreditAmount = 0, StripeCouponId = cycle.StripeCouponId, CreatedDate = DateTime.UtcNow, CreatedBy = 1 }; DayaxeDbContext.SubscriptionInvoices.InsertOnSubmit(subscriptionInvoice); var discountUsed = new SubsciptionDiscountUseds { CustomerId = param.SubscriptionBookingsObject.CustomerId, DiscountId = discount.Id, SubscriptionBookingId = param.SubscriptionBookingsObject.Id }; DayaxeDbContext.SubsciptionDiscountUseds.InsertOnSubmit(discountUsed); var cusCredits = DayaxeDbContext.CustomerCredits .SingleOrDefault(cc => cc.CustomerId == param.CustomerCreditsObject.CustomerId); // Add Logs when refund by Upgrade to Subscription if (param.RefundCreditByUpgrade > 0) { var creditLogs = new CustomerCreditLogs { Amount = param.RefundCreditByUpgrade, ProductId = 0, BookingId = 0, SubscriptionId = param.SubscriptionBookingsObject.SubscriptionId, CreatedBy = param.CustomerCreditsObject.CustomerId, CreatedDate = DateTime.UtcNow, CreditType = (byte)Enums.CreditType.PartialPuchaseRefund, Description = param.RefundCreditDescription, CustomerId = param.CustomerCreditsObject.CustomerId, ReferralId = param.CustomerCreditsObject.ReferralCustomerId, SubscriptionBookingId = param.SubscriptionBookingsObject.Id, Status = true, GiftCardId = 0 }; DayaxeDbContext.CustomerCreditLogs.InsertOnSubmit(creditLogs); if (cusCredits != null) { cusCredits.Amount += param.RefundCreditByUpgrade; } } // Add Logs when pay by DayAxe Credit if (param.PayByCredit > 0) { var creditLogs = new CustomerCreditLogs { Amount = param.PayByCredit, ProductId = 0, BookingId = 0, SubscriptionId = param.SubscriptionBookingsObject.SubscriptionId, CreatedBy = param.CustomerCreditsObject.CustomerId, CreatedDate = DateTime.UtcNow, CreditType = (byte)Enums.CreditType.Charge, Description = param.Description, CustomerId = param.CustomerCreditsObject.CustomerId, ReferralId = param.CustomerCreditsObject.ReferralCustomerId, SubscriptionBookingId = param.SubscriptionBookingsObject.Id, Status = true, GiftCardId = 0 }; DayaxeDbContext.CustomerCreditLogs.InsertOnSubmit(creditLogs); if (cusCredits != null) { cusCredits.Amount -= param.PayByCredit; } } // First Buy of referral if (param.CustomerCreditsObject != null && param.CustomerCreditsObject.ReferralCustomerId > 0 && ( DayaxeDbContext.Bookings.Count(x => x.CustomerId == param.SubscriptionBookingsObject.CustomerId) == 1 || DayaxeDbContext.SubscriptionBookings.Count(x => x.CustomerId == param.SubscriptionBookingsObject.CustomerId) == 1)) { var logs = DayaxeDbContext.CustomerCreditLogs .Where(ccl => ccl.CustomerId == param.CustomerCreditsObject.ReferralCustomerId && ccl.ReferralId == param.SubscriptionBookingsObject.CustomerId && !ccl.Status) .ToList(); if (logs.Any()) { logs.ForEach(log => { var cus = DayaxeDbContext.CustomerCredits .FirstOrDefault(cc => cc.CustomerId == log.CustomerId); if (cus != null) { cus.Amount += log.Amount; } log.Status = true; }); Commit(); } } // Add to Customer Credit Log var logsReferred = DayaxeDbContext.CustomerCreditLogs .Where(ccl => ccl.ReferralId == param.SubscriptionBookingsObject.CustomerId && !ccl.Status) .ToList(); if (logsReferred.Any()) { logsReferred.ForEach(log => { var cus = DayaxeDbContext.CustomerCredits .FirstOrDefault(cc => cc.CustomerId == log.CustomerId); if (cus != null) { cus.Amount += log.Amount; } log.Status = true; }); } // Insert Schedule var schedules = new Schedules { ScheduleSendType = (int)Enums.ScheduleSendType.IsEmailConfirmSubscription, Name = "Send Email confirm Subscription", Status = (int)Enums.ScheduleType.NotRun, SubscriptionBookingId = param.SubscriptionBookingsObject.Id }; DayaxeDbContext.Schedules.InsertOnSubmit(schedules); // Maybe not use here because flow upgrade to subscription do not use this if (param.BookingId > 0) { var bookings = DayaxeDbContext.Bookings.FirstOrDefault(b => b.BookingId == param.BookingId); if (bookings != null) { var chargePrice = (int)((bookings.TotalPrice - bookings.HotelPrice) * 100); try { bookings.TotalPrice -= bookings.HotelPrice; bookings.PassStatus = (int)Enums.BookingStatus.Active; var discounts = new DiscountBookings { DiscountId = discount.Id, ProductId = bookings.ProductId, BookingId = bookings.BookingId }; DayaxeDbContext.DiscountBookings.InsertOnSubmit(discounts); bookings.IsActiveSubscription = true; string responseString; if (chargePrice > 0) { var chargeService = new StripeChargeService(); StripeCharge charge = chargeService.Capture(bookings.StripeChargeId, chargePrice); responseString = charge.StripeResponse.ResponseJson; } else { var refundOptions = new StripeRefundCreateOptions { Reason = StripeRefundReasons.RequestedByCustomer }; var refundService = new StripeRefundService(); StripeRefund refund = refundService.Create(bookings.StripeChargeId, refundOptions); responseString = refund.StripeResponse.ResponseJson; } var logs = new Logs { LogKey = "UpgradeSubscriptionCharge", UpdatedContent = string.Format("Params: {0} - Response: {1}", JsonConvert.SerializeObject(param, CustomSettings.SerializerSettings()), responseString), UpdatedBy = param.SubscriptionBookingsObject.CustomerId, UpdatedDate = DateTime.UtcNow }; AddLog(logs); } catch (Exception ex) { var logs = new Logs { LogKey = "UpgradeSubscriptionChargeError", UpdatedContent = string.Format("Params: {0} - {1} - {2} - {3}", JsonConvert.SerializeObject(param, CustomSettings.SerializerSettings()), ex.Message, ex.StackTrace, ex.Source), UpdatedBy = param.SubscriptionBookingsObject.CustomerId, UpdatedDate = DateTime.UtcNow }; AddLog(logs); } } } Commit(); transaction.Complete(); } } catch (Exception ex) { var logs = new Logs { LogKey = "AddBookingError", UpdatedContent = string.Format("{0} - {1} - {2} - {3}", param.SubscriptionBookingsObject.CustomerId, ex.Message, ex.StackTrace, ex.Source), UpdatedBy = param.SubscriptionBookingsObject.CustomerId, UpdatedDate = DateTime.UtcNow }; AddLog(logs); throw new Exception(ex.Message, ex); } return(param.SubscriptionBookingsObject.Id); }
public void TestTransferPaid() { var transfer = new StripeTransfer { Id = "tx9876", Amount = 1443 }; var e = new StripeEvent { LiveMode = true, Type = "transfer.paid", Created = DateTime.Now.AddDays(-1), Data = new StripeEventData { Object = JObject.FromObject(transfer) } }; var paymentmetadata = new Dictionary <string, object> { { "crossroads_transaction_type", "payment" } }; var donationmetadata = new Dictionary <string, object> { { "crossroads_transaction_type", "donation" } }; var dateCreated = DateTime.Now; var charges = new List <StripeCharge> { new StripeCharge { Id = "ch111", Amount = 111, Fee = 1, Type = "charge", Created = dateCreated.AddDays(1), Metadata = paymentmetadata }, new StripeCharge { Id = "ch222", Amount = 222, Fee = 2, Type = "charge", Created = dateCreated.AddDays(2), Metadata = paymentmetadata }, new StripeCharge { Id = "ch333", Amount = 333, Fee = 3, Type = "charge", Created = dateCreated.AddDays(3), Metadata = donationmetadata }, new StripeCharge { Id = "ch777", Amount = 777, Fee = 7, Type = "charge", Created = dateCreated.AddDays(4), Metadata = donationmetadata }, new StripeCharge { Id = "ch888", Amount = 888, Fee = 8, Type = "charge", Created = dateCreated.AddDays(5), Metadata = donationmetadata }, new StripeCharge { Id = "re999", Amount = 999, Fee = 9, Type = "payment_refund", Created = dateCreated.AddDays(8), Metadata = donationmetadata }, new StripeCharge { Id = "ch444", Amount = 444, Fee = 4, Type = "charge", Created = dateCreated.AddDays(6), Metadata = donationmetadata }, new StripeCharge { Id = "ch555", Amount = 555, Fee = 5, Type = "refund", Created = dateCreated.AddDays(7), Metadata = donationmetadata } }; _paymentService.Setup(mocked => mocked.GetPaymentByTransactionCode("ch111")).Returns(new PaymentDTO { PaymentId = 1111, BatchId = null, Status = DonationStatus.Pending }); _paymentService.Setup(mocked => mocked.GetPaymentByTransactionCode("ch222")).Returns(new PaymentDTO { PaymentId = 2222, BatchId = null, Status = DonationStatus.Pending }); _donationService.Setup(mocked => mocked.GetDonationByProcessorPaymentId("ch333")).Returns(new DonationDTO { Id = "3333", BatchId = null, Status = DonationStatus.Pending }); _donationService.Setup(mocked => mocked.GetDonationByProcessorPaymentId("ch444")).Throws(new Exception("Not gonna do it, wouldn't be prudent.")); _paymentProcessorService.Setup(mocked => mocked.GetChargeRefund("ch555")).Returns(new StripeRefund { Data = new List <StripeRefundData> { new StripeRefundData() { Id = "ch555", Amount = "987", Charge = new StripeCharge { Id = "re_123456" } } } }); _donationService.Setup(mocked => mocked.GetDonationByProcessorPaymentId("ch555")).Returns(new DonationDTO { Id = "5555", BatchId = 1984 }); _donationService.Setup(mocked => mocked.GetDonationBatch(1984)).Returns(new DonationBatchDTO { Id = 5150, ProcessorTransferId = "OU812" }); var stripeRefundData = new StripeRefundData { Id = "re999", Amount = "999", ChargeId = "ch999", Charge = new StripeCharge { Id = "ch999" }, BalanceTransaction = new StripeBalanceTransaction { Created = DateTime.Now } }; var refund = new StripeRefund { Data = new List <StripeRefundData> { stripeRefundData } }; _paymentProcessorService.Setup(mocked => mocked.GetRefund("re999")).Returns(stripeRefundData); _donationService.Setup( mocked => mocked.CreateDonationForBankAccountErrorRefund(It.Is <StripeRefund>(r => r.Data != null && r.Data.Count == 1 && r.Data[0].Equals(stripeRefundData)))) .Returns(876); var firstRefund = true; _donationService.Setup(mocked => mocked.GetDonationByProcessorPaymentId("re999")).Returns(() => { if (firstRefund) { firstRefund = false; throw (new DonationNotFoundException("re999")); } return(new DonationDTO() { Id = "9999", BatchId = null, Amount = 999 }); }); _donationService.Setup(mocked => mocked.GetDonationByProcessorPaymentId("ch777")).Returns(new DonationDTO { Id = "7777", BatchId = 2112 }); _donationService.Setup(mocked => mocked.GetDonationBatch(2112)).Returns(new DonationBatchDTO { Id = 2112, ProcessorTransferId = null }); var first = true; _donationService.Setup(mocked => mocked.GetDonationByProcessorPaymentId("ch888")).Returns(() => { if (first) { first = false; throw (new DonationNotFoundException("ch888")); } return(new DonationDTO() { Id = "8888", BatchId = null, Amount = 888, Status = DonationStatus.Declined }); }); _donationService.Setup(mocked => mocked.UpdateDonationStatus(refund.Data[0].ChargeId, 777, refund.Data[0].BalanceTransaction.Created, null)).Returns(9999); var invoice = new StripeInvoice { Amount = 100, Id = "in_888" }; _paymentProcessorService.Setup(mocked => mocked.GetCharge("ch888")).Returns(new StripeCharge { Source = new StripeSource { Object = "bank_account" }, Invoice = invoice }); _donationService.Setup(mocked => mocked.CreateDonationForInvoice(invoice)).Returns(88); _paymentProcessorService.Setup(mocked => mocked.GetChargesForTransfer("tx9876")).Returns(charges); _donationService.Setup(mocked => mocked.GetDepositByProcessorTransferId("tx9876")).Returns((DepositDTO)null); _donationService.Setup( mocked => mocked.CreatePaymentProcessorEventError(e, It.IsAny <StripeEventResponseDTO>())); _paymentService.Setup(mocked => mocked.UpdatePaymentStatus(1111, 999, e.Created, null)).Returns(1111); _paymentService.Setup(mocked => mocked.UpdatePaymentStatus(2222, 999, e.Created, null)).Returns(2222); _donationService.Setup(mocked => mocked.UpdateDonationStatus(3333, 999, e.Created, null)).Returns(3333); _donationService.Setup(mocked => mocked.UpdateDonationStatus(7777, 999, e.Created, null)).Returns(7777); _donationService.Setup(mocked => mocked.UpdateDonationStatus(9999, 999, e.Created, null)).Returns(9999); _donationService.Setup(mocked => mocked.CreateDeposit(It.IsAny <DepositDTO>())).Returns( (DepositDTO o) => { o.Id = 98765; return(o); }); _donationService.Setup(mocked => mocked.CreateDonationBatch(It.IsAny <DonationBatchDTO>())).Returns((DonationBatchDTO o) => o); _paymentService.Setup(mocked => mocked.CreatePaymentBatch(It.IsAny <DonationBatchDTO>())).Returns((DonationBatchDTO o) => o); var result = _fixture.ProcessStripeEvent(e); Assert.IsNotNull(result); Assert.IsInstanceOf <TransferPaidResponseDTO>(result); var tp = (TransferPaidResponseDTO)result; Assert.AreEqual(8, tp.TotalTransactionCount); Assert.AreEqual(6, tp.SuccessfulUpdates.Count); Assert.AreEqual(charges.Take(6).Select(charge => charge.Id), tp.SuccessfulUpdates); Assert.AreEqual(2, tp.FailedUpdates.Count); Assert.AreEqual("ch555", tp.FailedUpdates[1].Key); Assert.AreEqual("ch444", tp.FailedUpdates[0].Key); Assert.AreEqual("Not gonna do it, wouldn't be prudent.", tp.FailedUpdates[0].Value); Assert.IsNotNull(tp.Batch); Assert.IsNotNull(tp.Deposit); Assert.IsNotNull(tp.Exception); _donationService.Verify(mocked => mocked.CreateDonationBatch(It.Is <DonationBatchDTO>(o => o.BatchName.Matches(@"MP\d{12}D") && o.SetupDateTime == o.FinalizedDateTime && o.BatchEntryType == 555 && o.ItemCount == 4 && o.BatchTotalAmount == ((333 + 777 + 888 + 999) / Constants.StripeDecimalConversionValue) && o.Donations != null && o.Donations.Count == 4 && o.DepositId == 98765 && o.ProcessorTransferId.Equals("tx9876") ))); _donationService.Verify(mocked => mocked.CreateDeposit(It.Is <DepositDTO>(o => o.DepositName.Matches(@"MP\d{12}") && !o.Exported && o.AccountNumber.Equals(" ") && o.BatchCount == 2 && o.DepositDateTime != null && o.DepositTotalAmount == ((transfer.Amount + 30) / Constants.StripeDecimalConversionValue) && o.ProcessorFeeTotal == (30 / Constants.StripeDecimalConversionValue) && o.DepositAmount == (transfer.Amount / Constants.StripeDecimalConversionValue) && o.Notes == null && o.ProcessorTransferId.Equals("tx9876") ))); _paymentProcessorService.VerifyAll(); _donationService.VerifyAll(); }
public int?CreateDonationForBankAccountErrorRefund(StripeRefund refund) { if (refund.Data[0].BalanceTransaction == null || !"payment_failure_refund".Equals(refund.Data[0].BalanceTransaction.Type)) { _logger.Error(string.Format("Balance transaction was not set, or was not a payment_failure_refund for refund ID {0}", refund.Data[0].Id)); return(null); } if (refund.Data[0].Charge == null || string.IsNullOrWhiteSpace(refund.Data[0].Charge.Id)) { _logger.Error(string.Format("No associated Charge for Refund {0}", refund.Data[0].Id)); return(null); } MpDonation donation; try { donation = _mpDonationRepository.GetDonationByProcessorPaymentId(refund.Data[0].Charge.Id, true); } catch (DonationNotFoundException) { _logger.Error(string.Format("No Donation with payment processor ID {0} in MP for Refund {1}", refund.Data[0].Charge.Id, refund.Data[0].Id)); return(null); } var donationAndDist = new MpDonationAndDistributionRecord { Anonymous = false, ChargeId = refund.Data[0].Id, CheckNumber = null, CheckScannerBatchName = null, DonationAmt = -(int.Parse(refund.Data[0].Amount) / Constants.StripeDecimalConversionValue), DonationStatus = (int)DonationStatus.Declined, DonorAcctId = string.Empty, DonorId = _bankErrorRefundDonorId, FeeAmt = refund.Data[0].BalanceTransaction.Fee, PledgeId = null, RecurringGift = false, ProcessorId = string.Empty, ProgramId = donation.Distributions[0].donationDistributionProgram, PymtType = MinistryPlatform.Translation.Enum.PaymentType.GetPaymentType(donation.paymentTypeId).name, RecurringGiftId = null, RegisteredDonor = false, SetupDate = refund.Data[0].BalanceTransaction.Created, Notes = string.Format("Reversed from DonationID {0}", donation.donationId) }; foreach (var distribution in donation.Distributions) { donationAndDist.Distributions.Add(new MpDonationDistribution { donationDistributionAmt = -distribution.donationDistributionAmt, donationDistributionProgram = distribution.donationDistributionProgram, PledgeId = distribution.PledgeId }); } // Create the refund donation and distribution(s), but do NOT send email return(_mpDonorRepository.CreateDonationAndDistributionRecord(donationAndDist, false)); }
public HttpResponseMessage ProcessTransaction(IncomingProcessTransaction model) { return(ErrorFactory.Handle(() => { var userId = User?.Identity?.GetUserId(); if (string.IsNullOrWhiteSpace(userId)) { throw new Exception(); } var context = new PoolReservationEntities(); using (var unitOfWork = new UnitOfWork(context)) { PrepareAndGetReservationForProcessing_Result reservation = null; try { reservation = context.PrepareAndGetReservationForProcessing(model.ReservationId)?.FirstOrDefault(); } catch (Exception) { context.ChangeProcessingStatusToPending(model.ReservationId); } if (reservation == null) { try { context.ChangeProcessingStatusToPending(model.ReservationId); } catch (Exception) { } return JsonFactory.CreateJsonMessage(null, HttpStatusCode.NotFound, this.Request); } if (reservation.StatusId != Convert.ToInt32(ReservationGroupStatusEnum.PROCESSING)) { try { context.ChangeProcessingStatusToPending(model.ReservationId); } catch (Exception) { } return JsonFactory.CreateJsonMessage(new OutgoingMessage { Action = "wrongStatus" }, HttpStatusCode.NotFound, this.Request); } ReservationGroup reservationDBObject = null; try { reservationDBObject = unitOfWork.Reservations.GetReservationWithItems(userId, model.ReservationId); if (reservationDBObject == null) { return JsonFactory.CreateJsonMessage(null, HttpStatusCode.NotFound, this.Request); } } catch (Exception) { context.ChangeProcessingStatusToPending(model.ReservationId); } if (reservationDBObject.StatusId != Convert.ToInt32(ReservationGroupStatusEnum.PROCESSING)) { try { context.ChangeProcessingStatusToPending(model.ReservationId); } catch (Exception) { } return JsonFactory.CreateJsonMessage(new OutgoingMessage { Action = "wrongStatus" }, HttpStatusCode.NotFound, this.Request); } ReservationTransaction resTransaction = null; int stripeModifiedPriceInCents = 0; try { decimal priceToCharge = 0M; foreach (var item in reservationDBObject.ReserveItems) { if (item.IsDeleted == true) { continue; } priceToCharge += item.FinalPrice; } decimal stripeModifiedPrice = priceToCharge * 100.0M; stripeModifiedPriceInCents = (int)Math.Round(stripeModifiedPrice); //Must Update Repo If Changed. Rounds to the nearest penny. if (stripeModifiedPriceInCents <= 50) { return JsonFactory.CreateJsonMessage(new OutgoingMessage { Action = "noPriceToCharge" }, HttpStatusCode.NotFound, this.Request); } resTransaction = unitOfWork.Reservations.AddStripeChargeToPendingReservation(userId, userId, model.ReservationId, model.StripeTokenId, priceToCharge); unitOfWork.Complete(); } catch (Exception e) { context.ChangeProcessingStatusToPending(model.ReservationId); } string chargeId = null; try { if (resTransaction == null) { throw new Exception(); } var myCharge = new StripeChargeCreateOptions(); // always set these properties myCharge.Amount = stripeModifiedPriceInCents; myCharge.Currency = "usd"; // set this if you want to myCharge.Description = "JustMosey Reservation"; myCharge.SourceTokenOrExistingSourceId = model.StripeTokenId; // (not required) set this to false if you don't want to capture the charge yet - requires you call capture later myCharge.Capture = true; var chargeService = new StripeChargeService(); StripeCharge stripeCharge = chargeService.Create(myCharge); chargeId = stripeCharge.Id; unitOfWork.Reservations.UpdateStripeSuccessfulChargeOnPendingReservation(userId, userId, resTransaction.Id, chargeId); unitOfWork.Complete(); } catch (Exception e) { try { var refundService = new StripeRefundService(); StripeRefund refund = refundService.Create(chargeId, new StripeRefundCreateOptions() { Amount = stripeModifiedPriceInCents, Reason = StripeRefundReasons.Unknown }); } catch (Exception) { } try { unitOfWork.Reservations.RefundStripeSuccessfulChargeOnPendingReservation(userId, userId, resTransaction.Id); unitOfWork.Complete(); } catch (Exception) { } try { } catch (Exception) { context.ChangeProcessingStatusToPending(model.ReservationId); } return JsonFactory.CreateJsonMessage(new OutgoingMessage { Action = "unknownErrorAfterProcessing" }, HttpStatusCode.InternalServerError, this.Request); } try { var updatedReservationDBObject = unitOfWork.Reservations.GetReservationWithItems(userId, model.ReservationId); var outgoingRes = OutgoingReservationGroup.Parse(updatedReservationDBObject); return JsonFactory.CreateJsonMessage(outgoingRes, HttpStatusCode.OK, this.Request); } catch (Exception) { return JsonFactory.CreateJsonMessage(null, HttpStatusCode.OK, this.Request); } } }, this.Request)); }