using System.Text.Json; using ComplianceBLL.Adapter; using ComplianceDAL.CustomCode.AdapterConfig; using ComplianceDAL.DTO.GSTReturn; using GB5Shared.DTO.Framework.Login; using GB5Shared.Resource.GB5Solution; using GB5Shared.Validation; using Microsoft.Extensions.Logging; namespace ComplianceBLL.GSTValidate; public class GSTValidateBLL : IGSTValidateBLL { private readonly IAdapterConfigDAL _adapterConfigDal; private readonly IComplianceAdapterFactory _adapterFactory; private readonly IValidation _validation; private readonly ILogger _logger; public GSTValidateBLL( IAdapterConfigDAL adapterConfigDal, IComplianceAdapterFactory adapterFactory, IValidation validation, ILogger logger) { _adapterConfigDal = adapterConfigDal; _adapterFactory = adapterFactory; _validation = validation; _logger = logger; } // Ported from GB4's GSTCafeServiceBLL.GetOTPRequest: step 1 of the OTP+auth-token flow every // GST Returns call requires. Builds the initial GSTHeaderDTO from the resolved AdapterConfigDTO // (Username/StateCode) — the FE has nothing more than the GSTIN at this point. public async Task RequestOTPAsync(string gstin, string returnPeriod, LoginDTO login, CancellationToken ct) { try { await _validation.NotEmpty(gstin, nameof(gstin)); var adapterConfig = await _adapterConfigDal.GetAdapterConfigByGSTIN(gstin, "GST_INDIA", login, ct).ConfigureAwait(false); if (adapterConfig is null) return JsonSerializer.Serialize(new { success = false, message = ComplianceResource.AdapterConfigNotFound }); var header = new GSTHeaderDTO { GSTIN = gstin, UserName = adapterConfig.GSTNUserId, StateCode = adapterConfig.StateCode, ReturnPeriod = returnPeriod }; var adapter = _adapterFactory.GetAdapter(adapterConfig); var result = await adapter.RequestOTPAsync(header, adapterConfig, ct).ConfigureAwait(false); if (!result.IsSuccess) return JsonSerializer.Serialize(new { success = false, message = ComplianceResource.PortalError, errorMessage = result.ErrorMessage }); // FE must echo this back as the appKey param on GetAuthTokenAsync — GSTN's Authentication // API spec reuses the same app-key across the OTP-request and auth-token-exchange calls. return JsonSerializer.Serialize(new { success = true, message = "OTP sent. Enter it to authenticate.", appKey = result.AppKey }); } catch (Exception ex) { _logger.LogError(ex, "GST Validate: RequestOTPAsync failed for GSTIN {GSTIN}", gstin); throw; } } // Ported from GB4's GSTCafeServiceBLL.GetAuthToken: step 2 — exchanges the OTP for auth_token/sek. // Returns the full GSTHeaderDTO (GSTIN/UserName/StateCode/AuthToken/Sek) so the FE can replay it // wholesale as the GSTHeader request header on every subsequent Submit/File/Sync/Fetch call. public async Task GetAuthTokenAsync(string gstin, string otp, string appKey, string returnPeriod, LoginDTO login, CancellationToken ct) { try { await _validation.NotEmpty(gstin, nameof(gstin)); await _validation.NotEmpty(otp, nameof(otp)); await _validation.NotEmpty(appKey, nameof(appKey)); var adapterConfig = await _adapterConfigDal.GetAdapterConfigByGSTIN(gstin, "GST_INDIA", login, ct).ConfigureAwait(false); if (adapterConfig is null) return JsonSerializer.Serialize(new { success = false, message = ComplianceResource.AdapterConfigNotFound }); var header = new GSTHeaderDTO { GSTIN = gstin, UserName = adapterConfig.GSTNUserId, StateCode = adapterConfig.StateCode, ReturnPeriod = returnPeriod, AppKey = appKey }; var adapter = _adapterFactory.GetAdapter(adapterConfig); var result = await adapter.GetAuthTokenAsync(otp, header, adapterConfig, ct).ConfigureAwait(false); if (!result.IsSuccess) return JsonSerializer.Serialize(new { success = false, message = ComplianceResource.PortalError, errorMessage = result.ErrorMessage }); header.AuthToken = result.AuthToken; header.Sek = result.Sek; return JsonSerializer.Serialize(new { success = true, header }); } catch (Exception ex) { _logger.LogError(ex, "GST Validate: GetAuthTokenAsync failed for GSTIN {GSTIN}", gstin); throw; } } }