Files
trakqr/src/TrackApi/TrackQrApi/Features/Billing/Endpoints/CreatePortalSessionEndpoint.cs

60 lines
1.8 KiB
C#

using System.Security.Claims;
using FastEndpoints;
using FluentValidation;
using TrackQrApi.Features.Auth.Common;
using TrackQrApi.Features.Billing.Common;
using TrackQrApi.Features.Billing.Services;
namespace TrackQrApi.Features.Billing.Endpoints;
public class CreatePortalSessionValidator : Validator<PortalSessionRequest>
{
public CreatePortalSessionValidator()
{
RuleFor(x => x.ReturnUrl).NotEmpty().Must(BeValidUrl);
}
private static bool BeValidUrl(string url)
{
return Uri.TryCreate(url, UriKind.Absolute, out var uri)
&& (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps);
}
}
public class CreatePortalSessionEndpoint(IStripeService stripeService)
: Endpoint<PortalSessionRequest, PortalSessionResponse>
{
public override void Configure()
{
Post("/billing/portal");
}
public override async Task HandleAsync(PortalSessionRequest req, CancellationToken ct)
{
var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
try
{
var portalUrl = await stripeService.CreateCustomerPortalSessionAsync(
userId,
req.ReturnUrl,
ct);
await HttpContext.Response.SendAsync(new PortalSessionResponse(portalUrl), cancellation: ct);
}
catch (InvalidOperationException ex)
{
await HttpContext.Response.SendAsync(
new MessageResponse(ex.Message),
400,
cancellation: ct);
}
catch (Exception ex)
{
await HttpContext.Response.SendAsync(
new MessageResponse($"Failed to create portal session: {ex.Message}"),
500,
cancellation: ct);
}
}
}