En 2015 haciendo mis prácticas profesionales en un despacho contable, conocí lo que era CFDI 3.2 y en mi afán de aprender, desarrollé una librería que generaba el XML sellado para su timbrado.
Pero justo al terminar mis prácticas, me contrató una empresa local dedicada a la facturación electrónica, donde laboré por más de 3 años dando soporte técnico al SDK para CFDI que comercializaban.
Con esa experiencia decidí volver a crear una librería para facturación electrónica, que coincidió con la llegada del Cfdi 3.3 y pude venderla cuando entró en vigor (ver aquí).
Además, al mismo tiempo en la empresa que trabajaba desarrollé una nueva versión del SDK, que también soportaba Cfdi 3.3, que entre sus características más resaltables eran:
- Retro compatibilidad con los proyectos que ya usaban el SDK anterior (prácticamente era quitar el viejo e incorporar el nuevo)
- Su nueva estructura le permitía darle soporte de forma mucho más facil
- Implementé un sistema de plugins que le permitía al SDK realizar operaciones antes, durante y después de generar y timbrar el Cfdi.
Con esos casi 4 años de experiencia y los casi 7 años de experiencia profesional, decidí crear una librería para CFDI 4.0.
Actualmente estoy desarrollando una librería que soporta las versiones 3.3 (aún vigente) y 4.0 de CFDI. Esta librería podrá incluir cualquier complemento que necesites por medio de librerías extra que iré desarrollando y liberando tan pronto como me sea posible.
¿Cómo consigo la librería?
La librería la puedes conseguir desde la NuGet Gallery o puedes buscarla en Visual Studio, desde nuget package manager, igual que los complementos.

¿De verdad es gratis?
Si, la librería para CFDI junto con las librerías para complementos son totalmente gratuitas. Este es un proyecto personal y deseó poder implementar la mayor cantidad de complementos posibles (a ser posible, todos).
Soporte Técnico
Actualmente no dispongo del tiempo que me gustaría para darle soporte a un proyecto como este y no puedo ofrecer soporte 24/7.
Como dije anteriormente, mi idea es implementar la mayoría de los complementos, por lo que si necesitas alguno en concreto házmelo saber.
Importante
- Actualmente estoy utilizando el ambiente de pruebas de Solución Factible para timbrar los CFDI y validar que las librerías estén trabajando correctamente.
- Pronto publicaré un repositorio de GitHub con los ejemplos que timbré para validar las librerías, está atento a este sitio para que puedas descargarlo.
Ejemplos
CFDI 4.0 de Ingreso
// Archivo XSLT necesario para la Cadena Original
string xsltFile = @"cadenaoriginal_4_0.xslt";
// Certificados
string cerFile = @"EKU9003173C9.cer";
string keyFile = @"EKU9003173C9.key";
string password = "12345678a";
// Se lee el Certificado
var cerInfo = CsdUtils.LeerCertificado(cerFile);
// Se crea el Comprobante
IsaRoGaMX.Cfdi.v40.Comprobante cfdi = new IsaRoGaMX.Cfdi.v40.Comprobante();
// Datos de la Factura
cfdi["Serie"] = "F";
cfdi["Folio"] = "1234";
cfdi["Fecha"] = DateTime.Now.ToString("s");
cfdi["CondicionesDePago"] = "CondicionesDePago";
cfdi["SubTotal"] = "200";
cfdi["Descuento"] = "1";
cfdi["Moneda"] = "MXN";
cfdi["TipoCambio"] = "1";
cfdi["Total"] = "198.95";
cfdi["TipoDeComprobante"] = "I";
cfdi["Exportacion"] = "01";
cfdi["MetodoPago"] = "PPD";
cfdi["FormaPago"] = "99";
cfdi["LugarExpedicion"] = "20000";
cfdi["Certificado"] = cerInfo.Certificado;
cfdi["NoCertificado"] = cerInfo.NoCertificado;
// Emisor
cfdi.Emisor["Rfc"] = "EKU9003173C9";
cfdi.Emisor["Nombre"] = "ESCUELA KEMPER URGATE";
cfdi.Emisor["RegimenFiscal"] = "601";
// Receptor
cfdi.Receptor["Rfc"] = "URE180429TM6";
cfdi.Receptor["Nombre"] = "UNIVERSIDAD ROBOTICA ESPAÑOLA";
cfdi.Receptor["DomicilioFiscalReceptor"] = "65000";
cfdi.Receptor["RegimenFiscalReceptor"] = "601";
cfdi.Receptor["UsoCFDI"] = "G01";
// Concepto
cfdi.Conceptos[0]["ClaveProdServ"] = "50211503";
cfdi.Conceptos[0]["Cantidad"] = "1";
cfdi.Conceptos[0]["ClaveUnidad"] = "H87";
cfdi.Conceptos[0]["Unidad"] = "Pieza";
cfdi.Conceptos[0]["Descripcion"] = "Cigarros";
cfdi.Conceptos[0]["ValorUnitario"] = "200.00";
cfdi.Conceptos[0]["Descuento"] = "1";
cfdi.Conceptos[0]["Importe"] = "200.00";
cfdi.Conceptos[0]["ObjetoImp"] = "02";
cfdi.Conceptos[0].Impuestos.Traslados[0]["Base"] = "1";
cfdi.Conceptos[0].Impuestos.Traslados[0]["Importe"] = "0.16";
cfdi.Conceptos[0].Impuestos.Traslados[0]["Impuesto"] = "002";
cfdi.Conceptos[0].Impuestos.Traslados[0]["TasaOCuota"] = "0.160000";
cfdi.Conceptos[0].Impuestos.Traslados[0]["TipoFactor"] = "Tasa";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["Base"] = "1";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["Impuesto"] = "001";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["TipoFactor"] = "Tasa";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["TasaOCuota"] = "0.100000";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["Importe"] = "0.10";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["Base"] = "1";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["Impuesto"] = "002";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["TipoFactor"] = "Tasa";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["TasaOCuota"] = "0.106666";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["Importe"] = "0.11";
cfdi.Impuestos["TotalImpuestosRetenidos"] = "0.21";
cfdi.Impuestos["TotalImpuestosTrasladados"] = "0.16";
cfdi.Impuestos.Retenciones[0]["Impuesto"] = "001";
cfdi.Impuestos.Retenciones[0]["Importe"] = "0.10";
cfdi.Impuestos.Retenciones[1]["Impuesto"] = "002";
cfdi.Impuestos.Retenciones[1]["Importe"] = "0.11";
cfdi.Impuestos.Traslados[0]["Base"] = "1";
cfdi.Impuestos.Traslados[0]["Importe"] = "0.16";
cfdi.Impuestos.Traslados[0]["Impuesto"] = "002";
cfdi.Impuestos.Traslados[0]["TasaOCuota"] = "0.160000";
cfdi.Impuestos.Traslados[0]["TipoFactor"] = "Tasa";
// Genera cadena original
string cadenaOriginal = XsltTransform.GeneraCadenaOriginal(cfdi.Documento, xsltFile);
// Genera sello
cfdi["Sello"] = CsdUtils.GeneraSelloFiscalDigital(cadenaOriginal, keyFile, password);
// Se guarda el Xml
cfdi.Documento.Save("F1234.xml");Cfdi 4.0 de Nómina
// Archivo XSLT necesario para la Cadena Original
string xsltFile = @"E:\Descargas\cadenaoriginal_4_0.xslt";
// Certificados
string cerFile = @"EKU9003173C9.cer";
string keyFile = @"EKU9003173C9.key";
string password = "12345678a";
// Se lee el Certificado
var cerInfo = CsdUtils.LeerCertificado(cerFile);
// Se crea el comprobante
IsaRoGaMX.Cfdi.v40.Comprobante cfdi = new IsaRoGaMX.Cfdi.v40.Comprobante();
// Datos del Comprobante
cfdi["Serie"] = "NOM";
cfdi["Folio"] = "789";
cfdi["Fecha"] = DateTime.Now.ToString("s");
cfdi["SubTotal"] = "5000.00";
cfdi["Descuento"] = "200";
cfdi["Moneda"] = "MXN";
cfdi["Total"] = "4800";
cfdi["TipoDeComprobante"] = "N";
cfdi["Exportacion"] = "01";
cfdi["MetodoPago"] = "PUE";
cfdi["LugarExpedicion"] = "20000";
cfdi["Certificado"] = cerInfo.Certificado;
cfdi["NoCertificado"] = cerInfo.NoCertificado;
// Emisor
cfdi.Emisor["Rfc"] = "URE180429TM6";
cfdi.Emisor["Nombre"] = "UNIVERSIDAD ROBOTICA ESPAÑOLA";
cfdi.Emisor["RegimenFiscal"] = "601";
// Receptor
cfdi.Receptor["Rfc"] = "XOJI740919U48";
cfdi.Receptor["Nombre"] = "INGRID XODAR JIMENEZ";
cfdi.Receptor["DomicilioFiscalReceptor"] = "88965";
cfdi.Receptor["RegimenFiscalReceptor"] = "605";
cfdi.Receptor["UsoCFDI"] = "CN01";
// Conceptos
cfdi.Conceptos[0]["ClaveProdServ"] = "84111505";
cfdi.Conceptos[0]["Cantidad"] = "1";
cfdi.Conceptos[0]["ClaveUnidad"] = "ACT";
cfdi.Conceptos[0]["Descripcion"] = "Pago de nómina";
cfdi.Conceptos[0]["ValorUnitario"] = "5000.00";
cfdi.Conceptos[0]["Descuento"] = "200";
cfdi.Conceptos[0]["Importe"] = "5000.00";
cfdi.Conceptos[0]["ObjetoImp"] = "01";
// Complemento Nomina
var nomina = new IsaRoGaMX.Cfdi.Nomina.v12.Nomina();
nomina["TipoNomina"] = "O";
nomina["FechaPago"] = "2021-12-24";
nomina["FechaInicialPago"] = "2021-12-09";
nomina["FechaFinalPago"] = "2021-12-24";
nomina["NumDiasPagados"] = "15";
nomina["TotalPercepciones"] = "5000.0";
nomina["TotalDeducciones"] = "200";
// Emisor
nomina.Emisor["RegistroPatronal"] = "B5510768108";
nomina.Emisor["RfcPatronOrigen"] = "URE180429TM6";
// Receptor
nomina.Receptor["Curp"] = "XEXX010101HNEXXXA4";
nomina.Receptor["NumSeguridadSocial"] = "000000";
nomina.Receptor["FechaInicioRelLaboral"] = "2015-01-01";
nomina.Receptor["Antigüedad"] = "P364W";
nomina.Receptor["TipoContrato"] = "01";
nomina.Receptor["TipoJornada"] = "01";
nomina.Receptor["TipoRegimen"] = "03";
nomina.Receptor["NumEmpleado"] = "120";
nomina.Receptor["Departamento"] = "Desarrollo";
nomina.Receptor["Puesto"] = "Ingeniero de Software";
nomina.Receptor["RiesgoPuesto"] = "1";
nomina.Receptor["PeriodicidadPago"] = "04";
nomina.Receptor["CuentaBancaria"] = "1111111111";
nomina.Receptor["Banco"] = "002";
nomina.Receptor["SalarioBaseCotApor"] = "490.22";
nomina.Receptor["SalarioDiarioIntegrado"] = "146.47";
nomina.Receptor["ClaveEntFed"] = "JAL";
// Percepciones
nomina.Percepciones["TotalSueldos"] = "5000.0";
nomina.Percepciones["TotalGravado"] = "2808.8";
nomina.Percepciones["TotalExento"] = "2191.2";
nomina.Percepciones[0]["TipoPercepcion"] = "001";
nomina.Percepciones[0]["Clave"] = "00500";
nomina.Percepciones[0]["Concepto"] = "Sueldos; Salarios Rayas y Jornales";
nomina.Percepciones[0]["ImporteGravado"] = "2808.8";
nomina.Percepciones[0]["ImporteExento"] = "2191.2";
// Deducciones
nomina.Deducciones["TotalOtrasDeducciones"] = "200";
nomina.Deducciones[0]["TipoDeduccion"] = "001";
nomina.Deducciones[0]["Clave"] = "00301";
nomina.Deducciones[0]["Concepto"] = "Seguridad Social";
nomina.Deducciones[0]["Importe"] = "200";
// Se agrega el complemento
cfdi.AgregaComplemento(nomina);
// Genera cadena original
string cadenaOriginal = XsltTransform.GeneraCadenaOriginal(cfdi.Documento, xsltFile);
// Genera sello
cfdi["Sello"] = CsdUtils.GeneraSelloFiscalDigital(cadenaOriginal, keyFile, password);
cfdi.Documento.Save("NUM789.xml");Cfdi 4.0 Instituciones Educativas Privadas
// Archivo XSLT necesario para la Cadena Original
string xsltFile = @"cadenaoriginal_4_0.xslt";
// Certificados
string cerFile = @"EKU9003173C9.cer";
string keyFile = @"EKU9003173C9.key";
string password = "12345678a";
// Se lee el Certificado
var cerInfo = CsdUtils.LeerCertificado(cerFile);
// Se crea el Comprobante
IsaRoGaMX.Cfdi.v40.Comprobante cfdi = new IsaRoGaMX.Cfdi.v40.Comprobante();
// Datos de la Factura
cfdi["Serie"] = "F";
cfdi["Folio"] = "1234";
cfdi["Fecha"] = DateTime.Now.ToString("s");
cfdi["CondicionesDePago"] = "CondicionesDePago";
cfdi["SubTotal"] = "200";
cfdi["Descuento"] = "1";
cfdi["Moneda"] = "MXN";
cfdi["TipoCambio"] = "1";
cfdi["Total"] = "198.95";
cfdi["TipoDeComprobante"] = "I";
cfdi["Exportacion"] = "01";
cfdi["MetodoPago"] = "PPD";
cfdi["FormaPago"] = "99";
cfdi["LugarExpedicion"] = "20000";
cfdi["Certificado"] = cerInfo.Certificado;
cfdi["NoCertificado"] = cerInfo.NoCertificado;
// Emisor
cfdi.Emisor["Rfc"] = "EKU9003173C9";
cfdi.Emisor["Nombre"] = "ESCUELA KEMPER URGATE";
cfdi.Emisor["RegimenFiscal"] = "601";
// Receptor
cfdi.Receptor["Rfc"] = "URE180429TM6";
cfdi.Receptor["Nombre"] = "UNIVERSIDAD ROBOTICA ESPAÑOLA";
cfdi.Receptor["DomicilioFiscalReceptor"] = "65000";
cfdi.Receptor["RegimenFiscalReceptor"] = "601";
cfdi.Receptor["UsoCFDI"] = "G01";
// Concepto
cfdi.Conceptos[0]["ClaveProdServ"] = "50211503";
cfdi.Conceptos[0]["Cantidad"] = "1";
cfdi.Conceptos[0]["ClaveUnidad"] = "H87";
cfdi.Conceptos[0]["Unidad"] = "Pieza";
cfdi.Conceptos[0]["Descripcion"] = "Cigarros";
cfdi.Conceptos[0]["ValorUnitario"] = "200.00";
cfdi.Conceptos[0]["Descuento"] = "1";
cfdi.Conceptos[0]["Importe"] = "200.00";
cfdi.Conceptos[0]["ObjetoImp"] = "02";
cfdi.Conceptos[0].Impuestos.Traslados[0]["Base"] = "1";
cfdi.Conceptos[0].Impuestos.Traslados[0]["Importe"] = "0.16";
cfdi.Conceptos[0].Impuestos.Traslados[0]["Impuesto"] = "002";
cfdi.Conceptos[0].Impuestos.Traslados[0]["TasaOCuota"] = "0.160000";
cfdi.Conceptos[0].Impuestos.Traslados[0]["TipoFactor"] = "Tasa";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["Base"] = "1";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["Impuesto"] = "001";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["TipoFactor"] = "Tasa";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["TasaOCuota"] = "0.100000";
cfdi.Conceptos[0].Impuestos.Retenciones[0]["Importe"] = "0.10";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["Base"] = "1";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["Impuesto"] = "002";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["TipoFactor"] = "Tasa";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["TasaOCuota"] = "0.106666";
cfdi.Conceptos[0].Impuestos.Retenciones[1]["Importe"] = "0.11";
// Complemento de Instituciones Educativas
var iedu = new IsaRoGaMX.Cfdi.Iedu.v10.InstEducativas();
iedu["CURP"] = "AAAA010101HNLRNL09";
iedu["autRVOE"] = "PEFHS821923KSDJ823";
iedu["nivelEducativo"] = "Secundaria";
iedu["nombreAlumno"] = "Nombre Alumno";
iedu["rfcPago"] = "BBB010101AAA";
// Se agrega al concepto
cfdi.Conceptos[0].AgregaComplemento(iedu);
// Impuestos
cfdi.Impuestos["TotalImpuestosRetenidos"] = "0.21";
cfdi.Impuestos["TotalImpuestosTrasladados"] = "0.16";
cfdi.Impuestos.Retenciones[0]["Impuesto"] = "001";
cfdi.Impuestos.Retenciones[0]["Importe"] = "0.10";
cfdi.Impuestos.Retenciones[1]["Impuesto"] = "002";
cfdi.Impuestos.Retenciones[1]["Importe"] = "0.11";
cfdi.Impuestos.Traslados[0]["Base"] = "1";
cfdi.Impuestos.Traslados[0]["Importe"] = "0.16";
cfdi.Impuestos.Traslados[0]["Impuesto"] = "002";
cfdi.Impuestos.Traslados[0]["TasaOCuota"] = "0.160000";
cfdi.Impuestos.Traslados[0]["TipoFactor"] = "Tasa";
// Genera cadena original
string cadenaOriginal = XsltTransform.GeneraCadenaOriginal(cfdi.Documento, xsltFile);
// Genera sello
cfdi["Sello"] = CsdUtils.GeneraSelloFiscalDigital(cadenaOriginal, keyFile, password);
// Se guarda el XML
cfdi.Documento.Save("F1234.xml");