Si operas cualquier tipo de negocio en México, sabrás que no estás librado de crear reportes de ingresos y egresos en forma de un Comprobante Fiscal Digital, también conocido como CFDI. Cada uno de estos comprobantes tiene un formato de archivo XML, y aunque muchas veces se incluye una versión en PDF para que sea legible por seres humanos, la factura válida como tal para efectos del SAT (Servicio de Administración Tributaria), es el archivo XML con su sello fiscal.
El manejo de los archivos XML´s se volvió parte de nuestras actividades diarias como Contadores, contribuyentes o encargado de algún área en específico (cuentas por pagar, crédito y cobranza, etc…). Es importante conocer mas de los XML’s ya que son la base de la comprobación ante el SAT, ya que con ellos se definen los ingresos y egresos de los contribuyentes. El problema con estos archivos es que no es sencillo mantener un control visual de la información que contienen a simple vista, porque están pensados para ser leídos y procesados por sistemas informáticos. Si quieres, por ejemplo, hacer una lista de todas las facturas emitidas y recibidas en el mes o leer algún dato específico de una factura, tendrías que descifrar el archivo XML manualmente y copiar la información relevante a mano.
Los CFDIs pueden incluir complementos, ya que existen varios para los comprobantes fiscales digitales.
Implementación de Procesamiento de CFDIs en Delphi
Para abordar la complejidad de los archivos XML de CFDI de manera eficiente, el desarrollo de soluciones personalizadas en entornos como Delphi se vuelve esencial. A continuación, detallamos los pasos y consideraciones para la lectura y, más específicamente, la firma de estos documentos fiscales digitales.
Preparación del XML de Cabecera
El proceso comienza con la gestión del XML de cabecera. Empiezo con código para el XML de cabecera, usamos un objetito simple que nos abre y cierra ramas en el XML, hay muchas clases parecidas y todas son sencillas de usar, pero nos creamos la nuestra porque...
Lea también: Aspectos Clave del Código Tributario de Panamá
Uso de la Librería SecureBlackBox para la Firma Digital
Y ahora la firma, yo utilizo la libreria SecureBlackBox, hay otras, pero la verdad, yo no la cambiaría, es barata, fiable, flexible, potente. El objeto Signer, junto con el preprocesador XAdES, crean esos nuevos nodos para que podamos referenciarlos -decirle al firmador que son unas referencias a ser firmadas- y al final, al firmar, unirá el XML original con estos nuevos nodos -formato de firma "enveloped"- y se graba el XML final.
Generación de Información XAdES
// Primero genero la zona de informacion XAdES: XML_Signer.XAdESProcessor.Generate;
// Ahora, al objeto firmador "generico" le pido lo mismo, con lo que// tambien se crea el nodo "KeyInfo" con el certificado a utilizar. XML_Signer.UpdateReferencesDigest;
Carga del Certificado para Firmar
//Cargo certificado para firmar
//=============================
Lea también: CP Ex Hacienda San Juan De Dios CDMX
// Cargo el certificado a usarse en la firma en el objeto firmador
// NOTA: Se incluira la parte publica del certificado en base64.
// De los certificados que me pases, elijo el primero con parte privada,
// ya que no quiero incluir el certificado raiz del emisor (no se
// menciona en la politica de firmado y no aparece en los ejemplos): XML_KeyData.IncludeKeyValue:= true;
Lea también: ¿Cuál es el Código Postal de Hacienda El Rosario, Nuevo León?
for i:= 0 to Cajon.Count-1 do begin
if Cajon.Certificates[i].PrivateKeyExists then begin
XML_KeyData.certificate:= Cajon.Certificates[i]; break;
end;
end;
//Compruebo que ha quedado algún certificado válido...
if not Assigned(XML_KeyData.certificate) then
raise Exception.create('FirmaXML: No se cargó un certificado válido para firmar, no contiene clave privada.');
XML_Signer.KeyData:= XML_KeyData;
Adición de Nodos a la Lista de Firmado
//Añado a la lista de nodos a firmar
//==================================
//NOTA: El metodo SHA1 no es el mas seguro, pero el SHA256 no se usa mucho
//y puede dar problemas (WinXP SP2 no lo admite) por eso el DNIe tampoco
//lo usa aun, asi que mejor dejo el valor por defecto.
// NODO 1: Se ha de firmar el documento original XML completo...
// XML_RefDocu.DigestMethod:= xdmSHA1; //El mas estandard/compatible de todos
// XML_RefDocu.URINode:= XML_Doc.DocumentElement; //El XML completo
// XML_RefDocu.URI:= ''; //No hay nombre especifico para este nodo
// En los ejemplos aparece la transformacion "Enveloped-Signature"
// aunque en el PDF de la firma V3.1 no lo menciona. XML_RefDocu.TransformChain.Add(TElXMLEnvelopedSignatureTransform.Create);
XML_Refs.Add(XML_RefDocu); //Lo sumo a las cosas a ser firmadas
// Actualizo digest con este nuevo nodo. XML_Signer.UpdateReferencesDigest;
// NODO 2: Se han de firmar las propiedades de firmado (XAdES)....
// El nodo SignedProperties es parte de la informacion XAdES que se// creo en XML_Signer.XAdESProcessor.Generate y se firma siempre en// el standard XAdES.
