node-sped-nfe 1.0.7 → 1.0.9
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/README.md +2 -54
- package/dist/utils/extras.js +204 -0
- package/dist/utils/make.d.ts +2 -1
- package/dist/utils/make.js +22 -3
- package/dist/utils/tools.d.ts +1 -0
- package/dist/utils/tools.js +34 -1
- package/docs/README.md +23 -12
- package/docs/Tools.md +105 -0
- package/docs/requisitos.md +26 -0
- package/exemplos/status.js +4 -1
- package/package.json +3 -2
- package/src/utils/extras.ts +223 -0
- package/src/utils/tools.ts +31 -2
package/README.md
CHANGED
@@ -34,57 +34,5 @@ Seja bem-vindo(a) à **Biblioteca de Emissão de NF-e** — sua parceira definit
|
|
34
34
|
|
35
35
|
---
|
36
36
|
|
37
|
-
## 📌
|
38
|
-
|
39
|
-
Para garantir o funcionamento correto da biblioteca, certifique-se de que os seguintes requisitos estejam atendidos:
|
40
|
-
|
41
|
-
### 🔧 Ambiente
|
42
|
-
|
43
|
-
- **Windows**/**Linux**
|
44
|
-
- **Node.js** `v22.14.0` (versão testada e recomendada)
|
45
|
-
- **xmllint** `2.9.3` (utilizado para validação dos XMLs gerados)
|
46
|
-
|
47
|
-
---
|
48
|
-
|
49
|
-
## 🧪 Estados Testados
|
50
|
-
|
51
|
-
A biblioteca já foi testada com sucesso nos seguintes estados brasileiros:
|
52
|
-
|
53
|
-
- ✅ MT — Mato Grosso
|
54
|
-
- ⬜ AC — Acre
|
55
|
-
- ⬜ AL — Alagoas
|
56
|
-
- ⬜ AM — Amazonas
|
57
|
-
- ⬜ AP — Amapá
|
58
|
-
- ⬜ BA — Bahia
|
59
|
-
- ⬜ CE — Ceará
|
60
|
-
- ⬜ DF — Distrito Federal
|
61
|
-
- ⬜ ES — Espírito Santo
|
62
|
-
- ⬜ GO — Goiás
|
63
|
-
- ⬜ MA — Maranhão
|
64
|
-
- ⬜ MG — Minas Gerais
|
65
|
-
- ⬜ MS — Mato Grosso do Sul
|
66
|
-
- ⬜ PA — Pará
|
67
|
-
- ⬜ PB — Paraíba
|
68
|
-
- ⬜ PE — Pernambuco
|
69
|
-
- ⬜ PI — Piauí
|
70
|
-
- ⬜ PR — Paraná
|
71
|
-
- ⬜ RJ — Rio de Janeiro
|
72
|
-
- ⬜ RN — Rio Grande do Norte
|
73
|
-
- ⬜ RO — Rondônia
|
74
|
-
- ⬜ RR — Roraima
|
75
|
-
- ⬜ RS — Rio Grande do Sul
|
76
|
-
- ⬜ SC — Santa Catarina
|
77
|
-
- ⬜ SE — Sergipe
|
78
|
-
- ⬜ SP — São Paulo
|
79
|
-
- ⬜ TO — Tocantins
|
80
|
-
|
81
|
-
Contribua com a comunidade! Testou com sucesso em algum estado? Envie um PR ou abra uma issue!
|
82
|
-
|
83
|
-
## 🚀 Começando
|
84
|
-
|
85
|
-
### 1. Instalação
|
86
|
-
|
87
|
-
```bash
|
88
|
-
npm install node-sped-nfe
|
89
|
-
# ou
|
90
|
-
yarn add node-sped-nfe
|
37
|
+
## 📌 Informações
|
38
|
+
[Documentação](https://github.com/kalmonv/node-sped-nfe/tree/main/docs)
|
package/dist/utils/extras.js
CHANGED
@@ -55,4 +55,208 @@ const cUF2UF = {
|
|
55
55
|
"GO": "52",
|
56
56
|
"DF": "53"
|
57
57
|
};
|
58
|
+
//Função auxliar de imposto
|
59
|
+
const impEstrutura = (imposto) => {
|
60
|
+
const gStruct = {
|
61
|
+
ICMS: {
|
62
|
+
ICMS_ICMSSN: {
|
63
|
+
"@label": "Tributação",
|
64
|
+
"@type": "select",
|
65
|
+
"@obrig": true,
|
66
|
+
"@values": [
|
67
|
+
{ "102": "Tributação Normal" },
|
68
|
+
{ "103": "Simples Nacional" }
|
69
|
+
],
|
70
|
+
"@next": {
|
71
|
+
CST: {
|
72
|
+
"@label": "Situação Tributaria",
|
73
|
+
"@type": "select",
|
74
|
+
"@obrig": true,
|
75
|
+
"@values": [
|
76
|
+
{ "00": "00 - Tributada integralmente" },
|
77
|
+
{ "10": "10 - Tributada com cobrança do ICMS por ST" },
|
78
|
+
{ "10v2": "10 - Tributada com cobrança do ICMS por ST(com partilha do ICMS entre UF de origem e a UF de destino ou a UFdefinida na legislação)" },
|
79
|
+
{ "20": "20 - Com redução de base de cálculo" },
|
80
|
+
{ "30": "30 - Isenta ou não tributada e com cobrança do ICMS por ST" },
|
81
|
+
{ "40": "40 - Isenta" },
|
82
|
+
{ "41": "41 - Não tributada" },
|
83
|
+
{ "41v2": "41 - Não tributada (ICMSST devido para UF de destino, nas operações interestaduais de produtos que tiveram retenção de ICMS na UF do rementente)" },
|
84
|
+
{ "50": "50 - Suspensão" },
|
85
|
+
{ "51": "51 - Diferimento" },
|
86
|
+
{ "60": "60 - Cobrado anteriormente por ST" },
|
87
|
+
{ "60v2": "60 - Cobrado anteriormente por ST" },
|
88
|
+
{ "70": "70 - Com redução de base de cálculo e cobrança do ICMS por ST" },
|
89
|
+
{ "90": "90 - Outros (Com partilha do ICMS entre a UF de origem e a UF de destino ou a UF definida na legistação)" },
|
90
|
+
{ "90v2": "90 - Outros" },
|
91
|
+
],
|
92
|
+
},
|
93
|
+
orig: {
|
94
|
+
"@label": "Origem",
|
95
|
+
"@type": "select",
|
96
|
+
"@obrig": true,
|
97
|
+
"@values": [
|
98
|
+
{ "0": "Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8" },
|
99
|
+
{ "1": "Estrangeira - Importação direta, exceto a indicada no código 6" },
|
100
|
+
{ "2": "Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7" },
|
101
|
+
{ "3": "Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% e inferior ou igual a 70%" },
|
102
|
+
{ "4": "Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam as legislações citadas nos Ajustes" },
|
103
|
+
{ "5": "Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% " },
|
104
|
+
{ "6": "Estrangeira - Importação direta, sem similar nacional, constante em lista da CAMEX e gás natural" },
|
105
|
+
{ "7": "Estrangeira - Adquirida no mercado interno, sem similar nacional, constante lista CAMEX e gás natural" }
|
106
|
+
],
|
107
|
+
},
|
108
|
+
"@next": {
|
109
|
+
"@CST_00": {
|
110
|
+
modBC: {
|
111
|
+
"@label": "Modalidade de determinação da base de calculo ICMS",
|
112
|
+
"@type": "select",
|
113
|
+
"@obrig": true,
|
114
|
+
"@values": [
|
115
|
+
{ "0": "0-Margem Valor Agregado (%)" },
|
116
|
+
{ "1": "1-Pauta (Valor)" },
|
117
|
+
{ "2": "2-Preço Tabelado Máx" },
|
118
|
+
{ "3": "3-Valor da operação" }
|
119
|
+
],
|
120
|
+
},
|
121
|
+
vBC: {
|
122
|
+
"@label": "Base de calculo ICMS",
|
123
|
+
"@type": "input",
|
124
|
+
"@obrig": true,
|
125
|
+
},
|
126
|
+
pICMS: {
|
127
|
+
"@label": "Líquota do ICMS",
|
128
|
+
"@type": "input",
|
129
|
+
"@obrig": true,
|
130
|
+
},
|
131
|
+
vICMS: {
|
132
|
+
"@label": "Valor ICMS",
|
133
|
+
"@type": "input",
|
134
|
+
"@obrig": true,
|
135
|
+
},
|
136
|
+
pFCP: {
|
137
|
+
"@label": "% Relativo ao FCP ST",
|
138
|
+
"@type": "input",
|
139
|
+
"@obrig": false,
|
140
|
+
},
|
141
|
+
vFCP: {
|
142
|
+
"@label": "Valor ICMS FCP ST",
|
143
|
+
"@type": "input",
|
144
|
+
"@obrig": false,
|
145
|
+
}
|
146
|
+
},
|
147
|
+
"@CST_10": {
|
148
|
+
modBC: {
|
149
|
+
"@label": "Modalidade de determinação da base de calculo ICMS",
|
150
|
+
"@type": "select",
|
151
|
+
"@obrig": true,
|
152
|
+
"@values": [
|
153
|
+
{ "0": "0-Margem Valor Agregado (%)" },
|
154
|
+
{ "1": "1-Pauta (Valor)" },
|
155
|
+
{ "2": "2-Preço Tabelado Máx" },
|
156
|
+
{ "3": "3-Valor da operação" }
|
157
|
+
],
|
158
|
+
},
|
159
|
+
vBC: {
|
160
|
+
"@label": "Base de calculo ICMS",
|
161
|
+
"@type": "input",
|
162
|
+
"@obrig": true,
|
163
|
+
},
|
164
|
+
pICMS: {
|
165
|
+
"@label": "Líquota do ICMS",
|
166
|
+
"@type": "input",
|
167
|
+
"@obrig": true,
|
168
|
+
},
|
169
|
+
vICMS: {
|
170
|
+
"@label": "Valor ICMS",
|
171
|
+
"@type": "input",
|
172
|
+
"@obrig": true,
|
173
|
+
},
|
174
|
+
modBCST: {
|
175
|
+
"@label": "Modalidade de determinação da BC do ICMS ST",
|
176
|
+
"@type": "select",
|
177
|
+
"@obrig": true,
|
178
|
+
"@values": [
|
179
|
+
{ "0": "Preço tabelado ou máximo sugerido" },
|
180
|
+
{ "1": "Lista Negativa (valor)" },
|
181
|
+
{ "2": "Lista Positiva (valor)" },
|
182
|
+
{ "3": "Lista Neutra (valor)" },
|
183
|
+
{ "4": "Margem Valor Agregado (%)" },
|
184
|
+
{ "5": "Pauta (valor)" },
|
185
|
+
{ "6": "Valor da Operação (NT 2019.001)" }
|
186
|
+
],
|
187
|
+
},
|
188
|
+
pMVAST: {
|
189
|
+
"@label": "% Margem de valor adic. ICMS ST",
|
190
|
+
"@type": "input",
|
191
|
+
"@obrig": true,
|
192
|
+
},
|
193
|
+
pRedBCST: {
|
194
|
+
"@label": "% Redução de BC ICMS ST",
|
195
|
+
"@type": "input",
|
196
|
+
"@obrig": true,
|
197
|
+
},
|
198
|
+
vBCST: {
|
199
|
+
"@label": "BC ICMS ST",
|
200
|
+
"@type": "input",
|
201
|
+
"@obrig": true,
|
202
|
+
},
|
203
|
+
pICMSST: {
|
204
|
+
"@label": "Alíquota de ICMS ST",
|
205
|
+
"@type": "input",
|
206
|
+
"@obrig": true,
|
207
|
+
},
|
208
|
+
vICMSST: {
|
209
|
+
"@label": "ICMS ST",
|
210
|
+
"@type": "input",
|
211
|
+
"@obrig": true,
|
212
|
+
},
|
213
|
+
vBCFCPST: {
|
214
|
+
"@label": "BC ICMS FCP ST",
|
215
|
+
"@type": "input",
|
216
|
+
"@obrig": true,
|
217
|
+
},
|
218
|
+
pFCPST: {
|
219
|
+
"@label": "% Relativo ao FCP ST",
|
220
|
+
"@type": "input",
|
221
|
+
"@obrig": true,
|
222
|
+
},
|
223
|
+
vFCPST: {
|
224
|
+
"@label": "Valor ICMS FCP ST",
|
225
|
+
"@type": "input",
|
226
|
+
"@obrig": true,
|
227
|
+
},
|
228
|
+
vBCFCP: {
|
229
|
+
"@label": "BC ICMS FCP",
|
230
|
+
"@type": "input",
|
231
|
+
"@obrig": false,
|
232
|
+
},
|
233
|
+
pFCP: {
|
234
|
+
"@label": "% Relativo ao FCP",
|
235
|
+
"@type": "input",
|
236
|
+
"@obrig": false,
|
237
|
+
},
|
238
|
+
vFCP: {
|
239
|
+
"@label": "Valor ICMS FCP",
|
240
|
+
"@type": "input",
|
241
|
+
"@obrig": false,
|
242
|
+
},
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
},
|
247
|
+
},
|
248
|
+
II: {},
|
249
|
+
ICMSint: {},
|
250
|
+
IPI: {},
|
251
|
+
IPIDev: {},
|
252
|
+
ISSQN: {},
|
253
|
+
COFINS: {},
|
254
|
+
PIS: {}
|
255
|
+
};
|
256
|
+
//Configurar valores
|
257
|
+
let configStruct = async (el, struc) => {
|
258
|
+
return el;
|
259
|
+
};
|
260
|
+
imposto = configStruct(imposto, gStruct);
|
261
|
+
};
|
58
262
|
export { cUF2UF, UF2cUF };
|
package/dist/utils/make.d.ts
CHANGED
@@ -19,7 +19,8 @@ declare class Make {
|
|
19
19
|
taginfAdProd(index: any, obj: any): void;
|
20
20
|
tagCEST(obj: any): void;
|
21
21
|
tagRECOPI(obj: any): void;
|
22
|
-
|
22
|
+
tagDI(index: any, obj: any): void;
|
23
|
+
tagAdi(index: any, obj: any): void;
|
23
24
|
tagDetExport(obj: any): void;
|
24
25
|
tagDetExportInd(obj: any): void;
|
25
26
|
tagRastro(obj: any): void;
|
package/dist/utils/make.js
CHANGED
@@ -167,7 +167,9 @@ class Make {
|
|
167
167
|
throw "não implementado!";
|
168
168
|
}
|
169
169
|
taginfAdProd(index, obj) {
|
170
|
-
|
170
|
+
Object.keys(obj).forEach(key => {
|
171
|
+
__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index][key] = obj[key];
|
172
|
+
});
|
171
173
|
}
|
172
174
|
tagCEST(obj) {
|
173
175
|
throw "não implementado!";
|
@@ -175,8 +177,25 @@ class Make {
|
|
175
177
|
tagRECOPI(obj) {
|
176
178
|
throw "não implementado!";
|
177
179
|
}
|
178
|
-
|
179
|
-
|
180
|
+
tagDI(index, obj) {
|
181
|
+
if (__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI === undefined)
|
182
|
+
__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI = {};
|
183
|
+
Object.keys(obj).forEach(key => {
|
184
|
+
__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI[key] = obj[key];
|
185
|
+
});
|
186
|
+
//Adicionar ao imposto global
|
187
|
+
__classPrivateFieldGet(this, _Make_instances, "m", _Make_calICMSTot).call(this, obj);
|
188
|
+
}
|
189
|
+
tagAdi(index, obj) {
|
190
|
+
if (__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI === undefined)
|
191
|
+
__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI = {};
|
192
|
+
if (__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI.adi === undefined)
|
193
|
+
__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI.adi = {};
|
194
|
+
Object.keys(obj).forEach(key => {
|
195
|
+
__classPrivateFieldGet(this, _Make_NFe, "f").infNFe.det[index].DI.adi[key] = obj[key];
|
196
|
+
});
|
197
|
+
//Adicionar ao imposto global
|
198
|
+
__classPrivateFieldGet(this, _Make_instances, "m", _Make_calICMSTot).call(this, obj);
|
180
199
|
}
|
181
200
|
tagDetExport(obj) {
|
182
201
|
throw "não implementado!";
|
package/dist/utils/tools.d.ts
CHANGED
package/dist/utils/tools.js
CHANGED
@@ -23,7 +23,7 @@ import pem from 'pem';
|
|
23
23
|
const __filename = fileURLToPath(import.meta.url);
|
24
24
|
const __dirname = path.dirname(__filename);
|
25
25
|
class Tools {
|
26
|
-
constructor(config = { mod: "", xmllint: 'xmllint', UF: '', tpAmb: 2, CSC: "", CSCid: "", versao: "4.00" }, certificado = { pfx: "", senha: "" }) {
|
26
|
+
constructor(config = { mod: "", xmllint: 'xmllint', UF: '', tpAmb: 2, CSC: "", CSCid: "", versao: "4.00", timeout: 30 }, certificado = { pfx: "", senha: "" }) {
|
27
27
|
_Tools_instances.add(this);
|
28
28
|
_Tools_cert.set(this, void 0);
|
29
29
|
_Tools_xmlTools.set(this, {
|
@@ -36,6 +36,18 @@ class Tools {
|
|
36
36
|
ca: [] // Uma lista de certificados da cadeia (se houver), ou null
|
37
37
|
});
|
38
38
|
_Tools_config.set(this, void 0);
|
39
|
+
if (typeof config != "object")
|
40
|
+
throw "Tools({config},{}): Config deve ser um objecto!";
|
41
|
+
if (typeof config.UF == "undefined")
|
42
|
+
throw "Tools({...,UF:?},{}): UF não definida!";
|
43
|
+
if (typeof config.tpAmb == "undefined")
|
44
|
+
throw "Tools({...,tpAmb:?},{}): tpAmb não definida!";
|
45
|
+
if (typeof config.versao == "undefined")
|
46
|
+
throw "Tools({...,versao:?},{}): versao não definida!";
|
47
|
+
if (typeof config.timeout == "undefined")
|
48
|
+
config.timeout = 30;
|
49
|
+
if (typeof config.xmllint == "undefined")
|
50
|
+
config.xmllint = 'xmllint';
|
39
51
|
//Configurar certificado
|
40
52
|
__classPrivateFieldSet(this, _Tools_config, config, "f");
|
41
53
|
__classPrivateFieldSet(this, _Tools_cert, certificado, "f");
|
@@ -101,6 +113,13 @@ class Tools {
|
|
101
113
|
resvol(data);
|
102
114
|
});
|
103
115
|
});
|
116
|
+
req.setTimeout(__classPrivateFieldGet(this, _Tools_config, "f").timeout * 1000, () => {
|
117
|
+
reject({
|
118
|
+
name: 'TimeoutError',
|
119
|
+
message: 'The operation was aborted due to timeout'
|
120
|
+
});
|
121
|
+
req.destroy(); // cancela a requisição
|
122
|
+
});
|
104
123
|
req.on('error', (erro) => {
|
105
124
|
reject(erro);
|
106
125
|
});
|
@@ -242,6 +261,13 @@ class Tools {
|
|
242
261
|
res.on('data', (chunk) => data += chunk);
|
243
262
|
res.on('end', () => resolve(data));
|
244
263
|
});
|
264
|
+
req.setTimeout(__classPrivateFieldGet(this, _Tools_config, "f").timeout * 1000, () => {
|
265
|
+
reject({
|
266
|
+
name: 'TimeoutError',
|
267
|
+
message: 'The operation was aborted due to timeout'
|
268
|
+
});
|
269
|
+
req.destroy(); // cancela a requisição
|
270
|
+
});
|
245
271
|
req.on('error', (err) => reject(err));
|
246
272
|
req.write(xml);
|
247
273
|
req.end();
|
@@ -308,6 +334,13 @@ class Tools {
|
|
308
334
|
resvol(data);
|
309
335
|
});
|
310
336
|
});
|
337
|
+
req.setTimeout(__classPrivateFieldGet(this, _Tools_config, "f").timeout * 1000, () => {
|
338
|
+
reject({
|
339
|
+
name: 'TimeoutError',
|
340
|
+
message: 'The operation was aborted due to timeout'
|
341
|
+
});
|
342
|
+
req.destroy(); // cancela a requisição
|
343
|
+
});
|
311
344
|
req.on('error', (erro) => {
|
312
345
|
reject(erro);
|
313
346
|
});
|
package/docs/README.md
CHANGED
@@ -13,25 +13,36 @@ Antes de começar, verifique se seu ambiente está preparado:
|
|
13
13
|
- ✅ **xmllint / libxml**
|
14
14
|
Utilizado para validação e assinatura de XML.
|
15
15
|
📚 Guia de instalação e uso:
|
16
|
-
👉 [
|
16
|
+
👉 [Validar XML com xmllint](https://github.com/kalmonv/node-sped-nfe/blob/main/docs/requisitos.md)
|
17
17
|
|
18
18
|
---
|
19
|
+
## 📌 Considerações
|
19
20
|
|
20
|
-
|
21
|
+
O sistema atualmente segue o layout da **NF-e versão 4.00**, conforme os padrões da SEFAZ.
|
21
22
|
|
22
|
-
|
23
|
+
Está sendo desenvolvido com estrutura flexível para facilitar futuras adaptações a novas versões da NF-e.
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
🔗 **Leitura obrigatória**:
|
26
|
+
Para uma integração correta, consulte sempre o **Manual de Integração do Contribuinte**, disponível em:
|
27
|
+
[https://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=ndIjl+iEFdE=](https://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=ndIjl+iEFdE=)
|
27
28
|
|
28
|
-
|
29
|
-
Assine digitalmente o XML com seu certificado A1.
|
30
|
-
👉 [Como assinar](https://github.com/kalmonv/node-sped-nfe/blob/main/docs/assinar_xml.md)
|
29
|
+
> ⚠️ Manter-se atualizado com esse manual é essencial para garantir conformidade fiscal.
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
---
|
32
|
+
|
33
|
+
### 1. 🧾 Criar o XML da NF-e ou NFC-e
|
34
|
+
📚 Guia de instalação e uso:
|
35
|
+
[Documentação](https://github.com/kalmonv/node-sped-nfe/blob/main/docs/xml.md)
|
36
|
+
- 📂 **NF-e**: [Ver exemplo completo](https://github.com/kalmonv/node-sped-nfe/blob/main/exemplos/nfe.js)
|
37
|
+
- 📂 **NFC-e**: [Ver exemplo completo](https://github.com/kalmonv/node-sped-nfe/blob/main/exemplos/nfce.js)
|
38
|
+
|
39
|
+
---
|
40
|
+
|
41
|
+
### 2. 🧾 Consulta status da sefaz
|
42
|
+
|
43
|
+
- 📂 **NF-e/NFC-e**: [Ver exemplo completo](https://github.com/kalmonv/node-sped-nfe/blob/main/exemplos/status.js)
|
44
|
+
|
45
|
+
---
|
35
46
|
|
36
47
|
4. 📬 **Entendendo as respostas da SEFAZ**
|
37
48
|
Interprete corretamente os códigos e status da resposta da SEFAZ.
|
package/docs/Tools.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# 🧰 Instanciando a classe `Tools`
|
2
|
+
|
3
|
+
A classe `Tools` é responsável por operações centrais da NF-e/NFC-e: geração, assinatura, envio e validação de XMLs.
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
## ✨ Sintaxe
|
8
|
+
|
9
|
+
```ts
|
10
|
+
const config = {
|
11
|
+
UF: 'SP', // Obrigatorio
|
12
|
+
tpAmb: 2, //1-Produçao, 2-Homologação
|
13
|
+
versao: '4.00', //Obrigatorio
|
14
|
+
xmllint: '/usr/bin/xmllint.exe', //Optativo, caso sistema não tenha declarado nas variaveis.
|
15
|
+
mod: '55', //Obrigatorio, 65 ou 55
|
16
|
+
timeout: 60 //Optativo - Tempo limite de requisição
|
17
|
+
};
|
18
|
+
const certificado = {
|
19
|
+
pfx: fs.readFileSync('./certs/empresa.pfx'), //Obrigatorio, caminho para o arquivo .pfx
|
20
|
+
senha: 'minhasenha123' //Obrigatorio, senha do certificado digital
|
21
|
+
};
|
22
|
+
const tools = new Tools(config, certificado);
|
23
|
+
```
|
24
|
+
|
25
|
+
## 📥 Método `xml2json(xml: string): Promise<object>`
|
26
|
+
## 📥 Método `json2xml(obj: object): Promise<string>`
|
27
|
+
Converte uma string XML em um objeto JavaScript.
|
28
|
+
Converte uma string XML em um objeto JavaScript.
|
29
|
+
|
30
|
+
### Exemplo entrada ou saida:
|
31
|
+
```xml
|
32
|
+
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
|
33
|
+
<soapenv:Body>
|
34
|
+
<nfeResultMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeStatusServico4">
|
35
|
+
<retConsStatServ xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
|
36
|
+
<tpAmb>0</tpAmb>
|
37
|
+
<verAplic>1.00</verAplic>
|
38
|
+
<cStat>999</cStat>
|
39
|
+
<xMotivo>Rejeicao: Erro nao catalogado</xMotivo>
|
40
|
+
<cUF>51</cUF>
|
41
|
+
</retConsStatServ>
|
42
|
+
</nfeResultMsg>
|
43
|
+
</soapenv:Body>
|
44
|
+
</soapenv:Envelope>
|
45
|
+
```
|
46
|
+
```json
|
47
|
+
{
|
48
|
+
"soapenv:Envelope": {
|
49
|
+
"@xmlns:soapenv": "http://www.w3.org/2003/05/soap-envelope",
|
50
|
+
"soapenv:Body": {
|
51
|
+
"nfeResultMsg": {
|
52
|
+
"@xmlns": "http://www.portalfiscal.inf.br/nfe/wsdl/NFeStatusServico4",
|
53
|
+
"retConsStatServ": {
|
54
|
+
"@xmlns": "http://www.portalfiscal.inf.br/nfe",
|
55
|
+
"@versao": "4.00",
|
56
|
+
"tpAmb": 0,
|
57
|
+
"verAplic": "1.00",
|
58
|
+
"cStat": 999,
|
59
|
+
"xMotivo": "Rejeicao: Erro nao catalogado",
|
60
|
+
"cUF": 51
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
```
|
67
|
+
## 📥 Método `sefazEnviaLote(xml: string, data: any = { idLote: 1, indSinc: 0, compactar: false }): Promise<string>`
|
68
|
+
Este método é responsável por enviar um lote de NF-e ou NFC-e para a SEFAZ. Ele recebe um XML contendo a NF-e/NFC-e a ser transmitida, além de um objeto de configuração que define parâmetros adicionais para o envio.
|
69
|
+
```ts
|
70
|
+
let xml = "Conteudo da NFCe/NFe".
|
71
|
+
let data = {
|
72
|
+
idLote: 1, //Identificador de controle do envio do lote.
|
73
|
+
indSinc: 0, // 0 - Não, 1 = Sim || síncrono
|
74
|
+
compactar: false
|
75
|
+
}
|
76
|
+
tools.sefazEnviaLote(xml, data);
|
77
|
+
```
|
78
|
+
|
79
|
+
## 📥 Método `async xmlSign(xmlJSON: string, data: any = { tag: "infNFe" }): Promise<string>`
|
80
|
+
Este método é responsável por **assinar digitalmente** o XML da NF-e ou NFC-e utilizando o certificado digital A1 (formato `.pfx`). A assinatura segue o padrão exigido pela SEFAZ e é essencial para a validação do documento fiscal.
|
81
|
+
```ts
|
82
|
+
let xml = "Conteudo da NFCe/NFe".
|
83
|
+
const xmlAssinado = await tools.xmlSign(xml, {
|
84
|
+
tag: "infNFe" //Tag que vai ser usada para gerar assinatura.
|
85
|
+
});
|
86
|
+
```
|
87
|
+
|
88
|
+
## 📥 Método `getCertificado: Promise<object>`
|
89
|
+
Este método retorna, de forma assíncrona, o conteúdo do certificado digital **A1 (.pfx)** carregado na instância da classe `Tools`.
|
90
|
+
```ts
|
91
|
+
const certificado = await tools.getCertificado();
|
92
|
+
console.log(certificado) //{ca,key,cert}
|
93
|
+
```
|
94
|
+
|
95
|
+
## 📥 Método `async consultarNFe(chNFe: string): Promise<string>`
|
96
|
+
O método `consultarNFe` realiza a **consulta de uma NF-e ou NFC-e na SEFAZ** utilizando a chave de acesso completa da nota e retorna o status dela em xml.
|
97
|
+
```ts
|
98
|
+
const xmlStatus = await tools.consultarNFe("CHAVE DA NFE");
|
99
|
+
```
|
100
|
+
|
101
|
+
## 📥 Método `async sefazStatus(): Promise<string>`
|
102
|
+
O método `sefazStatus` realiza a **consulta ao servidor da SEFAZ** utilizando a UF de inicializaçao.
|
103
|
+
```ts
|
104
|
+
const xmlStatus = await tools.sefazStatus();
|
105
|
+
```
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Requisitos do Projeto
|
2
|
+
|
3
|
+
Este projeto foi desenvolvido e testado com os seguintes requisitos. Certifique-se de instalá-los corretamente para garantir o funcionamento adequado.
|
4
|
+
|
5
|
+
## 1. Node.js
|
6
|
+
|
7
|
+
- **Versão testada**: `v22.1.4`
|
8
|
+
- É altamente recomendável utilizar a mesma versão para evitar incompatibilidades.
|
9
|
+
|
10
|
+
### 1.1 Links para Download
|
11
|
+
|
12
|
+
- [Node.js para Windows](https://nodejs.org/dist/v22.1.4/node-v22.1.4-x64.msi)
|
13
|
+
- [Node.js para Linux](https://nodejs.org/dist/v22.1.4/node-v22.1.4-linux-x64.tar.xz)
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
## 2. xmllint (libxml) 2.9.3
|
18
|
+
|
19
|
+
- Utilizado para validação de arquivos XML, essencial no processo de manipulação de NF-e/NFC-e.
|
20
|
+
|
21
|
+
### 2.1 Links para Download
|
22
|
+
|
23
|
+
- [libxml2 for Windows (includes xmllint)](http://xmlsoft.org/sources/win32/)
|
24
|
+
- Para Linux, você pode instalar via terminal:
|
25
|
+
```bash
|
26
|
+
sudo apt install libxml2-utils
|
package/exemplos/status.js
CHANGED
@@ -7,6 +7,7 @@ let myTools = new Tools({ //Configuração de habiente e sistema
|
|
7
7
|
UF: 'MT',
|
8
8
|
versao: "4.00",
|
9
9
|
|
10
|
+
|
10
11
|
//Optativo: Leia sobre Requisitos.
|
11
12
|
xmllint: `../libxml2-2.9.3-win32-x86_64/bin/xmllint.exe`
|
12
13
|
}, { //Certificado digital
|
@@ -14,6 +15,8 @@ let myTools = new Tools({ //Configuração de habiente e sistema
|
|
14
15
|
senha: fs.readFileSync('../senha.txt', { encoding: "utf8" }),
|
15
16
|
});
|
16
17
|
|
17
|
-
myTools.sefazStatus().then(res=>{
|
18
|
+
myTools.sefazStatus().then(res => {
|
18
19
|
console.log(res)
|
20
|
+
}).catch(err=>{
|
21
|
+
console.log(err)
|
19
22
|
})
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "node-sped-nfe",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.9",
|
4
4
|
"author": "Kalmon V. Tavares",
|
5
5
|
"type": "module",
|
6
6
|
"main": "dist/index.js",
|
@@ -51,5 +51,6 @@
|
|
51
51
|
"repository": {
|
52
52
|
"type": "git",
|
53
53
|
"url": "https://github.com/kalmonv/node-sped-nfe.git"
|
54
|
-
}
|
54
|
+
},
|
55
|
+
"license": "MIT"
|
55
56
|
}
|
package/src/utils/extras.ts
CHANGED
@@ -56,4 +56,227 @@ const cUF2UF: any = {
|
|
56
56
|
"GO": "52",
|
57
57
|
"DF": "53"
|
58
58
|
};
|
59
|
+
|
60
|
+
//Função auxliar de imposto
|
61
|
+
const impEstrutura = (imposto: any) => {
|
62
|
+
const gStruct = { //Estrutura global
|
63
|
+
ICMS: {
|
64
|
+
ICMS_ICMSSN: {
|
65
|
+
"@label": "Tributação",
|
66
|
+
"@type": "select",
|
67
|
+
"@obrig": true,
|
68
|
+
"@values": [
|
69
|
+
{ "102": "Tributação Normal" },
|
70
|
+
{ "103": "Simples Nacional" }
|
71
|
+
],
|
72
|
+
"@next": {
|
73
|
+
CST: {
|
74
|
+
"@label": "Situação Tributaria",
|
75
|
+
"@type": "select",
|
76
|
+
"@obrig": true,
|
77
|
+
"@values": [
|
78
|
+
{ "00": "00 - Tributada integralmente" },
|
79
|
+
{ "10": "10 - Tributada com cobrança do ICMS por ST" },
|
80
|
+
{ "10v2": "10 - Tributada com cobrança do ICMS por ST(com partilha do ICMS entre UF de origem e a UF de destino ou a UFdefinida na legislação)" },
|
81
|
+
{ "20": "20 - Com redução de base de cálculo" },
|
82
|
+
{ "30": "30 - Isenta ou não tributada e com cobrança do ICMS por ST" },
|
83
|
+
{ "40": "40 - Isenta" },
|
84
|
+
{ "41": "41 - Não tributada" },
|
85
|
+
{ "41v2": "41 - Não tributada (ICMSST devido para UF de destino, nas operações interestaduais de produtos que tiveram retenção de ICMS na UF do rementente)" },
|
86
|
+
{ "50": "50 - Suspensão" },
|
87
|
+
{ "51": "51 - Diferimento" },
|
88
|
+
{ "60": "60 - Cobrado anteriormente por ST" },
|
89
|
+
{ "60v2": "60 - Cobrado anteriormente por ST" },
|
90
|
+
{ "70": "70 - Com redução de base de cálculo e cobrança do ICMS por ST" },
|
91
|
+
{ "90": "90 - Outros (Com partilha do ICMS entre a UF de origem e a UF de destino ou a UF definida na legistação)" },
|
92
|
+
{ "90v2": "90 - Outros" },
|
93
|
+
],
|
94
|
+
},
|
95
|
+
orig: {
|
96
|
+
"@label": "Origem",
|
97
|
+
"@type": "select",
|
98
|
+
"@obrig": true,
|
99
|
+
"@values": [
|
100
|
+
{ "0": "Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8" },
|
101
|
+
{ "1": "Estrangeira - Importação direta, exceto a indicada no código 6" },
|
102
|
+
{ "2": "Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7" },
|
103
|
+
{ "3": "Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% e inferior ou igual a 70%" },
|
104
|
+
{ "4": "Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam as legislações citadas nos Ajustes" },
|
105
|
+
{ "5": "Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% " },
|
106
|
+
{ "6": "Estrangeira - Importação direta, sem similar nacional, constante em lista da CAMEX e gás natural" },
|
107
|
+
{ "7": "Estrangeira - Adquirida no mercado interno, sem similar nacional, constante lista CAMEX e gás natural" }
|
108
|
+
],
|
109
|
+
},
|
110
|
+
"@next": {
|
111
|
+
"@CST_00": {
|
112
|
+
modBC: {
|
113
|
+
"@label": "Modalidade de determinação da base de calculo ICMS",
|
114
|
+
"@type": "select",
|
115
|
+
"@obrig": true,
|
116
|
+
"@values": [
|
117
|
+
{ "0": "0-Margem Valor Agregado (%)" },
|
118
|
+
{ "1": "1-Pauta (Valor)" },
|
119
|
+
{ "2": "2-Preço Tabelado Máx" },
|
120
|
+
{ "3": "3-Valor da operação" }
|
121
|
+
],
|
122
|
+
},
|
123
|
+
vBC: {
|
124
|
+
"@label": "Base de calculo ICMS",
|
125
|
+
"@type": "input",
|
126
|
+
"@obrig": true,
|
127
|
+
},
|
128
|
+
pICMS: {
|
129
|
+
"@label": "Líquota do ICMS",
|
130
|
+
"@type": "input",
|
131
|
+
"@obrig": true,
|
132
|
+
},
|
133
|
+
vICMS: {
|
134
|
+
"@label": "Valor ICMS",
|
135
|
+
"@type": "input",
|
136
|
+
"@obrig": true,
|
137
|
+
},
|
138
|
+
pFCP: {
|
139
|
+
"@label": "% Relativo ao FCP ST",
|
140
|
+
"@type": "input",
|
141
|
+
"@obrig": false,
|
142
|
+
},
|
143
|
+
vFCP: {
|
144
|
+
"@label": "Valor ICMS FCP ST",
|
145
|
+
"@type": "input",
|
146
|
+
"@obrig": false,
|
147
|
+
}
|
148
|
+
},
|
149
|
+
"@CST_10": {
|
150
|
+
modBC: {
|
151
|
+
"@label": "Modalidade de determinação da base de calculo ICMS",
|
152
|
+
"@type": "select",
|
153
|
+
"@obrig": true,
|
154
|
+
"@values": [
|
155
|
+
{ "0": "0-Margem Valor Agregado (%)" },
|
156
|
+
{ "1": "1-Pauta (Valor)" },
|
157
|
+
{ "2": "2-Preço Tabelado Máx" },
|
158
|
+
{ "3": "3-Valor da operação" }
|
159
|
+
],
|
160
|
+
},
|
161
|
+
vBC: {
|
162
|
+
"@label": "Base de calculo ICMS",
|
163
|
+
"@type": "input",
|
164
|
+
"@obrig": true,
|
165
|
+
},
|
166
|
+
pICMS: {
|
167
|
+
"@label": "Líquota do ICMS",
|
168
|
+
"@type": "input",
|
169
|
+
"@obrig": true,
|
170
|
+
},
|
171
|
+
vICMS: {
|
172
|
+
"@label": "Valor ICMS",
|
173
|
+
"@type": "input",
|
174
|
+
"@obrig": true,
|
175
|
+
},
|
176
|
+
modBCST: {
|
177
|
+
"@label": "Modalidade de determinação da BC do ICMS ST",
|
178
|
+
"@type": "select",
|
179
|
+
"@obrig": true,
|
180
|
+
"@values": [
|
181
|
+
{ "0": "Preço tabelado ou máximo sugerido" },
|
182
|
+
{ "1": "Lista Negativa (valor)" },
|
183
|
+
{ "2": "Lista Positiva (valor)" },
|
184
|
+
{ "3": "Lista Neutra (valor)" },
|
185
|
+
{ "4": "Margem Valor Agregado (%)" },
|
186
|
+
{ "5": "Pauta (valor)" },
|
187
|
+
{ "6": "Valor da Operação (NT 2019.001)" }
|
188
|
+
],
|
189
|
+
},
|
190
|
+
pMVAST: {
|
191
|
+
"@label": "% Margem de valor adic. ICMS ST",
|
192
|
+
"@type": "input",
|
193
|
+
"@obrig": true,
|
194
|
+
},
|
195
|
+
pRedBCST: {
|
196
|
+
"@label": "% Redução de BC ICMS ST",
|
197
|
+
"@type": "input",
|
198
|
+
"@obrig": true,
|
199
|
+
},
|
200
|
+
vBCST: {
|
201
|
+
"@label": "BC ICMS ST",
|
202
|
+
"@type": "input",
|
203
|
+
"@obrig": true,
|
204
|
+
},
|
205
|
+
pICMSST: {
|
206
|
+
"@label": "Alíquota de ICMS ST",
|
207
|
+
"@type": "input",
|
208
|
+
"@obrig": true,
|
209
|
+
},
|
210
|
+
vICMSST: {
|
211
|
+
"@label": "ICMS ST",
|
212
|
+
"@type": "input",
|
213
|
+
"@obrig": true,
|
214
|
+
},
|
215
|
+
vBCFCPST: {
|
216
|
+
"@label": "BC ICMS FCP ST",
|
217
|
+
"@type": "input",
|
218
|
+
"@obrig": true,
|
219
|
+
},
|
220
|
+
pFCPST: {
|
221
|
+
"@label": "% Relativo ao FCP ST",
|
222
|
+
"@type": "input",
|
223
|
+
"@obrig": true,
|
224
|
+
},
|
225
|
+
vFCPST: {
|
226
|
+
"@label": "Valor ICMS FCP ST",
|
227
|
+
"@type": "input",
|
228
|
+
"@obrig": true,
|
229
|
+
},
|
230
|
+
|
231
|
+
vBCFCP: {
|
232
|
+
"@label": "BC ICMS FCP",
|
233
|
+
"@type": "input",
|
234
|
+
"@obrig": false,
|
235
|
+
},
|
236
|
+
pFCP: {
|
237
|
+
"@label": "% Relativo ao FCP",
|
238
|
+
"@type": "input",
|
239
|
+
"@obrig": false,
|
240
|
+
},
|
241
|
+
vFCP: {
|
242
|
+
"@label": "Valor ICMS FCP",
|
243
|
+
"@type": "input",
|
244
|
+
"@obrig": false,
|
245
|
+
},
|
246
|
+
}
|
247
|
+
}
|
248
|
+
}
|
249
|
+
},
|
250
|
+
},
|
251
|
+
II: {
|
252
|
+
|
253
|
+
},
|
254
|
+
ICMSint: {
|
255
|
+
|
256
|
+
},
|
257
|
+
IPI: {
|
258
|
+
|
259
|
+
},
|
260
|
+
IPIDev: {
|
261
|
+
|
262
|
+
},
|
263
|
+
ISSQN: {
|
264
|
+
|
265
|
+
},
|
266
|
+
COFINS: {
|
267
|
+
|
268
|
+
},
|
269
|
+
PIS: {
|
270
|
+
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
274
|
+
//Configurar valores
|
275
|
+
let configStruct = async (el: any, struc: any) => {
|
276
|
+
|
277
|
+
return el;
|
278
|
+
};
|
279
|
+
|
280
|
+
imposto = configStruct(imposto, gStruct)
|
281
|
+
}
|
59
282
|
export { cUF2UF, UF2cUF }
|
package/src/utils/tools.ts
CHANGED
@@ -43,9 +43,18 @@ class Tools {
|
|
43
43
|
CSC: string;
|
44
44
|
CSCid: string;
|
45
45
|
versao: string;
|
46
|
+
timeout: number;
|
46
47
|
};
|
47
48
|
|
48
|
-
constructor(config = { mod: "", xmllint: 'xmllint', UF: '', tpAmb: 2, CSC: "", CSCid: "", versao: "4.00" }, certificado = { pfx: "", senha: "" }) {
|
49
|
+
constructor(config = { mod: "", xmllint: 'xmllint', UF: '', tpAmb: 2, CSC: "", CSCid: "", versao: "4.00", timeout: 30 }, certificado = { pfx: "", senha: "" }) {
|
50
|
+
if (typeof config != "object") throw "Tools({config},{}): Config deve ser um objecto!";
|
51
|
+
if (typeof config.UF == "undefined") throw "Tools({...,UF:?},{}): UF não definida!";
|
52
|
+
if (typeof config.tpAmb == "undefined") throw "Tools({...,tpAmb:?},{}): tpAmb não definida!";
|
53
|
+
if (typeof config.versao == "undefined") throw "Tools({...,versao:?},{}): versao não definida!";
|
54
|
+
|
55
|
+
if (typeof config.timeout == "undefined") config.timeout = 30;
|
56
|
+
if (typeof config.xmllint == "undefined") config.xmllint = 'xmllint';
|
57
|
+
|
49
58
|
//Configurar certificado
|
50
59
|
this.#config = config;
|
51
60
|
this.#cert = certificado;
|
@@ -113,6 +122,13 @@ class Tools {
|
|
113
122
|
});
|
114
123
|
});
|
115
124
|
|
125
|
+
req.setTimeout(this.#config.timeout * 1000, () => {
|
126
|
+
reject({
|
127
|
+
name: 'TimeoutError',
|
128
|
+
message: 'The operation was aborted due to timeout'
|
129
|
+
});
|
130
|
+
req.destroy(); // cancela a requisição
|
131
|
+
});
|
116
132
|
req.on('error', (erro) => {
|
117
133
|
reject(erro);
|
118
134
|
});
|
@@ -285,8 +301,14 @@ class Tools {
|
|
285
301
|
res.on('end', () => resolve(data));
|
286
302
|
});
|
287
303
|
|
304
|
+
req.setTimeout(this.#config.timeout * 1000, () => {
|
305
|
+
reject({
|
306
|
+
name: 'TimeoutError',
|
307
|
+
message: 'The operation was aborted due to timeout'
|
308
|
+
});
|
309
|
+
req.destroy(); // cancela a requisição
|
310
|
+
});
|
288
311
|
req.on('error', (err) => reject(err));
|
289
|
-
|
290
312
|
req.write(xml);
|
291
313
|
req.end();
|
292
314
|
} catch (err) {
|
@@ -358,6 +380,13 @@ class Tools {
|
|
358
380
|
});
|
359
381
|
});
|
360
382
|
|
383
|
+
req.setTimeout(this.#config.timeout * 1000, () => {
|
384
|
+
reject({
|
385
|
+
name: 'TimeoutError',
|
386
|
+
message: 'The operation was aborted due to timeout'
|
387
|
+
});
|
388
|
+
req.destroy(); // cancela a requisição
|
389
|
+
});
|
361
390
|
req.on('error', (erro) => {
|
362
391
|
reject(erro);
|
363
392
|
});
|