@devlas/dte-sii 2.12.20 → 2.12.21
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/EnviadorSII.js +5 -1
- package/cert/BoletaCert.js +4 -4
- package/package.json +4 -1
- package/utils/pfx.js +38 -1
package/EnviadorSII.js
CHANGED
|
@@ -1174,7 +1174,11 @@ class EnviadorSII {
|
|
|
1174
1174
|
log.log('XML Length:', xml.length, 'bytes');
|
|
1175
1175
|
|
|
1176
1176
|
const [rutNum, dv] = rutEmisor.split('-');
|
|
1177
|
-
|
|
1177
|
+
// Fallback a rutEmisor si el certificado no expone RUT (ver
|
|
1178
|
+
// docs/EXTRACCION_RUT_CERTIFICADO.md) — evita un TypeError por .split
|
|
1179
|
+
// sobre null cuando el PFX no tiene el RUT en ningún campo conocido.
|
|
1180
|
+
const rutEnvia = this.certificado.rut || rutEmisor;
|
|
1181
|
+
const [rutEnviaNum, dvEnvia] = rutEnvia.split('-');
|
|
1178
1182
|
|
|
1179
1183
|
const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2);
|
|
1180
1184
|
|
package/cert/BoletaCert.js
CHANGED
|
@@ -214,7 +214,7 @@ class BoletaCert {
|
|
|
214
214
|
|
|
215
215
|
const envioBoleta = new EnvioBOLETA({
|
|
216
216
|
rutEmisor: this.emisor.rut,
|
|
217
|
-
rutEnvia: this.certificado.rut,
|
|
217
|
+
rutEnvia: this.certificado.rut || this.emisor.rut,
|
|
218
218
|
fchResol: this.resolucion.fecha,
|
|
219
219
|
nroResol: this.resolucion.numero,
|
|
220
220
|
certificado: this.certificado,
|
|
@@ -228,7 +228,7 @@ class BoletaCert {
|
|
|
228
228
|
// Carátula para certificación
|
|
229
229
|
envioBoleta.setCaratula({
|
|
230
230
|
RutEmisor: this.emisor.rut,
|
|
231
|
-
RutEnvia: this.certificado.rut,
|
|
231
|
+
RutEnvia: this.certificado.rut || this.emisor.rut,
|
|
232
232
|
RutReceptor: '60803000-K', // SII en certificación
|
|
233
233
|
FchResol: this.resolucion.fecha,
|
|
234
234
|
NroResol: this.resolucion.numero,
|
|
@@ -291,7 +291,7 @@ class BoletaCert {
|
|
|
291
291
|
// Establecer carátula
|
|
292
292
|
consumoFolio.setCaratula({
|
|
293
293
|
RutEmisor: this.emisor.rut,
|
|
294
|
-
RutEnvia: this.certificado.rut,
|
|
294
|
+
RutEnvia: this.certificado.rut || this.emisor.rut,
|
|
295
295
|
FchResol: this.resolucion.fecha,
|
|
296
296
|
NroResol: this.resolucion.numero,
|
|
297
297
|
SecEnvio: options?.secEnvio || 1,
|
|
@@ -358,7 +358,7 @@ class BoletaCert {
|
|
|
358
358
|
|
|
359
359
|
consumoFolio.setCaratula({
|
|
360
360
|
RutEmisor: this.emisor.rut,
|
|
361
|
-
RutEnvia: this.certificado.rut,
|
|
361
|
+
RutEnvia: this.certificado.rut || this.emisor.rut,
|
|
362
362
|
FchResol: this.resolucion.fecha,
|
|
363
363
|
NroResol: this.resolucion.numero,
|
|
364
364
|
SecEnvio: options.secEnvio,
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devlas/dte-sii",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.21",
|
|
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",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "Devlas SpA <ti@devlas.cl> (https://devlas.cl)",
|
|
9
9
|
"homepage": "https://github.com/devlas-cl/dte-sii",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node test/pfx.test.js"
|
|
12
|
+
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
15
|
"url": "https://github.com/devlas-cl/dte-sii.git"
|
package/utils/pfx.js
CHANGED
|
@@ -179,11 +179,48 @@ function extractSubjectFields(cert) {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/**
|
|
182
|
-
* Extraer RUT
|
|
182
|
+
* Extraer RUT desde el Subject Alternative Name (SAN) con OID
|
|
183
|
+
* 1.3.6.1.4.1.8321.1 — reservado bajo la normativa chilena de firma
|
|
184
|
+
* electrónica (Ley 19.799). A diferencia de serialNumber/OU/CN, que son
|
|
185
|
+
* convención de cada CA, este OID es consistente entre CAs (verificado
|
|
186
|
+
* contra Acepta, IDOK y Signapis — ver docs/EXTRACCION_RUT_CERTIFICADO.md).
|
|
187
|
+
* @param {forge.pki.Certificate} cert - Certificado
|
|
188
|
+
* @returns {string|null} RUT o null
|
|
189
|
+
*/
|
|
190
|
+
function extractRutFromSan(cert) {
|
|
191
|
+
const san = cert.getExtension('subjectAltName');
|
|
192
|
+
if (!san || !san.altNames) return null;
|
|
193
|
+
|
|
194
|
+
for (const alt of san.altNames) {
|
|
195
|
+
if (alt.type !== 0) continue; // 0 = otherName
|
|
196
|
+
try {
|
|
197
|
+
const oid = forge.asn1.derToOid(alt.value[0].value);
|
|
198
|
+
if (oid !== '1.3.6.1.4.1.8321.1') continue;
|
|
199
|
+
|
|
200
|
+
const inner = alt.value[1] && alt.value[1].value && alt.value[1].value[0];
|
|
201
|
+
if (!inner || !inner.value) continue;
|
|
202
|
+
|
|
203
|
+
const clean = inner.value.replace(/\./g, '').toUpperCase();
|
|
204
|
+
if (/^\d{7,8}-[\dK]$/.test(clean)) {
|
|
205
|
+
return clean;
|
|
206
|
+
}
|
|
207
|
+
} catch {
|
|
208
|
+
// OID no parseable en este altName — seguir con el resto y caer al fallback
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Extraer RUT del certificado (desde SAN OID, serialNumber, OU o CN)
|
|
183
217
|
* @param {forge.pki.Certificate} cert - Certificado
|
|
184
218
|
* @returns {string|null} RUT o null
|
|
185
219
|
*/
|
|
186
220
|
function extractRutFromCertificate(cert) {
|
|
221
|
+
const sanRut = extractRutFromSan(cert);
|
|
222
|
+
if (sanRut) return sanRut;
|
|
223
|
+
|
|
187
224
|
const subject = extractSubjectFields(cert);
|
|
188
225
|
|
|
189
226
|
// Intentar desde serialNumber (más confiable)
|