chore: correct namespaces and hiearchy

This commit is contained in:
2026-01-31 02:16:32 -05:00
parent 56d393e127
commit 19e2c22111
136 changed files with 1366 additions and 1404 deletions

View File

@@ -0,0 +1,60 @@
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);
}
}
}