dty-fy
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
- Inicio Rapido
- Arquitectura
- Certificados Digitales
- Gestion de CAF
- Constructor de DTE
- Timbre Electronico y Codigo PDF417
- Cliente SII
- Funciones Utiles
- Constantes y Tipos
- Manejo de Errores
- Ambientes
- Licencia
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.