@devlas/dte-sii 2.13.0 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CafSolicitor.js +119 -13
- package/package.json +1 -1
package/CafSolicitor.js
CHANGED
|
@@ -238,7 +238,7 @@ class CafSolicitor {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
static esBloqueoTimbraje(html) {
|
|
241
|
-
return /NO\s+(SE\s+)?AUTORIZA\s+TIMBRAJE/i.test(
|
|
241
|
+
return /NO\s+(SE\s+)?AUTORIZA\s+TIMBRAJE/i.test(CafSolicitor.textoVisible(html, 4000));
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
/**
|
|
@@ -254,7 +254,8 @@ class CafSolicitor {
|
|
|
254
254
|
* no confirmado por el mensaje) de un fallo real desconocido.
|
|
255
255
|
*/
|
|
256
256
|
static esNoAutorizadoIngresarOpcion(html) {
|
|
257
|
-
return /no\s+est
|
|
257
|
+
return /no\s+est.{0,8}\s*autorizado\s+para\s+ingresar\s+a\s+esta\s+opci.{0,8}n/i
|
|
258
|
+
.test(CafSolicitor.textoVisible(html, 4000));
|
|
258
259
|
}
|
|
259
260
|
|
|
260
261
|
/**
|
|
@@ -267,9 +268,91 @@ class CafSolicitor {
|
|
|
267
268
|
* es reenviar los permisos del usuario (Paso 5 de la inscripción) EN EL MISMO
|
|
268
269
|
* AMBIENTE donde se está pidiendo el folio.
|
|
269
270
|
*/
|
|
271
|
+
/**
|
|
272
|
+
* El SII exige hacer el trámite PRESENCIALMENTE en la oficina.
|
|
273
|
+
*
|
|
274
|
+
* Sale al intentar inscribir a la empresa como facturador electrónico, incluso en el
|
|
275
|
+
* sistema gratuito: "deberá presentarse en la oficina del SII correspondiente a su
|
|
276
|
+
* domicilio y solicitar la asistencia de un funcionario". Suele deberse a observaciones
|
|
277
|
+
* en el RUT, domicilio sin verificar o anotaciones del contribuyente.
|
|
278
|
+
*
|
|
279
|
+
* Se detecta porque es un callejón sin salida para el software: mientras esté, la
|
|
280
|
+
* empresa no puede inscribirse, no queda autorizada en palena, no puede enrolar
|
|
281
|
+
* usuarios ni timbrar. Sin este mensaje el usuario ve un error genérico y vuelve a
|
|
282
|
+
* intentar sin saber que lo único que corresponde es ir al SII.
|
|
283
|
+
*
|
|
284
|
+
* Caso real (12/08/2026, RUT 78441936-3): Verificación de Actividades aprobada,
|
|
285
|
+
* usuario enrolado en maullin y certificación de boleta enviada — y aun así palena
|
|
286
|
+
* rechazaba todo, porque la inscripción por internet estaba bloqueada de origen.
|
|
287
|
+
*/
|
|
288
|
+
static esRequiereTramitePresencial(html) {
|
|
289
|
+
const t = CafSolicitor.textoVisible(html, 4000);
|
|
290
|
+
return /deber.{0,8}\s*presentarse\s+en\s+la\s+oficina\s+del\s+SII/i.test(t)
|
|
291
|
+
|| (/no\s+cumple\s+con\s+los\s+requisitos/i.test(t)
|
|
292
|
+
&& /asistencia\s+de\s+un\s+funcionario/i.test(t));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* "la empresa no está autorizada para operar en esta modalidad"
|
|
297
|
+
*
|
|
298
|
+
* Distinto de `esUsuarioSinPermiso`: ahí el sujeto es el USUARIO del certificado, acá
|
|
299
|
+
* es la EMPRESA. El SII lo devuelve en palena cuando el contribuyente todavía no fue
|
|
300
|
+
* autorizado como emisor electrónico en producción — no hay nada que arreglar del lado
|
|
301
|
+
* del enrolamiento, porque el portal ni siquiera deja abrir la mantención de usuarios.
|
|
302
|
+
*
|
|
303
|
+
* Caso real (12/08/2026, RUT 78441936-3): el flujo de enrolamiento siguió de largo con
|
|
304
|
+
* páginas vacías —sin formulario ni hidden `key`— hasta reventar con un 500 en
|
|
305
|
+
* `eu_graba_usuario`. El 500 era el síntoma; esta frase, en el PRIMER paso, la causa.
|
|
306
|
+
*/
|
|
307
|
+
static esEmpresaNoAutorizada(html) {
|
|
308
|
+
return /(la\s+)?empresa\s+no\s+est.{0,8}\s*autorizada\s+para\s+operar/i
|
|
309
|
+
.test(CafSolicitor.textoVisible(html, 4000));
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* ¿Este HTML es un rechazo que hace inútil seguir el flujo?
|
|
314
|
+
*
|
|
315
|
+
* ⚠️ Los rechazos del SII NO llegan siempre en la última respuesta. Este caso real
|
|
316
|
+
* (12/08/2026, RUT 78441936-3, tipo 39 en palena) llegó en el PASO 2
|
|
317
|
+
* (`of_solicita_folios_dcto`), donde solo se miraba `esBloqueoTimbraje`. El flujo
|
|
318
|
+
* siguió de largo y terminó devolviendo el genérico `UNKNOWN: No se obtuvo CAF`,
|
|
319
|
+
* escondiendo un mensaje que la librería ya sabía interpretar desde julio.
|
|
320
|
+
*
|
|
321
|
+
* Por eso el chequeo es UNO SOLO y se aplica en TODOS los pasos: agregar un patrón
|
|
322
|
+
* nuevo no debe obligar a acordarse de replicarlo en cada punto del flujo.
|
|
323
|
+
*/
|
|
324
|
+
static esRechazoDuro(html) {
|
|
325
|
+
const h = String(html || '');
|
|
326
|
+
return CafSolicitor.esBloqueoTimbraje(h)
|
|
327
|
+
|| CafSolicitor.esRequiereTramitePresencial(h)
|
|
328
|
+
|| CafSolicitor.esEmpresaNoAutorizada(h)
|
|
329
|
+
|| CafSolicitor.esNoAutorizadoIngresarOpcion(h)
|
|
330
|
+
|| CafSolicitor.esUsuarioSinPermiso(h)
|
|
331
|
+
|| /no\s+registra\s+Verificaci.{0,8}n\s+de\s+Actividades/i.test(CafSolicitor.textoVisible(h, 4000));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Texto legible de una página del SII, sin markup.
|
|
336
|
+
*
|
|
337
|
+
* Para que un rechazo desconocido no se pierda: sin esto, el motivo real queda solo
|
|
338
|
+
* en el HTML —que en producción no se guarda— y el operador ve `UNKNOWN` sin más.
|
|
339
|
+
*/
|
|
340
|
+
static textoVisible(html, max = 400) {
|
|
341
|
+
return String(html || '')
|
|
342
|
+
.replace(/<script[\s\S]*?<\/script>/gi, ' ')
|
|
343
|
+
.replace(/<style[\s\S]*?<\/style>/gi, ' ')
|
|
344
|
+
.replace(/<[^>]+>/g, ' ')
|
|
345
|
+
.replace(/ /gi, ' ').replace(/á/gi, 'a').replace(/é/gi, 'e')
|
|
346
|
+
.replace(/í/gi, 'i').replace(/ó/gi, 'o').replace(/ú/gi, 'u')
|
|
347
|
+
.replace(/ñ/gi, 'n').replace(/&[a-z]+;/gi, ' ')
|
|
348
|
+
.replace(/\s+/g, ' ')
|
|
349
|
+
.trim()
|
|
350
|
+
.slice(0, max);
|
|
351
|
+
}
|
|
352
|
+
|
|
270
353
|
static esUsuarioSinPermiso(html) {
|
|
271
|
-
return /no\s+tiene\s+permiso\s+en\s+(la\s+)?empresa|usuario\s+no\s+autorizado\s+para\s+(la\s+)?empresa|no\s+est
|
|
272
|
-
.test(
|
|
354
|
+
return /no\s+tiene\s+permiso\s+en\s+(la\s+)?empresa|usuario\s+no\s+autorizado\s+para\s+(la\s+)?empresa|no\s+est.{0,8}\s*autorizado\s+para\s+operar\s+en\s+la\s+empresa/i
|
|
355
|
+
.test(CafSolicitor.textoVisible(html, 4000));
|
|
273
356
|
}
|
|
274
357
|
|
|
275
358
|
/**
|
|
@@ -402,6 +485,22 @@ class CafSolicitor {
|
|
|
402
485
|
return { success: false, errorCode: 'TIMBRAJE_BLOQUEADO', error: 'SII: No se autoriza timbraje. Folios acumulados excesivos o situaciones tributarias pendientes. Revisa el portal SII → Factura Electrónica → Solicitud de Timbraje.' };
|
|
403
486
|
}
|
|
404
487
|
|
|
488
|
+
if (response.body && CafSolicitor.esRequiereTramitePresencial(response.body)) {
|
|
489
|
+
return {
|
|
490
|
+
success: false,
|
|
491
|
+
errorCode: 'REQUIERE_TRAMITE_PRESENCIAL',
|
|
492
|
+
error: 'El SII exige completar la inscripción en Factura Electrónica de forma presencial: el representante legal debe ir con su cédula a la oficina del SII del domicilio de la empresa. Hasta entonces no se pueden obtener folios. Suele deberse a observaciones en el RUT o al domicilio sin verificar.',
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (response.body && CafSolicitor.esEmpresaNoAutorizada(response.body)) {
|
|
497
|
+
return {
|
|
498
|
+
success: false,
|
|
499
|
+
errorCode: 'EMPRESA_NO_AUTORIZADA',
|
|
500
|
+
error: `SII (${this.ambiente}): la EMPRESA no está autorizada para operar como emisor electrónico en este ambiente. No es un problema del usuario ni de sus permisos: hasta que el SII autorice al contribuyente, el portal no permite ni enrolar usuarios ni solicitar folios.`,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
405
504
|
if (response.body && CafSolicitor.esNoAutorizadoIngresarOpcion(response.body)) {
|
|
406
505
|
return {
|
|
407
506
|
success: false,
|
|
@@ -524,7 +623,14 @@ class CafSolicitor {
|
|
|
524
623
|
return { success: false, errorCode: 'SESSION_EXPIRED', error: 'Sesión SII inválida — registro limpiado, el próximo intento reautenticará.' };
|
|
525
624
|
}
|
|
526
625
|
|
|
527
|
-
|
|
626
|
+
// Se adjunta lo que dijo el SII: un `UNKNOWN` sin el motivo obliga a reproducir
|
|
627
|
+
// el fallo con el debug encendido, que es justo lo que no se puede hacer en
|
|
628
|
+
// producción cuando el problema es de un cliente concreto.
|
|
629
|
+
return {
|
|
630
|
+
success: false,
|
|
631
|
+
errorCode: 'UNKNOWN',
|
|
632
|
+
error: `No se obtuvo CAF en la respuesta. El SII respondió: "${CafSolicitor.textoVisible(response.body)}"`,
|
|
633
|
+
};
|
|
528
634
|
|
|
529
635
|
} catch (err) {
|
|
530
636
|
const msg = err.message || '';
|
|
@@ -557,8 +663,8 @@ class CafSolicitor {
|
|
|
557
663
|
|
|
558
664
|
// Defensivo: mismo rechazo por Verificación de Actividades puede aparecer si el SII
|
|
559
665
|
// lo entrega recién en un paso posterior en vez del response inicial de solicitar().
|
|
560
|
-
if (
|
|
561
|
-
return response; // solicitar()
|
|
666
|
+
if (CafSolicitor.esRechazoDuro(currentHtml)) {
|
|
667
|
+
return response; // solicitar() traduce el motivo desde response.body
|
|
562
668
|
}
|
|
563
669
|
|
|
564
670
|
const realFormAction = SiiSession.extractFormAction(currentHtml);
|
|
@@ -592,8 +698,8 @@ class CafSolicitor {
|
|
|
592
698
|
|
|
593
699
|
// Rechazo duro antes del check de COD_DOCTO: la página de rechazo también contiene
|
|
594
700
|
// "COD_DOCTO" en su JavaScript, lo que causaría un POST innecesario con datos vacíos.
|
|
595
|
-
if (CafSolicitor.
|
|
596
|
-
return response; // solicitar()
|
|
701
|
+
if (CafSolicitor.esRechazoDuro(currentHtml)) {
|
|
702
|
+
return response; // solicitar() traduce el motivo desde response.body
|
|
597
703
|
}
|
|
598
704
|
|
|
599
705
|
// Selección de tipo de documento
|
|
@@ -615,8 +721,8 @@ class CafSolicitor {
|
|
|
615
721
|
currentHtml = response.body || '';
|
|
616
722
|
this._saveDebug(debugDir, 'select.html', currentHtml);
|
|
617
723
|
|
|
618
|
-
if (CafSolicitor.
|
|
619
|
-
return response; // solicitar()
|
|
724
|
+
if (CafSolicitor.esRechazoDuro(currentHtml)) {
|
|
725
|
+
return response; // solicitar() traduce el motivo desde response.body
|
|
620
726
|
}
|
|
621
727
|
}
|
|
622
728
|
|
|
@@ -634,8 +740,8 @@ class CafSolicitor {
|
|
|
634
740
|
async _processStep3(response, rut, dv, tipoDte, cantidad, debugDir) {
|
|
635
741
|
let currentHtml = response.body || '';
|
|
636
742
|
|
|
637
|
-
if (
|
|
638
|
-
return response; // solicitar()
|
|
743
|
+
if (CafSolicitor.esRechazoDuro(currentHtml)) {
|
|
744
|
+
return response; // solicitar() traduce el motivo desde response.body
|
|
639
745
|
}
|
|
640
746
|
|
|
641
747
|
const formAction3 = SiiSession.extractFormAction(currentHtml) || '/cvc_cgi/dte/of_confirma_folio';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devlas/dte-sii",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.1",
|
|
4
4
|
"description": "Facturación y boletas electrónicas para el SII de Chile. Genera, timbra, firma y envía DTEs, libros electrónicos y automatiza la certificación.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "dte-sii.d.ts",
|