Skip to content

XMLMaker ​

XMLMaker convierte un payload PHP en un DOMDocument compatible con la estructura XML del SRI.

Para ejemplos completos de cada comprobante soportado, revisa Generar XML por tipo.

Estado de soporte ​

DocumentoEstado
Factura (XmlDocumentType::Invoice)Implementado
Liquidacion de compra (XmlDocumentType::PurchaseSettlement)Implementado
Nota de credito (XmlDocumentType::CreditNote)Implementado
Nota de debito (XmlDocumentType::DebitNote)Implementado
Guia de remision (XmlDocumentType::DeliveryGuide)Implementado
Comprobante de retencion (XmlDocumentType::WithholdingReceipt)Implementado

API principal ​

php
use MTZ\Toolkit\XMLMaker\Data\XmlGenerationData;
use MTZ\Toolkit\XMLMaker\Enums\XmlDocumentType;
use MTZ\Toolkit\XMLMaker\Enums\XmlEnvironment;
use MTZ\Toolkit\XMLMaker\XMLMaker;

$generatedXml = (new XMLMaker())->generate(
    XmlGenerationData::make(
        documentType: XmlDocumentType::Invoice,
        environment: XmlEnvironment::Testing,
        accessKey: $accessKey,
        data: $invoicePayload,
    ),
);

$xml = $generatedXml->toString();
$document = $generatedXml->document;

Resultado ​

GeneratedXml expone:

PropiedadTipoDescripcion
documentTypeXmlDocumentTypeTipo generado
accessKeystringClave de acceso usada
documentDOMDocumentDocumento XML
toString()stringXML serializado

Payload base de factura ​

php
$invoicePayload = [
    'date' => '13/05/2026',
    'sequential' => '000000025',
    'company' => [
        'ruc' => '1790012345001',
        'legal_name' => 'MTZ TEST S.A.',
        'trade_name' => 'MTZ TEST',
        'head_office_address' => 'Quito',
        'withholding_agent' => null,
        'rimpe_regime_taxpayer' => null,
    ],
    'establishment' => [
        'code' => '001',
    ],
    'emission_point' => [
        'code' => '001',
    ],
    'customer' => [
        'identification_type' => '05',
        'identification_number' => '1710034065',
        'name' => 'CONSUMIDOR FINAL',
        'address' => 'Quito',
    ],
    'establishment_address' => 'Quito',
    'requires_accounting' => 'NO',
    'total_without_taxes' => '10.00',
    'total_discount' => '0.00',
    'tax_totals' => [
        [
            'code' => '2',
            'percentage_code' => '4',
            'taxable_base' => '10.00',
            'value' => '1.50',
        ],
    ],
    'tip' => '0.00',
    'total_amount' => '11.50',
    'currency' => 'DOLAR',
    'payments' => [
        [
            'method' => '01',
            'total' => '11.50',
            'term' => null,
            'time_unit' => null,
        ],
    ],
    'details' => [
        [
            'main_code' => 'P001',
            'auxiliary_code' => null,
            'description' => 'Producto de prueba',
            'quantity' => '1.00',
            'unit_price' => '10.00',
            'discount' => '0.00',
            'total_without_tax' => '10.00',
            'taxes' => [
                [
                    'code' => '2',
                    'percentage_code' => '4',
                    'rate' => '15.00',
                    'taxable_base' => '10.00',
                    'value' => '1.50',
                ],
            ],
        ],
    ],
    'additional_info' => [
        'Email' => 'cliente@example.com',
    ],
];

Campos obligatorios de factura ​

CampoDescripcion
dateFecha de emision en formato SRI, por ejemplo 13/05/2026
sequentialSecuencial de 9 digitos
company.rucRUC emisor
company.legal_nameRazon social
company.head_office_addressDireccion matriz
establishment.codeCodigo de establecimiento
emission_point.codePunto de emision
customer.identification_typeTipo de identificacion del comprador
customer.identification_numberIdentificacion del comprador
customer.nameRazon social del comprador
establishment_addressDireccion del establecimiento
total_without_taxesTotal sin impuestos
total_discountTotal descuento
tax_totalsTotales de impuestos, no puede estar vacio
total_amountImporte total
detailsDetalles, no puede estar vacio
details.*.taxesImpuestos por detalle, no puede estar vacio

Campos opcionales ​

trade_name, withholding_agent, rimpe_regime_taxpayer, requires_accounting, customer.address, tip, currency, payments, payments.*.term, payments.*.time_unit, details.*.auxiliary_code, details.*.discount y additional_info.

Si currency esta vacio, el builder usa DOLAR.

Calculo automatico de totales ​

Por defecto, XMLMaker deriva total_without_taxes, total_amount y tax_totals desde las lineas de detalle (factura, liquidacion de compra y nota de credito), usando aritmetica decimal exacta. Esto mantiene el XML cuadrado y evita el error 52 (diferencias en calculos). Los valores calculados sobrescriben los provistos en el payload.

Para enviar los totales manualmente, desactivalo:

php
use MTZ\Toolkit\XMLMaker\Config\XmlMakerConfig;
use MTZ\Toolkit\XMLMaker\XMLMaker;

$maker = new XMLMaker(new XmlMakerConfig(calculateTotals: false));

Ver Validacion para el detalle de TotalsCalculator.

Validacion contra XSD ​

Antes de firmar, valida el XML contra el esquema oficial incluido:

php
use MTZ\Toolkit\XMLMaker\Validation\XsdValidator;

$errors = (new XsdValidator())->validate($xml, XmlDocumentType::Invoice);

Los seis tipos generan XML conforme al XSD oficial del SRI.

Variantes de factura ​

La factura admite bloques opcionales que se emiten solo cuando envias su clave en el payload:

VarianteClave del payload
Exportacion (comercio exterior, incoterms, fletes)export
Reembolso (detalle de reembolsos)reimbursements
Sustitutiva de guia de remisionsubstitute_delivery_guide
Rubros de tercerosthird_party_items
Maquina fiscalfiscal_machine
Placa (combustibles)plate

Ejemplo de exportacion:

php
$invoicePayload['export'] = [
    'foreign_trade' => 'EXPORTADOR',
    'incoterm' => 'FOB',
    'incoterm_place' => 'GUAYAQUIL',
    'origin_country' => '593',
    'destination_country' => '840',
    'international_freight' => '0.00',
    'international_insurance' => '0.00',
    'customs_expenses' => '0.00',
    'other_transport_expenses' => '0.00',
];

Devolucion de IVA ​

Para la devolucion de IVA (ANEXO 20), agrega refund_value en el impuesto de la linea. Se agrega y se emite como valorDevolucionIva en totalConImpuestos. Solo aplica con comprador de tipo cedula (05) y el monto debe coincidir con el autorizado por el servicio DIG.

php
'taxes' => [
    ['code' => '2', 'percentage_code' => '0', 'rate' => '12.00', 'taxable_base' => '50.00', 'value' => '6.00', 'refund_value' => '6.00'],
],

XML generado ​

El nodo raiz se crea con id="comprobante" y la version del tipo documental:

xml
<factura id="comprobante" version="2.1.0">

Ese atributo es necesario para la firma posterior.

Publicado bajo licencia MIT.