Wrapper SOAP stateless simplificado para facturación electrónica del SRI Ecuador
INTEGRACIÓN 100% FUNCIONAL Y PROBADA contra el ambiente de certificación del SRI:
- ✅ Comprobantes RECIBIDOS por el SRI (estado:
RECIBIDA) - ✅ Clave de acceso de 49 dígitos generada correctamente (módulo 11)
- ✅ XML firmado con XAdES-BES según especificaciones SRI v2.1.0
- ✅ SOAP wrapper operativo con endpoints de pruebas y producción
- ✅ Generación automática de RIDE (PDF) desde XML autorizado
⚠️ Requiere certificado digital oficial para autorización completa (ver Certificado Requerido)
Un wrapper minimalista y stateless del servicio SOAP del SRI (Servicio de Rentas Internas) de Ecuador para facturación electrónica.
No es un sistema completo de facturación, es solo un puente entre tu aplicación y los servicios web del SRI.
- ✅ Stateless: Sin base de datos, sin persistencia
- ✅ Certificado P12 dinámico: El cliente envía el certificado en cada request
- ✅ Solo 2 endpoints: Enviar y consultar facturas
- ✅ Generación automática de RIDE (PDF): Desde el XML autorizado
- ✅ Retry automático: Con backoff exponencial
- ✅ Cache de clientes SOAP: Para mejor performance
- ✅ Validación completa: DTOs con class-validator
- Node.js >= 20.3.1
- npm >= 9.x
- Certificado digital P12 oficial (emitido por Security Data, BCE, ANFAC, etc.)
- Costo: ~$50-100 USD/año
- Tiempo de emisión: 1-3 días hábiles
- Ver guía completa de certificados
- RUC autorizado para facturación electrónica por el SRI
- Establecimiento activo en el sistema del SRI
# Instalar dependencias
npm install
# Compilar
npm run build
# Ejecutar en desarrollo
npm run start:dev
# Ejecutar en producción
npm run start:prodLa API estará disponible en http://localhost:3000
Envía una factura al SRI para validación y autorización.
Request:
POST /invoice
Content-Type: multipart/form-data
Fields:
- certificado: archivo .p12 (file)
- certificadoPassword: string
- rucEmisor: string (13 dígitos)
- razonSocialEmisor: string
- direccionEmisor: string
- establecimiento: string (3 dígitos, ej: "001")
- puntoEmision: string (3 dígitos, ej: "001")
- secuencial: string (hasta 9 dígitos, ej: "000000001")
- identificacionComprador: string
- razonSocialComprador: string
- fechaEmision: string (DD/MM/YYYY)
- items: JSON array de items de factura
- ambiente: "1" | "2" (opcional, default: "1" = Pruebas)Response:
{
"claveAcceso": "0101202501176001321000110010030009900641234567814",
"estado": "RECIBIDA",
"mensajes": [
{
"identificador": "43",
"mensaje": "CLAVE ACCESO REGISTRADA",
"tipo": "INFO"
}
]
}Consulta el estado de autorización y obtiene XML + RIDE si está autorizada.
Request:
GET /invoice/0101202501176001321000110010030009900641234567814Response (AUTORIZADO):
{
"claveAcceso": "0101202501...",
"estado": "AUTORIZADO",
"numeroAutorizacion": "0101202501...",
"fechaAutorizacion": "2025-01-01T10:30:00-05:00",
"ambiente": "PRUEBAS",
"xml": "base64_encoded_xml...",
"ride": "base64_encoded_pdf..."
}Response (EN PROCESO):
{
"claveAcceso": "0101202501...",
"estado": "EN PROCESO",
"mensajes": []
}src/
├── app.module.ts # Módulo principal
├── modules/
│ ├── billing/ # Módulo de facturación
│ │ ├── application/dto/
│ │ │ └── send-invoice.dto.ts # DTO de entrada
│ │ ├── infrastructure/
│ │ │ ├── controllers/
│ │ │ │ └── invoice.controller.ts # Controlador principal ⭐
│ │ │ └── xml/
│ │ │ └── sri-xml-generator.service.ts # Generador XML SRI
│ │ └── billing.module.ts
│ │
│ ├── digital-signature/ # Módulo de firma digital
│ │ ├── services/
│ │ │ ├── xades-signer.service.ts # Firma XAdES-BES ⭐
│ │ │ └── xml-validator.service.ts # Validador XML
│ │ └── digital-signature.module.ts
│ │
│ └── sri-integration/ # Módulo de integración SRI
│ ├── domain/value-objects/
│ │ ├── sri-message.value-object.ts
│ │ └── access-key.value-object.ts
│ ├── infrastructure/
│ │ ├── config/
│ │ │ └── sri-endpoints.config.ts # Endpoints SOAP
│ │ └── services/
│ │ ├── sri-client.service.ts # Cliente SOAP mejorado ⭐
│ │ └── ride-generator.service.ts # Generador PDF ⭐
│ ├── types/
│ │ └── sri-response.types.ts # Tipos de respuesta SRI
│ └── sri-integration.module.ts
Crea un archivo .env en la raíz:
# Ambiente de PRUEBAS (default)
SRI_RECEPCION_WSDL=https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl
SRI_AUTORIZACION_WSDL=https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl
# Ambiente de PRODUCCIÓN
# SRI_RECEPCION_WSDL=https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl
# SRI_AUTORIZACION_WSDL=https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl- USAGE_EXAMPLES.md - Ejemplos de uso con código (cURL, JavaScript, Python)
- ARCHITECTURE_CHANGES.md - Explicación de la arquitectura y cambios
- API_DOCUMENTATION.md - Documentación detallada de la API
1. Cliente envía POST /invoice con datos + certificado.p12
↓
2. API genera clave de acceso (49 dígitos)
↓
3. API genera XML conforme a SRI v2.1.0
↓
4. API firma XML con P12 (XAdES-BES)
↓
5. API envía a RecepcionComprobantes (SOAP)
↓
6. API retorna: claveAcceso + estado
---
7. Cliente hace polling manual con GET /invoice/:claveAcceso
↓
8. API consulta AutorizacionComprobantes (SOAP)
↓
9. Si AUTORIZADO:
- API extrae XML autorizado del SRI
- API genera RIDE (PDF)
- Retorna XML + RIDE en base64
↓
10. Cliente guarda archivos y finaliza
const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');
async function example() {
// 1. Enviar factura
const form = new FormData();
form.append('certificado', fs.createReadStream('./certificado.p12'));
form.append('certificadoPassword', 'password123');
form.append('rucEmisor', '1792146739001');
form.append('razonSocialEmisor', 'MI EMPRESA S.A.');
form.append('direccionEmisor', 'Quito, Ecuador');
form.append('establecimiento', '001');
form.append('puntoEmision', '001');
form.append('secuencial', '000000001');
form.append('identificacionComprador', '1234567890');
form.append('razonSocialComprador', 'CLIENTE PRUEBA');
form.append('fechaEmision', '15/01/2025');
form.append('items', JSON.stringify([
{ descripcion: 'Producto 1', cantidad: 1, precioUnitario: 100 }
]));
const { data } = await axios.post('http://localhost:3000/invoice', form, {
headers: form.getHeaders()
});
console.log('Clave de Acceso:', data.claveAcceso);
// 2. Consultar hasta obtener autorización
while (true) {
const status = await axios.get(`http://localhost:3000/invoice/${data.claveAcceso}`);
if (status.data.estado === 'AUTORIZADO') {
// Guardar archivos
fs.writeFileSync('factura.xml', Buffer.from(status.data.xml, 'base64'));
fs.writeFileSync('factura.pdf', Buffer.from(status.data.ride, 'base64'));
console.log('✅ Factura autorizada y guardada');
break;
}
console.log('⏳ En proceso, esperando 30 segundos...');
await new Promise(r => setTimeout(r, 30000));
}
}
example();- NestJS 10: Framework backend
- TypeScript 5: Tipado estático
- SOAP: Librería soap para WSDL
- node-forge: Manejo de certificados P12
- pdfkit: Generación de RIDE (PDF)
- xmldsigjs: Firma digital XAdES-BES
- fast-xml-parser: Parser XML
- class-validator: Validación de DTOs
- Polling Manual: El cliente debe consultar el estado periódicamente (cada 30-60 segundos)
- Tiempo SRI: El SRI tiene hasta 24 horas para autorizar, pero usualmente toma 30-120 segundos
- RIDE: Lo genera la API, no viene del SRI
- Certificado: Debe ser válido y no expirado (ver sección de certificados)
- Clave de Acceso: Se genera automáticamente con dígito verificador módulo 11
- Establecimiento: Debe estar activo en el sistema del SRI
El SRI siempre valida la firma electrónica, incluso en ambiente de pruebas. No es posible simular o evitar esta validación.
Estado actual con certificado de prueba:
{
"estado": "RECIBIDA", // ✅ Comprobante aceptado
"mensajes": []
}
// Pero en autorización:
{
"estado": "NO AUTORIZADO",
"mensajes": [{
"identificador": "39",
"mensaje": "FIRMA INVALIDA", // ❌ Certificado auto-firmado no reconocido
"informacionAdicional": "La validacion de la cadena de confianza ha fallado"
}]
}- Sitio: https://www.securitydata.net.ec
- Costo: $50-100 USD/año
- Tiempo: 1-2 días hábiles
- Teléfono: (02) 2553-330
- Sitio: https://www.eci.bce.ec
- Costo: $60 USD/año
- Tiempo: 2-3 días hábiles
- Teléfono: 1800-322-322
- Sitio: https://firmaselectronicas.ec
- Costo: $80 USD/año
- Tiempo: 1-2 días hábiles
- Sitio: https://datil.com
- Costo: $30-50 USD/mes
- Incluye: API + certificado + soporte
-
Obtener certificado oficial (~2-3 días)
# Recibirás un archivo .p12 y una contraseña -
Reemplazar certificado de prueba
cp ~/Downloads/firma_oficial.p12 ./certificado_produccion.p12 -
Actualizar configuración
// Cambiar endpoints a producción en sri.config.ts recepcion: 'https://comprobantes.sri.gob.ec/...', autorizacion: 'https://comprobantes.sri.gob.ec/...'
-
Probar en ambiente de certificación primero
# Usar endpoints: celcer.sri.gob.ec npm run start:dev -
Desplegar a producción ✅
Resultado esperado con certificado oficial:
{
"estado": "AUTORIZADO", // ✅✅✅
"numeroAutorizacion": "0710202501...",
"fechaAutorizacion": "2025-10-07T23:45:00.000Z"
}Ver CERTIFICADO_REQUERIDO.md para:
- Comparación detallada de entidades certificadoras
- Proceso completo paso a paso
- Solución de problemas comunes
- Checklist de producción
Causa: Certificado auto-firmado o no emitido por entidad certificadora autorizada. Solución: Obtener certificado oficial (ver sección de certificados).
Causa: El establecimiento no está activo en el sistema del SRI. Solución:
- Verificar en SRI en Línea: https://srienlinea.sri.gob.ec
- Activar el establecimiento con documentos en oficina del SRI
- O usar un establecimiento diferente que esté activo (ej:
001)
Causa: Clave de acceso incorrecta (debe ser exactamente 49 dígitos). Solución: ✅ Ya corregido - El algoritmo módulo 11 está implementado correctamente.
Verifica que el certificado P12 esté vigente y la contraseña sea correcta.
El SRI puede tardar. Aumenta el intervalo de polling a 60 segundos.
El SRI puede tardar hasta 24 horas, pero usualmente es 30-120 segundos. Si supera 10 minutos, revisar logs del SRI o contactar soporte.
UNLICENSED - Uso privado
Para consultas sobre el SRI Ecuador:
Versión: 1.0.0 Última actualización: Enero 2025