Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/eclipxe13/CfdiUtils/llms.txt

Use this file to discover all available pages before exploring further.

The Cadena de Origen (origin string) is a pipe-delimited text string that the SAT derives from a CFDI’s key fields using an XSLT transformation. It is the exact data over which the digital sello (seal) is computed: you hash the Cadena de Origen with SHA-256, encrypt the hash with your private key, and Base64-encode the result to produce the Sello attribute. Because the Cadena de Origen is generated by a deterministic transformation of specific CFDI attributes (not all of them), non-structural modifications — adding an addenda, reformatting whitespace, removing unused namespace declarations — do not invalidate the signature. This intentional design means a CFDI can be “repaired” without re-signing as long as no signed field is changed. The SAT’s method for generating the Cadena de Origen uses XSLT (Extensible Stylesheet Language Transformations). The SAT publishes XSLT files for each version of CFDI and for each complement. CfdiUtils provides pluggable XSLT processors through XsltBuilderInterface.

XsltBuilderInterface

All XSLT processors implement the single-method interface CfdiUtils\CadenaOrigen\XsltBuilderInterface:
<?php
namespace CfdiUtils\CadenaOrigen;

interface XsltBuilderInterface
{
    public function build(string $xmlContent, string $xsltLocation): string;
}
xmlContent
string
required
The full XML content of the document to transform (the CFDI or complement XML string).
xsltLocation
string
required
The absolute local path or remote URL of the XSLT file to apply. Use XmlResolver::resolveCadenaOrigenLocation() to obtain the correct local path.
The method returns the generated Cadena de Origen as a string.

Available Implementations

ImplementationClassRequirementXSLT versionNotes
DOMBuilderCfdiUtils\CadenaOrigen\DOMBuilderPHP ext-xsl (built-in)1.0 (processes SAT v2 files)Default; no extra packages required
GenkgoXslBuilderCfdiUtils\CadenaOrigen\GenkgoXslBuildercomposer require genkgo/xsl2.0 (native)Pure-PHP XSLT 2.0 implementation
SaxonbCliBuilderCfdiUtils\CadenaOrigen\SaxonbCliBuilderapt-get install libsaxonb-java2.0 (native)Executes Saxon-B as a shell command

DOMBuilder

DOMBuilder is the default implementation. It uses PHP’s built-in DOMDocument and XSLTProcessor classes (provided by the ext-xsl extension) — no additional Composer packages are required. PHP’s XSLTProcessor implements XSLT 1.0. The SAT’s XSLT files are written for XSLT 2.0, but in practice the features they use are backward-compatible and DOMBuilder produces the correct Cadena de Origen. All three implementations have been verified to produce identical output in CfdiUtils’ test suite.
<?php
use CfdiUtils\CadenaOrigen\DOMBuilder;
use CfdiUtils\XmlResolver\XmlResolver;

$xmlContent = file_get_contents('/facturas/invoice.xml');
$resolver   = new XmlResolver();

// Get the local XSLT path for CFDI 4.0 (downloads if not cached)
$xsltLocation = $resolver->resolveCadenaOrigenLocation('4.0');

$builder      = new DOMBuilder();
$cadenaOrigen = $builder->build($xmlContent, $xsltLocation);

echo $cadenaOrigen;
// ||4.0|2024-01-15T10:00:00|...||
If you are not sure which implementation to choose, start with DOMBuilder. It is the default used by CfdiCreator40, CfdiCreator33, and the TFD helper, and it requires no extra dependencies beyond a standard PHP installation with ext-xsl.

GenkgoXslBuilder

GenkgoXslBuilder delegates to the genkgo/xsl library, a pure-PHP XSLT 2.0 processor. Use it if you need native XSLT 2.0 support (for example, if the SAT updates its XSLT files to use XSLT 2.0-only constructs). Install the dependency:
composer require genkgo/xsl
<?php
use CfdiUtils\CadenaOrigen\GenkgoXslBuilder;
use CfdiUtils\XmlResolver\XmlResolver;

$resolver     = new XmlResolver();
$xsltLocation = $resolver->resolveCadenaOrigenLocation('4.0');

$builder      = new GenkgoXslBuilder();
$cadenaOrigen = $builder->build(
    file_get_contents('/facturas/invoice.xml'),
    $xsltLocation
);

SaxonbCliBuilder

SaxonbCliBuilder invokes the Saxon-B XSLT Processor as an external command-line process. Saxon-B is a Java-based, fully compliant XSLT 2.0 processor. Install Saxon-B on Debian/Ubuntu:
apt-get install libsaxonb-java
<?php
use CfdiUtils\CadenaOrigen\SaxonbCliBuilder;
use CfdiUtils\XmlResolver\XmlResolver;

$resolver     = new XmlResolver();
$xsltLocation = $resolver->resolveCadenaOrigenLocation('4.0');

// Pass the absolute path to the saxonb-xslt executable
$builder      = new SaxonbCliBuilder('/usr/bin/saxonb-xslt');
$cadenaOrigen = $builder->build(
    file_get_contents('/facturas/invoice.xml'),
    $xsltLocation
);
SaxonbCliBuilder requires the absolute path to the saxonb-xslt executable as its constructor argument. The executable must exist and be executable by the PHP process. Review your server’s security policy before enabling shell execution.

Using Cadena de Origen with CfdiCreator

When you build a CFDI with CfdiCreator40 or CfdiCreator33, the Cadena de Origen is generated automatically when you call addSello(). You can also generate it manually:
<?php
use CfdiUtils\CfdiCreator40;
use CfdiUtils\CadenaOrigen\DOMBuilder;

$creator = new CfdiCreator40();
// ... populate comprobante attributes and elements ...

// Generate the Cadena de Origen for the comprobante
// (uses the configured XmlResolver and XsltBuilder)
$cadenaOrigen = $creator->buildCadenaDeOrigen();

// Sign it with a private key and set the Sello attribute
$creator->addSello('file://path/to/key.pem', 'passphrase');
To use a non-default builder with the creator:
<?php
use CfdiUtils\CfdiCreator40;
use CfdiUtils\CadenaOrigen\GenkgoXslBuilder;

$creator = new CfdiCreator40();
$creator->setXsltBuilder(new GenkgoXslBuilder());

Cadena de Origen for Timbre Fiscal Digital

The Cadena de Origen of the Timbre Fiscal Digital (TFD) is required for the printed representation (PDF) of a CFDI. Use the dedicated TfdCadenaDeOrigen helper:
<?php
use CfdiUtils\TimbreFiscalDigital\TfdCadenaDeOrigen;
use CfdiUtils\Nodes\XmlNodeUtils;
use CfdiUtils\Cfdi;

// Option 1: from a CFDI object
$cfdi       = Cfdi::newFromString(file_get_contents('/cfdis/fei-123456.xml'));
$cfdiNode   = $cfdi->getNode();
$tfd        = $cfdiNode->searchNode('cfdi:Complemento', 'tfd:TimbreFiscalDigital');
$tfdXml     = XmlNodeUtils::nodeToXmlString($tfd);

$tfdBuilder = new TfdCadenaDeOrigen();
$cadena     = $tfdBuilder->build($tfdXml);

// Option 2: with a custom XmlResolver and XsltBuilder
use CfdiUtils\XmlResolver\XmlResolver;
use CfdiUtils\CadenaOrigen\GenkgoXslBuilder;

$tfdBuilder->setXmlResolver(new XmlResolver('/custom/cache/'));
$tfdBuilder->setXsltBuilder(new GenkgoXslBuilder());
$cadena = $tfdBuilder->build($tfdXml);
TfdCadenaDeOrigen supports TFD versions 1.0 and 1.1. Passing any other version throws an exception.

PHP and XSLT 2.0

PHP’s built-in XSLTProcessor implements XSLT 1.0. The SAT currently writes its XSLT files in XSLT 2.0 syntax, but the features in use happen to be backward-compatible with 1.0 processors. All three implementations (DOMBuilder, GenkgoXslBuilder, SaxonbCliBuilder) produce identical Cadena de Origen strings in CfdiUtils’ test suite. If the SAT were to start using XSLT 2.0-exclusive constructs, DOMBuilder could silently produce incorrect output. In that case, switch to GenkgoXslBuilder or SaxonbCliBuilder for fully standards-compliant XSLT 2.0 processing.

Build docs developers (and LLMs) love