julioserpone / sri-comprobantes-php
Paquete PHP para emitir y consultar comprobantes electrónicos del SRI de Ecuador (esquema off-line).
Package info
github.com/julioserpone/sri-comprobantes-php
pkg:composer/julioserpone/sri-comprobantes-php
Requires
- php: ^8.2
- ext-dom: *
- ext-libxml: *
- ext-openssl: *
- ext-soap: *
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-21 01:37:15 UTC
README
Paquete PHP sin framework para integrar la emisión y consulta de comprobantes electrónicos del Servicio de Rentas Internas (SRI) de Ecuador, esquema off-line.
Estado: alfa (0.1.x). El paquete implementa la clave de acceso, el transporte SOAP, los clientes de recepción/autorización/consulta, los DTO de respuesta, el catálogo de errores, reintentos, validación XSD, armado de lotes y almacenamiento local. No incluye un firmador XAdES-BES ni un generador de XML por tipo de comprobante; esas piezas se integran mediante interfaces explícitas. Lea Firma y Alcance.
Este proyecto no está afiliado ni respaldado por el SRI. La fuente de verdad es la ficha técnica oficial y los XSD publicados por el SRI. La versión de referencia de esta documentación es la Ficha Técnica de Comprobantes Electrónicos Offline v2.34 (julio 2026).
Contenido
- Requisitos
- Instalación
- Inicio rápido
- Qué incluye y qué no
- Endpoints
- Clave de acceso
- Firma
- Reintentos y estados
- Seguridad
- Pruebas y calidad
- Documentación
- Contribuir
Requisitos
- PHP 8.2 o superior.
- Extensiones
soap,openssl,domylibxml. - Acceso HTTPS a
celcer.sri.gob.ec(pruebas) ocel.sri.gob.ec(producción). - Certificado de firma electrónica válido, emitido por una entidad de certificación autorizada en Ecuador (PKCS#12 para el flujo soportado).
- Un firmador XAdES-BES validado (HSM, servicio de firma o librería especializada). Ver Firma.
- Opcional:
aws/aws-sdk-phpsi usa el adaptadorAwsLambdaInvokercon AWS Lambda.
Instalación
El paquete todavía no está publicado en Packagist. Mientras tanto, instálelo desde el repositorio VCS. Si en el futuro el repositorio vuelve a ser privado, configure las credenciales de GitHub para Composer.
{
"repositories": [
{ "type": "vcs", "url": "https://github.com/julioserpone/sri-comprobantes-php" }
],
"require": {
"julioserpone/sri-comprobantes-php": "^0.1"
}
}
composer update julioserpone/sri-comprobantes-php
Cuando se publique en Packagist, bastará con:
composer require julioserpone/sri-comprobantes-php
Inicio rápido
1. Consultar una autorización
<?php declare(strict_types=1); use JulioSerpone\SriComprobantes\Client\AutorizacionClient; use JulioSerpone\SriComprobantes\Config\SriEnvironment; use JulioSerpone\SriComprobantes\Config\SriService; use JulioSerpone\SriComprobantes\Transport\SoapTransport; $environment = SriEnvironment::fromCode('1'); // 1 = pruebas, 2 = producción $transport = new SoapTransport( wsdl: $environment->wsdl(SriService::AUTORIZACION), connectionTimeout: 10.0, timeout: 30.0, ); $result = (new AutorizacionClient($transport))->consultar($claveAcceso); if ($result->isAutorizado()) { $xmlAutorizado = $result->xmlAutorizado(); $numeroAutorizacion = $result->first()?->numeroAutorizacion; }
2. Generar una clave de acceso
use JulioSerpone\SriComprobantes\AccessKey\AccessKeyGenerator; $clave = (new AccessKeyGenerator())->generate( fechaEmision: new DateTimeImmutable('2026-10-20'), tipoComprobante: '01', // factura ruc: '1790012345001', ambiente: '1', // pruebas serie: '001001', secuencial: '000000123', codigoNumerico: '12345678', tipoEmision: '1', ); // 49 dígitos; el último es el verificador módulo 11.
3. Validar el XML y armar un lote
use JulioSerpone\SriComprobantes\Xml\LoteBuilder; use JulioSerpone\SriComprobantes\Xml\XsdValidator; // El XSD oficial debe estar versionado o montado localmente. (new XsdValidator())->validate($xmlFirmado, __DIR__ . '/xsd/factura_V1.1.0.xsd'); $lote = (new LoteBuilder())->build( claveAccesoLote: $claveDelLote, ruc: '1790012345001', comprobantes: [$xmlFirmado1, $xmlFirmado2], // máximo 50 / 500 KB );
4. Enviar y esperar autorización
use JulioSerpone\SriComprobantes\Client\AutorizacionClient; use JulioSerpone\SriComprobantes\Client\RecepcionClient; use JulioSerpone\SriComprobantes\Retry\RetryPolicy; use JulioSerpone\SriComprobantes\Service\EmisionService; $service = new EmisionService( new RecepcionClient(new SoapTransport($environment->wsdl(SriService::RECEPCION))), new AutorizacionClient(new SoapTransport($environment->wsdl(SriService::AUTORIZACION))), new RetryPolicy(maxAttempts: 3, baseDelayMs: 250, maxDelayMs: 5000), ); $autorizacion = $service->emitir( xml: $xmlFirmado, claveAcceso: $clave, intentos: 10, segundosEntreIntentos: 3, );
emitir() lanza SriException si la recepción es DEVUELTA o la autorización
termina en un estado no autorizado. Si prefiere controlar el flujo, use
enviar() y esperarAutorizacion() por separado.
5. Consultar el estado desde el portal/WS de consultas
use JulioSerpone\SriComprobantes\Client\ConsultaClient; $consulta = (new ConsultaClient( new SoapTransport($environment->wsdl(SriService::CONSULTA)) ))->estado($clave); $consulta->estadoAutorizacion; // AUTORIZADO, NO AUTORIZADO, ...
Qué incluye y qué no
| Área | Incluido |
|---|---|
| Clave de acceso de 49 dígitos (módulo 11) | Sí, con validación |
| Ambientes y WSDL oficiales | Sí, pruebas y producción |
| Transporte SOAP con TLS y timeout | Sí (ext-soap) |
| Recepción individual y por lote | Sí (cliente) |
| Autorización individual y por lote | Sí (clientes y DTO) |
| Consulta de estado y factura negociable | Sí |
| Catálogo de errores/advertencias v2.34 | Sí |
| Reintentos con backoff | Sí, solo fallos de transporte |
| Validación contra XSD local | Sí |
| Armado del XML de lote (Tabla 8) | Sí |
| Almacenamiento local de XML/estado | Sí, implementación mínima |
| Generación del XML de factura/notas/retenciones | No |
| Firma XAdES-BES | No (interfaz, carga de PKCS#12 y adaptador Lambda) |
| Descarga masiva desde el portal | No (no existe API oficial) |
Alcance
Este paquete es una capa de integración, no un facturador completo. La generación de cada comprobante depende del tipo, versión de esquema y anexos vigentes; hacerlo bien exige modelar cada XSD y sus reglas de negocio. El paquete ofrece las piezas estables alrededor de ese XML: clave, validación, transporte, estados, errores, reintentos y persistencia.
Endpoints
Verificados en vivo el 20/10/2026 contra los WSDL del SRI:
| Servicio | Pruebas | Producción |
|---|---|---|
| Recepción | https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl |
https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl |
| Autorización | https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl |
https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl |
| Consulta | https://celcer.sri.gob.ec/comprobantes-electronicos-ws/ConsultaComprobante?wsdl |
https://cel.sri.gob.ec/comprobantes-electronicos-ws/ConsultaComprobante?wsdl |
| Factura negociable | https://celcer.sri.gob.ec/comprobantes-electronicos-ws/ConsultaFactura?wsdl |
https://cel.sri.gob.ec/comprobantes-electronicos-ws/ConsultaFactura?wsdl |
No use los endpoints antiguos RecepcionComprobantes ni
AutorizacionComprobantes: ya no responden. No fije certificados ni IPs en el
código; el SRI puede rotarlos. Use TLS con verificación del certificado.
Operaciones WSDL confirmadas:
validarComprobante(xml)→RespuestaRecepcionComprobanteautorizacionComprobante(claveAccesoComprobante)→RespuestaAutorizacionComprobanteautorizacionComprobanteLote(claveAccesoLote)→RespuestaAutorizacionLoteconsultarEstadoAutorizacionComprobante(claveAcceso)→EstadoAutorizacionComprobanteconsultarEstadoConfirmacionFacturaComercialNegociable(claveAcceso)→EstadoConfirmacionFacturaComercialNegociable
Clave de acceso
Estructura de 49 dígitos (ficha v2.34, sección 5.2):
ddmmaaaa tipo(2) RUC(13) ambiente(1) serie(6) secuencial(9)
códigoNumérico(8) tipoEmisión(1) dígitoVerificador(1)
- Ambiente:
1pruebas,2producción. - Tipo de emisión del esquema off-line:
1(normal). - Dígito verificador: módulo 11 con pesos 2..7 de derecha a izquierda;
resultado 11 →
0, resultado 10 →1. - Ejemplo oficial del algoritmo:
41261533→6.
El paquete valida longitud, caracteres numéricos y dígito verificador. No valida que el RUC exista, que el establecimiento esté activo ni que la clave no haya sido registrada; eso lo determina el SRI.
Firma
El SRI exige XAdES-BES enveloped, esquema 1.3.2, UTF-8, RSA-SHA1 y clave de
2048 bits (ficha v2.34, sección 6). El paquete no implementa la firma:
hacerlo sin validación contra el SRI es propenso a errores de canonicalización,
namespaces y SignedProperties.
Use Signature\Signer para integrar un firmador validado:
use JulioSerpone\SriComprobantes\Signature\CallbackSigner; $signer = new CallbackSigner( fn (string $xml): string => $miFirmadorXadesBes->firmar($xml) ); $xmlFirmado = $signer->sign($xml);
Firmador Lambda del proyecto
Si usas el firmador sri-xades-signer
en modo multicliente, el paquete incluye LambdaSigner. El backend debe instalar el SDK de AWS
(opcional, no es dependencia obligatoria del paquete):
composer require aws/aws-sdk-php
use Aws\Lambda\LambdaClient; use JulioSerpone\SriComprobantes\Signature\AwsLambdaInvoker; use JulioSerpone\SriComprobantes\Signature\LambdaSigner; $lambda = new LambdaClient([ 'version' => 'latest', 'region' => 'us-east-2', // Usa la cadena de credenciales IAM del backend; no hardcodees claves. ]); $signer = new LambdaSigner( new AwsLambdaInvoker($lambda, 'sri-xades-signer-invoke'), $tenantUuid, $passwordDelPkcs12, ); $xmlFirmado = $signer->sign($xml);
LambdaSigner representa a un inquilino: constrúyalo por operación y no reutilice la instancia
para otro UUID. El password se envía al firmador por la invocación IAM/TLS; no lo registre, no lo
ponga en una cola ni lo persista en claro. El firmador lee el .p12 desde
tenants/<uuid>/certificate.p12 en S3 y devuelve el XML firmado.
Para pruebas o integraciones propias puede usar CallableLambdaInvoker:
use JulioSerpone\SriComprobantes\Signature\CallableLambdaInvoker; use JulioSerpone\SriComprobantes\Signature\LambdaSigner; $invoker = new CallableLambdaInvoker( fn (array $payload): array => $miClienteLambda->invocar($payload) ); $signer = new LambdaSigner($invoker, $tenantUuid, $passwordDelPkcs12);
P12Certificate carga un PKCS#12 y expone certificado/clave en PEM para un
firmador externo. Trate la clave privada como secreto: no la loguee, no la
persista y no la envíe por red.
Reintentos y estados
RECIBIDA: el SRI aceptó el archivo; todavía no implica autorización.DEVUELTA: el archivo no pasó validación. Corrija el XML y reenvíe con la misma clave de acceso y secuencial (ficha v2.34, sección 5.10).PPR: en procesamiento. El SRI puede tardar hasta 24 horas. No reenvíe ni genere otra clave mientras esté enPPR(error 70).AUT: autorizado.NAT: no autorizado; corrija, reenvíe y notifique al receptor.
RetryPolicy solo reintenta TransportException por defecto. Los errores de
validación del SRI no se reintentan: el XML debe corregirse. Ajuste el número de
intentos y el intervalo según su operación; no bloquee un worker durante horas.
Seguridad
- Nunca versione
.env, certificados.p12/.pfx, claves PEM ni XML con datos personales. - Use TLS con verificación de certificado; no desactive
verify_peer. - Restrinja permisos del directorio de almacenamiento (0700) y de los archivos (0600). La implementación de filesystem es local y no apta para múltiples servidores.
- No registre XML completos, claves privadas ni contraseñas. Los mensajes del SRI pueden contener información fiscal.
- Rote credenciales y certificados; valide la cadena de confianza y la vigencia antes de firmar.
- Consulte SECURITY.md para reportar vulnerabilidades.
Pruebas y calidad
composer install composer check # php-cs-fixer + phpstan nivel 8 + phpunit composer test composer analyse
Las pruebas no llaman al SRI: usan un transporte falso. La integración real debe probarse en el ambiente de certificación con un certificado de pruebas y los XSD oficiales. Para una comprobación manual del servicio de consulta:
php scripts/smoke-consulta.php <clave-de-49-digitos> 1
No use claves de producción en terminales compartidas ni ejecute este script en CI.
Documentación
- Guía técnica SRI: flujo, endpoints, firma, estados, errores y consultas.
- Arquitectura: capas, decisiones y puntos de extensión.
- Consulta masiva: qué existe, qué no y alternativas.
- Fuentes oficiales: enlaces y fecha de verificación.
- Reglas de GitHub: protección de rama, checks y releases.
- ADRs: decisiones de arquitectura.
- AGENTS.md: instrucciones para agentes de IA.
Contribuir
Lea CONTRIBUTING.md y el Código de Conducta. Los cambios de documentación técnica deben citar la sección/página de la ficha o el WSDL verificado y la fecha.
Licencia
MIT. Ver LICENSE.
Descargo de responsabilidad: este software se distribuye "tal cual", sin garantía. La normativa tributaria, los esquemas XSD, los endpoints y los certificados pueden cambiar. El usuario es responsable de validar su implementación ante el SRI y de cumplir sus obligaciones tributarias.