feat: fase 2 - services externos (dte, transbank, email)
- New solution ServicesExternos.slnx with standalone API project - DteService + DteController (LibreDTE: emitir, generar PDF, consultar folio) - TransbankService + TransbankController (crear transacción, confirmar, voucher SP) - EmailService + EmailController (MailKit: send with HTML + attachments) - Models for DTE, Transbank, Email requests/responses - Dockerfile + appsettings.json with all service configs - HttpClient factory for Transbank and LibreDTE - Build: 0 errors
This commit is contained in:
+15
-7
@@ -20,7 +20,7 @@
|
||||
| Reportes QuestPDF (17 reportes Crystal) | ✅ COMPLETO |
|
||||
| Reportes empresa (variantes) + controller | ✅ COMPLETO |
|
||||
| Reportes QuestPDF (17 reportes) | ❌ PENDIENTE |
|
||||
| ServicesExternos.API | ❌ PENDIENTE |
|
||||
| ServicesExternos.API | ✅ COMPLETO |
|
||||
| Frontend Next.js | ❌ PENDIENTE |
|
||||
| Contenedores (Docker) | ❌ PENDIENTE |
|
||||
| Tests E2E | ❌ PENDIENTE |
|
||||
@@ -61,12 +61,19 @@
|
||||
|
||||
### FASE 2: SERVICES EXTERNOS API (~2-3 semanas)
|
||||
|
||||
- [ ] **2.0 Setup**
|
||||
- [ ] ServicesExternos.sln + proyectos
|
||||
- [ ] Program.cs + Dockerfile
|
||||
- [ ] **2.1 LibreDTE** (~1 sem)
|
||||
- [ ] **2.2 Transbank Webpay** (~1 sem)
|
||||
- [ ] **2.3 Email con MailKit** (~2 días)
|
||||
- [x] **2.0 Setup**
|
||||
- [x] ServicesExternos.slnx + API project + Dockerfile
|
||||
- [x] Program.cs con DI (HttpClient factory + servicios)
|
||||
- [x] appsettings.json con config de servicios
|
||||
- [x] **2.1 LibreDTE** (~1 sem)
|
||||
- [x] DteService (emitir, generar PDF, consultar folio)
|
||||
- [x] DteController (emitir endpoint with PDF download)
|
||||
- [x] **2.2 Transbank Webpay** (~1 sem)
|
||||
- [x] TransbankService (crear transacción, confirmar, voucher)
|
||||
- [x] TransbankController + Voucher SP integration
|
||||
- [x] **2.3 Email con MailKit** (~2 días)
|
||||
- [x] EmailService (send with HTML templates + attachments)
|
||||
- [x] EmailController (send endpoint)
|
||||
|
||||
### FASE 3: FRONTEND NEXT.JS (~6-8 semanas)
|
||||
|
||||
@@ -112,6 +119,7 @@
|
||||
| 2026-07-08 | F1.3-1.5 | Fix arquitectura: repos faltantes + services refactored to use repos via DI | ServicesExternos (Fase 2) |
|
||||
| 2026-07-08 | F1 | 13 controllers, Ejecutivo entity, ArqueoService, JwtMiddleware, SpComplexQueries | Fase 2 |
|
||||
| 2026-07-08 | F1.7 | Reportes restantes: Anexo, ContratoBlack, Presupuesto, CAEMP/CAEMPSNC, CC_EMPCSD, PropuestaComercial | Fase 2 |
|
||||
| 2026-07-08 | F2 | ServicesExternos: DTE (LibreDTE), Transbank Webpay, Email (MailKit) + API + Dockerfile | Fase 3 (Frontend) |
|
||||
| | | | |
|
||||
| | | | |
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<Solution>
|
||||
<Folder Name="/src/">
|
||||
<Project Path="src/ServicesExternos.API/ServicesExternos.API.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
@@ -0,0 +1,34 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ServicesExternos.API.Models;
|
||||
using ServicesExternos.API.Services;
|
||||
|
||||
namespace ServicesExternos.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/dte")]
|
||||
public class DteController : ControllerBase
|
||||
{
|
||||
private readonly DteService _dteService;
|
||||
|
||||
public DteController(DteService dteService)
|
||||
{
|
||||
_dteService = dteService;
|
||||
}
|
||||
|
||||
[HttpPost("emitir")]
|
||||
public async Task<IActionResult> Emitir([FromBody] DteEmissionRequest request)
|
||||
{
|
||||
var result = await _dteService.EmitirYDescargarPdfAsync(request);
|
||||
if (result.PdfBytes != null)
|
||||
return File(result.PdfBytes, "application/pdf", $"dte_{result.Folio}.pdf");
|
||||
|
||||
return BadRequest(new { error = result.Estado });
|
||||
}
|
||||
|
||||
[HttpGet("estado/{codigo}")]
|
||||
public async Task<IActionResult> ConsultarEstado(string codigo, [FromQuery] int dte, [FromQuery] long emisor)
|
||||
{
|
||||
var result = await _dteService.ConsultarSiguienteFolioAsync(dte, emisor);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ServicesExternos.API.Models;
|
||||
using ServicesExternos.API.Services;
|
||||
|
||||
namespace ServicesExternos.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/email")]
|
||||
public class EmailController : ControllerBase
|
||||
{
|
||||
private readonly EmailService _emailService;
|
||||
|
||||
public EmailController(EmailService emailService)
|
||||
{
|
||||
_emailService = emailService;
|
||||
}
|
||||
|
||||
[HttpPost("send")]
|
||||
public async Task<IActionResult> Send([FromBody] EmailRequest request)
|
||||
{
|
||||
var result = await _emailService.SendAsync(request);
|
||||
if (result == "ok")
|
||||
return Ok(new { mensaje = result });
|
||||
|
||||
return BadRequest(new { error = result });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ServicesExternos.API.Models;
|
||||
using ServicesExternos.API.Services;
|
||||
|
||||
namespace ServicesExternos.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/pagos/transbank")]
|
||||
public class TransbankController : ControllerBase
|
||||
{
|
||||
private readonly TransbankService _transbankService;
|
||||
|
||||
public TransbankController(TransbankService transbankService)
|
||||
{
|
||||
_transbankService = transbankService;
|
||||
}
|
||||
|
||||
[HttpPost("crear-transaccion")]
|
||||
public async Task<IActionResult> CrearTransaccion([FromBody] TransbankTransactionRequest request)
|
||||
{
|
||||
var result = await _transbankService.CrearTransaccionAsync(request);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("confirmar")]
|
||||
public async Task<IActionResult> Confirmar([FromBody] TransbankConfirmRequest request)
|
||||
{
|
||||
var result = await _transbankService.ConfirmarTransaccionAsync(request.TokenWs!);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("voucher")]
|
||||
public async Task<IActionResult> GrabarVoucher([FromBody] Models.VoucherRequest request)
|
||||
{
|
||||
var result = await _transbankService.GrabarVoucherAsync(
|
||||
request.Token, request.AccountingDate, request.BuyOrder,
|
||||
request.CardNumber, request.AuthorizationCode, request.PaymentType,
|
||||
request.SharesNumber, request.Amount);
|
||||
return Ok(new { mensaje = result });
|
||||
}
|
||||
|
||||
[HttpGet("buscar/{token}")]
|
||||
public async Task<IActionResult> Buscar(string token)
|
||||
{
|
||||
var result = await _transbankService.BuscarTransaccionAsync(token);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
namespace ServicesExternos.API.Models;
|
||||
|
||||
public class DteEmissionRequest
|
||||
{
|
||||
public int Dte { get; set; } = 33;
|
||||
public int Emisor { get; set; }
|
||||
public string? Fecha { get; set; }
|
||||
public string? Sucursal { get; set; }
|
||||
public int? SucursalSii { get; set; }
|
||||
public string? Terminal { get; set; }
|
||||
public string? IndicadorServicio { get; set; }
|
||||
public string? TipoDespacho { get; set; }
|
||||
public string? TipoTraslado { get; set; }
|
||||
public string? TpoTranCompra { get; set; }
|
||||
public string? TpoTranVenta { get; set; }
|
||||
public string? FechaVencimiento { get; set; }
|
||||
public Receptor? Receptor { get; set; }
|
||||
public List<DetalleItem>? Detalles { get; set; }
|
||||
public Referencia? Referencia { get; set; }
|
||||
}
|
||||
|
||||
public class Receptor
|
||||
{
|
||||
public string? RUT { get; set; }
|
||||
public string? RazonSocial { get; set; }
|
||||
public string? Direccion { get; set; }
|
||||
public string? Comuna { get; set; }
|
||||
public string? Ciudad { get; set; }
|
||||
}
|
||||
|
||||
public class DetalleItem
|
||||
{
|
||||
public string? Nombre { get; set; }
|
||||
public int Cantidad { get; set; }
|
||||
public int Precio { get; set; }
|
||||
public string? Descuento { get; set; }
|
||||
}
|
||||
|
||||
public class Referencia
|
||||
{
|
||||
public int TipoDocReferencia { get; set; }
|
||||
public int FolioReferencia { get; set; }
|
||||
public string? FechaReferencia { get; set; }
|
||||
public string? RazonReferencia { get; set; }
|
||||
}
|
||||
|
||||
public class DteGenerarPorCodigo
|
||||
{
|
||||
public string? Codigo { get; set; }
|
||||
public int TipoDte { get; set; }
|
||||
public int Emisor { get; set; }
|
||||
public int Receptor { get; set; }
|
||||
}
|
||||
|
||||
public class DteFolioInfo
|
||||
{
|
||||
public int FoliosDisponibles { get; set; }
|
||||
public int FolioActual { get; set; }
|
||||
public int? Siguiente { get; set; }
|
||||
}
|
||||
|
||||
public class DteResultado
|
||||
{
|
||||
public byte[]? PdfBytes { get; set; }
|
||||
public int Folio { get; set; }
|
||||
public string Estado { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ServicesExternos.API.Models;
|
||||
|
||||
public class EmailRequest
|
||||
{
|
||||
public string? To { get; set; }
|
||||
public string? Subject { get; set; }
|
||||
public string? Body { get; set; }
|
||||
public bool IsHtml { get; set; } = true;
|
||||
public List<string>? AttachmentPaths { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace ServicesExternos.API.Models;
|
||||
|
||||
public class TransbankTransactionRequest
|
||||
{
|
||||
public string? BuyOrder { get; set; }
|
||||
public string? SessionId { get; set; }
|
||||
public int Amount { get; set; }
|
||||
public string? ReturnUrl { get; set; }
|
||||
}
|
||||
|
||||
public class TransbankConfirmRequest
|
||||
{
|
||||
public string? TokenWs { get; set; }
|
||||
}
|
||||
|
||||
public class VoucherRequest
|
||||
{
|
||||
public string Token { get; set; } = string.Empty;
|
||||
public string AccountingDate { get; set; } = string.Empty;
|
||||
public string BuyOrder { get; set; } = string.Empty;
|
||||
public string CardNumber { get; set; } = string.Empty;
|
||||
public string AuthorizationCode { get; set; } = string.Empty;
|
||||
public string PaymentType { get; set; } = string.Empty;
|
||||
public string SharesNumber { get; set; } = string.Empty;
|
||||
public int Amount { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using ServicesExternos.API.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
builder.Services.AddHttpClient<DteService>();
|
||||
builder.Services.AddHttpClient<TransbankService>();
|
||||
builder.Services.AddScoped<EmailService>();
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddDefaultPolicy(policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
app.MapOpenApi();
|
||||
|
||||
app.UseCors();
|
||||
app.MapControllers();
|
||||
app.Run();
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5194",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ServicesExternos.API.Models;
|
||||
|
||||
namespace ServicesExternos.API.Services;
|
||||
|
||||
public class DteService
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
private readonly string _userHash;
|
||||
private readonly string _ambiente;
|
||||
|
||||
public DteService(HttpClient client, IConfiguration configuration)
|
||||
{
|
||||
_client = client;
|
||||
_client.BaseAddress = new Uri("https://libredte.cl");
|
||||
_client.Timeout = TimeSpan.FromSeconds(60);
|
||||
_userHash = configuration["LibreDTE:UserHash"] ?? throw new Exception("LibreDTE:UserHash required");
|
||||
_ambiente = configuration["LibreDTE:Ambiente"] ?? "1";
|
||||
}
|
||||
|
||||
private void SetAuth()
|
||||
{
|
||||
var authString = Convert.ToBase64String(Encoding.ASCII.GetBytes("X:" + _userHash));
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authString);
|
||||
}
|
||||
|
||||
public async Task<DteResultado> EmitirYDescargarPdfAsync(DteEmissionRequest datos)
|
||||
{
|
||||
SetAuth();
|
||||
string jsonFinal = JsonConvert.SerializeObject(datos, Formatting.Indented);
|
||||
var jsonContent = new StringContent(jsonFinal, Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _client.PostAsync("/api/dte/documentos/emitir", jsonContent);
|
||||
string respuestaJson = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return new DteResultado { Estado = respuestaJson };
|
||||
|
||||
JObject jsonResp = JObject.Parse(respuestaJson);
|
||||
string cod = (string)jsonResp["codigo"]!;
|
||||
int emi = (int)jsonResp["emisor"]!;
|
||||
int rec = (int)jsonResp["receptor"]!;
|
||||
int dte = (int)jsonResp["dte"]!;
|
||||
|
||||
var payload = new DteGenerarPorCodigo
|
||||
{
|
||||
Codigo = cod,
|
||||
TipoDte = dte,
|
||||
Emisor = emi,
|
||||
Receptor = rec
|
||||
};
|
||||
|
||||
jsonFinal = JsonConvert.SerializeObject(payload);
|
||||
jsonContent = new StringContent(jsonFinal, Encoding.UTF8, "application/json");
|
||||
|
||||
response = await _client.PostAsync("/api/dte/documentos/generar?getXML=0&links=1&email=1&retry=1&gzip=0", jsonContent);
|
||||
respuestaJson = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return new DteResultado { Estado = respuestaJson };
|
||||
|
||||
jsonResp = JObject.Parse(respuestaJson);
|
||||
int folio = (int)jsonResp["folio"]!;
|
||||
|
||||
var responsePdf = await _client.GetAsync($"/api/dte/dte_emitidos/pdf/{dte}/{folio}/{emi}?formato=general&papelContinuo=0&copias_tributarias=1&copias_cedibles=1&cedible=0&compress=0&base64=0");
|
||||
|
||||
if (!responsePdf.IsSuccessStatusCode)
|
||||
throw new Exception("Se generó el DTE pero falló la descarga del PDF.");
|
||||
|
||||
await _client.GetAsync($"/api/dte/dte_emitidos/actualizar_estado/{dte}/{folio}/{emi}?usarWebservice=1");
|
||||
|
||||
byte[] pdfBytes = await responsePdf.Content.ReadAsByteArrayAsync();
|
||||
return new DteResultado { PdfBytes = pdfBytes, Folio = folio, Estado = "ok" };
|
||||
}
|
||||
|
||||
public async Task<DteFolioInfo> ConsultarSiguienteFolioAsync(int dte, long emisor)
|
||||
{
|
||||
SetAuth();
|
||||
var response = await _client.GetAsync($"/api/dte/admin/dte_folios/info/{dte}/{emisor}");
|
||||
string respuestaJson = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new Exception($"Error al consultar folio ({response.StatusCode}): {respuestaJson}");
|
||||
|
||||
return JsonConvert.DeserializeObject<DteFolioInfo>(respuestaJson)!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Security;
|
||||
using MimeKit;
|
||||
using ServicesExternos.API.Models;
|
||||
|
||||
namespace ServicesExternos.API.Services;
|
||||
|
||||
public class EmailService
|
||||
{
|
||||
private readonly string _smtpHost;
|
||||
private readonly int _smtpPort;
|
||||
private readonly string _smtpUser;
|
||||
private readonly string _smtpPassword;
|
||||
|
||||
public EmailService(IConfiguration configuration)
|
||||
{
|
||||
_smtpHost = configuration["Email:Host"] ?? "smtp.gmail.com";
|
||||
_smtpPort = int.Parse(configuration["Email:Port"] ?? "587");
|
||||
_smtpUser = configuration["Email:User"] ?? "noresponder@norteamericano.cl";
|
||||
_smtpPassword = configuration["Email:Password"] ?? "";
|
||||
}
|
||||
|
||||
public async Task<string> SendAsync(EmailRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = new MimeMessage();
|
||||
message.From.Add(new MailboxAddress("Norteamericano", _smtpUser));
|
||||
message.To.Add(new MailboxAddress("", request.To));
|
||||
message.Subject = request.Subject;
|
||||
|
||||
var body = new TextPart(request.IsHtml ? "html" : "plain")
|
||||
{
|
||||
Text = request.Body
|
||||
};
|
||||
|
||||
if (request.AttachmentPaths != null && request.AttachmentPaths.Count > 0)
|
||||
{
|
||||
var multipart = new Multipart("mixed") { body };
|
||||
foreach (var path in request.AttachmentPaths)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
multipart.Add(new MimePart("application", "pdf")
|
||||
{
|
||||
Content = new MimeContent(File.OpenRead(path), ContentEncoding.Default),
|
||||
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
|
||||
FileName = Path.GetFileName(path)
|
||||
});
|
||||
}
|
||||
message.Body = multipart;
|
||||
}
|
||||
else
|
||||
{
|
||||
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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using ServicesExternos.API.Models;
|
||||
using Dapper;
|
||||
using Npgsql;
|
||||
|
||||
namespace ServicesExternos.API.Services;
|
||||
|
||||
public class TransbankService
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
private readonly string _apiKey;
|
||||
private readonly string _commerceCode;
|
||||
private readonly string _connectionString;
|
||||
private readonly string _environment;
|
||||
|
||||
public TransbankService(HttpClient client, IConfiguration configuration)
|
||||
{
|
||||
_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")!;
|
||||
_environment = configuration["Transbank:Environment"] ?? "integration";
|
||||
|
||||
var baseUrl = _environment == "production"
|
||||
? "https://webpay3g.transbank.cl"
|
||||
: "https://webpay3gint.transbank.cl";
|
||||
|
||||
_client.BaseAddress = new Uri(baseUrl);
|
||||
_client.DefaultRequestHeaders.Add("Tbk-Api-Key-Id", _commerceCode);
|
||||
_client.DefaultRequestHeaders.Add("Tbk-Api-Key-Secret", _apiKey);
|
||||
}
|
||||
|
||||
public async Task<string> CrearTransaccionAsync(TransbankTransactionRequest request)
|
||||
{
|
||||
var payload = new
|
||||
{
|
||||
buy_order = request.BuyOrder,
|
||||
session_id = request.SessionId,
|
||||
amount = request.Amount,
|
||||
return_url = request.ReturnUrl
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(payload);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var response = await _client.PostAsync("/rswebpaytransaction/api/webpay/v1.2/transactions", content);
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
public async Task<string> ConfirmarTransaccionAsync(string tokenWs)
|
||||
{
|
||||
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)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
await connection.ExecuteAsync(
|
||||
"caja_tbk.GrabaVoucher",
|
||||
new
|
||||
{
|
||||
token_id = token,
|
||||
xaccountingDate = accountingDate,
|
||||
xbuyOrder = buyOrder,
|
||||
xcardDetailcardNumber = cardNumber,
|
||||
xdetailOutputAuthorizationCode = authCode,
|
||||
xdetailOutputPaymentTypeCode = paymentType,
|
||||
xdetailOutputSharesNumber = sharesNumber,
|
||||
xdetailOutputAmount = amount
|
||||
},
|
||||
commandType: System.Data.CommandType.StoredProcedure);
|
||||
return "ok";
|
||||
}
|
||||
|
||||
public async Task<string> BuscarTransaccionAsync(string token)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
var rows = await connection.QueryAsync(
|
||||
"caja_tbk.BuscarInfoToken",
|
||||
new { tokenid = token },
|
||||
commandType: System.Data.CommandType.StoredProcedure);
|
||||
return JsonConvert.SerializeObject(rows);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<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="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Npgsql" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
@ServicesExternos.API_HostAddress = http://localhost:5194
|
||||
|
||||
GET {{ServicesExternos.API_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"Default": "Host=192.168.0.254;Port=5432;Database=ichn;Username=postgres;Password=apoca11"
|
||||
},
|
||||
"LibreDTE": {
|
||||
"UserHash": "",
|
||||
"Ambiente": "1"
|
||||
},
|
||||
"Transbank": {
|
||||
"ApiKey": "",
|
||||
"CommerceCode": "",
|
||||
"Environment": "integration"
|
||||
},
|
||||
"Email": {
|
||||
"Host": "smtp.gmail.com",
|
||||
"Port": 587,
|
||||
"User": "noresponder@norteamericano.cl",
|
||||
"Password": ""
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user