### Install eclipxe/cfdiutils with Composer Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/instalar/instalacion.md Use this command to install the library via Composer. It ensures you get the latest stable version and handles dependency checks. ```shell composer require eclipxe/cfdiutils ``` -------------------------------- ### Get QuickReader Instance Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/leer/quickreader.md Instantiate a CFDI object from an XML string and obtain its QuickReader instance using the dedicated method. ```php getQuickReader(); ``` -------------------------------- ### Read Certificate File - PHP Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/certificado.md Instantiate the Certificado class by passing the certificate file path. This example shows how to retrieve the RFC from a .cer file. ```php getRfc()); // algo como COSC8001137NA ``` -------------------------------- ### CFDI 3.3 Creation Workflow Source: https://github.com/eclipxe13/cfdiutils/wiki/Crear-cfdi33 Example of the standard workflow to create, populate, sign, and save a CFDI 3.3 document. ```APIDOC ## CFDI 3.3 Creation Example ### Description Standard implementation steps for creating a CFDI 3.3 document using the CfdiCreator33 library. ### Request Example ```php $certificado = new \CfdiUtils\Certificado\Certificado('path/to/cer'); $creator = new \CfdiUtils\CfdiCreator33(['Serie' => 'XXX', 'Folio' => '0000123456'], $certificado); $comprobante = $creator->comprobante(); $comprobante->addEmisor(['RegimenFiscal' => '601']); $comprobante->addReceptor([...]); $comprobante->addConcepto([...])->addTraslado([...]); $creator->addSumasConceptos(null, 2); $creator->addSello('path/to/key.pem', 'password'); $creator->saveXml('path/to/save/cfdi.xml'); ``` ``` -------------------------------- ### Install eclipxe/cfdiutils without Composer Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/instalar/instalacion.md This method is for projects not using Composer. It involves creating a directory, requiring the package into that directory, and then including the generated autoloader in your PHP script. ```shell cd mi_proyecto mkdir cfdiutils composer require --working-dir=cfdiutils eclipxe/cfdiutils ``` ```php require __DIR__ . '/cfdiutils/vendor/autoload.php'; ``` -------------------------------- ### Uso de métodos de ayuda para nodos Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/complemento-nomina12b.md Ejemplifica el uso de métodos get, add y multi para manipular nodos de aparición única y múltiple. ```php getEmisor(); $emisor['Curp'] = '...'; // agregar con prefijo add (Receptor es de 1 aparición) $receptor = $nomina->addReceptor(['NumEmpleado' => 'JFIK000045']); // agregar con prefijo add (Subcontratacion es de múltiples) $receptor->addSubContratacion(['RfcLabora' => 'EKU9003173C9', 'PorcentajeTiempo' => '50']); // devuelve SubContratacion $receptor->addSubContratacion(['RfcLabora' => 'XXXX010101XXX', 'PorcentajeTiempo' => '60']); // devuelve SubContratacion // agregar con prefijo multi (Subcontratacion es de múltiples) $receptor->multiSubContratacion( ['RfcLabora' => 'EKU9003173C9', 'PorcentajeTiempo' => '50'], ['RfcLabora' => 'XXXX010101XXX', 'PorcentajeTiempo' => '60'] ); // devuelve Receptor (exactamente $receptor) ``` -------------------------------- ### Add Nodes to Comercio Exterior 2.0 Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/complemento-comercio-exterior-20.md Use `get` methods for single-occurrence elements and `add` or `multi` methods for multiple occurrences. `addElemento` adds a new element, while `multiElemento` can add multiple elements at once. ```php getMercancias(); // agregar con prefijo add (Mercancia es de 1 aparición) $mercancia = $mercancias->addMercancia(['NoIdentificacion'=> 'PN001122', ...]); // agregar con prefijo multi (DescripcionesEspecificas es de múltiples) $mercancia->multiDescripcionesEspecificas( ['Marca' => 'Hitachi', 'Modelo' => 'XB-112244', ...], ['Marca' => 'Samsung', 'Modelo' => 'ECL-1-PXE', ...] ); ``` -------------------------------- ### Create Credential Object from Files Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/crear-cfdi-40.md This snippet shows how to create a Credential object using the file paths for the certificate and private key, along with the passphrase. This is a common setup when working with digital certificates. ```php getUbicaciones(); // agregar con prefijo add (Ubicacion es de 1 aparición) $ubicacion = $ubicaciones->addUbicacion(['TipoUbicacion'=> 'Origen', ...]); // agregar con prefijo multi (Domicilio es de múltiples) $ubicacion->multiDomicilio( ['Calle' => 'xxx', 'NumeroExterior' => 'xxx', ...], ['Calle' => 'xxx', 'NumeroExterior' => 'xxx', ...] ); ``` -------------------------------- ### Instalar mkdocs con pip (instalación de usuario) Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Instala mkdocs utilizando pip, el gestor de paquetes de Python. El parámetro --user asegura que la instalación se realice en el espacio de trabajo del usuario, evitando posibles conflictos de permisos. ```shell pip install --user mkdocs ``` -------------------------------- ### Add CartaPorte Complement to CFDI Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/complemento-carta-porte-31.md Use the `Comprobante::addComplemento()` method to insert the `CartaPorte` element into a CFDI. This example demonstrates the basic setup using `CfdiCreator40` and adding a `CartaPorte` object. ```php comprobante(); $cartaPorte = new \CfdiUtils\Elements\CartaPorte31\CartaPorte(); // ... llenar la información de $cartaPorte // agregar $cartaPorte como complemento del $comprobante $comprobante->addComplemento($cartaporte); ``` -------------------------------- ### Instalar mkdocs en Debian/Ubuntu Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Instala la herramienta mkdocs en sistemas Debian GNU/Linux y derivados utilizando el gestor de paquetes apt-get. ```shell apt-get install mkdocs ``` -------------------------------- ### Get CFDI Version from XML String Source: https://github.com/eclipxe13/cfdiutils/wiki/Leer-Cfdi Use `CfdiUtils\CfdiVersion` to get the CFDI version from its XML content. This method is useful when you have the entire XML as a string. ```php getFromXmlString($xmlContents); ``` -------------------------------- ### Open Certificate and Private Key using phpcfdi/credentials Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/crear-cfdi-40.md Demonstrates how to use the phpcfdi/credentials library to open a certificate and private key file. This is recommended for managing FIEL and CSD files. ```php putCertificado( new Certificado($csd->certificate()->pem()), true // establecer RFC y el nombre del emisor sin régimen de capital ); // se construye el pre-cfdi ... // sellado del cfdi $creator->addSello($csd->privateKey()->pem(), $csd->privateKey()->passPhrase()); ``` -------------------------------- ### Servir la documentación localmente con mkdocs Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Inicia un servidor local para previsualizar los cambios en la documentación mientras se edita. La documentación estará disponible en http://127.0.0.1:8000/. ```shell mkdocs serve ``` -------------------------------- ### Accessing Attributes as Array Source: https://github.com/eclipxe13/cfdiutils/wiki/Nodes The Attributes class supports array-like access for getting, setting, checking, and removing attributes. ```php $attributes[$name] ``` ```php $attributes[$name] = $value ``` ```php isset($attributes[$name]) ``` ```php unset($attributes[$name]) ``` -------------------------------- ### Instalar dependencias del proyecto con npm Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Instala las dependencias del proyecto, incluyendo markdownlint-cli, definidas en el archivo package.json. Esto es necesario para ejecutar las verificaciones de sintaxis de markdown. ```shell npm install ``` -------------------------------- ### Example of PEM content extraction Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/utilerias/openssl.md Shows how the PemExtractor processes PEM-formatted text, discarding invalid or unrecognized sections. ```text Contenidos antes de primer sección son descartados -----BEGIN CERTIFICATE----- FOO-BAR -----END CERTIFICATE----- -----BEGIN PUBLIC KEY----- Esta sección contiene una "o" acentuada y comillas dobles por lo que simplemente es descartada -----END PUBLIC KEY----- Contenidos entre secciones son descartados -----BEGIN SOMETHING----- SOMETHING no es requerido por lo que es descartado -----END SOMETHING----- Contenidos después de última sección son descartados ``` -------------------------------- ### Display XML Error Exception Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/CHANGELOG.md Example of the error message format when a DOM Document cannot be created from an XML string. ```text Cannot create a DOM Document from xml string XML Fatal [L: 1, C: 7]: Input is not proper UTF-8 ``` -------------------------------- ### Configure XmlResolver with Custom Downloader (Proxy) Source: https://context7.com/eclipxe13/cfdiutils/llms.txt Illustrates how to provide a custom downloader implementation to `XmlResolver`, such as one that uses a proxy server for downloading resources. This is useful for environments with network restrictions. ```php resolveCadenaOrigenLocation('4.0'); echo "XSLT Location: " . $xsltLocation . "\n"; ``` -------------------------------- ### Read PEM files and contents with OpenSSL Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/utilerias/openssl.md Demonstrates how to read certificates and private keys from files or strings using the OpenSSL class. ```php readPemFile($cerFile)->certificate(); // Leer una llave privada desde una cadena de caracteres con finales de línea convertidas a PHP_EOL $keyFile = 'EKU9003173C9.key.pem'; $keyContents = file_get_contents($keyFile); $privateKey = $openssl->readPemContents($keyContents)->privateKey(); // Leer un archivo PEM y averiguar sus contenidos: $pemFile = 'EKU9003173C9.pem'; $pem = $openssl->readPemFile($pemFile); // usando hasCertificate if ($pem->hasCertificate()) { echo 'CERTIFICATE:', PHP_EOL, $pem->certificate(), PHP_EOL; } // obteniendo directamente, si no hay entonces devuelve una cadena de caracteres vacía echo 'PUBLIC KEY:', PHP_EOL, $pem->publicKey(), PHP_EOL; ``` -------------------------------- ### Instalar mkdocs en Windows con Chocolatey Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Instala mkdocs en sistemas Windows utilizando el gestor de paquetes Chocolatey. ```shell choco install mkdocs ``` -------------------------------- ### Get CFDI Version from XML String Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/leer/leer-cfdi.md Use `CfdiVersion::getFromXmlString()` to retrieve the CFDI version when you have the XML content as a string. Ensure the `CfdiVersion` class is instantiated. ```php getFromXmlString($xmlContents); ``` -------------------------------- ### Ejecutar markdownlint-cli con node Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Ejecuta la herramienta markdownlint-cli utilizando Node.js para verificar la sintaxis de los archivos markdown del proyecto. Se accede a través de la ruta de node_modules. ```shell node node_modules/markdownlint-cli/markdownlint.js ``` -------------------------------- ### Instalar dependencias Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-desarrollador.md Comando para instalar las dependencias del proyecto mediante Composer. ```shell composer update ``` -------------------------------- ### Generate CFDI Origin String with SaxonbCliBuilder Source: https://context7.com/eclipxe13/cfdiutils/llms.txt Generates the origin string for a CFDI XML using SaxonbCliBuilder. This method requires the 'saxonb-xslt' tool to be installed and specifies its path. ```php build($xmlContent, $xsltLocation); ``` -------------------------------- ### Implementing and configuring a custom Downloader Source: https://github.com/eclipxe13/cfdiutils/wiki/XmlResolver Create a custom class implementing DownloaderInterface to handle file downloads, then inject it into the XmlResolver instance. ```php setDownloader($myDownloader); // establecer el descargador a un descargador simple (ver PhpDownloader) $myResolver->setDownloader(null); ``` -------------------------------- ### Configure XmlResolver with Custom Local Path Source: https://context7.com/eclipxe13/cfdiutils/llms.txt Demonstrates how to initialize `XmlResolver` with a custom directory for storing local XML resources (XSD and XSLT). This helps in managing and caching SAT resources. ```php setXmlResolver($resolver); // Use with CfdiValidator (from constructor) $validator = new CfdiValidator40($resolver); ``` -------------------------------- ### Get the Node Name as a String Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/leer/quickreader.md Retrieve the name of the current CFDI node by casting the QuickReader object to a string. This is useful for debugging or when the node's name itself is required. ```php getQuickReader(); echo (string) $comprobante; // (string) "Comprobante" ``` -------------------------------- ### Get Serial Number Formats - PHP Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/certificado.md Obtain a copy of the internal SerialNumber object from a Certificado instance to retrieve the serial number in ASCII, hexadecimal, or decimal formats. ```php // SerialNumber::asAscii(): 30001000000300023708 the same as Certificado::getSerial() // SerialNumber::getHexadecimal(): 333030303130303030303030333030303233373038 // SerialNumber::getDecimal(): 292233162870206001759766198425879490508935868472 ``` -------------------------------- ### Construir documentación Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-windows.md Comandos para instalar dependencias de Node.js, validar sintaxis Markdown y construir o servir la documentación con MkDocs. ```batch :: instalar las dependencias de nodejs para markdownlint npm install :: revisar la sintaxis de markdown node node_modules\markdownlint-cli\markdownlint.js *.md docs :: instalar mkdocs usando chocolatey choco install -y mkdocs mkdocs-material :: construyendo los documentos mkdocs build --strict --site-dir build\docs :: sirviendo los documentos mkdocs serve ``` -------------------------------- ### Actualizar herramientas y dependencias Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-desarrollador.md Comandos para actualizar las herramientas de desarrollo y las dependencias del proyecto. ```shell phive update && composer update ``` -------------------------------- ### CfdiUtils\Nodes\Attributes Class Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/nodes.md This class represents a collection of attributes identified by name. It allows iteration over attributes and provides array-like access for getting, setting, checking existence, and removing attributes. ```APIDOC ## CfdiUtils\Nodes\Attributes Class ### Description Represents a collection of attributes identified by name. Iterating over the object returns each attribute as a key/value pair. Supports array-like access for attribute manipulation. ### Methods - `get(string $name): string` - Retrieves the value of an attribute. - `set(string $name, string $value)` - Sets the value of an attribute. - `remove(string $name)` - Removes an attribute. - `removeAll()` - Removes all attributes. - `exists(string $name): bool` - Checks if an attribute exists. ### Array-like Access - `$attributes[$name]` is equivalent to `$attributes->get($name)`. - `$attributes[$name] = $value` is equivalent to `$attributes->set($name, $value)`. - `isset($attributes[$name])` is equivalent to `$attributes->exists($name)`. - `unset($attributes[$name])` is equivalent to `$attributes->remove($name)`. ``` -------------------------------- ### Configurar Git para finales de línea Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-windows.md Ajusta la configuración global de Git para manejar correctamente los finales de línea en Windows. ```shell git config --global core.autocrlf input ``` -------------------------------- ### Create CartaPorte20 Elements Source: https://github.com/eclipxe13/cfdiutils/blob/master/development/README.md Example of generating CartaPorte20 elements. This involves removing existing files, creating a new directory, running the elements-maker script, and fixing code style. ```shell rm -rf src/CfdiUtils/Elements/CartaPorte20 mkdir -p src/CfdiUtils/Elements/CartaPorte20 php development/bin/elements-maker.php development/ElementsMaker/specifications/cartaporte20.json src/CfdiUtils/Elements/CartaPorte20/ composer dev:fix-style ``` -------------------------------- ### Get Certificate Information - Shell Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/certificado.md Use the OpenSSL command-line tool to display various details of a certificate file, including dates, serial number, subject, fingerprint, and public key. ```shell openssl x509 -nameopt utf8,sep_multiline,lname -inform DER -noout -dates -serial \ -subject -fingerprint -pubkey -in EKU9003173C9.cer ``` -------------------------------- ### Leer contenido XML con CfdiUtils\Cfdi Source: https://github.com/eclipxe13/cfdiutils/wiki/Leer-Cfdi Utiliza el método estático newFromString para inicializar un objeto Cfdi a partir de una cadena XML. ```php ...'; $cfdi = CfdiUtils\Cfdi::newFromString($xmlContents); $cfdi->getVersion(); // (string) 3.3 $cfdi->getDocument(); // clon del objeto DOMDocument $cfdi->getSource(); // (string) getNode(); // Nodo de trabajo del nodo cfdi:Comprobante ``` -------------------------------- ### Leer un CFDI con CfdiUtils Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/leer/leer-cfdi.md Ejemplo básico de cómo instanciar un objeto Cfdi a partir de una cadena XML y acceder a sus métodos principales. ```php ...'; $cfdi = \CfdiUtils\Cfdi::newFromString($xmlContents); $cfdi->getVersion(); // (string) 3.3 $cfdi->getDocument(); // clon del objeto DOMDocument $cfdi->getSource(); // (string) getNode(); // Nodo de trabajo del nodo cfdi:Comprobante ``` -------------------------------- ### Extract Certificate from CFDI - PHP Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/certificado.md Use NodeCertificado to extract a certificate from a CFDI XML file and then obtain a Certificado object. This example demonstrates retrieving the RFC from a certificate embedded in a CFDI. ```php obtain(); var_dump($certificate->getRfc()); // algo como COSC8001137NA ``` -------------------------------- ### Consultar estado de CFDI desde archivo Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/estado-sat.md Utiliza un archivo XML existente para crear los parámetros de consulta y realizar la petición al WebService del SAT. ```php request($request); // $response contiene toda la información ``` -------------------------------- ### Manipulación de nodos de Carta Porte 3.0 Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/complemento-carta-porte-30.md Ejemplo de inicialización del objeto CartaPorte y uso de métodos get, add y multi para gestionar ubicaciones y domicilios. ```php getUbicaciones(); // agregar con prefijo add (Ubicacion es de 1 aparición) $ubicacion = $ubicaciones->addUbicacion(['TipoUbicacion'=> 'Origen', ...]); // agregar con prefijo multi (Domicilio es de múltiples) $ubicacion->multiDomicilio( ['Calle' => 'xxx', 'NumeroExterior' => 'xxx', ...], ['Calle' => 'xxx', 'NumeroExterior' => 'xxx', ...] ); ``` -------------------------------- ### Manage Private Keys Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/utilerias/openssl.md Shows how to convert PKCS#8 keys to PEM format and manage password protection. ```php derKeyConvert($keyDerFile, $keyDerPass, $keyPemFileUnprotected); // poner contraseña a $keyPemFileUnprotected, guardar en $keyPemFile $openssl->pemKeyProtect($keyPemFileUnprotected, '', $keyPemFile, $keyPemPass); // convertir la llave original DER a formato PEM con nueva contraseña, guardar en $keyPemFile // lo mismo que los dos pasos anteriores pero en una llamada $openssl->derKeyProtect($keyDerFile, $keyDerPass, $keyPemFile, $keyPemPass); // supongamos que requerimos un certificado PEM con contraseña "abc/123-xyz" // y tenemos la llave en $keyPemFile con la contraseña $keyPemPass // por ejemplo, para finkok $keyForFinkOk = $openssl->pemKeyProtectOut($keyPemFile, $keyPemPass, 'abc/123-xyz'); ``` -------------------------------- ### Inicializar Retenciones con DOMDocument Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/leer/leer-cfdi-retenciones.md Se utiliza la clase `CfdiUtils\Retenciones\Retenciones` para leer CFDI de retenciones. Inicializa el objeto pasando una instancia de `DOMDocument` al constructor. ```php $retenciones = new Retenciones(DOMDocument $document) ``` -------------------------------- ### Accessing Nested Child Nodes and Their Children Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/leer/quickreader.md Demonstrates accessing nested child nodes, such as 'conceptos' and their 'impuestos' and 'traslados' children, using a combination of property access and function invocation. This example shows two ways to access children: assigning to a variable first or using parentheses to separate the property before invocation. ```php getQuickReader(); // using variable assignment $conceptos = $comprobante->conceptos; foreach($conceptos() as $concepto) { // using property foreach(($concepto->impuestos->traslados)() as $traslado) { echo $traslado['impuesto']; } } ``` -------------------------------- ### Verificar la sintaxis de markdown y construir la documentación Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/contribuir/guia-documentador.md Ejecuta comandos para verificar la sintaxis de los archivos markdown y construir el sitio de documentación estáticamente. Estos pasos son cruciales antes de publicar cambios. ```shell markdownlint *.md docs/ ``` ```shell mkdocs build --strict --site-dir build/docs ``` -------------------------------- ### Consultar estado de CFDI desde datos conocidos Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/componentes/estado-sat.md Realiza una consulta al WebService del SAT proporcionando manualmente los datos del CFDI y muestra cómo acceder a los resultados de la respuesta. ```php request($request); // obtener las respuestas echo $response->getCode(); // S - ... echo $response->getCfdi(); // Vigente echo $response->getCancellable(); // Cancelable con aceptación echo $response->getCancellationStatus(); // En proceso echo $response->getValidationEfos(); // 200 ``` -------------------------------- ### Creación básica de un CFDI 4.0 Source: https://github.com/eclipxe13/cfdiutils/blob/master/docs/crear/crear-cfdi-40.md Este snippet muestra el flujo principal para crear un CFDI 4.0, desde la inicialización del certificado y creador hasta la adición de emisor, receptor, conceptos, cálculo de sumas, firma, validación y guardado del XML. Requiere la ubicación de archivos CER y KEY, así como la contraseña de la llave privada. ```php 'XXX', 'Folio' => '0000123456', // y otros atributos más... ]; $creator = new \CfdiUtils\CfdiCreator40($comprobanteAtributos, $certificado); $comprobante = $creator->comprobante(); // No agrego (aunque puedo) el Rfc y Nombre porque uso los que están establecidos en el certificado $comprobante->addEmisor([ 'RegimenFiscal' => '601', // General de Ley Personas Morales ]); $comprobante->addReceptor([/* Atributos del receptor */]); $comprobante->addConcepto([ /* Atributos del concepto */ ])->addTraslado([ /* Atributos del impuesto trasladado */ ]); // método de ayuda para establecer las sumas del comprobante e impuestos // con base en la suma de los conceptos y la agrupación de sus impuestos $creator->addSumasConceptos(null, 2); // método de ayuda para generar el sello (obtener la cadena de origen y firmar con la llave privada) $creator->addSello('file:// ... ruta para mi archivo key convertido a PEM ...', 'contraseña de la llave'); // método de ayuda para mover las declaraciones de espacios de nombre al nodo raíz $creator->moveSatDefinitionsToComprobante(); // método de ayuda para validar usando las validaciones estándar de creación de la librería $asserts = $creator->validate(); if ($asserts->hasErrors()) { // contiene si hay o no errores print_r(['errors' => $asserts->errors()]); return; } // método de ayuda para generar el xml y guardar los contenidos en un archivo $creator->saveXml('... lugar para almacenar el cfdi ...'); // método de ayuda para generar el xml y retornarlo como un string $creator->asXml(); ```