diff --git a/MidrandBooksApi/ApiVersionTargetAttribute.cs b/MidrandBooksApi/ApiVersionTargetAttribute.cs
deleted file mode 100644
index d02fb28..0000000
--- a/MidrandBooksApi/ApiVersionTargetAttribute.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MidrandBooksApi;
-
-[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
-public sealed class ApiVersionTargetAttribute(int majorVersion) : Attribute
-{
- public int MajorVersion { get; } = majorVersion;
-}
diff --git a/MidrandBooksApi/EndpointTags.cs b/MidrandBooksApi/EndpointTags.cs
deleted file mode 100644
index af64953..0000000
--- a/MidrandBooksApi/EndpointTags.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MidrandBooksApi;
-
-public static class EndpointTags
-{
- public const string Books = nameof(Books);
- public const string Payments = nameof(Payments);
-}
diff --git a/MidrandBooksApi/IEndpoint.cs b/MidrandBooksApi/IEndpoint.cs
deleted file mode 100644
index e2a2c05..0000000
--- a/MidrandBooksApi/IEndpoint.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace MidrandBooksApi;
-
-public interface IEndpoint
-{
- void Map(IEndpointRouteBuilder builder);
-}
diff --git a/MidrandBooksApi/MidrandBooksApi.csproj b/MidrandBooksApi/MidrandBooksApi.csproj
index b6be5dd..db53633 100644
--- a/MidrandBooksApi/MidrandBooksApi.csproj
+++ b/MidrandBooksApi/MidrandBooksApi.csproj
@@ -34,6 +34,7 @@
+
@@ -53,13 +54,13 @@
-
+
-
+
diff --git a/MidrandBooksApi/OpenApiBearerSecuritySchemeTransformer.cs b/MidrandBooksApi/OpenApiBearerSecuritySchemeTransformer.cs
deleted file mode 100644
index de99e93..0000000
--- a/MidrandBooksApi/OpenApiBearerSecuritySchemeTransformer.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace MidrandBooksApi;
-
-public sealed class OpenApiBearerSecuritySchemeTransformer : IOpenApiDocumentTransformer
-{
- public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
- {
- var bearerScheme = new OpenApiSecurityScheme
- {
- Type = SecuritySchemeType.Http,
- Scheme = "bearer",
- Description = "JWT Authorization header using the Bearer scheme. Example: \"Bearer {token}\""
- };
-
- document.AddComponent("Bearer", bearerScheme);
- }
-}
diff --git a/MidrandBooksApi/Payments/Endpoints/ConfirmationEndpoint.cs b/MidrandBooksApi/Payments/Endpoints/ConfirmationEndpoint.cs
index 5417e65..c83540f 100644
--- a/MidrandBooksApi/Payments/Endpoints/ConfirmationEndpoint.cs
+++ b/MidrandBooksApi/Payments/Endpoints/ConfirmationEndpoint.cs
@@ -1,7 +1,11 @@
-using LiteCharms.Features.MidrandBooks.Payments;
+using LiteCharms.Features.Abstractions;
+using LiteCharms.Features.Api;
+using LiteCharms.Features.Extensions;
+using LiteCharms.Features.MidrandBooks.Payments;
using LiteCharms.Features.MidrandBooks.Payments.Events;
using LiteCharms.Features.MidrandBooks.Payments.Models;
using LiteCharms.Features.Quartz.Abstractions;
+using static LiteCharms.Features.Extensions.Api;
namespace MidrandBooksApi.Payments.Endpoints;
@@ -22,7 +26,7 @@ public sealed class ConfirmationEndpoint : IEndpoint
string? remoteIp = request.HttpContext.Connection.RemoteIpAddress?.ToString();
- var ipValidation = await payfastService.ValidateReferrerIpAsync(remoteIp!, cancellationToken);
+ var ipValidation = await payfastService.ValidateReferrerIpAsync(remoteIp!, !hostEnvironment.IsProduction(), cancellationToken);
if (ipValidation.IsFailed || !ipValidation.Value) return Results.Unauthorized();
@@ -54,7 +58,7 @@ public sealed class ConfirmationEndpoint : IEndpoint
return Results.Unauthorized();
var notification = PayfastPaymentConfirmationReceivedEvent.Create(payload, payload.MerchantPaymentId!,
- performBackgroundChecks: false); // Set to false because comprehensive checks are completed inline above
+ allowLoopback: !hostEnvironment.IsProduction(), performBackgroundChecks: false); // Set to false because comprehensive checks are completed inline above
await jobOrchestrator.SendAsync(notification, cancellationToken);
@@ -68,7 +72,7 @@ public sealed class ConfirmationEndpoint : IEndpoint
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
- .WithTags(EndpointTags.Payments);
+ .WithTags(Api.Payments);
}
private static PayfastWebhookPayload ParseForm(IFormCollection formCollection, string incomingSignature) => new()
diff --git a/MidrandBooksApi/Program.cs b/MidrandBooksApi/Program.cs
index 2e801d0..5df7539 100644
--- a/MidrandBooksApi/Program.cs
+++ b/MidrandBooksApi/Program.cs
@@ -1,9 +1,6 @@
-using Asp.Versioning.Builder;
-using k8s.Models;
using LiteCharms.Features.Extensions;
using LiteCharms.Features.Mediator;
using LiteCharms.Features.MidrandBooks.Extensions;
-using MidrandBooksApi;
using static LiteCharms.Features.Extensions.Quartz;
var builder = WebApplication.CreateBuilder(args);
diff --git a/MidrandBooksApi/Setup.cs b/MidrandBooksApi/Setup.cs
deleted file mode 100644
index a34a8a7..0000000
--- a/MidrandBooksApi/Setup.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-namespace MidrandBooksApi;
-
-public static class Setup
-{
- public static IApplicationBuilder MapEndpoints(this WebApplication app, Dictionary versionGroups)
- {
- var endpoints = app.Services.GetRequiredService>();
-
- foreach (var endpoint in endpoints)
- {
- var versionAttributes = endpoint.GetType().GetCustomAttributes().ToList();
-
- if (versionAttributes.Count != 0)
- {
- foreach (var attr in versionAttributes)
- if (versionGroups.TryGetValue(attr.MajorVersion, out var targetGroup))
- endpoint.Map(targetGroup);
- }
- else
- endpoint.Map(app);
- }
-
- return app;
- }
-
- public static IServiceCollection AddEndpoints(this IServiceCollection services, Assembly assembly)
- {
- ServiceDescriptor[] discriptors = [.. assembly.DefinedTypes
- .Where(t => t is { IsInterface: false, IsAbstract: false })
- .Where(t => t.IsAssignableTo(typeof(IEndpoint)))
- .Select(t => ServiceDescriptor.Transient(typeof(IEndpoint), t))];
-
- services.TryAddEnumerable(discriptors);
-
- return services;
- }
-
- public static string ToEndpointName(this Type target, string? annotation = "") =>
- $"{target.Name.Replace("Endpoint", string.Empty)}{annotation}".ToLower();
-
- public static IServiceCollection AddApiServices(this IServiceCollection services, IConfiguration configuration)
- {
- services.AddHttpClient();
-
- services.AddApiVersioning(options =>
- {
- options.DefaultApiVersion = new ApiVersion(1);
- options.ReportApiVersions = true;
- options.AssumeDefaultVersionWhenUnspecified = true;
- options.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
- new QueryStringApiVersionReader("version"),
- new QueryStringApiVersionReader("version"),
- new MediaTypeApiVersionReader("version"));
- })
- .AddApiExplorer(options =>
- {
- options.GroupNameFormat = "'v'VVV";
- options.SubstituteApiVersionInUrl = true;
- });
-
- var urls = configuration["ASPNETCORE_URLS"] ?? configuration["Urls"];
- var healthUrl = "http://localhost:8080/health";
-
- if (!string.IsNullOrWhiteSpace(urls))
- {
- string firstUrl = urls.Split(';').FirstOrDefault(s => s.Contains("http://"))!
- .Replace("*", "localhost").Replace("+", "localhost");
-
- healthUrl = $"{firstUrl.TrimEnd('/')}/health";
- }
-
- services.AddHealthChecksUI(setup =>
- {
- setup.SetNotifyUnHealthyOneTimeUntilChange();
- setup.AddHealthCheckEndpoint("primary, heal", healthUrl);
- setup.SetHeaderText("Midrand Books");
- })
- .AddInMemoryStorage();
-
- services.AddOutputCache(options =>
- {
- options.AddBasePolicy(builder => builder.Cache());
- options.DefaultExpirationTimeSpan = TimeSpan.FromSeconds(10);
- });
-
- services.AddOpenApi(options => options.AddDocumentTransformer());
-
- return services;
- }
-}
diff --git a/MidrandBooksApi/http/app.http b/MidrandBooksApi/http/app.http
deleted file mode 100644
index 7297a16..0000000
--- a/MidrandBooksApi/http/app.http
+++ /dev/null
@@ -1,8 +0,0 @@
-## Payfast Payment Confirmation
-# This endpoint is used by Payfast to confirm the payment status of a transaction.
-# It receives a POST request with the payment details and updates the order status accordingly.
-
-POST {{baseUrl}}/v1/payments/payfast/confirm
-Content-Type: application/x-www-form-urlencoded
-
-amount={{amount}}&item_name={{item_name}}&m_payment_id={{paymentId}}&signature={{signature}}