facturacionelectronicapy-xmlsign
Version:
Módulo NodeJs para la firma de Archivo XML para la Facturación Electrónica en Paraguay
290 lines • 25.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const find_java_home_1 = __importDefault(require("find-java-home"));
const { exec } = require("child_process");
var fs = require("fs");
class XMLDsig {
constructor() { }
/**
* Firma con Java, retornando el documento firmado en el buffer de salida
* @param xml
* @param tag
* @returns
*/
signDocument(xml, tag, file, passphase) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
find_java_home_1.default({ allowJre: true }, (err, java8Path) => {
java8Path += "/bin/java";
if (err)
return console.log(err);
//Comentar esta linea al llevar a Produccion, por que aqui trae java 6
if (process.env.java8_home) {
//java8Path = `"C:\\Program Files\\Java\\jdk1.8.0_221\\bin\\java"`;
java8Path = `${process.env.java8_home}`;
}
const classPath = "" + __dirname + "";
//const tmpXMLToSign = "" + __dirname + "/xml_sign_temp.xml";
const tmpXMLToSign = "" +
__dirname +
"/xml_sign_temp_" +
Math.round(Math.random() * 999999) +
".xml";
fs.writeFileSync(tmpXMLToSign, xml, { encoding: "utf8" });
if (process.platform === "linux") {
passphase = passphase.replace(/\$/g, "\\$");
}
let fullCommand = `"${java8Path}" -Dfile.encoding=IBM850 -classpath "${classPath}" SignXML "${tmpXMLToSign}" "${file}" "${passphase}" "${tag}"`;
//console.log("fullCommand", fullCommand);
exec(fullCommand, { encoding: "UTF-8" }, (error, stdout, stderr) => {
let entro = 0;
if (entro == 0) {
//Evita hacer 2 veces reject
if (stderr) {
entro++;
console.log(stderr.cmd);
stderr.code = stderr.killed = stderr.signal = stderr.cmd = null;
if (!stderr.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(stderr);
}
}
}
if (entro == 0) {
//Evita hacer 2 veces reject
if (error) {
entro++;
console.log(error.cmd);
error.code = error.killed = error.signal = error.cmd = null;
if (!error.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(error);
}
}
}
try {
fs.unlinkSync(tmpXMLToSign);
}
catch (err) { }
resolve(`${stdout}`);
});
});
}));
});
}
/**
* Firma con Java, varios documentos al mismo tiempo
* @param xml
* @param tag
* @returns
*/
signDocuments(xmls, tag, file, passphase) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
//console.log("A firmar", xml);
find_java_home_1.default({ allowJre: true }, (err, java8Path) => {
java8Path += "/bin/java";
if (err)
return console.log(err);
//Comentar esta linea al llevar a Produccion, por que aqui trae java 6
if (process.env.java8_home) {
//java8Path = `"C:\\Program Files\\Java\\jdk1.8.0_221\\bin\\java"`;
java8Path = `${process.env.java8_home}`;
}
const classPath = "" + __dirname + "";
//const tmpXMLToSign = "" + __dirname + "/xml_sign_temp.xml";
const arrayNameFiles = new Array();
for (let i = 0; i < xmls.length; i++) {
const xml = xmls[i];
const tmpXMLToSign = "" +
__dirname +
"/xml_sign_temp_" +
Math.round(Math.random() * 999999) +
".xml";
fs.writeFileSync(tmpXMLToSign, xml, { encoding: "utf8" });
arrayNameFiles.push(tmpXMLToSign);
}
if (process.platform === "linux") {
passphase = passphase.replace(/\$/g, "\\$");
}
let fullCommand = `"${java8Path}" -Dfile.encoding=IBM850 -classpath "${classPath}" SignXMLFiles "${arrayNameFiles.join(",")}" "${file}" "${passphase}" "${tag}"`;
//console.log("fullCommand", fullCommand);
exec(fullCommand, { encoding: "UTF-8" }, (error, stdout, stderr) => {
let stdOutProcesed = stdout;
/*console.log("error", error);
console.log("stdout", stdout);
console.log("stderr", stderr);
*/
if (stdOutProcesed.includes("_SEPARATOR_")) {
//Por si haya algun log que quedo en la colita, entonces elimina ese
stdOutProcesed = stdout.substring(0, stdout.lastIndexOf("_SEPARATOR_") + 11);
}
let entro = 0;
if (entro == 0) {
if (stderr) {
if (!stdOutProcesed.includes("_SEPARATOR_")) {
entro++;
//console.log("stderr", stderr, typeof stderr);
//console.log(stderr.cmd);
/*stderr.code =
stderr.killed =
stderr.signal =
stderr.cmd =
null;
*/
if (!stderr.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(new Error(stderr));
return;
}
}
}
}
if (entro == 0) {
if (error) {
if (!stdOutProcesed.includes("_SEPARATOR_")) {
entro++;
console.log(error.cmd);
error.code = error.killed = error.signal = error.cmd = null;
if (!stderr.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(error);
return;
}
}
}
}
try {
for (let i = 0; i < arrayNameFiles.length; i++) {
const nameFile = arrayNameFiles[i];
fs.unlinkSync(nameFile);
}
//file removed
}
catch (err) {
console.error("Error al borrar referencias ", err);
}
resolve(`${stdOutProcesed}`);
});
});
}));
});
}
/**
* Firma el XML del Evento con Java
* @param xml
* @param tag
* @returns
*/
signEvento(xml, tag, file, passphase) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
find_java_home_1.default({ allowJre: true }, (err, java8Path) => {
java8Path += "/bin/java";
if (err)
return console.log(err);
//Comentar esta linea al llevar a Produccion, por que aqui trae java 6
if (process.env.java8_home) {
//java8Path = `"C:\\Program Files\\Java\\jdk1.8.0_221\\bin\\java"`;
java8Path = `${process.env.java8_home}`;
}
const classPath = "" + __dirname + "";
const tmpXMLToSign = "" + __dirname + "/xml_sign_temp.xml";
fs.writeFileSync(tmpXMLToSign, xml, { encoding: "utf8" });
if (process.platform === "linux") {
passphase = passphase.replace(/\$/g, "\\$");
}
let fullCommand = `"${java8Path}" -Dfile.encoding=IBM850 -classpath "${classPath}" SignXMLEvento "${tmpXMLToSign}" "${file}" "${passphase}"`;
exec(fullCommand, { encoding: "UTF-8" }, (error, stdout, stderr) => {
if (error) {
if (!error.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(error);
}
}
if (stderr) {
if (!stderr.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(stderr);
}
}
try {
fs.unlinkSync(tmpXMLToSign);
//file removed
}
catch (err) {
console.error(err);
}
resolve(`${stdout}`);
});
});
}));
});
}
/**
* Firma con Java, retornando el documento firmado en el buffer de salida
* @param xml
* @param tag
* @returns
*/
getExpiration(file, passphase) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
find_java_home_1.default({ allowJre: true }, (err, java8Path) => {
java8Path += "/bin/java";
if (err)
return console.log(err);
//Comentar esta linea al llevar a Produccion, por que aqui trae java 6
if (process.env.java8_home) {
//java8Path = `"C:\\Program Files\\Java\\jdk1.8.0_221\\bin\\java"`;
java8Path = `${process.env.java8_home}`;
}
const classPath = "" + __dirname + "";
if (process.platform === "linux") {
passphase = passphase.replace(/\$/g, "\\$");
}
let fullCommand = `"${java8Path}" -Dfile.encoding=IBM850 -classpath "${classPath}" CertExpiration "${file}" "${passphase}"`;
exec(fullCommand, { encoding: "UTF-8" }, (error, stdout, stderr) => {
if (error) {
if (!error.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(new Error(error));
}
}
if (stderr) {
if (!stderr.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
//Warning que no debe ser tomado com error
reject(new Error(stderr));
}
}
try {
//file removed
}
catch (err) {
console.error(err);
}
let respuestaJson = {};
if (stdout && (stdout + "").startsWith("{")) {
respuestaJson = JSON.parse(`${stdout}`);
}
resolve(respuestaJson);
});
});
}));
});
}
}
exports.default = new XMLDsig();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWE1MRHNpZ0phdmEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvWE1MRHNpZ0phdmEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvRUFBMEM7QUFFMUMsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUMxQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFFdkIsTUFBTSxPQUFPO0lBQ1gsZ0JBQWUsQ0FBQztJQUVoQjs7Ozs7T0FLRztJQUNHLFlBQVksQ0FBQyxHQUFXLEVBQUUsR0FBUSxFQUFFLElBQVMsRUFBRSxTQUFjOztZQUNqRSxPQUFPLElBQUksT0FBTyxDQUFDLENBQU8sT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUMzQyx3QkFBWSxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBUSxFQUFFLFNBQWMsRUFBRSxFQUFFO29CQUM1RCxTQUFTLElBQUksV0FBVyxDQUFDO29CQUN6QixJQUFJLEdBQUc7d0JBQUUsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUVqQyxzRUFBc0U7b0JBQ3RFLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUU7d0JBQzFCLG1FQUFtRTt3QkFDbkUsU0FBUyxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztxQkFDekM7b0JBRUQsTUFBTSxTQUFTLEdBQUcsRUFBRSxHQUFHLFNBQVMsR0FBRyxFQUFFLENBQUM7b0JBQ3RDLDZEQUE2RDtvQkFDN0QsTUFBTSxZQUFZLEdBQ2hCLEVBQUU7d0JBQ0YsU0FBUzt3QkFDVCxpQkFBaUI7d0JBQ2pCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQzt3QkFDbEMsTUFBTSxDQUFDO29CQUVULEVB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