Skip to content

Latest commit

 

History

History

README.md

@cfdi/xml

Librerias modernas para trabajar con CFDI 4.0 en Node.js

npm version npm downloads license node typescript

Documentacion


Ecosistema CFDI

CFDI Ecosystem

@cfdi/complementos @cfdi/xsd @cfdi/csd
@cfdi/csf @cfdi/catalogos @cfdi/transform
@cfdi/elements @cfdi/types @cfdi/expresiones
@cfdi/xml2json @cfdi/rfc @cfdi/utils
@clir/openssl @saxon-he/cli

Por que @cfdi/xml?

Sin Java
Motor XSLT nativo en Node.js con @cfdi/transform. Saxon-HE disponible como alternativa.
TypeScript nativo
Tipos estrictos, autocompletado y seguridad de tipos en todo el flujo de facturacion.
SAT 4.0 compliant
Cumple con Anexo 20 del SAT. Genera XML valido contra esquemas XSD oficiales.
Modular
Usa solo lo que necesitas. Cada paquete del ecosistema es independiente.

Quick Start

1. Instalar

npm install @cfdi/xml

2. Crear y firmar un CFDI

import { CFDI, Emisor, Receptor, Concepto, Impuestos } from '@cfdi/xml';

const cfdi = new CFDI({
  xslt: { path: './resources/4.0/cadenaoriginal.xslt' },
});

cfdi.comprobante({
  Serie: 'A',
  Folio: '1',
  Fecha: '2024-01-15T10:30:00',
  FormaPago: '01',
  MetodoPago: 'PUE',
  TipoDeComprobante: 'I',
  LugarExpedicion: '64000',
  Moneda: 'MXN',
  SubTotal: '1000.00',
  Total: '1160.00',
});

cfdi.emisor(
  new Emisor({
    Rfc: 'AAA010101AAA',
    Nombre: 'Empresa SA de CV',
    RegimenFiscal: '601',
  })
);

cfdi.receptor(
  new Receptor({
    Rfc: 'BBB020202BBB',
    Nombre: 'Cliente SA de CV',
    UsoCFDI: 'G03',
    DomicilioFiscalReceptor: '64000',
    RegimenFiscalReceptor: '601',
  })
);

const concepto = new Concepto({
  ClaveProdServ: '01010101',
  Cantidad: '1',
  ClaveUnidad: 'E48',
  Descripcion: 'Servicio de consultoria',
  ValorUnitario: '1000.00',
  Importe: '1000.00',
  ObjetoImp: '02',
});
concepto.setTraslado({
  Base: '1000.00',
  Impuesto: '002',
  TipoFactor: 'Tasa',
  TasaOCuota: '0.160000',
  Importe: '160.00',
});
cfdi.concepto(concepto);

const impuestos = new Impuestos({
  TotalImpuestosTrasladados: '160.00',
});
impuestos.traslados({
  Impuesto: '002',
  TipoFactor: 'Tasa',
  TasaOCuota: '0.160000',
  Importe: '160.00',
  Base: '1000.00',
});
cfdi.impuesto(impuestos);

3. Certificar y sellar

cfdi.certificar('./certs/certificado.cer');
await cfdi.sellar('./certs/llave.key', '12345678a');

4. Obtener el XML

const xml = cfdi.getXmlCdfi();

Flujo de firmado

graph LR
    A[XML CFDI] --> B[Cadena Original]
    B --> C[Sello Digital]
    C --> D[CFDI Firmado]

    B -- "@cfdi/transform (default)" --> B
    B -. "@saxon-he/cli (opcional)" .-> B
    C -- ".key + SHA-256" --> C
    A -- ".cer" --> D
Loading

Output de ejemplo

<?xml version="1.0" encoding="utf-8"?>
<cfdi:Comprobante
  xmlns:cfdi="http://www.sat.gob.mx/cfd/4"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd"
  Version="4.0"
  Serie="A"
  Folio="1"
  Fecha="2024-01-15T10:30:00"
  FormaPago="01"
  MetodoPago="PUE"
  TipoDeComprobante="I"
  Moneda="MXN"
  SubTotal="1000.00"
  Total="1160.00"
  LugarExpedicion="64000"
  NoCertificado="20001000000300022815"
  Certificado="MIIFxTCCA62g..."
  Sello="GshKsM2IjAR0+7...">
  <cfdi:Emisor Rfc="AAA010101AAA" Nombre="Empresa SA de CV" RegimenFiscal="601"/>
  <cfdi:Receptor Rfc="BBB020202BBB" Nombre="Cliente SA de CV" UsoCFDI="G03"
    DomicilioFiscalReceptor="64000" RegimenFiscalReceptor="601"/>
  <cfdi:Conceptos>
    <cfdi:Concepto ClaveProdServ="01010101" Cantidad="1" ClaveUnidad="E48"
      Descripcion="Servicio de consultoria" ValorUnitario="1000.00"
      Importe="1000.00" ObjetoImp="02">
      <cfdi:Impuestos>
        <cfdi:Traslados>
          <cfdi:Traslado Base="1000.00" Impuesto="002" TipoFactor="Tasa"
            TasaOCuota="0.160000" Importe="160.00"/>
        </cfdi:Traslados>
      </cfdi:Impuestos>
    </cfdi:Concepto>
  </cfdi:Conceptos>
</cfdi:Comprobante>

Motor XSLT

La cadena original se genera mediante transformacion XSLT. Se soportan dos motores:

Motor Paquete Requiere Java Default
@cfdi/transform @cfdi/transform No Si
Saxon-HE @saxon-he/cli Si No
// Default: @cfdi/transform (pure Node.js)
const cfdi = new CFDI({
  xslt: { path: './resources/4.0/cadenaoriginal.xslt' },
});

// Saxon-HE: requiere Java + Saxon instalado
const cfdiSaxon = new CFDI({
  xslt: { path: './resources/4.0/cadenaoriginal.xslt' },
  saxon: { binary: 'transform' },
});

API

Metodo Descripcion
comprobante(attr) Atributos del comprobante (Serie, Folio, Fecha, etc.)
emisor(emisor) Datos del emisor
receptor(receptor) Datos del receptor
concepto(concepto) Agrega un concepto (puede llamarse multiples veces)
impuesto(impuesto) Resumen de impuestos del documento
certificar(cerpath) Carga certificado .cer
sellar(keyfile, password) Genera cadena original y sello digital
getXmlCdfi() Retorna el XML firmado
getJsonCdfi() Retorna representacion JSON
saveFile(file, path, name) Guarda archivo XML
generarCadenaOriginal() Genera cadena original via XSLT
setDebug(debug) Activa/desactiva modo debug

Configuracion

interface Config {
  debug?: boolean;
  compact?: boolean;
  xslt?: { path: string }; // Ruta al archivo XSLT (requerido para sellar)
  saxon?: { binary: string }; // Si se omite, usa @cfdi/transform
  schema?: { path: string };
}

Soporte

issues discussions npm


Autor

Amir Misael Marin Coh

Licencia

MIT