envio-comprobantes-sri
Version:
Envia comprobantes electronicos al SRI (Ecuador). Recibe un objeto JSON. Lo convierte a XML, lo firma, lo envía al servicio web del SRI y devuelve la respuesta.
62 lines (61 loc) • 3.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.aptoParaFirma = exports.estaVigente = exports.elegirCertificadoVigente = void 0;
const node_forge_1 = __importDefault(require("node-forge"));
// Un .p12 puede traer la cadena CA (sin llave) y, en certificados del Banco Central,
// el historial de la persona (vencidos + vigentes). Por defecto se usa el primer bag,
// igual que siempre; solo si no está vigente se busca un reemplazo vigente.
function seleccionarCertificadoDeFirma(p12, fechaReferencia = new Date()) {
var certBags = p12.getBags({ bagType: node_forge_1.default.pki.oids.certBag })[node_forge_1.default.pki.oids.certBag] ?? [];
var llaveBags = p12.getBags({ bagType: node_forge_1.default.pki.oids.pkcs8ShroudedKeyBag })[node_forge_1.default.pki.oids.pkcs8ShroudedKeyBag] ?? [];
var certBag0 = certBags[0]?.cert ?? undefined;
var llave0 = llaveBags[0]?.key;
var bagPorDefecto = { cert: certBag0, key: llave0 };
if (certBag0 && estaVigente(certBag0, fechaReferencia))
return bagPorDefecto;
var llaves = llaveBags
.map(bag => bag.key)
.filter((llave) => !!llave && !!llave.n);
// Empareja cada certificado con su llave por módulo RSA (descarta la cadena CA).
var candidatos = [];
for (var bag of certBags) {
var cert = bag.cert;
var moduloCert = cert?.publicKey?.n;
if (!cert || !moduloCert)
continue;
var llave = llaves.find(llave => moduloCert.compareTo(llave.n) === 0);
if (llave)
candidatos.push({ cert, key: llave });
}
var elegido = elegirCertificadoVigente(candidatos, fechaReferencia);
return elegido && estaVigente(elegido.cert, fechaReferencia) ? elegido : bagPorDefecto;
}
exports.default = seleccionarCertificadoDeFirma;
// Prioridad: vigentes > aptos para firma > caducidad más reciente.
function elegirCertificadoVigente(candidatos, fechaReferencia = new Date()) {
if (candidatos.length === 0)
return undefined;
var vigentes = candidatos.filter(({ cert }) => estaVigente(cert, fechaReferencia));
var elegibles = vigentes.length > 0 ? vigentes : candidatos;
var aptos = elegibles.filter(({ cert }) => aptoParaFirma(cert));
var finalistas = aptos.length > 0 ? aptos : elegibles;
return finalistas.reduce((mejor, actual) => actual.cert.validity.notAfter.valueOf() > mejor.cert.validity.notAfter.valueOf() ? actual : mejor);
}
exports.elegirCertificadoVigente = elegirCertificadoVigente;
function estaVigente(cert, fechaReferencia = new Date()) {
var ahora = fechaReferencia.valueOf();
return cert.validity.notBefore.valueOf() <= ahora && ahora <= cert.validity.notAfter.valueOf();
}
exports.estaVigente = estaVigente;
// Las CA del Ecuador emiten un cert de firma y otro de cifrado; solo el de firma sirve.
// Sin keyUsage declarado no se asume restricción.
function aptoParaFirma(cert) {
var usoDeClave = cert.extensions?.find(extension => extension.name === "keyUsage");
if (!usoDeClave)
return true;
return !!(usoDeClave.digitalSignature || usoDeClave.nonRepudiation);
}
exports.aptoParaFirma = aptoParaFirma;