1
0
mirror of https://github.com/bitwarden/server synced 2025-12-31 23:53:17 +00:00

[PM-12420] Stripe events recovery (#4793)

* Billing: Add event recovery endpoints

* Core: Add InternalBilling to BaseServiceUriSettings

* Admin: Scaffold billing section

* Admin: Scaffold ProcessStripeEvents section

* Admin: Implement event processing

* Run dotnet format
This commit is contained in:
Alex Morask
2024-09-26 09:18:21 -04:00
committed by GitHub
parent 3f629e0a5a
commit 05247d2525
21 changed files with 379 additions and 3 deletions

View File

@@ -0,0 +1,68 @@
using Bit.Billing.Models.Recovery;
using Bit.Billing.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace Bit.Billing.Controllers;
[Route("stripe/recovery")]
[SelfHosted(NotSelfHostedOnly = true)]
public class RecoveryController(
IStripeEventProcessor stripeEventProcessor,
IStripeFacade stripeFacade,
IWebHostEnvironment webHostEnvironment) : Controller
{
private readonly string _stripeURL = webHostEnvironment.IsDevelopment() || webHostEnvironment.IsEnvironment("QA")
? "https://dashboard.stripe.com/test"
: "https://dashboard.stripe.com";
// ReSharper disable once RouteTemplates.ActionRoutePrefixCanBeExtractedToControllerRoute
[HttpPost("events/inspect")]
public async Task<Ok<EventsResponseBody>> InspectEventsAsync([FromBody] EventsRequestBody requestBody)
{
var inspected = await Task.WhenAll(requestBody.EventIds.Select(async eventId =>
{
var @event = await stripeFacade.GetEvent(eventId);
return Map(@event);
}));
var response = new EventsResponseBody { Events = inspected.ToList() };
return TypedResults.Ok(response);
}
// ReSharper disable once RouteTemplates.ActionRoutePrefixCanBeExtractedToControllerRoute
[HttpPost("events/process")]
public async Task<Ok<EventsResponseBody>> ProcessEventsAsync([FromBody] EventsRequestBody requestBody)
{
var processed = await Task.WhenAll(requestBody.EventIds.Select(async eventId =>
{
var @event = await stripeFacade.GetEvent(eventId);
try
{
await stripeEventProcessor.ProcessEventAsync(@event);
return Map(@event);
}
catch (Exception exception)
{
return Map(@event, exception.Message);
}
}));
var response = new EventsResponseBody { Events = processed.ToList() };
return TypedResults.Ok(response);
}
private EventResponseBody Map(Event @event, string processingError = null) => new()
{
Id = @event.Id,
URL = $"{_stripeURL}/workbench/events/{@event.Id}",
APIVersion = @event.ApiVersion,
Type = @event.Type,
CreatedUTC = @event.Created,
ProcessingError = processingError
};
}