The Mexican tax authority (SAT) defines a second category of electronic document alongside the familiarDocumentation 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.
cfdi:Comprobante invoice: the CFDI de Retenciones e Información de Pagos. These documents report withholding taxes under the LIVA, LISR, and LIEPS laws and are structurally distinct from regular CFDI — they use a different XML namespace, different attribute names, their own catalogs, and SHA-1 rather than SHA-256 for digest calculation. Despite these differences, CfdiUtils provides a reader class — CfdiUtils\Retenciones\Retenciones — that mirrors the Cfdi class API, so the navigation patterns you already know apply here too.
The SAT does not provide a free tool for generating Retenciones documents (unlike regular CFDI). You will need a PAC’s services to stamp the Pre-CFDI and receive the final document including the Timbre Fiscal Digital.
Key Differences from Regular CFDI
| Characteristic | Regular CFDI | CFDI Retenciones |
|---|---|---|
| XML namespace | http://www.sat.gob.mx/cfd/3 or /cfd/4 | http://www.sat.gob.mx/esquemas/retencionpago/1 or /retencionpago/2 |
| Namespace prefix | cfdi | retenciones |
| Root element | cfdi:Comprobante | retenciones:Retenciones |
| Certificate attribute | cfdi:Comprobante@Certificado | retenciones:Retenciones@Cert |
| Digest algorithm | SHA-256 | SHA-1 |
| Date format | ISO-8601 without offset | ISO-8601 with offset (e.g. -06:00) |
| Supported versions | 3.2, 3.3, 4.0 | 1.0, 2.0 |
The Retenciones Class
CfdiUtils\Retenciones\Retenciones uses the same XmlReaderTrait as the Cfdi class, meaning it exposes the same four primary getters and supports both formal node navigation and quick reading. It validates at construction time that:
- The document implements the Retenciones namespace (
/retencionpago/1or/retencionpago/2) using the prefixretenciones. - The root element is
retenciones:Retenciones.
DOMDocument is cloned at construction time, so changes made to the original document after instantiation are not reflected in the reader — and vice versa.
Create a Retenciones Object
Use the static factory Retenciones::newFromString() to parse a raw XML string, or pass a DOMDocument directly to the constructor.
Cfdi:
| Method | Return type | Description |
|---|---|---|
getVersion() | string | Detected version string: "1.0" or "2.0", empty string if unrecognised |
getDocument() | DOMDocument | A clone of the internal DOMDocument |
getSource() | string | The original XML source string |
getNode() | NodeInterface | Root node for the retenciones:Retenciones element |
Navigating Nodes (Formal Reader)
The formal reader usesgetNode() to obtain the root NodeInterface. Element names include their namespace prefix; attribute names use their exact casing from the XML.
Navigating Nodes (Quick Reader)
CallgetQuickReader() for the same case-insensitive, namespace-agnostic access available on regular CFDI:
QuickReader API reference.
Version Detection Without Constructing the Object
If you need to detect the Retenciones version before constructing a fullRetenciones object, use CfdiUtils\Retenciones\RetencionVersion:
| Method | Use when you have… |
|---|---|
getFromXmlString(string $xml) | Raw XML string |
getFromNode(NodeInterface $node) | An existing NodeInterface |
getFromDOMDocument(DOMDocument $doc) | A loaded DOMDocument |
getFromDOMElement(DOMElement $el) | A DOMElement |
Retenciones::newFromString() performs version detection internally. Only use RetencionVersion directly if you need the version without constructing the full reader object.Version Differences (1.0 vs 2.0)
IfgetVersion() returns an empty string, the document could not be matched to either supported namespace. This mirrors the behaviour of the Cfdi class when presented with an unrecognised version.