using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using GB5Shared.GB5Constant; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GoodBooks.PAY.PAYDAL.CustomCode.Gateway; using GoodBooks.PAY.PAYDAL.DTO.Gateway; using Microsoft.Extensions.Logging; using static GB5Shared.GB5Constant.Constant; namespace GoodBooks.PAY.PAYBLL.Gateway { // ───────────────────────────────────────────────────────────────────────── // PayGatewayConfigBLL // // MPAYGATEWAYCONFIG is tenant-scoped (TENANTID filter on all DAL queries). // Cache level: CLIENT_LEVEL. // Vault key-path columns are stored AS-IS — BLL never decrypts them. // EntityConstant.OBJECTPAYGATEWAYCONFIG = -1382000002 // ───────────────────────────────────────────────────────────────────────── public class PayGatewayConfigBLL : IPayGatewayConfigBLL { private readonly IPayGatewayConfigDAL _dal; private readonly AutoNumber _autoNumber; private readonly KeyInvalidate _keyInvalidate; private readonly EventLogPublish _eventLogPublish; private readonly ILogger _logger; public PayGatewayConfigBLL( IPayGatewayConfigDAL dal, AutoNumber autoNumber, KeyInvalidate keyInvalidate, EventLogPublish eventLogPublish, ILogger logger) { _dal = dal; _autoNumber = autoNumber; _keyInvalidate = keyInvalidate; _eventLogPublish = eventLogPublish; _logger = logger; } // ── Get single config ───────────────────────────────────────────────── public async Task GetPayGatewayConfig(int payGatewayConfId, LoginDTO login, CancellationToken ct) { try { return await _dal.GetPayGatewayConfig(payGatewayConfId, login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "GetPayGatewayConfig failed for PayGatewayConfId {PayGatewayConfId}", payGatewayConfId); throw; } } // ── Get by gateway ID ───────────────────────────────────────────────── public async Task GetPayGatewayConfigByGatewayId(int payGatewayId, LoginDTO login, CancellationToken ct) { try { return await _dal.GetPayGatewayConfigByGatewayId(payGatewayId, login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "GetPayGatewayConfigByGatewayId failed for PayGatewayId {PayGatewayId}", payGatewayId); throw; } } // ── Save (insert or update) ─────────────────────────────────────────── // IMPORTANT: Vault key-path columns (ApiKeyIdVaultKey, ApiSecretVaultKey, // WebhookSecretVaultKey) are stored exactly as provided — never decrypted here. public async Task SavePayGatewayConfig(PayGatewayConfigDTO dto, LoginDTO login, CancellationToken ct) { if (dto is null) throw new ArgumentNullException(nameof(dto)); try { bool isNew = dto.PayGatewayConfId == 0; dto.TenantId = login.ClientId; if (isNew) { var autoNum = await _autoNumber.GetAutoNumber(1, "PAYGATEWAYCONFIG", login) .ConfigureAwait(false); dto.PayGatewayConfId = autoNum.StartNumber; dto.CreatedById = login.UserId; dto.CreatedOn = DateTime.UtcNow; } dto.ModifiedById = login.UserId; dto.ModifiedOn = DateTime.UtcNow; if (isNew) await _dal.SavePayGatewayConfig(dto, login).ConfigureAwait(false); else await _dal.UpdatePayGatewayConfig(dto, login).ConfigureAwait(false); // Invalidate tenant-level cache var cacheKey = new CacheKeyGeneration().KeyGeneration( dto.PayGatewayConfId.ToString(), EntityConstant.OBJECTPAYGATEWAYCONFIG, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); try { await _eventLogPublish.PublishEventLogAsync( isNew ? "Pay Gateway Config Created" : "Pay Gateway Config Updated", new { dto.PayGatewayConfId, dto.PayGatewayId }, Constant.EventTypeConstant.SAVEPAYGATEWAYCONFIGENTTYPEID, 0, login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogWarning(ex, "Event log publish failed for PayGatewayConfig {PayGatewayConfId}", dto.PayGatewayConfId); } return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.PayGatewayConfId}" : $"{SuccessResponse.UpdateSuccessMessage} {dto.PayGatewayConfId}"; } catch (Exception ex) { _logger.LogError(ex, "SavePayGatewayConfig failed for PayGatewayId {PayGatewayId}", dto.PayGatewayId); throw; } } // ── Soft-delete ─────────────────────────────────────────────────────── public async Task DeletePayGatewayConfig(int payGatewayConfId, LoginDTO login, CancellationToken ct) { try { var dto = new PayGatewayConfigDTO { PayGatewayConfId = payGatewayConfId, Status = 0, ModifiedById = login.UserId, ModifiedOn = DateTime.UtcNow, TenantId = login.ClientId }; await _dal.UpdatePayGatewayConfig(dto, login).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( payGatewayConfId.ToString(), EntityConstant.OBJECTPAYGATEWAYCONFIG, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { _logger.LogError(ex, "DeletePayGatewayConfig failed for PayGatewayConfId {PayGatewayConfId}", payGatewayConfId); throw; } } } }