fix: Resolve encoding issue for AgroFetcher and authorization for BcrFetcher
This commit is contained in:
@@ -11,19 +11,23 @@ namespace Mercados.Infrastructure.DataFetchers
|
|||||||
public class BcrDataFetcher : IDataFetcher
|
public class BcrDataFetcher : IDataFetcher
|
||||||
{
|
{
|
||||||
#region Clases DTO para la respuesta de la API de BCR
|
#region Clases DTO para la respuesta de la API de BCR
|
||||||
private class BcrTokenResponse {
|
private class BcrTokenResponse
|
||||||
|
{
|
||||||
[JsonPropertyName("data")]
|
[JsonPropertyName("data")]
|
||||||
public TokenData? Data { get; set; }
|
public TokenData? Data { get; set; }
|
||||||
}
|
}
|
||||||
private class TokenData {
|
private class TokenData
|
||||||
|
{
|
||||||
[JsonPropertyName("token")]
|
[JsonPropertyName("token")]
|
||||||
public string? Token { get; set; }
|
public string? Token { get; set; }
|
||||||
}
|
}
|
||||||
private class BcrPreciosResponse {
|
private class BcrPreciosResponse
|
||||||
|
{
|
||||||
[JsonPropertyName("data")]
|
[JsonPropertyName("data")]
|
||||||
public List<BcrPrecioItem>? Data { get; set; }
|
public List<BcrPrecioItem>? Data { get; set; }
|
||||||
}
|
}
|
||||||
private class BcrPrecioItem {
|
private class BcrPrecioItem
|
||||||
|
{
|
||||||
[JsonPropertyName("precio_Cotizacion")]
|
[JsonPropertyName("precio_Cotizacion")]
|
||||||
public decimal PrecioCotizacion { get; set; }
|
public decimal PrecioCotizacion { get; set; }
|
||||||
[JsonPropertyName("variacion_Precio_Cotizacion")]
|
[JsonPropertyName("variacion_Precio_Cotizacion")]
|
||||||
@@ -47,10 +51,10 @@ namespace Mercados.Infrastructure.DataFetchers
|
|||||||
private readonly ILogger<BcrDataFetcher> _logger;
|
private readonly ILogger<BcrDataFetcher> _logger;
|
||||||
|
|
||||||
public BcrDataFetcher(
|
public BcrDataFetcher(
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
ICotizacionGranoRepository cotizacionRepository,
|
ICotizacionGranoRepository cotizacionRepository,
|
||||||
IFuenteDatoRepository fuenteDatoRepository,
|
IFuenteDatoRepository fuenteDatoRepository,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
ILogger<BcrDataFetcher> logger)
|
ILogger<BcrDataFetcher> logger)
|
||||||
{
|
{
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
@@ -65,19 +69,26 @@ namespace Mercados.Infrastructure.DataFetchers
|
|||||||
_logger.LogInformation("Iniciando fetch para {SourceName}.", SourceName);
|
_logger.LogInformation("Iniciando fetch para {SourceName}.", SourceName);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = _httpClientFactory.CreateClient();
|
var client = _httpClientFactory.CreateClient(); // Creamos el cliente una vez
|
||||||
|
|
||||||
var token = await GetAuthTokenAsync(client);
|
var token = await GetAuthTokenAsync(client);
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
return (false, "No se pudo obtener el token de autenticación de BCR.");
|
return (false, "No se pudo obtener el token de autenticación de BCR.");
|
||||||
}
|
}
|
||||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
// Añadimos el token a las cabeceras por defecto de este cliente para todas las peticiones futuras.
|
||||||
|
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Replace("Bearer ", "")); // Aseguramos que no haya doble "Bearer"
|
||||||
|
|
||||||
var cotizaciones = new List<CotizacionGrano>();
|
var cotizaciones = new List<CotizacionGrano>();
|
||||||
|
var fechaDesde = DateTime.Now.AddDays(-3).ToString("yyyy-MM-dd");
|
||||||
|
var fechaHasta = DateTime.Now.ToString("yyyy-MM-dd");
|
||||||
|
|
||||||
foreach (var grain in _grainIds)
|
foreach (var grain in _grainIds)
|
||||||
{
|
{
|
||||||
var response = await client.GetFromJsonAsync<BcrPreciosResponse>(
|
var requestUrl = $"{BaseUrl}/PreciosCamara?idGrano={grain.Value}&fechaConcertacionDesde={fechaDesde}&fechaConcertacionHasta={fechaHasta}";
|
||||||
$"{BaseUrl}/PreciosCamara?idGrano={grain.Value}&fechaConcertacionDesde={DateTime.Now.AddDays(-3):yyyy-MM-dd}&fechaConcertacionHasta={DateTime.Now:yyyy-MM-dd}");
|
|
||||||
|
// Usamos el mismo cliente que ya tiene el token configurado.
|
||||||
|
var response = await client.GetFromJsonAsync<BcrPreciosResponse>(requestUrl);
|
||||||
|
|
||||||
var latestRecord = response?.Data?.OrderByDescending(r => r.FechaOperacionPizarra).FirstOrDefault();
|
var latestRecord = response?.Data?.OrderByDescending(r => r.FechaOperacionPizarra).FirstOrDefault();
|
||||||
if (latestRecord != null)
|
if (latestRecord != null)
|
||||||
@@ -92,12 +103,12 @@ namespace Mercados.Infrastructure.DataFetchers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cotizaciones.Any()) return (false, "No se obtuvieron datos de granos de BCR.");
|
if (!cotizaciones.Any()) return (false, "No se obtuvieron datos de granos de BCR.");
|
||||||
|
|
||||||
await _cotizacionRepository.GuardarMuchosAsync(cotizaciones);
|
await _cotizacionRepository.GuardarMuchosAsync(cotizaciones);
|
||||||
await UpdateSourceInfoAsync();
|
await UpdateSourceInfoAsync();
|
||||||
|
|
||||||
_logger.LogInformation("Fetch para {SourceName} completado. Se guardaron {Count} registros.", SourceName, cotizaciones.Count);
|
_logger.LogInformation("Fetch para {SourceName} completado. Se guardaron {Count} registros.", SourceName, cotizaciones.Count);
|
||||||
return (true, $"Proceso completado. Se guardaron {cotizaciones.Count} registros.");
|
return (true, $"Proceso completado. Se guardaron {cotizaciones.Count} registros.");
|
||||||
}
|
}
|
||||||
@@ -113,14 +124,14 @@ namespace Mercados.Infrastructure.DataFetchers
|
|||||||
var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/Login");
|
var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/Login");
|
||||||
request.Headers.Add("api_key", _configuration["ApiKeys:Bcr:Key"]);
|
request.Headers.Add("api_key", _configuration["ApiKeys:Bcr:Key"]);
|
||||||
request.Headers.Add("secret", _configuration["ApiKeys:Bcr:Secret"]);
|
request.Headers.Add("secret", _configuration["ApiKeys:Bcr:Secret"]);
|
||||||
|
|
||||||
var response = await client.SendAsync(request);
|
var response = await client.SendAsync(request);
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
var tokenResponse = await response.Content.ReadFromJsonAsync<BcrTokenResponse>();
|
var tokenResponse = await response.Content.ReadFromJsonAsync<BcrTokenResponse>();
|
||||||
return tokenResponse?.Data?.Token;
|
return tokenResponse?.Data?.Token;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateSourceInfoAsync()
|
private async Task UpdateSourceInfoAsync()
|
||||||
{
|
{
|
||||||
var fuente = await _fuenteDatoRepository.ObtenerPorNombreAsync(SourceName);
|
var fuente = await _fuenteDatoRepository.ObtenerPorNombreAsync(SourceName);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" />
|
||||||
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.6" />
|
||||||
<PackageReference Include="ThreeFourteen.Finnhub.Client" Version="1.2.0" />
|
<PackageReference Include="ThreeFourteen.Finnhub.Client" Version="1.2.0" />
|
||||||
<PackageReference Include="YahooFinanceApi" Version="2.3.3" />
|
<PackageReference Include="YahooFinanceApi" Version="2.3.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
using System.Text;
|
||||||
using Mercados.Infrastructure;
|
using Mercados.Infrastructure;
|
||||||
using Mercados.Infrastructure.DataFetchers;
|
using Mercados.Infrastructure.DataFetchers;
|
||||||
using Mercados.Infrastructure.Persistence;
|
using Mercados.Infrastructure.Persistence;
|
||||||
using Mercados.Infrastructure.Persistence.Repositories;
|
using Mercados.Infrastructure.Persistence.Repositories;
|
||||||
using Mercados.Worker;
|
using Mercados.Worker;
|
||||||
|
|
||||||
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
// --- Configuración del Host ---
|
// --- Configuración del Host ---
|
||||||
// Esto prepara el host del servicio, permitiendo la inyección de dependencias,
|
// Esto prepara el host del servicio, permitiendo la inyección de dependencias,
|
||||||
// la configuración desde appsettings.json y el logging.
|
// la configuración desde appsettings.json y el logging.
|
||||||
|
|||||||
Reference in New Issue
Block a user