Added job interruption handling

This commit is contained in:
Khwezi Mngoma
2026-06-03 10:40:29 +02:00
parent 4bac14881d
commit a0cf847e51
7 changed files with 71 additions and 31 deletions
@@ -1,17 +1,21 @@
using LiteCharms.Features.Hasher;
using LiteCharms.Features.Hasher.Configuration;
using LiteCharms.Features.Mediator;
using LiteCharms.Features.MidrandBooks.Orders;
using LiteCharms.Features.MidrandBooks.Payments.Models;
namespace LiteCharms.Features.MidrandBooks.Payments.Events.Handlers;
public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvider services, IOptions<HasherSettings> hasherOptions, ILogger<PayfastPaymentConfirmationReceivedEvent> logger) :
public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvider services, IOptions<HasherSettings> hasherOptions, ILogger<PayfastPaymentConfirmationReceivedEvent> logger) :
INotificationHandler<PayfastPaymentConfirmationReceivedEvent>
{
private readonly HasherSettings hasherSettings = hasherOptions.Value;
public async ValueTask Handle(PayfastPaymentConfirmationReceivedEvent notification, CancellationToken cancellationToken)
{
using var activity = MediatorTelemetry.Source.StartActivity($"Quartz: {typeof(PayfastPaymentConfirmationReceivedEvent).Name}");
activity?.SetTag("event.correlation_id", notification.CorrelationId);
await using var scope = services.CreateAsyncScope();
var hashService = scope.ServiceProvider.GetRequiredService<HashService>();
var orderService = scope.ServiceProvider.GetRequiredService<OrderService>();
@@ -23,7 +27,7 @@ public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvi
var dict = payload.ToParamDictionary();
var localSignature = PayfastService.GenerateSignature(dict, hasherSettings.PayfastPassphrase);
if(localSignature.IsFailed)
if (localSignature.IsFailed)
throw new Exception("Failed to generate local signature for incoming webhook payload.");
if (!string.Equals(localSignature.Value, payload.Signature, StringComparison.OrdinalIgnoreCase))
@@ -63,7 +67,7 @@ public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvi
{
var isHostValid = await payfastService.ValidateReferrerIpAsync(notification.RemoteIpAddress!, notification.AllowLoopback, cancellationToken);
if (isHostValid.IsFailed)
if (isHostValid.IsFailed)
throw new Exception("Security validation exception: Webhook packet source address failed cluster validation checks.");
if (!isHostValid.Value)
@@ -71,7 +75,7 @@ public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvi
var isAmountValid = payfastService.ValidatePaymentAmount(orderResult.Value.Total, payload.AmountGross);
if (!isAmountValid.Value)
if (!isAmountValid.Value)
throw new Exception("Security validation exception: Transaction cost variance bounds breached.");
var paramList = new List<string>();
@@ -91,8 +95,8 @@ public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvi
var serverConfirmation = await payfastService.ValidateServerConfirmationAsync(rawParamString, isSandbox: true, cancellationToken);
if (serverConfirmation.IsFailed)
throw new Exception("Security validation exception: Payfast central handshake server rejected payload legitimacy.");
if (serverConfirmation.IsFailed)
throw new Exception("Security validation exception: Payfast central handshake server rejected payload legitimacy.");
}
await payfastService.WriteLedgerEntryAsync(new CreateGatewayLedgerEntry
@@ -105,7 +109,7 @@ public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvi
AmountFee = fee,
AmountGross = gross,
AmountNet = net,
PaymentStatus = status,
PaymentStatus = status,
}, cancellationToken);
if (status.Equals("COMPLETE", StringComparison.OrdinalIgnoreCase))
@@ -154,5 +158,7 @@ public sealed class PayfastPaymentConfirmationReceivedEventHandler(IServiceProvi
logger.LogInformation("Webhook validation pipeline passed checks successfully, logged entry to ledger with status: {Status}", status);
}
activity?.SetStatus(ActivityStatusCode.Ok);
}
}