npm.io
0.5.1 • Published 12h ago

dty-fy

Licence
SEE LICENSE IN LICENSE
Version
0.5.1
Deps
5
Size
385 kB
Vulns
0
Weekly
0

dty-fy

npm version License: EULA Node TypeScript

Libreria completa para gestionar Documentos Tributarios Electronicos (DTE) ante el Servicio de Impuestos Internos (SII) de Chile.

Soporta los 12 tipos de DTE: facturas, boletas, notas de credito/debito, guias de despacho y documentos de exportacion.


Tabla de Contenidos


Instalacion

npm install dty-fy
Requisitos
  • Node.js 18+
  • Certificado digital (.pfx/.p12) de una CA acreditada por el SII
  • Archivos CAF (Codigo de Autorizacion de Folios) entregados por el SII
Formatos de Modulo

La libreria distribuye tanto ESM como CommonJS:

// ESM (recomendado)
import { DteBuilder, SiiClient } from 'dty-fy';

// CommonJS
const { DteBuilder, SiiClient } = require('dty-fy');

Inicio Rapido

import { SiiClient, DteBuilder, CafManager, CertificateLoader } from 'dty-fy';

// 1. Cargar certificado digital
const cert = await CertificateLoader.fromPfx('./certificado.pfx', 'password');

// 2. Cargar folios autorizados (CAF)
const cafManager = new CafManager();
await cafManager.loadCaf('./caf-factura-33.xml');

// 3. Configurar cliente SII
const sii = new SiiClient({
  environment: 'certification',
  certificate: cert,
  rutSender: '11111111-1',
  rutCompany: '76543210-3',
  fechaResolucion: '2024-01-15',
  numeroResolucion: 0,
});

// 4. Construir una Factura Electronica (TipoDTE 33)
const factura = new DteBuilder()
  .tipo(33)
  .folio(cafManager.nextFolio(33))
  .emisor({
    rut: '76543210-3',
    razonSocial: 'Mi Empresa SpA',
    giro: 'Desarrollo de Software',
    acteco: 620200,
    direccion: 'Av. Providencia 1234',
    comuna: 'Providencia',
  })
  .receptor({
    rut: '87654321-4',
    razonSocial: 'Cliente Ejemplo Ltda',
    giro: 'Comercio',
    direccion: 'Los Leones 999',
    comuna: 'Providencia',
  })
  .addDetalle({ nombre: 'Servicio de desarrollo', cantidad: 1, precioUnitario: 500000 })
  .addDetalle({ nombre: 'Hosting anual', cantidad: 12, unidad: 'mes', precioUnitario: 15000 })
  .formaPago('credito')
  .build();

// 5. Firmar, timbrar y enviar al SII
const result = await sii.emitir(factura, cafManager);

if (result.success) {
  console.log(`DTE enviado! TrackID: ${result.trackId}`);
  console.log(`Folio: ${result.folio}`);

  const estado = await sii.consultarEstadoEnvio(result.trackId!);
  console.log(`Estado: ${estado.status} - ${estado.glosa}`);
} else {
  console.error(`Error: ${result.error}`);
}

Arquitectura

┌─────────────────────────────────────────────────────────┐
│                     SiiClient                           │
│  (orquestador: autenticacion, firma, envio, consulta)  │
└──────┬───────────────────────────────────────┬─────────┘
       │                                       │
       ▼                                       ▼
┌──────────────┐  ┌──────────┐  ┌──────────────────────┐
│  DteBuilder  │  │ XmlSigner│  │  CertificateLoader    │
│  (fluido)    │  │(XMLDSig) │  │  (.pfx, .pem, base64) │
└──────┬───────┘  └──────────┘  └──────────────────────┘
       │              │                    │
       ▼              ▼                    ▼
┌──────────┐  ┌──────────────┐  ┌──────────────────────┐
│ CafManager│  │ TED Generator│  │  SII Auth & Sender   │
│ (folios)  │  │(Timbre Elec)│  │  (seed, token, POST)  │
└──────────┘  └──────────────┘  └──────────────────────┘

Certificados Digitales

El certificado digital se obtiene a traves de una Autoridad Certificadora (CA) acreditada por el SII, no directamente desde el SII. La CA entrega un archivo .pfx (o .p12) que contiene la llave privada y el certificado X.509, protegido por una contrasena.

Metodos de Carga
import { CertificateLoader } from 'dty-fy';

// Desde archivo .pfx (el mas comun)
const cert = await CertificateLoader.fromPfx('./cert.pfx', 'password');

// Desde Buffer (base de datos, S3, cloud storage)
const cert = CertificateLoader.fromPfxBuffer(buffer, 'password');

// Desde string base64 (variables de entorno, serverless, CI/CD)
const cert = CertificateLoader.fromPfxBase64(process.env.CERT_PFX_B64!, process.env.CERT_PASSWORD!);

// Desde archivos PEM separados
const cert = await CertificateLoader.fromPem('./cert.pem', './key.pem');

// Desde strings PEM en memoria
const cert = CertificateLoader.fromPemStrings(certPem, keyPem);
Utilidades del Certificado
import {
  isCertificateValid,
  daysUntilCertExpiry,
  getRutFromCertificate,
  getCertificateSummary,
} from 'dty-fy';

const cert = await CertificateLoader.fromPfx('./cert.pfx', 'pass');

isCertificateValid(cert);                // boolean — esta vigente?
daysUntilCertExpiry(cert);               // number | null — dias restantes
getRutFromCertificate(cert);             // string | null — RUT embebido por la CA
getCertificateSummary(cert);             // string — resumen legible

Gestion de CAF

CafParser y CafManager administran la ingesta, validación criptográfica y asignación de folios desde los archivos CAF (Código de Autorización de Folios) entregados por el SII.

Parseo y Validación Criptográfica (CafParser)

CafParser valida que el CAF coincida con el RUT emisor, tipo de DTE, rango de folios ($D \le F \le H$) y verifica la firma digital <FRMA> del SII sobre <DA>:

import { CafParser } from 'dty-fy';

// Parsear desde string XML o Buffer (ej. subido vía API o leído de S3/GCS)
const cafData = CafParser.fromXml(xmlBuffer, {
  expectedRut: '76543210-3',       // Valida RUT emisor
  expectedTipoDte: 33,              // Valida TipoDTE
  targetFolio: 15,                  // Valida que el folio esté en el rango autorizado
  verifySignature: true,            // Verifica firma <FRMA> con clave pública SII
  siiPublicKey: process.env.SII_CAF_PUBKEY,
});

// O parsear directamente desde archivo en disco
const cafData = await CafParser.fromFile('./caf-33.xml');
Asignación y Ciclo de Vida de Folios (CafManager)
import { CafManager } from 'dty-fy';

const caf = new CafManager();

// Cargar desde archivo XML
await caf.loadCaf('./caf-33.xml');

// Cargar desde string XML
caf.addCaf(xmlString);

// Cargar datos CAF pre-parseados directamente
caf.addCafData(cafData);

// Obtener siguiente folio disponible (lanza CafFolioExhaustedError si se agotan)
const folio = caf.nextFolio(33);

// Consultar folios restantes
const remaining = caf.remainingFolios(33);

// Obtener datos CAF para un folio especifico
const cafData = caf.getCaf(33, folio);

// Verificar y marcar uso manualmente
caf.isFolioUsed(33, folio);       // boolean
caf.markFolioUsed(33, folio);     // void

// Listar todos los CAF cargados para un tipo de DTE
const cafs = caf.getCafsForType(33);

// Reiniciar todo el estado
caf.clearAll();

Constructor de DTE

DteBuilder proporciona una API fluida (builder pattern) para construir documentos DTE. Todos los metodos son encadenables.

Metodos
Metodo Parametros Descripcion
tipo code: TipoDteCode Establecer tipo de DTE (33, 39, 61, etc.)
folio n: number Establecer numero de folio
fechaEmision date: string | Date Fecha de emision (default: hoy)
fechaVencimiento date: string | Date Fecha de vencimiento (facturas credito)
formaPago tipo: 'contado' | 'credito' | 'gratis' Establecer forma de pago
montoBruto bruto: boolean Activar montos brutos (requerido para boletas)
emisor data: EmisorInput Datos del emisor
receptor data: ReceptorInput Datos del receptor
indTraslado code: number Establecer indicador de traslado (obligatorio para DTE 52)
tipoDespacho code: number Establecer tipo de despacho (para DTE 52: 1, 2 o 3)
tpoImpresion code: number Establecer tipo de impresión (opcional)
transporte data: TransporteInput Establecer datos logísticos del transporte terrestre (DTE 52)
addDetalle data: DetalleInput Agregar linea de detalle
addReferencia data: ReferenciaInput Agregar referencia a otro documento (requerido para NC/ND)
addDescuento data: DescuentoRecargoInput Agregar descuento o recargo global
build Validar y retornar DteDocument
Tipos de Entrada
interface EmisorInput {
  rut: string;
  razonSocial: string;
  giro: string;
  acteco: number;
  direccion: string;
  comuna: string;
  ciudad?: string;
  telefono?: string;
  correo?: string;
  sucursal?: string;
}

interface ReceptorInput {
  rut: string;
  razonSocial?: string;
  giro?: string;
  direccion?: string;
  comuna?: string;
  ciudad?: string;
  contacto?: string;
  correo?: string;
}

interface DetalleInput {
  nombre: string;
  descripcion?: string;
  cantidad?: number;        // default: 1
  unidad?: string;          // default: 'unidad'
  precioUnitario: number;
  montoItem?: number;
  descuentoPct?: number;
  descuentoMonto?: number;
  exento?: boolean;
  codigos?: Array<{ tipo: string; valor: string }>;
}

interface ReferenciaInput {
  tipoDocRef: number;
  folioRef: number;
  fechaRef: string;
  codigoRef?: number;       // 1=anula, 2=corrige texto, 3=corrige montos
  razon?: string;
}

interface DescuentoRecargoInput {
  tipo: 'descuento' | 'recargo';
  glosa?: string;
  tipoValor: 'porcentaje' | 'monto';
  valor: number;
}

interface ChoferInput {
  rut?: string;
  nombre?: string;
}

interface TransporteInput {
  patente?: string;
  patenteCarro?: string;
  rutTrans?: string;
  chofer?: ChoferInput;
  fchSalida?: string | Date;
  hraSalida?: string;
  fchLlegada?: string | Date;
  dirDest?: string;
  cmnaDest?: string;
  ciudadDest?: string;
}
Ejemplos

Factura con descuento global:

const factura = new DteBuilder()
  .tipo(33)
  .folio(1)
  .emisor(emisorData)
  .receptor(receptorData)
  .addDetalle({ nombre: 'Producto A', cantidad: 10, precioUnitario: 5000 })
  .addDetalle({ nombre: 'Producto B', cantidad: 5, precioUnitario: 8000 })
  .addDescuento({ tipo: 'descuento', tipoValor: 'porcentaje', valor: 10, glosa: 'Volumen' })
  .build();
// IVA se calcula sobre el neto posterior al descuento

Nota de Credito referenciando una factura:

const notaCredito = new DteBuilder()
  .tipo(61)
  .folio(cafManager.nextFolio(61))
  .emisor(emisorData)
  .receptor(receptorData)
  .addDetalle({ nombre: 'Servicio web', cantidad: 1, precioUnitario: 500000 })
  .addReferencia({
    tipoDocRef: 33,
    folioRef: 123,
    fechaRef: '2024-03-15',
    codigoRef: 1,
    razon: 'Anulacion por devolucion',
  })
  .build();

Boleta Electronica con montos brutos:

const boleta = new DteBuilder()
  .tipo(39)
  .folio(cafManager.nextFolio(39))
  .emisor({ rut: '76543210-3', razonSocial: 'Mi Tienda', giro: 'Venta al detalle', acteco: 471100, direccion: 'Calle 1', comuna: 'Santiago' })
  .receptor({ rut: '66666666-6', razonSocial: 'Consumidor Final' })
  .montoBruto(true)
  .addDetalle({ nombre: 'Cafe Latte', cantidad: 2, precioUnitario: 3500 })
  .addDetalle({ nombre: 'Croissant', cantidad: 1, precioUnitario: 2500 })
  .build();
// Los montos de boleta incluyen IVA (MntBruto=true)

Guía de Despacho (DTE 52) con datos de transporte:

const guiaDespacho = new DteBuilder()
  .tipo(52)
  .folio(cafManager.nextFolio(52))
  .emisor(emisorData)
  .receptor(receptorData)
  .indTraslado(5) // 5 = Traslados internos (obligatorio para DTE 52)
  .transporte({
    patente: 'AA1122',
    patenteCarro: 'BB3344',
    rutTrans: '77777777-7',
    chofer: {
      rut: '11111111-1',
      nombre: 'Juan Pérez'
    },
    dirDest: 'Av. Vitacura 5000',
    cmnaDest: 'Vitacura',
    ciudadDest: 'Santiago'
  })
  .addDetalle({ nombre: 'Pallets de madera', cantidad: 50, precioUnitario: 3500 })
  .build();

Timbre Electronico y Codigo PDF417

El Timbre Electrónico DTE (TED) y su representación bidimensional PDF417 constituyen la firma gráfica y mecanismo de verificación offline exigido por el SII (Resolución Ex. SII N° 11 de 2003).

Generación de Código PDF417 (renderPdf417)

Genera el código de barras PDF417 conforme al estándar del SII: nivel de corrección de error ECL 5 y ancho de 10 a 14 columnas.

import { renderPdf417 } from 'dty-fy';

// Renderizar SVG vectorial (ideal para facturas en PDF, impresión térmica o web)
const svg = await renderPdf417(tedXml, {
  format: 'svg',
  columns: 12,                  // 10 a 14 (default: 12)
  errorCorrectionLevel: 5,      // Estándar SII: nivel 5 (default: 5)
  scale: 2,
});

// Renderizar PNG en Buffer (ideal para canvas o guardado directo a archivo)
const pngBuffer = await renderPdf417(tedXml, {
  format: 'png',
  columns: 12,
  errorCorrectionLevel: 5,
  scale: 3,
});
Generación y Firma de TED
import { generateTed, buildTedXml, signTed, verifyTed } from 'dty-fy';

// Generar estructura TED a partir del documento y datos CAF
const ted = generateTed(documento, cafData);

// Construir XML del TED
const tedXml = buildTedXml(ted);

// O firmar y verificar manualmente con clave privada CAF y codificación ISO-8859-1
const signedTed = signTed(rawTedXml, cafData.privateKey);
const isValid = verifyTed(signedTed, cafData.publicKey);

Cliente SII

SiiClient orquesta el ciclo de vida completo del DTE: autenticacion, generacion de TED, firma XML, construccion del sobre de envio y envio al SII.

Constructor
import { SiiClient } from 'dty-fy';

const sii = new SiiClient({
  environment: 'certification' | 'production',
  certificate: certificateData,
  rutSender: string,      // RUT de la persona/sistema que envia
  rutCompany: string,     // RUT de la empresa (emisor)
  fechaResolucion?: string, // YYYY-MM-DD (default: vacio)
  numeroResolucion?: number, // 0 para certificacion (default: 0)
});
Metodos
Metodo Firma Descripcion
authenticate (): Promise<string> Obtener y cachear token de sesion SII (gestión automática de TTL y concurrencia)
emitir (doc: DteDocument, caf: CafManager): Promise<EmitirResult> Flujo completo individual: TED -> firma DTE -> sobre -> envio
emitirBatch (docs: DteDocument[], caf: CafManager): Promise<{ trackId?: string; results: EmitirResult[] }> Emisión en lote dentro de un único sobre (hasta 2000 DTEs)
consultarEstadoEnvio (trackId: string): Promise<EstadoEnvio> Consultar estado de envio por TrackID (inmediato)
pollEnvio (trackId: string, options?: Partial<PollTrackIdOptions>): Promise<EstadoEnvio> Sondeo automático de TrackID con backoff exponencial y jitter
consultarEstadoDte (tipoDte, folio, fechaEmision, montoTotal, rutReceptor): Promise<EstadoDte> Consultar estado de un DTE especifico
Sondeo de Envío con Backoff (pollEnvio)

El SII procesa los envíos de forma asíncrona. pollEnvio realiza consultas periódicas con retroceso exponencial (exponential backoff) y fluctuación (jitter) hasta obtener un estado terminal (EPR, RCT, RFL, RFR, RSC):

const estado = await sii.pollEnvio(result.trackId!, {
  maxAttempts: 10,
  initialDelayMs: 3000,
  backoffFactor: 1.5,
  maxDelayMs: 60000,
  onAttempt: (attempt, delayMs) => {
    console.log(`Intento ${attempt}: esperando ${delayMs}ms...`);
  },
});

console.log(`Estado final: ${estado.status} - ${estado.glosa}`);
Gestión de Tokens de Sesión (TokenManager)

TokenManager encapsula la obtención y renovación de tokens con el SII:

  • TTL de 50 minutos (los tokens del SII expiran tras 60 minutos de inactividad).
  • Deduplicación concurrente: múltiples solicitudes simultáneas comparten la misma promesa de autenticación para evitar saturar el endpoint de semillas.
import { TokenManager } from 'dty-fy';

const tokenManager = new TokenManager(cert, 'certification', 50);
const token = await tokenManager.getToken(); // Reutiliza el token activo o renueva si caducó
Resultado de Emision
interface EmitirResult {
  success: boolean;
  trackId?: string;     // TrackID del SII (en exito)
  folio: number;
  tipoDte: TipoDteCode;
  xml: string;          // XML del sobre firmado
  error?: string;       // Mensaje de error (en fallo)
}
Resultados de Estado
interface EstadoEnvio {
  status: string;       // 'SOK' | 'CRT' | 'EPR' | 'RSC' | 'RFR' | 'RCT' | 'RPS'
  glosa: string;        // Descripcion legible
  trackId: string;
  numDtes?: number;
  informados?: number;
  aceptados?: number;
  rechazados?: number;
  reparos?: number;
}

interface EstadoDte {
  status: string;       // 'DOK' | 'RCH' | 'RPR' | 'DNK'
  glosa: string;
  tipoDte: number;
  folio: number;
  fechaEmision?: string;
  rutEmisor?: string;
  rutReceptor?: string;
  montoTotal?: number;
  errorCode?: string;
}

Funciones Utiles

Validacion y Formateo de RUT
import { validateRut, formatRut, formatRutPretty, cleanRut, calculateDv } from 'dty-fy';

validateRut('11111111-1');      // true
validateRut('11111111-2');      // false
formatRut('111111111');         // '11111111-1'
formatRutPretty('111111111');   // '11.111.111-1'
cleanRut('11.111.111-1');       // '11111111-1'
calculateDv('11111111');        // '1'
Calculos de Impuestos
import { calculateIva, calculateNetoFromBruto, calculateTotals, calculateMontoItem } from 'dty-fy';

calculateIva(100000);              // 19000 (IVA 19%)
calculateIva(100000, 10);          // 10000 (tasa personalizada)
calculateNetoFromBruto(119000);    // 100000
calculateMontoItem(10, 5000);      // 50000
calculateMontoItem(10, 5000, 10);  // 45000 (10% descuento)
Construccion XML (Bajo Nivel)
import { buildDocumentoXml, buildEnvioDteXml, buildEnvioBoletaXml } from 'dty-fy';

const docXml: string = buildDocumentoXml(dteDocument);
const envelope: string = buildEnvioDteXml([signedDocXml], caratula);
const boletaEnvelope: string = buildEnvioBoletaXml([signedBoletaXml], caratula);
Parseo XML
import { parseSiiResponse, parseUploadResponse } from 'dty-fy';

const result = parseSiiResponse(siiXmlResponse);        // { estado, seed?, token?, glosa? }
const upload = parseUploadResponse(siiHtmlResponse);    // { success, trackId?, error? }
Fechas y Zona Horaria

Todas las fechas y marcas de tiempo operan de manera determinista bajo la zona horaria chilena (America/Santiago, GMT-3 / GMT-4 según horario de verano):

import { formatDate, formatTimestamp, CHILE_TIMEZONE } from 'dty-fy';

CHILE_TIMEZONE;                        // 'America/Santiago'
formatDate();                          // '2024-01-15' (fecha actual en Chile)
formatDate(new Date('2024-06-01'));    // '2024-06-01'
formatTimestamp();                     // '2024-01-15T14:30:00' (timestamp ISO local sin offset)
Manejo de Codificación ISO-8859-1 (Latin-1)

El SII rechaza documentos que contengan caracteres fuera del repertorio ISO-8859-1. La librería provee sanitización y validación a nivel de bytes:

import { sanitizeToLatin1, isLatin1, toLatin1Buffer } from 'dty-fy';

isLatin1('Factura Nº 123');            // true
isLatin1('Producto \u2014 test');       // false (contiene em-dash)

sanitizeToLatin1('Cotización — $500'); // 'Cotizacion - $500' (translitera caracteres incompatibles)
const buf: Buffer = toLatin1Buffer('Texto legal'); // Buffer en codificación latin1

Constantes y Tipos

Codigos de Tipo de DTE
import { TipoDTE, TIPO_DTE_DESCRIPTIONS, VALID_DTE_CODES } from 'dty-fy';

TipoDTE.FacturaElectronica           // 33
TipoDTE.FacturaExenta               // 34
TipoDTE.BoletaElectronica           // 39
TipoDTE.BoletaExenta               // 41
TipoDTE.LiquidacionFactura          // 43
TipoDTE.FacturaCompra               // 46
TipoDTE.GuiaDespacho                // 52
TipoDTE.NotaDebito                  // 56
TipoDTE.NotaCredito                 // 61
TipoDTE.FacturaExportacion          // 110
TipoDTE.NotaDebitoExportacion       // 111
TipoDTE.NotaCreditoExportacion      // 112

TIPO_DTE_DESCRIPTIONS[33];           // 'Factura Electronica'
VALID_DTE_CODES;                     // Set { 33, 34, 39, 41, 43, 46, 52, 56, 61, 110, 111, 112 }
Conjuntos por Tipo
import { BOLETA_TYPES, EXPORT_TYPES, EXENTO_TYPES } from 'dty-fy';

BOLETA_TYPES  // Set { 39, 41 }
EXPORT_TYPES  // Set { 110, 111, 112 }
EXENTO_TYPES  // Set { 34, 41 }
Constantes del Sistema
import { IVA_RATE, RUT_SII, SII_URLS, SII_NAMESPACES } from 'dty-fy';

IVA_RATE                    // 19
RUT_SII                     // '60803000-K'
SII_URLS.certification      // { host, getSeed, getToken, upload, ... }
SII_NAMESPACES              // { DTE, DS, C14N, SHA1, RSA_SHA1, ... }
Codigos de Estado
import { ESTADO_ENVIO, ESTADO_DTE } from 'dty-fy';

ESTADO_ENVIO.SOK  // '0' — Aceptado OK
ESTADO_ENVIO.CRT  // '?' — En proceso / carátula recibida
ESTADO_ENVIO.EPR  // 'EPR' — Envío Procesado
ESTADO_ENVIO.RFL  // 'RFL' — Rechazado por Firma/Línea
ESTADO_DTE.DOK    // '0' — DTE Aceptado OK
ESTADO_DTE.RCH    // '1' — DTE Rechazado
Tipos Principales
import type {
  DteDocument,            // Estructura completa del documento DTE
  TipoDteCode,            // 33 | 34 | 39 | 41 | 43 | 46 | 52 | 56 | 61 | 110 | 111 | 112
  SiiEnvironment,         // 'certification' | 'production'
  SiiConfig,              // Objeto de configuracion del cliente
  EmitirResult,           // Resultado de emision
  EstadoEnvio,            // Estado del envio batch
  EstadoDte,              // Estado del DTE individual
  CafData,                // Datos de CAF parseados
  CertificateData,        // Datos del certificado parseados
  PollTrackIdOptions,     // Opciones para sondeo de TrackID
  Pdf417RenderOptions,    // Opciones para renderizado de código de barras
} from 'dty-fy';

Manejo de Errores

La librería define una jerarquía estricta de errores con propiedades tipadas para capturar fallos específicos de negocio, CAF y comunicación con el SII:

Excepciones Tipadas de Dominio
Clase de Error Cuándo se lanza Propiedades clave
DteSchemaValidationError Violación de reglas de esquema/negocio (ej. DTE 61 sin CodRef 1, 2 o 3; DTE 52 sin IndTraslado) field, value
CafFolioExhaustedError Se agotan los folios autorizados en el rango del CAF tipoDte, requestedFolio, availableRange
CafInvalidSignatureError La firma <FRMA> sobre <DA> en el CAF no coincide o el CAF fue alterado tipoDte, folioRange
SiiTokenExpiredError La sesión del token ha expirado o el SII retorna código de rechazo de sesión token
SiiWafBlockedError El cortafuegos/WAF del SII bloquea la petición (HTML de error, HTTP 403/503) url, statusCode
SiiRejectedStatusError El envío o documento fue formalmente rechazado por el SII (RSC, RFR, RCT, RFL) status, glosa, trackId, detalles
import {
  SiiError,
  DteSchemaValidationError,
  CafFolioExhaustedError,
  CafInvalidSignatureError,
  SiiTokenExpiredError,
  SiiWafBlockedError,
  SiiRejectedStatusError,
} from 'dty-fy';

try {
  const result = await sii.emitir(factura, cafManager);
} catch (error) {
  if (error instanceof CafFolioExhaustedError) {
    console.error(`Folios agotados para tipo ${error.tipoDte}: rango ${error.availableRange.desde}-${error.availableRange.hasta}`);
  } else if (error instanceof DteSchemaValidationError) {
    console.error(`Validación fallida en campo ${error.field}: valor '${error.value}'`);
  } else if (error instanceof SiiWafBlockedError) {
    console.error(`Petición bloqueada por WAF en ${error.url} (HTTP ${error.statusCode})`);
  } else if (error instanceof SiiRejectedStatusError) {
    console.error(`Rechazado por SII [${error.status}]: ${error.glosa} (TrackID: ${error.trackId})`);
  } else if (error instanceof SiiError) {
    console.error(`Error general SII: ${error.message}`);
  }
}

Ambientes

Ambiente Host SII Uso
certification maullin.sii.cl Pruebas y certificacion
production palena.sii.cl Produccion
const sii = new SiiClient({
  environment: 'certification',  // o 'production'
  // ...
});

Licencia

EULA (End User License Agreement) — Copyright (c) 2026 bm0x.

Ver el archivo LICENSE para los terminos completos.

Keywords