Skip to content

Commit 2fa7e12

Browse files
authored
Merge pull request #3 from FiscalAPI/feat/logging
Feat/logging
2 parents 5f2b1b1 + 5a1045e commit 2fa7e12

19 files changed

+360
-82
lines changed

Auth/AuthResponseService.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
using Fiscalapi.XmlDownloader.Common;
2121
using Fiscalapi.XmlDownloader.Common.Enums;
2222
using Fiscalapi.XmlDownloader.Common.Http;
23+
using Microsoft.Extensions.Logging;
2324

2425
namespace Fiscalapi.XmlDownloader.Auth;
2526

2627
public static class AuthResponseService
2728
{
28-
public static AuthResponse Build(SatResponse satResponse, ICredential credential)
29+
public static AuthResponse Build(SatResponse satResponse, ICredential credential, ILogger logger)
2930
{
3031
/*
3132
*<s:envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
@@ -56,24 +57,54 @@ public static AuthResponse Build(SatResponse satResponse, ICredential credential
5657
if (satResponse.IsSuccessStatusCode)
5758
{
5859
var envelope = XmlSerializerService.Deserialize<AuthEnvelope>(satResponse.RawResponse!);
59-
return new AuthResponse
60+
var tokenValue = envelope?.Body?.AutenticaResponse?.AutenticaResult;
61+
62+
var authResponse = new AuthResponse
6063
{
6164
Succeeded = true,
6265
SatStatus = SatStatus.RequestSucceeded,
6366
SatStatusCode = SatStatus.RequestSucceeded.ToEnumCode(),
6467
SatMessage = "",
65-
TokenValue = envelope?.Body?.AutenticaResponse?.AutenticaResult,
68+
TokenValue = tokenValue,
6669
ValidFrom = envelope?.Header?.Security?.Timestamp?.Created,
6770
ValidTo = envelope?.Header?.Security?.Timestamp?.Expires,
6871
RawRequest = satResponse.RawRequest,
6972
RawResponse = satResponse.RawResponse,
7073
Tin = credential.Certificate.Rfc
7174
};
75+
76+
// Critical logging: Verify token was received
77+
if (string.IsNullOrWhiteSpace(tokenValue))
78+
{
79+
logger.LogWarning(
80+
"Authentication succeeded but token is missing. RFC: {Rfc}, HasEnvelope: {HasEnvelope}, HasBody: {HasBody}, HasAutenticaResponse: {HasAutenticaResponse}",
81+
credential.Certificate.Rfc,
82+
envelope != null,
83+
envelope?.Body != null,
84+
envelope?.Body?.AutenticaResponse != null);
85+
}
86+
else
87+
{
88+
logger.LogInformation(
89+
"Authentication succeeded. RFC: {Rfc}, TokenLength: {TokenLength}, ValidFrom: {ValidFrom}, ValidTo: {ValidTo}",
90+
credential.Certificate.Rfc,
91+
tokenValue.Length,
92+
authResponse.ValidFrom,
93+
authResponse.ValidTo);
94+
}
95+
96+
return authResponse;
7297
}
7398

7499
if (satResponse.RawResponse is not null && satResponse.RawResponse.ToLowerInvariant().Contains("fault"))
75100
{
76101
var faultEnvelope = XmlSerializerService.Deserialize<AuthFaultEnvelope>(satResponse.RawResponse);
102+
logger.LogError(
103+
"Authentication failed with SOAP fault. RFC: {Rfc}, FaultCode: {FaultCode}, FaultMessage: {FaultMessage}",
104+
credential.Certificate.Rfc,
105+
faultEnvelope?.Body?.Fault?.FaultCode,
106+
faultEnvelope?.Body?.Fault?.FaultMessage);
107+
77108
return new AuthResponse
78109
{
79110
Succeeded = false,
@@ -85,6 +116,12 @@ public static AuthResponse Build(SatResponse satResponse, ICredential credential
85116
};
86117
}
87118

119+
logger.LogError(
120+
"Authentication failed with unexpected status. RFC: {Rfc}, HttpStatusCode: {StatusCode}, ReasonPhrase: {ReasonPhrase}",
121+
credential.Certificate.Rfc,
122+
satResponse.HttpStatusCode,
123+
satResponse.ReasonPhrase);
124+
88125
return new AuthResponse
89126
{
90127
Succeeded = false,

Auth/AuthService.cs

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Fiscalapi.XmlDownloader.Auth.Models;
2020
using Fiscalapi.XmlDownloader.Common;
2121
using Fiscalapi.XmlDownloader.Common.Http;
22+
using Microsoft.Extensions.Logging;
2223

2324
namespace Fiscalapi.XmlDownloader.Auth;
2425

@@ -28,33 +29,87 @@ namespace Fiscalapi.XmlDownloader.Auth;
2829
public class AuthService : SatService, IAuthService
2930
{
3031
/// <summary>
31-
/// Authenticates with SAT using the provided credential and returns the authentication token
32+
/// Constructor for dependency injection scenarios
3233
/// </summary>
33-
public async Task<AuthResponse> AuthenticateAsync(ICredential credential,
34-
CancellationToken cancellationToken = default)
34+
/// <param name="httpClient">HttpClient instance</param>
35+
/// <param name="logger">Logger instance</param>
36+
public AuthService(HttpClient httpClient, ILogger<AuthService> logger)
37+
: base(httpClient, logger)
3538
{
36-
// Generate Sat XML security token ID
37-
var uuid = CreateSecurityToken();
38-
39-
// Create digest and signature using unified template
40-
var digest = CreateDigest(credential);
41-
var signature = CreateSignature(digest, credential, uuid);
42-
43-
// Build SOAP envelope
44-
var authXml = BuildEnvelope(digest, uuid, credential.Certificate.RawDataBytes.ToBase64String(),
45-
signature);
39+
}
4640

47-
// Send request
48-
var satResponse = await SendRequestAsync(
49-
url: SatUrl.AuthUrl,
50-
action: SatUrl.AuthAction,
51-
payload: authXml,
52-
cancellationToken: cancellationToken);
41+
/// <summary>
42+
/// Constructor for direct instantiation scenarios
43+
/// </summary>
44+
/// <param name="logger">Logger instance</param>
45+
public AuthService(ILogger<AuthService> logger)
46+
: base(logger)
47+
{
48+
}
5349

54-
// Map response
55-
var authResponse = AuthResponseService.Build(satResponse, credential);
50+
/// <summary>
51+
/// Authenticates with SAT using the provided credential and returns the authentication token
52+
/// </summary>
53+
public async Task<AuthResponse> AuthenticateAsync(ICredential credential,
54+
ILogger logger, CancellationToken cancellationToken = default)
55+
{
56+
logger.LogInformation("Starting SAT authentication process for RFC: {Rfc}", credential.Certificate.Rfc);
5657

57-
return authResponse;
58+
try
59+
{
60+
// Generate Sat XML security token ID
61+
var uuid = CreateSecurityToken();
62+
logger.LogDebug("Generated security token UUID: {Uuid}", uuid);
63+
64+
// Create digest and signature using unified template
65+
var digest = CreateDigest(credential);
66+
var signature = CreateSignature(digest, credential, uuid);
67+
68+
// Build SOAP envelope
69+
var authXml = BuildEnvelope(digest, uuid, credential.Certificate.RawDataBytes.ToBase64String(),
70+
signature);
71+
72+
// Send request
73+
logger.LogInformation("Sending authentication request to SAT. URL: {Url}", SatUrl.AuthUrl);
74+
var satResponse = await SendRequestAsync(
75+
url: SatUrl.AuthUrl,
76+
action: SatUrl.AuthAction,
77+
payload: authXml,
78+
cancellationToken: cancellationToken);
79+
80+
logger.LogInformation("SAT authentication response received. Success: {IsSuccessStatusCode}, Status: {StatusCode}",
81+
satResponse.IsSuccessStatusCode,
82+
satResponse.HttpStatusCode);
83+
84+
// Log complete XML response for debugging
85+
if (!satResponse.IsSuccessStatusCode || string.IsNullOrWhiteSpace(satResponse.RawResponse))
86+
{
87+
logger.LogError(
88+
"SAT authentication failed. RFC: {Rfc}, StatusCode: {StatusCode}, ReasonPhrase: {ReasonPhrase}, RawResponse: {RawResponse}",
89+
credential.Certificate.Rfc,
90+
satResponse.HttpStatusCode,
91+
satResponse.ReasonPhrase,
92+
satResponse.RawResponse ?? "[Empty Response]");
93+
}
94+
else
95+
{
96+
logger.LogDebug(
97+
"SAT authentication raw response XML. RFC: {Rfc}, ResponseLength: {Length}, RawResponse: {RawResponse}",
98+
credential.Certificate.Rfc,
99+
satResponse.RawResponse?.Length ?? 0,
100+
satResponse.RawResponse);
101+
}
102+
103+
// Map response
104+
var authResponse = AuthResponseService.Build(satResponse, credential, logger);
105+
106+
return authResponse;
107+
}
108+
catch (Exception ex)
109+
{
110+
logger.LogError(ex, "Error during SAT authentication process for RFC: {Rfc}", credential.Certificate.Rfc);
111+
throw;
112+
}
58113
}
59114

60115
/// <summary>

Auth/IAuthService.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
using Fiscalapi.Credentials.Core;
1818
using Fiscalapi.XmlDownloader.Auth.Models;
19+
using Microsoft.Extensions.Logging;
1920

2021
namespace Fiscalapi.XmlDownloader.Auth;
2122

@@ -29,6 +30,7 @@ public interface IAuthService
2930
/// </summary>
3031
/// <param name="credential"></param>
3132
/// <param name="cancellationToken">CancellationToken</param>
33+
/// <param name="logger">Logger</param>
3234
/// <returns></returns>
33-
Task<AuthResponse> AuthenticateAsync(ICredential credential, CancellationToken cancellationToken = default);
35+
Task<AuthResponse> AuthenticateAsync(ICredential credential, ILogger logger, CancellationToken cancellationToken = default);
3436
}

Common/Http/SatService.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
using System.Net;
1818
using System.Text;
19+
using Microsoft.Extensions.Logging;
1920

2021
namespace Fiscalapi.XmlDownloader.Common.Http;
2122

@@ -26,25 +27,28 @@ public abstract class SatService : IDisposable
2627
{
2728
private readonly HttpClient _httpClient;
2829
private readonly bool _ownsHttpClient;
30+
private readonly ILogger _logger;
2931
private bool _disposed;
3032

3133
protected bool IsDebugEnabled { get; set; }
3234

3335
/// <summary>
3436
/// Constructor for dependency injection scenarios
3537
/// </summary>
36-
protected SatService(HttpClient httpClient)
38+
protected SatService(HttpClient httpClient, ILogger logger)
3739
{
3840
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
41+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
3942
_ownsHttpClient = false;
4043
}
4144

4245
/// <summary>
4346
/// Constructor for direct instantiation scenarios
4447
/// </summary>
45-
protected SatService()
48+
protected SatService(ILogger logger)
4649
{
4750
_httpClient = new HttpClient();
51+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
4852
_ownsHttpClient = true;
4953
}
5054

@@ -100,6 +104,8 @@ protected async Task<SatResponse> SendRequestAsync(string url, string action, st
100104
{
101105
if (IsDebugEnabled)
102106
LogError(ex, url, action);
107+
108+
_logger.LogError(ex, "Error sending SOAP request to {Url} with action {Action}", url, action);
103109
104110
return new SatResponse
105111
{
@@ -118,7 +124,7 @@ protected async Task<SatResponse> SendRequestAsync(string url, string action, st
118124
/// <param name="url">Request URL</param>
119125
/// <param name="soapAction">SOAP action header</param>
120126
/// <param name="payload">Request payload</param>
121-
private static void LogRequest(HttpRequestMessage request, string url, string soapAction, string payload)
127+
private void LogRequest(HttpRequestMessage request, string url, string soapAction, string payload)
122128
{
123129
try
124130
{
@@ -150,11 +156,11 @@ private static void LogRequest(HttpRequestMessage request, string url, string so
150156
sb.AppendLine(payload);
151157
sb.AppendLine("=== END REQUEST ===");
152158

153-
Console.WriteLine(sb.ToString());
159+
_logger.LogDebug(sb.ToString());
154160
}
155161
catch (Exception ex)
156162
{
157-
Console.WriteLine($"Error logging request: {ex.Message}");
163+
_logger.LogError(ex, "Error logging request");
158164
}
159165
}
160166

@@ -165,7 +171,7 @@ private static void LogRequest(HttpRequestMessage request, string url, string so
165171
/// <param name="responseContent">Response content</param>
166172
/// <param name="url">Original request URL</param>
167173
/// <param name="soapAction">Original SOAP action</param>
168-
private static void LogResponse(HttpResponseMessage response, string responseContent, string url,
174+
private void LogResponse(HttpResponseMessage response, string responseContent, string url,
169175
string soapAction)
170176
{
171177
try
@@ -200,11 +206,11 @@ private static void LogResponse(HttpResponseMessage response, string responseCon
200206
sb.AppendLine(string.IsNullOrEmpty(responseContent) ? "[Empty Response]" : responseContent);
201207
sb.AppendLine("=== END RESPONSE ===");
202208

203-
Console.WriteLine(sb.ToString());
209+
_logger.LogDebug(sb.ToString());
204210
}
205211
catch (Exception ex)
206212
{
207-
Console.WriteLine($"Error logging response: {ex.Message}");
213+
_logger.LogError(ex, "Error logging response");
208214
}
209215
}
210216

@@ -214,7 +220,7 @@ private static void LogResponse(HttpResponseMessage response, string responseCon
214220
/// <param name="ex">Exception that occurred</param>
215221
/// <param name="url">Request URL</param>
216222
/// <param name="soapAction">SOAP action</param>
217-
private static void LogError(Exception ex, string url, string soapAction)
223+
private void LogError(Exception ex, string url, string soapAction)
218224
{
219225
try
220226
{
@@ -235,11 +241,11 @@ private static void LogError(Exception ex, string url, string soapAction)
235241
sb.AppendLine(ex.StackTrace);
236242
sb.AppendLine("=== END ERROR ===");
237243

238-
Console.WriteLine(sb.ToString());
244+
_logger.LogError(sb.ToString());
239245
}
240246
catch (Exception logEx)
241247
{
242-
Console.WriteLine($"Error logging exception: {logEx.Message}");
248+
_logger.LogError(logEx, "Error logging exception");
243249
}
244250
}
245251

Download/DownloadResponseService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
using Fiscalapi.XmlDownloader.Common.Http;
2020
using Fiscalapi.XmlDownloader.Download.Models;
2121
using Fiscalapi.XmlDownloader.Download.Models.Sat;
22+
using Microsoft.Extensions.Logging;
2223

2324
namespace Fiscalapi.XmlDownloader.Download;
2425

2526
public static class DownloadResponseService
2627
{
27-
public static DownloadResponse Build(SatResponse satResponse)
28+
public static DownloadResponse Build(SatResponse satResponse, ILogger logger)
2829
{
2930
if (satResponse.IsSuccessStatusCode)
3031
{

0 commit comments

Comments
 (0)