ElRoso.ARCA 2.1.2

dotnet add package ElRoso.ARCA --version 2.1.2
                    
NuGet\Install-Package ElRoso.ARCA -Version 2.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ElRoso.ARCA" Version="2.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ElRoso.ARCA" Version="2.1.2" />
                    
Directory.Packages.props
<PackageReference Include="ElRoso.ARCA" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ElRoso.ARCA --version 2.1.2
                    
#r "nuget: ElRoso.ARCA, 2.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ElRoso.ARCA@2.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ElRoso.ARCA&version=2.1.2
                    
Install as a Cake Addin
#tool nuget:?package=ElRoso.ARCA&version=2.1.2
                    
Install as a Cake Tool

ElRoso.ARCA

CI codecov NuGet Downloads License: MIT .NET 9

Cliente .NET 9 para facturación electrónica con ARCA (ex-AFIP). Hecho para que devs argentinos no sufran integrando como sufrimos los que vinimos antes.

Soporta:

  • ✅ Autenticación WSAA (PKCS#7 + token cache cifrado DPAPI)
  • ✅ Facturación doméstica WSFEv1 (FA / FB / FC + Notas de Crédito y Débito)
  • ✅ Facturación exportación WSFEXv1 (Factura, NC, ND)
  • ✅ Padrón A5 (consulta de inscripción AFIP por CUIT)
  • ✅ Generación del QR oficial para impresión
  • Verificación de comprobantes recibidos vía WSCDC (desde v1.1.0)
  • Notificaciones del Domicilio Fiscal Electrónico (e-Ventanilla) vía WSCComu (desde v1.1.0)

📑 Tabla de contenidos


📦 Instalación

dotnet add package ElRoso.ARCA

Requisitos: .NET 9.0 o superior. Funciona en Windows, Linux y macOS. El cache de tokens usa DPAPI en Windows y JSON plano en Linux/macOS (si esto es problema, ver Cookbook → cache de tokens).


⚡ Quick Start — Factura A en 5 líneas

// 1) Registrá la lib en DI
builder.Services.AddARCAClient(options =>
{
    options.IsProduction        = false;                    // homologación
    options.CertificatePath     = "/certs/mi-empresa.pfx";
    options.CertificatePassword = "miPassword";
});

// 2) Emití la factura
var response = await billingService.AuthorizeAsync(new BillingDocumentNumberingRequest
{
    BillingDocumentType       = BillingDocumentTypeARCAEnum.FA,
    BillingDocumentBookPrefix = 1,
    BillingDocumentDate       = DateTime.Today,
    Currency                  = "Pesos",
    ExchangeRate              = 1,
    ConceptType               = ConceptTypeARCAEnum.Products,
    AmountTax                 = 826.45,
    BillingDocumentNumberingTaxes = [new() { PercentageTax = "21.00", BaseAmount = 826.45, Amount = 173.55 }],
    IssuingCompany = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 20123456789 },
    Client         = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 30987654321 },
});

Console.WriteLine(response.Result
    ? $"CAE: {response.CAE} — Nro: {response.BillingDocumentNumber}"
    : $"Errores: {string.Join("; ", response.Errors)}");

⚙️ Configuración

appsettings.json

{
  "Arca": {
    "IsProduction": false,
    "CertificatePath": "/certs/mi-empresa.pfx",
    "CertificatePassword": "",
    "TokenCacheDirectory": "/tmp/arca-tokens",
    "SoapTimeoutSeconds": 30
  }
}

🔒 Seguridad: nunca commitees CertificatePassword en texto plano. Usá variables de entorno, Azure Key Vault, AWS Secrets Manager, o User Secrets en desarrollo.

Registro en Program.cs

builder.Services.AddARCAClient(options =>
{
    var cfg = builder.Configuration.GetSection("Arca");
    options.IsProduction        = cfg.GetValue<bool>("IsProduction");
    options.CertificatePath     = cfg["CertificatePath"]!;
    options.CertificatePassword = cfg["CertificatePassword"];
    options.TokenCacheDirectory = cfg["TokenCacheDirectory"] ?? Path.GetTempPath();
    options.SoapTimeoutSeconds  = cfg.GetValue<int>("SoapTimeoutSeconds", 30);
});

🔐 Manejo de certificados

ARCA requiere un certificado X.509 con clave privada (.pfx o .p12) para firmar los tokens de sesión (WSAA).

Generar el certificado paso a paso

# 1. Generar la clave privada
openssl genrsa -out empresa.key 2048

# 2. Generar el CSR (Certificate Signing Request)
openssl req -new -key empresa.key -subj "/C=AR/O=Mi Empresa/CN=20123456789/serialNumber=CUIT 20123456789" -out empresa.csr

# 3. Cargar el CSR en el portal ARCA → "Administración de Certificados Digitales"
#    y descargar el .crt firmado.

# 4. Combinar clave privada + certificado en un .pfx
openssl pkcs12 -export -in empresa.crt -inkey empresa.key -out empresa.pfx -passout pass:miPassword

Docker

services:
  myapp:
    volumes:
      - ./certs:/certs:ro
    environment:
      Arca__CertificatePath: /certs/empresa.pfx
      Arca__CertificatePassword: ${ARCA_CERT_PASSWORD}

⚠️ El .pfx contiene la clave privada. Nunca lo commitees. Si por error te pasó, revocá el certificado en ARCA inmediatamente.


📋 Tipos de comprobante soportados

Enum Código ARCA Descripción
FA 1 Factura A
NDA / NCA 2 / 3 Nota de Débito / Crédito A
FB 6 Factura B
NDB / NCB 7 / 8 Nota de Débito / Crédito B
FC 11 Factura C
NDC / NCC 12 / 13 Nota de Débito / Crédito C
InvoiceExport 19 Factura de Exportación
DebitNoteExport / CreditNoteExport 20 / 21 Notas Débito / Crédito Exportación
Remittances 91 Remito R

📖 Recetario por escenario

Factura A con CUIT del cliente

new BillingDocumentNumberingRequest
{
    BillingDocumentType       = BillingDocumentTypeARCAEnum.FA,
    BillingDocumentBookPrefix = 1,
    BillingDocumentDate       = DateTime.Today,
    Currency                  = "Pesos",
    ExchangeRate              = 1,
    ConceptType               = ConceptTypeARCAEnum.Products,
    AmountTax                 = 1000,
    BillingDocumentNumberingTaxes =
    [
        new() { PercentageTax = "21.00", BaseAmount = 1000, Amount = 210 }
    ],
    IssuingCompany = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 20123456789 },
    Client         = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 30987654321 },
}

La lib consulta automáticamente el Padrón para resolver el nombre y la condición IVA del cliente.

Factura B / Factura C (Monotributo)

// FC — Monotributo no discrimina IVA
new BillingDocumentNumberingRequest
{
    BillingDocumentType       = BillingDocumentTypeARCAEnum.FC,
    BillingDocumentBookPrefix = 1,
    BillingDocumentDate       = DateTime.Today,
    Currency                  = "Pesos",
    ExchangeRate              = 1,
    ConceptType               = ConceptTypeARCAEnum.Products,
    AmountTax                 = 1210,                          // total con IVA incluido
    IssuingCompany = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 20123456789 },
    Client         = new() { DocumentType = DocumentTypeARCAEnum.SIN_IDENTIFICAR, DocumentNumber = 0 },
}

Notas de Crédito y Débito

Deben incluir los comprobantes asociados:

new BillingDocumentNumberingRequest
{
    BillingDocumentType = BillingDocumentTypeARCAEnum.NCA,
    BillingDocumentNumberingAssociateds =
    [
        new()
        {
            BillingDocumentType       = BillingDocumentTypeARCAEnum.FA,
            BillingDocumentNumber     = 42,
            BillingDocumentBookPrefix = 1,
            BillingDocumentDate       = new DateTime(2026, 1, 15),
        }
    ],
    // resto de campos como Factura A...
}

Factura de Servicios

Concepto Services requiere rango de fechas y vencimiento:

ConceptType        = ConceptTypeARCAEnum.Services,
DateOfServicesFrom = new DateTime(2026, 3, 1),
DateOfServicesTo   = new DateTime(2026, 3, 31),
PaymentDue         = new DateTime(2026, 4, 10),

Verificar un comprobante recibido (WSCDC)

Cuando recibís una Factura A de un proveedor, antes de pagarla podés validarla contra ARCA:

var verifier = sp.GetRequiredService<IInvoiceVerificationService>();

var response = await verifier.VerifyAsync(new InvoiceVerificationRequest
{
    BillingDocumentType       = BillingDocumentTypeARCAEnum.FA,
    BillingDocumentBookPrefix = 1,                          // Punto de venta
    BillingDocumentNumber     = 42,                         // Nro. de comprobante
    BillingDocumentDate       = new DateTime(2026, 5, 1),
    TotalAmount               = 1210.00,
    AuthorizationCode         = "75123456789012",           // CAE / CAI / CAEA
    AuthorizationMode         = AuthorizationModeARCAEnum.CAE,
    IssuingCompany = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 20123456789 },
});

if (response.IsAuthorized)
    Console.WriteLine($"✅ CAE válido. Procesado: {response.ProcessedDate:yyyy-MM-dd}");
else
{
    Console.WriteLine("❌ NO autorizado:");
    foreach (var obs in response.Observations) Console.WriteLine($"  {obs}");
}

Requiere el servicio wscdc adherido en el portal de ARCA. Sample runnable en samples/InvoiceVerification/.

Leer notificaciones del DFE (e-Ventanilla)

Consulta el buzón fiscal electrónico — ideal para correr en background y notificar al usuario apenas llega algo.

var mailbox = sp.GetRequiredService<IElectronicMailboxService>();

var inbox = await mailbox.ListAsync(new MailboxQueryRequest
{
    IssuingCompany = new() { DocumentType = DocumentTypeARCAEnum.CUIT, DocumentNumber = 20123456789 },
    Page = 1,
    PageSize = 50,
});

foreach (var msg in inbox.Messages)
    Console.WriteLine($"[{msg.Id}] {msg.PublishedDate:yyyy-MM-dd} {msg.StateName} {msg.Subject}");

// Leer el contenido completo (marca como leída en ARCA):
var detail = await mailbox.ConsumeAsync(new MailboxConsumeRequest
{
    IssuingCompany = new() { DocumentNumber = 20123456789 },
    MessageId = inbox.Messages[0].Id,
});

Console.WriteLine(detail.Message?.Body);
foreach (var a in detail.Message?.Attachments ?? [])
    File.WriteAllBytes(a.FileName, a.Content);

Requiere wsccomu adherido + DFE constituido. Sample en samples/ElectronicMailbox/. Producción URL: ver Cookbook.

Factura de Exportación

new BillingDocumentNumberingRequest
{
    BillingDocumentType = BillingDocumentTypeARCAEnum.InvoiceExport,
    BillingDocumentId   = 1,                                  // ID único de la factura de exportación
    Currency            = "Dolares",
    ExchangeRate        = 1050.50,
    ConceptType         = ConceptTypeARCAEnum.Products,
    AmountTax           = 500.00,
    Client = new()
    {
        DocumentType   = DocumentTypeARCAEnum.CUIT,
        DocumentNumber = 55123456789,
        CountryId      = 123,                                 // código de país ARCA
        Address        = "123 Main St",
        ClientLanguage = "Inglés",
    },
    Items = [ new() { ItemDescription = "Software license", Amount = 500.00 } ],
}

⚠️ Manejo de errores

La lib lanza excepciones tipadas:

try
{
    var response = await billingService.AuthorizeAsync(request);
}
catch (ARCAValidationException ex)
{
    // Validaciones locales (FluentValidation) — no llegó a la red
    foreach (var err in ex.Errors) Console.WriteLine(err);
}
catch (ARCAAuthException ex)
{
    // Falla de autenticación: certificado mal, WSAA caído, firma PKCS#7 fallida
    Console.WriteLine(ex.Message);
}
catch (ARCAServiceException ex)
{
    // ARCA devolvió un error desde WSFEv1/WSFEXv1/Padrón
    Console.WriteLine($"Code {ex.ErrorCode}: {ex.Message}");
}

🌐 Ambientes (Homologación vs Producción)

Servicio Homologación (IsProduction=false) Producción (IsProduction=true)
WSAA wsaahomo.afip.gov.ar wsaa.afip.gov.ar
WSFEv1 wswhomo.afip.gov.ar servicios1.afip.gov.ar
WSFEXv1 wswhomo.afip.gov.ar servicios1.afip.gov.ar
Padrón awshomo.afip.gov.ar aws.afip.gov.ar

Tip: siempre arrancá en homologación. Un mismo certificado no sirve para ambos ambientes — necesitás dos certificados separados.


🔳 QR code para impresión

var qr = response.QRCode();
// Devuelve: https://www.afip.gob.ar/fe/qr/?p=eyJ2ZXIiOjEsImZl...

Esa URL la generás como QR (con QRCoder, ZXing, etc.) y la imprimís en el ticket o PDF junto con el resto de los datos del CAE.


🤝 Contribuir

PRs y issues bienvenidos. Antes de mandar un PR grande, abrí una Discussion para alinear el approach. Ver CONTRIBUTING.md.

Si encontraste una vulnerabilidad de seguridad, no la reportes como issue público — ver SECURITY.md.


❤️ Apoyar el proyecto

Si esta lib te ahorró horas de sufrimiento con ARCA, considerá:


📜 Licencia

MIT © Di Rosolini Ezequiel (El Roso)

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.2 238 5/14/2026
2.1.1 104 5/14/2026
2.1.0 100 5/14/2026
2.0.0 109 5/14/2026
1.1.0 91 5/14/2026
1.0.0 95 5/14/2026
1.0.0-preview.1 51 5/14/2026