Browse Source

refactoring continues

AC-1527-refactor-the-stripe-webhook-logic
Cy Okeke 2 years ago
parent
commit
7c5724e48f
No known key found for this signature in database
GPG Key ID: B758F6C46EB146A2
  1. 9
      src/Billing/Services/Implementations/ChargeSucceededHandler.cs
  2. 33
      src/Billing/Services/Implementations/InvoiceCreatedHandler.cs
  3. 105
      src/Billing/Services/Implementations/PaymentMethodAttachedHandler.cs
  4. 7
      src/Billing/Services/Implementations/PaymentSucceededHandler.cs
  5. 9
      src/Billing/Services/Implementations/SubscriptionUpdatedHandler.cs

9
src/Billing/Services/Implementations/ChargeSucceededHandler.cs

@ -15,16 +15,19 @@ public class ChargeSucceededHandler : StripeWebhookHandler
private readonly ITransactionRepository _transactionRepository; private readonly ITransactionRepository _transactionRepository;
private readonly ILogger<StripeController> _logger; private readonly ILogger<StripeController> _logger;
private readonly IStripeEventService _stripeEventService; private readonly IStripeEventService _stripeEventService;
private readonly IWebhookUtility _webhookUtility;
public ChargeSucceededHandler( public ChargeSucceededHandler(
ITransactionRepository transactionRepository, ITransactionRepository transactionRepository,
ILogger<StripeController> logger, ILogger<StripeController> logger,
IStripeEventService stripeEventService) IStripeEventService stripeEventService,
IWebhookUtility webhookUtility)
{ {
_transactionRepository = transactionRepository; _transactionRepository = transactionRepository;
_logger = logger; _logger = logger;
_stripeEventService = stripeEventService; _stripeEventService = stripeEventService;
_webhookUtility = webhookUtility;
} }
protected override bool CanHandle(Event parsedEvent) protected override bool CanHandle(Event parsedEvent)
@ -54,7 +57,7 @@ public class ChargeSucceededHandler : StripeWebhookHandler
if (invoice?.SubscriptionId != null) if (invoice?.SubscriptionId != null)
{ {
subscription = await subscriptionService.GetAsync(invoice.SubscriptionId); subscription = await subscriptionService.GetAsync(invoice.SubscriptionId);
ids = GetIdsFromMetaData(subscription?.Metadata); ids = _webhookUtility.GetIdsFromMetaData(subscription?.Metadata);
} }
} }
@ -68,7 +71,7 @@ public class ChargeSucceededHandler : StripeWebhookHandler
{ {
if (sub.Status != StripeSubscriptionStatus.Canceled && sub.Status != StripeSubscriptionStatus.IncompleteExpired) if (sub.Status != StripeSubscriptionStatus.Canceled && sub.Status != StripeSubscriptionStatus.IncompleteExpired)
{ {
ids = GetIdsFromMetaData(sub.Metadata); ids = _webhookUtility.GetIdsFromMetaData(sub.Metadata);
if (ids.Item1.HasValue || ids.Item2.HasValue) if (ids.Item1.HasValue || ids.Item2.HasValue)
{ {
subscription = sub; subscription = sub;

33
src/Billing/Services/Implementations/InvoiceCreatedHandler.cs

@ -0,0 +1,33 @@
using Bit.Billing.Constants;
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace Bit.Billing.Services.Implementations;
public class InvoiceCreatedHandler : StripeWebhookHandler
{
private readonly IStripeEventService _stripeEventService;
private readonly IWebhookUtility _webhookUtility;
public InvoiceCreatedHandler(IStripeEventService stripeEventService,
IWebhookUtility webhookUtility)
{
_stripeEventService = stripeEventService;
_webhookUtility = webhookUtility;
}
protected override bool CanHandle(Event parsedEvent)
{
return parsedEvent.Type.Equals(HandledStripeWebhook.InvoiceCreated);
}
protected override async Task<IActionResult> ProcessEvent(Event parsedEvent)
{
var invoice = await _stripeEventService.GetInvoice(parsedEvent, true);
if (!invoice.Paid && _webhookUtility.UnpaidAutoChargeInvoiceForSubscriptionCycle(invoice))
{
await _webhookUtility.AttemptToPayInvoice(invoice);
}
return new OkResult();
}
}

105
src/Billing/Services/Implementations/PaymentMethodAttachedHandler.cs

@ -0,0 +1,105 @@
using Bit.Billing.Constants;
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace Bit.Billing.Services.Implementations;
public class PaymentMethodAttachedHandler : StripeWebhookHandler
{
private readonly IStripeEventService _stripeEventService;
private readonly IWebhookUtility _webhookUtility;
private readonly ILogger<PaymentMethodAttachedHandler> _logger;
public PaymentMethodAttachedHandler(IStripeEventService stripeEventService,
IWebhookUtility webhookUtility,
ILogger<PaymentMethodAttachedHandler> logger)
{
_stripeEventService = stripeEventService;
_webhookUtility = webhookUtility;
_logger = logger;
}
protected override bool CanHandle(Event parsedEvent)
{
return parsedEvent.Type.Equals(HandledStripeWebhook.InvoiceCreated);
}
protected override async Task<IActionResult> ProcessEvent(Event parsedEvent)
{
var paymentMethod = await _stripeEventService.GetPaymentMethod(parsedEvent);
await HandlePaymentMethodAttachedAsync(paymentMethod);
return new OkResult();
}
private async Task HandlePaymentMethodAttachedAsync(PaymentMethod paymentMethod)
{
if (paymentMethod is null)
{
_logger.LogWarning("Attempted to handle the event payment_method.attached but paymentMethod was null");
return;
}
var subscriptionService = new SubscriptionService();
var subscriptionListOptions = new SubscriptionListOptions
{
Customer = paymentMethod.CustomerId,
Status = StripeSubscriptionStatus.Unpaid,
Expand = new List<string> { "data.latest_invoice" }
};
StripeList<Subscription> unpaidSubscriptions;
try
{
unpaidSubscriptions = await subscriptionService.ListAsync(subscriptionListOptions);
}
catch (Exception e)
{
_logger.LogError(e,
"Attempted to get unpaid invoices for customer {CustomerId} but encountered an error while calling Stripe",
paymentMethod.CustomerId);
return;
}
foreach (var unpaidSubscription in unpaidSubscriptions)
{
await AttemptToPayOpenSubscriptionAsync(unpaidSubscription);
}
}
private async Task AttemptToPayOpenSubscriptionAsync(Subscription unpaidSubscription)
{
var latestInvoice = unpaidSubscription.LatestInvoice;
if (unpaidSubscription.LatestInvoice is null)
{
_logger.LogWarning(
"Attempted to pay unpaid subscription {SubscriptionId} but latest invoice didn't exist",
unpaidSubscription.Id);
return;
}
if (latestInvoice.Status != StripeInvoiceStatus.Open)
{
_logger.LogWarning(
"Attempted to pay unpaid subscription {SubscriptionId} but latest invoice wasn't \"open\"",
unpaidSubscription.Id);
return;
}
try
{
await _webhookUtility.AttemptToPayInvoice(latestInvoice, true);
}
catch (Exception e)
{
_logger.LogError(e,
"Attempted to pay open invoice {InvoiceId} on unpaid subscription {SubscriptionId} but encountered an error",
latestInvoice.Id, unpaidSubscription.Id);
throw;
}
}
}

7
src/Billing/Services/Implementations/PaymentSucceededHandler.cs

@ -21,6 +21,7 @@ public class PaymentSucceededHandler : StripeWebhookHandler
private readonly ICurrentContext _currentContext; private readonly ICurrentContext _currentContext;
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IUserRepository _userRepository; private readonly IUserRepository _userRepository;
private readonly IWebhookUtility _webhookUtility;
public PaymentSucceededHandler(IStripeEventService stripeEventService, public PaymentSucceededHandler(IStripeEventService stripeEventService,
IOrganizationService organizationService, IOrganizationService organizationService,
@ -28,7 +29,8 @@ public class PaymentSucceededHandler : StripeWebhookHandler
IReferenceEventService referenceEventService, IReferenceEventService referenceEventService,
ICurrentContext currentContext, ICurrentContext currentContext,
IUserService userService, IUserService userService,
IUserRepository userRepository) IUserRepository userRepository,
IWebhookUtility webhookUtility)
{ {
_stripeEventService = stripeEventService; _stripeEventService = stripeEventService;
_organizationService = organizationService; _organizationService = organizationService;
@ -37,6 +39,7 @@ public class PaymentSucceededHandler : StripeWebhookHandler
_currentContext = currentContext; _currentContext = currentContext;
_userService = userService; _userService = userService;
_userRepository = userRepository; _userRepository = userRepository;
_webhookUtility = webhookUtility;
} }
protected override bool CanHandle(Event parsedEvent) protected override bool CanHandle(Event parsedEvent)
{ {
@ -57,7 +60,7 @@ public class PaymentSucceededHandler : StripeWebhookHandler
await Task.Delay(5000); await Task.Delay(5000);
} }
var ids = GetIdsFromMetaData(subscription.Metadata); var ids = _webhookUtility.GetIdsFromMetaData(subscription.Metadata);
// org // org
if (ids.Item1.HasValue) if (ids.Item1.HasValue)
{ {

9
src/Billing/Services/Implementations/SubscriptionUpdatedHandler.cs

@ -12,16 +12,19 @@ public class SubscriptionUpdatedHandler : StripeWebhookHandler
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IStripeEventService _stripeEventService; private readonly IStripeEventService _stripeEventService;
private readonly IOrganizationSponsorshipRenewCommand _organizationSponsorshipRenewCommand; private readonly IOrganizationSponsorshipRenewCommand _organizationSponsorshipRenewCommand;
private readonly IWebhookUtility _webhookUtility;
public SubscriptionUpdatedHandler(IOrganizationService organizationService, public SubscriptionUpdatedHandler(IOrganizationService organizationService,
IUserService userService, IUserService userService,
IStripeEventService stripeEventService, IStripeEventService stripeEventService,
IOrganizationSponsorshipRenewCommand organizationSponsorshipRenewCommand) IOrganizationSponsorshipRenewCommand organizationSponsorshipRenewCommand,
IWebhookUtility webhookUtility)
{ {
_organizationService = organizationService; _organizationService = organizationService;
_userService = userService; _userService = userService;
_stripeEventService = stripeEventService; _stripeEventService = stripeEventService;
_organizationSponsorshipRenewCommand = organizationSponsorshipRenewCommand; _organizationSponsorshipRenewCommand = organizationSponsorshipRenewCommand;
_webhookUtility = webhookUtility;
} }
protected override bool CanHandle(Event parsedEvent) protected override bool CanHandle(Event parsedEvent)
{ {
@ -33,7 +36,7 @@ public class SubscriptionUpdatedHandler : StripeWebhookHandler
if (parsedEvent.Type.Equals(HandledStripeWebhook.SubscriptionUpdated)) if (parsedEvent.Type.Equals(HandledStripeWebhook.SubscriptionUpdated))
{ {
var subscription = await _stripeEventService.GetSubscription(parsedEvent, true); var subscription = await _stripeEventService.GetSubscription(parsedEvent, true);
var ids = GetIdsFromMetaData(subscription.Metadata); var ids = _webhookUtility.GetIdsFromMetaData(subscription.Metadata);
var organizationId = ids.Item1 ?? Guid.Empty; var organizationId = ids.Item1 ?? Guid.Empty;
var userId = ids.Item2 ?? Guid.Empty; var userId = ids.Item2 ?? Guid.Empty;
var subActive = subscription.Status == StripeSubscriptionStatus.Active; var subActive = subscription.Status == StripeSubscriptionStatus.Active;
@ -51,7 +54,7 @@ public class SubscriptionUpdatedHandler : StripeWebhookHandler
await _organizationService.UpdateExpirationDateAsync(organizationId, subscription.CurrentPeriodEnd); await _organizationService.UpdateExpirationDateAsync(organizationId, subscription.CurrentPeriodEnd);
if (IsSponsoredSubscription(subscription)) if (_webhookUtility.IsSponsoredSubscription(subscription))
{ {
await _organizationSponsorshipRenewCommand.UpdateExpirationDateAsync(organizationId, await _organizationSponsorshipRenewCommand.UpdateExpirationDateAsync(organizationId,
subscription.CurrentPeriodEnd); subscription.CurrentPeriodEnd);

Loading…
Cancel
Save