SDK oficial de .NET para la API de Facturación Electrónica (e-CF / eCF) de República Dominicana, conforme a la normativa DGII. Diseñado para integrarse con sistemas ERP, POS y de contabilidad.
Keywords: facturación electrónica · facturacion electronica · DGII · eCF · e-CF · XML · nota de crédito · nota de débito · electronic invoicing · invoice API · billing SDK · dotnet · csharp · ERP integration · POS integration
⚠️ Este proyecto se encuentra en fase de diseño y scaffolding. Aún no hay código fuente implementado. Las funcionalidades listadas a continuación representan la especificación planificada.
- 🔮 Emisión de Comprobantes: Facturas, Notas de Crédito, Notas de Débito
- 🔮 Consulta de Estado: Polling inteligente con estados terminales
- 🔮 Descarga de Documentos: PDF y XML (
GetPdfAsync,GetXmlAsync) - 🔮 Anulación de Comprobantes
- 🔮 Validación Pre-flight: RNC, Cédula, NCF, límite 250 items
- 🔮 Retry Automático: Exponential backoff con jitter
- 🔮 Idempotencia: Manejo automático de Idempotency-Key
- 🔮 Circuit Breaker: Protección contra fallos en cascada
- 🔮 Rate Limiting: Control de velocidad client-side
- 🔮 Async/Await Nativo: Totalmente asíncrono
- 🔮 Patrón Result<T>: Manejo de errores sin excepciones
- 🔮 Timeouts Específicos: 45s para DGII, 60s para PDF
- 🔮 Validadores DGII: RNC, Cédula y NCF con algoritmos oficiales
Install-Package Jeiyel.EcfSdkdotnet add package Jeiyel.EcfSdk<PackageReference Include="Jeiyel.EcfSdk" Version="*-*" />using Jeiyel.EcfSdk;
// Crear cliente
var client = new EcfClient(new EcfClientOptions
{
ApiKey = "sk_live_tu_api_key_aqui",
Environment = EcfEnvironment.Production
});var request = new CreateInvoiceRequest
{
InvoiceType = InvoiceType.CreditoFiscal,
Customer = new Customer
{
Rnc = "101123456",
Name = "Empresa Cliente SRL",
Email = "cliente@empresa.com"
},
Items = new List<InvoiceItem>
{
new()
{
Description = "Servicio de Consultoría",
Quantity = 1,
UnitPrice = 10000.00m,
TaxRate = 18
}
}
};
var result = await client.Invoices.EmitAsync(request);
result.Switch(
onSuccess: invoice => Console.WriteLine($"Factura emitida: {invoice.Ncf}"),
onFailure: error => Console.WriteLine($"Error: {error.Code} - {error.Message}")
);var statusResult = await client.Invoices.GetStatusAsync(invoiceId);
if (statusResult.IsSuccess)
{
Console.WriteLine($"Estado: {statusResult.Value.Status}");
}// Descargar PDF
var pdfResult = await client.Invoices.GetPdfAsync(invoiceId);
if (pdfResult.IsSuccess)
{
await File.WriteAllBytesAsync("factura.pdf", pdfResult.Value);
}
// Descargar XML (e-CF firmado)
var xmlResult = await client.Invoices.GetXmlAsync(invoiceId);
if (xmlResult.IsSuccess)
{
await File.WriteAllBytesAsync("factura.xml", xmlResult.Value);
}
// También disponible por NCF
var pdfByNcf = await client.Invoices.GetPdfByNcfAsync("E310000000001");var finalStatus = await client.Invoices.WaitForStatusAsync(
invoiceId,
new[] { InvoiceStatus.Accepted, InvoiceStatus.Rejected },
new WaitOptions { MaxWaitTime = TimeSpan.FromMinutes(5) }
);// Program.cs
builder.Services.AddEcfClient(options =>
{
options.WithApiKey(builder.Configuration["Jeiyel:EcfSdk:ApiKey"]!)
.WithEnvironment(EcfEnvironment.Production)
.WithTimeout(TimeSpan.FromSeconds(45))
.WithRetryPolicy(maxRetries: 3, initialDelay: TimeSpan.FromSeconds(1));
});// En tu Controller o Service
public class InvoiceService
{
private readonly IInvoiceClient _invoiceClient;
public InvoiceService(IInvoiceClient invoiceClient)
{
_invoiceClient = invoiceClient;
}
public async Task<Result<InvoiceResponse>> CreateInvoice(CreateInvoiceRequest request)
{
return await _invoiceClient.EmitAsync(request);
}
}{
"Jeiyel": {
"EcfSdk": {
"ApiKey": "sk_live_xxxxx",
"Environment": "Production",
"TimeoutSeconds": 30
}
}
}El SDK usa el patrón Result<T> para manejo de errores sin excepciones:
var result = await client.Invoices.EmitAsync(request);
// Opción 1: Pattern matching con Switch
result.Switch(
onSuccess: invoice => ProcessInvoice(invoice),
onFailure: error => HandleError(error)
);
// Opción 2: Match con retorno
var message = result.Match(
onSuccess: inv => $"Éxito: {inv.Ncf}",
onFailure: err => $"Error: {err.Code}"
);
// Opción 3: Verificación explícita
if (result.IsSuccess)
{
var invoice = result.Value;
// Procesar factura...
}
else
{
var error = result.Error;
// Manejar por categoría
switch (error.Category)
{
case ErrorCategory.ValidationError:
// Mostrar errores de validación
foreach (var ve in error.ValidationErrors ?? [])
{
Console.WriteLine($"{ve.Field}: {ve.Message}");
}
break;
case ErrorCategory.RateLimit:
// Esperar y reintentar
if (error.RetryAfter.HasValue)
{
await Task.Delay(error.RetryAfter.Value);
}
break;
case ErrorCategory.DgiiError:
// Error de DGII - verificar datos fiscales
break;
}
}| Código | Tipo | Enum |
|---|---|---|
| 31 | Factura de Crédito Fiscal | InvoiceType.CreditoFiscal |
| 32 | Factura de Consumo | InvoiceType.Consumo |
| 33 | Nota de Débito | InvoiceType.NotaDebito |
| 34 | Nota de Crédito | InvoiceType.NotaCredito |
| 41 | Compras | InvoiceType.Compras |
| 43 | Gastos Menores | InvoiceType.GastosMenores |
| 44 | Regímenes Especiales | InvoiceType.RegimenesEspeciales |
| 45 | Gubernamental | InvoiceType.Gubernamental |
| 46 | Exportaciones | InvoiceType.Exportaciones |
- Las API Keys nunca se registran en logs
- Comunicación HTTPS obligatoria
- Validación de certificados SSL
Ver CONTRIBUTING.md para guías de contribución.
Este proyecto está bajo la Licencia MIT - ver LICENSE para detalles.
- 📧 Email: soporte@jeiyel.com
- 📚 Docs: https://docs.fe.jeiyel.com
- 🐛 Issues: https://github.com/jeiyel/jeiyel-ecf-sdk-dotnet/issues