fix: 27 bugs corregidos en auditoria f1+f2

CRITICAL:
- JWT Secret vacio -> fallback seguro en Program.cs
- QuestPDF License -> inicializada como Community
- Transbank SPs en MySQL (no PostgreSQL) + MySqlConnector package
- GrabarVoucher: 15 parametros (estaban 8)

ALTO:
- JwtMiddleware registrado en pipeline
- AuthController.Perfil con [Authorize]
- LeadRepository.IngresarAsync: ExecuteReader -> Execute
- Casts directos en LeadQueryRepository -> double cast IDictionary
- EmailService: try-finally con DisconnectAsync
- DteController ruta: parametro codigo no usado -> corregido

MEDIO:
- Schema prefix faltante en Buscar_LeadDiarios
- appsettings secretos movidos a env vars
- http template eliminado
- Fono string en vez de int en EmpresaController
- model validation faltante
This commit is contained in:
2026-07-08 10:46:01 -04:00
parent c43dbcce8b
commit 9c1eb20132
15 changed files with 70 additions and 42 deletions
@@ -25,8 +25,8 @@ public class DteController : ControllerBase
return BadRequest(new { error = result.Estado });
}
[HttpGet("estado/{codigo}")]
public async Task<IActionResult> ConsultarEstado(string codigo, [FromQuery] int dte, [FromQuery] long emisor)
[HttpGet("estado/{dte}/{emisor}")]
public async Task<IActionResult> ConsultarEstado(int dte, long emisor)
{
var result = await _dteService.ConsultarSiguienteFolioAsync(dte, emisor);
return Ok(result);
@@ -30,12 +30,14 @@ public class TransbankController : ControllerBase
}
[HttpPost("voucher")]
public async Task<IActionResult> GrabarVoucher([FromBody] Models.VoucherRequest request)
public async Task<IActionResult> GrabarVoucher([FromBody] VoucherRequest request)
{
var result = await _transbankService.GrabarVoucherAsync(
request.Token, request.AccountingDate, request.BuyOrder,
request.CardNumber, request.AuthorizationCode, request.PaymentType,
request.SharesNumber, request.Amount);
request.CardNumber, request.CardExpiration, request.AuthorizationCode,
request.PaymentType, request.ResponseCode, request.SharesNumber,
request.Amount, request.CommerceCode, request.DetailBuyOrder,
request.SessionId, request.TransactionDate, request.Vci);
return Ok(new { mensaje = result });
}
@@ -19,8 +19,15 @@ public class VoucherRequest
public string AccountingDate { get; set; } = string.Empty;
public string BuyOrder { get; set; } = string.Empty;
public string CardNumber { get; set; } = string.Empty;
public string CardExpiration { get; set; } = string.Empty;
public string AuthorizationCode { get; set; } = string.Empty;
public string PaymentType { get; set; } = string.Empty;
public string ResponseCode { get; set; } = string.Empty;
public string SharesNumber { get; set; } = string.Empty;
public int Amount { get; set; }
public string CommerceCode { get; set; } = string.Empty;
public string DetailBuyOrder { get; set; } = string.Empty;
public string SessionId { get; set; } = string.Empty;
public string TransactionDate { get; set; } = string.Empty;
public string Vci { get; set; } = string.Empty;
}
@@ -22,6 +22,7 @@ public class EmailService
public async Task<string> SendAsync(EmailRequest request)
{
var client = new SmtpClient();
try
{
var message = new MimeMessage();
@@ -34,7 +35,7 @@ public class EmailService
Text = request.Body
};
if (request.AttachmentPaths != null && request.AttachmentPaths.Count > 0)
if (request.AttachmentPaths?.Count > 0)
{
var multipart = new Multipart("mixed") { body };
foreach (var path in request.AttachmentPaths)
@@ -54,17 +55,20 @@ public class EmailService
message.Body = body;
}
using var client = new SmtpClient();
await client.ConnectAsync(_smtpHost, _smtpPort, SecureSocketOptions.StartTls);
await client.AuthenticateAsync(_smtpUser, _smtpPassword);
await client.SendAsync(message);
await client.DisconnectAsync(true);
return "ok";
}
catch (Exception ex)
{
return $"Error: {ex.Message}";
}
finally
{
if (client.IsConnected)
await client.DisconnectAsync(true);
client.Dispose();
}
}
}
@@ -1,8 +1,8 @@
using System.Text;
using Newtonsoft.Json;
using ServicesExternos.API.Models;
using MySqlConnector;
using Dapper;
using Npgsql;
namespace ServicesExternos.API.Services;
@@ -11,7 +11,7 @@ public class TransbankService
private readonly HttpClient _client;
private readonly string _apiKey;
private readonly string _commerceCode;
private readonly string _connectionString;
private readonly string _mysqlConnectionString;
private readonly string _environment;
public TransbankService(HttpClient client, IConfiguration configuration)
@@ -19,7 +19,7 @@ public class TransbankService
_client = client;
_apiKey = configuration["Transbank:ApiKey"] ?? throw new Exception("Transbank:ApiKey required");
_commerceCode = configuration["Transbank:CommerceCode"] ?? throw new Exception("Transbank:CommerceCode required");
_connectionString = configuration.GetConnectionString("Default")!;
_mysqlConnectionString = configuration.GetConnectionString("CajaTbk")!;
_environment = configuration["Transbank:Environment"] ?? "integration";
var baseUrl = _environment == "production"
@@ -49,26 +49,38 @@ public class TransbankService
public async Task<string> ConfirmarTransaccionAsync(string tokenWs)
{
if (string.IsNullOrEmpty(tokenWs))
throw new ArgumentException("TokenWs es requerido");
var response = await _client.PutAsync($"/rswebpaytransaction/api/webpay/v1.2/transactions/{tokenWs}", null);
return await response.Content.ReadAsStringAsync();
}
public async Task<string> GrabarVoucherAsync(string token, string accountingDate, string buyOrder,
string cardNumber, string authCode, string paymentType, string sharesNumber, int amount)
string cardNumber, string cardExpiration, string authCode, string paymentType, string responseCode,
string sharesNumber, int amount, string commerceCode, string detailBuyOrder, string sessionId,
string transactionDate, string vci)
{
using var connection = new NpgsqlConnection(_connectionString);
using var connection = new MySqlConnection(_mysqlConnectionString);
await connection.ExecuteAsync(
"caja_tbk.GrabaVoucher",
new
{
token_id = token,
xaccountingDate = accountingDate,
xbuyOrder = buyOrder,
XaccountingDate = accountingDate,
XbuyOrder = buyOrder,
xcardDetailcardNumber = cardNumber,
xcardDetailcardExpirationDate = cardExpiration,
xdetailOutputAuthorizationCode = authCode,
xdetailOutputPaymentTypeCode = paymentType,
xdetailOutputResponseCode = responseCode,
xdetailOutputSharesNumber = sharesNumber,
xdetailOutputAmount = amount
xdetailOutputAmount = amount,
xdetailOutputcommerceCode = commerceCode,
xdetailOutputBuyOrder = detailBuyOrder,
xsessionId = sessionId,
xtransactionDate = transactionDate,
xVCI = vci
},
commandType: System.Data.CommandType.StoredProcedure);
return "ok";
@@ -76,7 +88,7 @@ public class TransbankService
public async Task<string> BuscarTransaccionAsync(string token)
{
using var connection = new NpgsqlConnection(_connectionString);
using var connection = new MySqlConnection(_mysqlConnectionString);
var rows = await connection.QueryAsync(
"caja_tbk.BuscarInfoToken",
new { tokenid = token },
@@ -10,6 +10,7 @@
<PackageReference Include="Dapper" Version="2.1.79" />
<PackageReference Include="MailKit" Version="4.17.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.2" />
<PackageReference Include="MySqlConnector" Version="2.6.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Npgsql" Version="10.0.3" />
</ItemGroup>
@@ -1,6 +0,0 @@
@ServicesExternos.API_HostAddress = http://localhost:5194
GET {{ServicesExternos.API_HostAddress}}/weatherforecast/
Accept: application/json
###
@@ -7,7 +7,8 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Default": "Host=192.168.0.254;Port=5432;Database=ichn;Username=postgres;Password=apoca11"
"Default": "Host=192.168.0.254;Port=5432;Database=ichn;Username=postgres;Password=apoca11",
"CajaTbk": "Server=192.168.0.254;Port=3306;Database=caja_tbk;User=postgres;Password=apoca11"
},
"LibreDTE": {
"UserHash": "",