ghinfe 0.6.0 → 0.6.2
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/.env.example +24 -15
- package/LICENSE +21 -21
- package/README.md +491 -413
- package/docs/developer-guide.html +421 -421
- package/docs/openapi.yaml +428 -428
- package/examples/dce-homologacao.js +141 -0
- package/examples/emitir-nfce.js +51 -51
- package/examples/emitir-nfe.js +83 -83
- package/examples/emitir-nfse.js +46 -46
- package/examples/endpoints-sefaz.js +14 -14
- package/examples/eventos-nfe.js +49 -49
- package/examples/gerar-chave.js +25 -25
- package/examples/gerar-dace.js +59 -0
- package/examples/gerar-danfe.js +75 -75
- package/examples/gerar-dce.js +58 -0
- package/examples/layouts-nfse.js +51 -51
- package/examples/mock-sefaz.js +52 -52
- package/examples/nfse-eventos.js +57 -57
- package/examples/reforma-ibscbs.js +27 -27
- package/examples/reforma-nfe-xml.js +52 -52
- package/examples/status-sefaz.js +12 -12
- package/examples/validar-xsd.js +48 -48
- package/package.json +59 -68
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consSitDCeTiposBasico_v1.00.xsd +123 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consSitDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consStatServDCeTiposBasico_v1.00.xsd +110 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consStatServDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/dceTiposBasico_v1.00.xsd +1388 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/retConsSitDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/retConsStatServDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/tiposGeralDCe_v1.00.xsd +712 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/xmldsig-core-schema_v1.01.xsd +98 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/dceTiposBasico_v1.00.xsd +1410 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/dce_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/evCancDCe_v1.00.xsd +36 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/eventoDCeTiposBasico_v1.00.xsd +283 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/eventoDCe_v1.00.xsd +9 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/procEventoDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/retEventoDCe_v1.00.xsd +9 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/tiposGeralDCe_v1.00.xsd +712 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/xmldsig-core-schema_v1.01.xsd +98 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/procDCe_v1.00.xsd +37 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/retDCe_v1.00.xsd +9 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/tiposGeralDCe_v1.00.xsd +712 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/xmldsig-core-schema_v1.01.xsd +98 -0
- package/schemas/nfe/PL_009_V4/enviNFe_v3.10.xsd +8 -8
- package/schemas/nfe/PL_009_V4/xmldsig-core-schema_v1.01.xsd +97 -97
- package/scripts/download-schemas.js +39 -39
- package/scripts/test-xsd.js +34 -34
- package/src/api/server.js +316 -316
- package/src/constants/sefaz.js +69 -69
- package/src/danfe/DanfeService.js +205 -205
- package/src/danfe/xml-extract.js +69 -69
- package/src/dce/builders/DCeEventoXmlBuilder.js +86 -0
- package/src/dce/builders/DCeXmlBuilder.js +345 -0
- package/src/dce/constants/dce.js +87 -0
- package/src/dce/dace/DaceService.js +356 -0
- package/src/dce/dace/dace-extract.js +114 -0
- package/src/dce/services/DCeService.js +263 -0
- package/src/dce/services/DCeSoapService.js +235 -0
- package/src/dce/services/DCeXmlService.js +67 -0
- package/src/dce/types/DCeDocument.js +106 -0
- package/src/dce/utils/qrcode.utils.js +59 -0
- package/src/errors/GhinfeError.js +13 -13
- package/src/errors/SefazError.js +25 -25
- package/src/errors/XsdValidationError.js +15 -15
- package/src/index.js +84 -60
- package/src/nfce/builders/NFCeXmlBuilder.js +178 -178
- package/src/nfce/constants/qrcode.js +26 -26
- package/src/nfce/services/NFCeService.js +188 -188
- package/src/nfce/services/NFCeXmlService.js +38 -38
- package/src/nfce/types/NFCeDocument.js +42 -42
- package/src/nfce/utils/qrcode.utils.js +92 -92
- package/src/nfe/builders/NFeEventoXmlBuilder.js +110 -110
- package/src/nfe/builders/NFeXmlBuilder.js +215 -215
- package/src/nfe/mocks/sefaz-responses.js +195 -195
- package/src/nfe/services/NFeEventoService.js +95 -95
- package/src/nfe/services/NFeService.js +196 -196
- package/src/nfe/services/NFeSignService.js +127 -111
- package/src/nfe/services/NFeSoapService.js +437 -437
- package/src/nfe/services/NFeXmlService.js +41 -41
- package/src/nfe/services/NFeXsdService.js +56 -56
- package/src/nfe/types/NFeDocument.js +92 -92
- package/src/nfe/types/NFeEvento.js +44 -44
- package/src/nfse/NFSeMunicipioResolver.js +42 -42
- package/src/nfse/builders/NFSeEventoXmlBuilder.js +92 -92
- package/src/nfse/builders/NFSeXmlBuilder.js +16 -16
- package/src/nfse/constants/municipios.js +82 -82
- package/src/nfse/layouts/adapters.js +202 -202
- package/src/nfse/mocks/nfse-responses.js +142 -142
- package/src/nfse/services/NFSeService.js +191 -191
- package/src/nfse/services/NFSeSoapService.js +232 -232
- package/src/nfse/services/NFSeXmlService.js +12 -12
- package/src/nfse/types/NFSeDocument.js +54 -54
- package/src/queue/NFCeQueue.js +63 -63
- package/src/queue/NFSeQueue.js +59 -59
- package/src/queue/NFeQueue.js +76 -76
- package/src/reforma/ibscbs.js +175 -175
- package/src/sefaz/SefazEndpointResolver.js +95 -95
- package/src/sefaz/ca/icp-brasil-raiz-v10.pem +38 -0
- package/src/sefaz/endpoints.registry.js +205 -205
- package/src/sefaz/httpsAgent.js +33 -0
- package/src/shared/fiscal.helpers.js +53 -53
- package/src/utils/certificate.utils.js +69 -47
- package/src/utils/chave.utils.js +205 -117
- package/src/utils/code128.utils.js +67 -0
- package/src/utils/date.utils.js +26 -26
- package/src/utils/xml.utils.js +44 -44
- package/src/validation/XsdValidator.js +133 -114
- package/src/validation/schemas.js +18 -14
|
@@ -1,114 +1,133 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import libxmljs from 'libxmljs2';
|
|
4
|
-
import { pathToFileURL } from 'url';
|
|
5
|
-
import { XsdValidationError } from '../errors/XsdValidationError.js';
|
|
6
|
-
import { GhinfeError } from '../errors/GhinfeError.js';
|
|
7
|
-
|
|
8
|
-
const schemaCache = new Map();
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Validador XSD genérico usando libxmljs2 e schemas oficiais SEFAZ.
|
|
12
|
-
*/
|
|
13
|
-
export class XsdValidator {
|
|
14
|
-
/**
|
|
15
|
-
* @param {string} xsdPath Caminho absoluto do arquivo .xsd
|
|
16
|
-
*/
|
|
17
|
-
static loadSchema(xsdPath) {
|
|
18
|
-
if (schemaCache.has(xsdPath)) {
|
|
19
|
-
return schemaCache.get(xsdPath);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!fs.existsSync(xsdPath)) {
|
|
23
|
-
throw new GhinfeError(
|
|
24
|
-
`Schema XSD não encontrado: ${xsdPath}. Execute: node scripts/download-schemas.js`,
|
|
25
|
-
'XSD_SCHEMA_NOT_FOUND'
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const dir = path.dirname(xsdPath);
|
|
30
|
-
const baseUrl = pathToFileURL(dir + path.sep).href;
|
|
31
|
-
const content = fs.readFileSync(xsdPath, 'utf8');
|
|
32
|
-
const schema = libxmljs.parseXml(content, { baseUrl });
|
|
33
|
-
|
|
34
|
-
schemaCache.set(xsdPath, schema);
|
|
35
|
-
return schema;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Valida XML contra schema XSD.
|
|
40
|
-
* @param {string} xml
|
|
41
|
-
* @param {string} xsdPath
|
|
42
|
-
* @param {{ injetarAssinaturaStub?: boolean, modelo?: '55'|'65' }} [options]
|
|
43
|
-
* @returns {{ valido: true, avisos: string[] }}
|
|
44
|
-
*/
|
|
45
|
-
static validar(xml, xsdPath, options = {}) {
|
|
46
|
-
let xmlParaValidar = xml;
|
|
47
|
-
|
|
48
|
-
if (options.
|
|
49
|
-
xmlParaValidar = this.#
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import libxmljs from 'libxmljs2';
|
|
4
|
+
import { pathToFileURL } from 'url';
|
|
5
|
+
import { XsdValidationError } from '../errors/XsdValidationError.js';
|
|
6
|
+
import { GhinfeError } from '../errors/GhinfeError.js';
|
|
7
|
+
|
|
8
|
+
const schemaCache = new Map();
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validador XSD genérico usando libxmljs2 e schemas oficiais SEFAZ.
|
|
12
|
+
*/
|
|
13
|
+
export class XsdValidator {
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} xsdPath Caminho absoluto do arquivo .xsd
|
|
16
|
+
*/
|
|
17
|
+
static loadSchema(xsdPath) {
|
|
18
|
+
if (schemaCache.has(xsdPath)) {
|
|
19
|
+
return schemaCache.get(xsdPath);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!fs.existsSync(xsdPath)) {
|
|
23
|
+
throw new GhinfeError(
|
|
24
|
+
`Schema XSD não encontrado: ${xsdPath}. Execute: node scripts/download-schemas.js`,
|
|
25
|
+
'XSD_SCHEMA_NOT_FOUND'
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const dir = path.dirname(xsdPath);
|
|
30
|
+
const baseUrl = pathToFileURL(dir + path.sep).href;
|
|
31
|
+
const content = fs.readFileSync(xsdPath, 'utf8');
|
|
32
|
+
const schema = libxmljs.parseXml(content, { baseUrl });
|
|
33
|
+
|
|
34
|
+
schemaCache.set(xsdPath, schema);
|
|
35
|
+
return schema;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Valida XML contra schema XSD.
|
|
40
|
+
* @param {string} xml
|
|
41
|
+
* @param {string} xsdPath
|
|
42
|
+
* @param {{ injetarAssinaturaStub?: boolean, modelo?: '55'|'65'|'99' }} [options]
|
|
43
|
+
* @returns {{ valido: true, avisos: string[] }}
|
|
44
|
+
*/
|
|
45
|
+
static validar(xml, xsdPath, options = {}) {
|
|
46
|
+
let xmlParaValidar = xml;
|
|
47
|
+
|
|
48
|
+
if (options.modelo === '99') {
|
|
49
|
+
xmlParaValidar = this.#compatibilizarDCe(xmlParaValidar);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (options.injetarAssinaturaStub) {
|
|
53
|
+
xmlParaValidar = this.#prepararXmlEstrutural(xmlParaValidar, options.modelo ?? '55');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const schema = this.loadSchema(xsdPath);
|
|
57
|
+
const doc = libxmljs.parseXml(xmlParaValidar);
|
|
58
|
+
|
|
59
|
+
const valido = doc.validate(schema);
|
|
60
|
+
if (valido) {
|
|
61
|
+
return { valido: true, avisos: [] };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const erros = doc.validationErrors.map((e) => e.message).filter(Boolean);
|
|
65
|
+
throw new XsdValidationError(erros, path.basename(xsdPath));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Valida e retorna boolean (sem lançar exceção).
|
|
70
|
+
* @param {string} xml
|
|
71
|
+
* @param {string} xsdPath
|
|
72
|
+
* @param {object} [options]
|
|
73
|
+
*/
|
|
74
|
+
static tentarValidar(xml, xsdPath, options = {}) {
|
|
75
|
+
try {
|
|
76
|
+
return this.validar(xml, xsdPath, options);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (error instanceof XsdValidationError) {
|
|
79
|
+
return { valido: false, erros: error.erros };
|
|
80
|
+
}
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* O XSD da DC-e exige infSolicDCe, mas o grupo é exclusivo do Fisco (tpEmit=0):
|
|
87
|
+
* informá-lo nos demais casos gera rejeição 229. Para validar a estrutura sem
|
|
88
|
+
* enviar o grupo, injeta-se um infSolicDCe vazio apenas na cópia validada.
|
|
89
|
+
* @param {string} xml
|
|
90
|
+
*/
|
|
91
|
+
static #compatibilizarDCe(xml) {
|
|
92
|
+
if (xml.includes('<infSolicDCe>')) return xml;
|
|
93
|
+
return xml.replace('</infDCe>', '</infDCe><infSolicDCe><xSolic></xSolic></infSolicDCe>');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Injeta elementos exigidos pelo XSD para validação estrutural pré-assinatura.
|
|
98
|
+
* O schema exige Signature (NF-e/DC-e) ou infNFeSupl + Signature (NFC-e).
|
|
99
|
+
* @param {string} xml
|
|
100
|
+
* @param {'55'|'65'|'99'} modelo
|
|
101
|
+
*/
|
|
102
|
+
static #prepararXmlEstrutural(xml, modelo) {
|
|
103
|
+
if (xml.includes('</Signature>')) return xml;
|
|
104
|
+
|
|
105
|
+
const idMatch = xml.match(/Id="((?:NFe|DCe)\d{44})"/);
|
|
106
|
+
const id = idMatch?.[1];
|
|
107
|
+
if (!id) return xml;
|
|
108
|
+
|
|
109
|
+
if (modelo === '99') {
|
|
110
|
+
return xml.replace('</DCe>', `${this.#assinaturaStub(id)}</DCe>`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let complemento = '';
|
|
114
|
+
|
|
115
|
+
if (modelo === '65' && !xml.includes('infNFeSupl')) {
|
|
116
|
+
const qrStub = 'https://nfce.sefaz.example/qr?p=STUB';
|
|
117
|
+
complemento += `<infNFeSupl><qrCode><![CDATA[${qrStub}]]></qrCode><urlChave>${qrStub}</urlChave></infNFeSupl>`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
complemento += this.#assinaturaStub(id);
|
|
121
|
+
return xml.replace('</NFe>', `${complemento}</NFe>`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** @param {string} id */
|
|
125
|
+
static #assinaturaStub(id) {
|
|
126
|
+
return `<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="#${id}"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>WCF0TVY=</DigestValue></Reference></SignedInfo><SignatureValue>WCF0TVY=</SignatureValue><KeyInfo><X509Data><X509Certificate>WCF0TVY=</X509Certificate></X509Data></KeyInfo></Signature>`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Limpa cache de schemas (útil em testes). */
|
|
130
|
+
static limparCache() {
|
|
131
|
+
schemaCache.clear();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
|
|
4
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
-
const SCHEMAS_ROOT = path.resolve(__dirname, '../../schemas');
|
|
6
|
-
|
|
7
|
-
/** Caminhos dos schemas XSD oficiais (
|
|
8
|
-
export const XSD_SCHEMAS = {
|
|
9
|
-
NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/nfe_v4.00.xsd'),
|
|
10
|
-
ENVI_NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/enviNFe_v4.00.xsd'),
|
|
11
|
-
EVENTO: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/leiauteNFe_v4.00.xsd'),
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
|
|
4
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
const SCHEMAS_ROOT = path.resolve(__dirname, '../../schemas');
|
|
6
|
+
|
|
7
|
+
/** Caminhos dos schemas XSD oficiais (NF-e/NFC-e PL_009_V4 e DC-e PL_DCe_v1.00a + NT 2024.001). */
|
|
8
|
+
export const XSD_SCHEMAS = {
|
|
9
|
+
NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/nfe_v4.00.xsd'),
|
|
10
|
+
ENVI_NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/enviNFe_v4.00.xsd'),
|
|
11
|
+
EVENTO: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/leiauteNFe_v4.00.xsd'),
|
|
12
|
+
DCE: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/dce_v1.00.xsd'),
|
|
13
|
+
DCE_PROC: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/procDCe_v1.00.xsd'),
|
|
14
|
+
DCE_EVENTO: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/evento/eventoDCe_v1.00.xsd'),
|
|
15
|
+
DCE_EVENTO_CANCELAMENTO: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/evento/evCancDCe_v1.00.xsd'),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const SCHEMAS_ROOT_PATH = SCHEMAS_ROOT;
|