using LiteCharms.Features.Extensions; using LiteCharms.Features.Hasher; using LiteCharms.Features.Models; namespace MidrandBooksApi.Payments.Endpoints; [ApiVersionTarget(1)] public sealed class ConfirmationEndpoint : IEndpoint { public void Map(IEndpointRouteBuilder builder) { builder.MapPost("payments/confirm", async (HttpRequest request, HashService hashService, CancellationToken cancellationToken) => { var formCollection = await request.ReadFormAsync(cancellationToken); if (!formCollection.TryGetValue("signature", out var signatureValues) || string.IsNullOrWhiteSpace(signatureValues.ToString())) return Results.BadRequest("Missing Payfast validation signature."); string incomingSignature = signatureValues.ToString(); var payload = new PayfastWebhookPayload { Amount = formCollection.TryGetValue("amount", out var amountValues) ? amountValues.ToString() : null, ItemName = formCollection.TryGetValue("item_name", out var itemValues) ? itemValues.ToString() : null, MPaymentId = formCollection.TryGetValue("m_payment_id", out var paymentIdValues) ? paymentIdValues.ToString() : null }; var validationResult = hashService.VerifyPayfastWebhookSignature(payload, incomingSignature); return validationResult.IsFailed || !validationResult.Value ? Results.Unauthorized() : Results.Ok(); }) .WithDescription("Securely confirm and process an incoming Payfast merchant payment callback.") .WithName(typeof(ConfirmationEndpoint).ToEndpointName()) .MapToApiVersion(new ApiVersion(1)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status400BadRequest) .Produces(StatusCodes.Status401Unauthorized) .WithTags(EndpointTags.Payments); } }