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
package/README.md
CHANGED
|
@@ -1,413 +1,491 @@
|
|
|
1
|
-
# GHINFE
|
|
2
|
-
|
|
3
|
-
Biblioteca Node.js para emissão de documentos fiscais eletrônicos brasileiros: **NF-e**, **NFC-e** e **
|
|
4
|
-
|
|
5
|
-
Inspirada na filosofia do [ACBr](https://projetoacbr.com.br/) (objeto de domínio → XML → assinatura → envio SEFAZ), a GHINFE separa responsabilidades em serviços modulares, prontos para integração com **Sequelize**, filas **Bull/Redis** e ambientes de alta escala.
|
|
6
|
-
|
|
7
|
-
## Funcionalidades (v0.6)
|
|
8
|
-
|
|
9
|
-
| Módulo | Status |
|
|
10
|
-
|--------|--------|
|
|
11
|
-
| Geração XML NF-e / NFC-e / NFS-e | ✅ |
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
├──
|
|
26
|
-
│
|
|
27
|
-
|
|
28
|
-
├──
|
|
29
|
-
│
|
|
30
|
-
|
|
31
|
-
│ ├──
|
|
32
|
-
│ │ └──
|
|
33
|
-
│ ├──
|
|
34
|
-
│ │
|
|
35
|
-
│
|
|
36
|
-
│ ├──
|
|
37
|
-
│ │
|
|
38
|
-
│
|
|
39
|
-
│ │
|
|
40
|
-
│ │ ├──
|
|
41
|
-
│ │ │ └──
|
|
42
|
-
│ │ ├──
|
|
43
|
-
│ │ │
|
|
44
|
-
│ │
|
|
45
|
-
│ │ │ ├──
|
|
46
|
-
│ │ │ ├──
|
|
47
|
-
│ │ │
|
|
48
|
-
│ │
|
|
49
|
-
│ │
|
|
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
|
-
npm
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
1
|
+
# GHINFE
|
|
2
|
+
|
|
3
|
+
Biblioteca Node.js para emissão de documentos fiscais eletrônicos brasileiros: **NF-e**, **NFC-e**, **NFS-e** e **DC-e**.
|
|
4
|
+
|
|
5
|
+
Inspirada na filosofia do [ACBr](https://projetoacbr.com.br/) (objeto de domínio → XML → assinatura → envio SEFAZ), a GHINFE separa responsabilidades em serviços modulares, prontos para integração com **Sequelize**, filas **Bull/Redis** e ambientes de alta escala.
|
|
6
|
+
|
|
7
|
+
## Funcionalidades (v0.6)
|
|
8
|
+
|
|
9
|
+
| Módulo | Status |
|
|
10
|
+
|--------|--------|
|
|
11
|
+
| Geração XML NF-e / NFC-e / NFS-e | ✅ |
|
|
12
|
+
| DC-e (modelo 99): geração, autorização, consulta, status e cancelamento | ✅ |
|
|
13
|
+
| DACE completa e resumida (HTML imprimível, CODE-128C + QR Code) | ✅ |
|
|
14
|
+
| IBS/CBS injetado no XML NF-e (item + totais) | ✅ experimental |
|
|
15
|
+
| Cancelamento e substituição NFS-e | ✅ |
|
|
16
|
+
| DANFE / DANFCE (HTML imprimível) | ✅ |
|
|
17
|
+
| Assinatura A1, XSD, multi-UF, filas Bull | ✅ |
|
|
18
|
+
| Injeção completa conforme XSD PL_010 estável | 🔜 |
|
|
19
|
+
|
|
20
|
+
## Estrutura de pastas
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
ghinfe/
|
|
24
|
+
├── docs/
|
|
25
|
+
│ ├── openapi.yaml # Especificação Swagger/OpenAPI
|
|
26
|
+
│ └── developer-guide.html # Guia completo para desenvolvedores
|
|
27
|
+
├── examples/
|
|
28
|
+
│ ├── emitir-nfe.js # Exemplo de geração + mock
|
|
29
|
+
│ └── mock-sefaz.js # Cenários de retorno SEFAZ
|
|
30
|
+
├── src/
|
|
31
|
+
│ ├── api/
|
|
32
|
+
│ │ └── server.js # Servidor Express + Swagger UI
|
|
33
|
+
│ ├── constants/
|
|
34
|
+
│ │ └── sefaz.js # UF, cStat, URLs, versão layout
|
|
35
|
+
│ ├── errors/
|
|
36
|
+
│ │ ├── GhinfeError.js
|
|
37
|
+
│ │ └── SefazError.js # Erros reais da SEFAZ (cStat)
|
|
38
|
+
│ ├── nfe/
|
|
39
|
+
│ │ ├── builders/
|
|
40
|
+
│ │ │ ├── NFeXmlBuilder.js
|
|
41
|
+
│ │ │ └── NFeEventoXmlBuilder.js # Cancelamento, CC-e
|
|
42
|
+
│ │ ├── mocks/
|
|
43
|
+
│ │ │ └── sefaz-responses.js
|
|
44
|
+
│ │ ├── services/
|
|
45
|
+
│ │ │ ├── NFeXmlService.js
|
|
46
|
+
│ │ │ ├── NFeSignService.js
|
|
47
|
+
│ │ │ ├── NFeSoapService.js
|
|
48
|
+
│ │ │ ├── NFeEventoService.js # Eventos SEFAZ
|
|
49
|
+
│ │ │ └── NFeService.js
|
|
50
|
+
│ │ └── types/
|
|
51
|
+
│ │ ├── NFeDocument.js
|
|
52
|
+
│ │ └── NFeEvento.js
|
|
53
|
+
│ ├── sefaz/
|
|
54
|
+
│ │ ├── endpoints.registry.js # URLs por autorizador (SVRS, SP, MG...)
|
|
55
|
+
│ │ └── SefazEndpointResolver.js
|
|
56
|
+
│ ├── nfse/
|
|
57
|
+
│ │ ├── builders/NFSeXmlBuilder.js
|
|
58
|
+
│ │ ├── services/ # NFSeService, NFSeSoapService
|
|
59
|
+
│ │ └── NFSeMunicipioResolver.js
|
|
60
|
+
│ ├── queue/
|
|
61
|
+
│ │ ├── NFeQueue.js
|
|
62
|
+
│ │ ├── NFCeQueue.js
|
|
63
|
+
│ │ └── NFSeQueue.js
|
|
64
|
+
│ ├── utils/
|
|
65
|
+
│ │ ├── certificate.utils.js
|
|
66
|
+
│ │ ├── chave.utils.js # Chave de acesso + DV
|
|
67
|
+
│ │ ├── date.utils.js
|
|
68
|
+
│ │ └── xml.utils.js
|
|
69
|
+
│ └── index.js # Exports públicos
|
|
70
|
+
├── .env.example
|
|
71
|
+
└── package.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Instalação
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install
|
|
78
|
+
cp .env.example .env
|
|
79
|
+
npm run schemas:download # baixa XSDs se necessário (já inclusos em schemas/)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Uso rápido
|
|
83
|
+
|
|
84
|
+
### 1. Montar o objeto e gerar XML (chave automática)
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
import { NFeService } from 'ghinfe';
|
|
88
|
+
|
|
89
|
+
const service = new NFeService();
|
|
90
|
+
|
|
91
|
+
const documento = {
|
|
92
|
+
// chaveAcesso é opcional — gerada automaticamente
|
|
93
|
+
ambiente: 2,
|
|
94
|
+
ide: { uf: 'SP', codigoMunicipio: '3550308', serie: 1, numero: 1 },
|
|
95
|
+
emitente: { cnpj: '12345678000199', /* ... */ },
|
|
96
|
+
destinatario: { /* ... */ },
|
|
97
|
+
itens: [{ /* ... */ }],
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const xml = service.gerarXml(documento);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 1b. Gerar chave de acesso manualmente
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
import { gerarChaveAcesso, validarChaveAcesso } from 'ghinfe';
|
|
107
|
+
|
|
108
|
+
const chave = gerarChaveAcesso({
|
|
109
|
+
uf: 'SP',
|
|
110
|
+
cnpj: '12345678000199',
|
|
111
|
+
serie: 1,
|
|
112
|
+
numero: 42,
|
|
113
|
+
});
|
|
114
|
+
console.log(validarChaveAcesso(chave)); // true
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Endpoints SEFAZ automáticos (multi-UF)
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
import { SefazEndpointResolver, NFeService } from 'ghinfe';
|
|
121
|
+
|
|
122
|
+
// Por UF — resolve autorizador (SVRS, SP, MG...) automaticamente
|
|
123
|
+
const urls = SefazEndpointResolver.paraNFe('RJ', 2); // homologação
|
|
124
|
+
console.log(urls.endpoint);
|
|
125
|
+
|
|
126
|
+
// No serviço — basta informar UF
|
|
127
|
+
const service = new NFeService({ mock: false, uf: 'SP', ambiente: 2 });
|
|
128
|
+
|
|
129
|
+
// Ou configurar em runtime a partir do documento
|
|
130
|
+
service.configurarUf('MG', 2);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### NFS-e (layouts municipais)
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
import { NFSeService, NFSE_LAYOUTS, NFSeMunicipioResolver } from 'ghinfe';
|
|
137
|
+
|
|
138
|
+
// Layout explícito ou automático pelo município
|
|
139
|
+
const service = new NFSeService({ mock: true, layout: NFSE_LAYOUTS.GINFES });
|
|
140
|
+
const xml = service.gerarXml(documento);
|
|
141
|
+
|
|
142
|
+
// Assinatura A1 do RPS
|
|
143
|
+
const xmlAssinado = service.gerarXmlAssinado(documento, { pfx, senha });
|
|
144
|
+
|
|
145
|
+
// Emissão com assinatura opcional
|
|
146
|
+
const resultado = await service.emitir(documento, { pfx, senha });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Layouts: `abrasf`, `ginfes`, `betha`, `issnet` — municípios pré-cadastrados em SP, RJ, BH, Curitiba, POA, Floripa, Salvador, Recife, Fortaleza.
|
|
150
|
+
|
|
151
|
+
### Consulta status SEFAZ
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
const service = new NFeService({ mock: true });
|
|
155
|
+
const status = await service.consultarStatus('SP', 2);
|
|
156
|
+
// { emOperacao: true, cStat: '107', xMotivo: 'Serviço em Operação', tMed: '1' }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Reforma tributária (IBS/CBS no XML)
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
import { NFeService, calcularIBSCBS } from 'ghinfe';
|
|
163
|
+
|
|
164
|
+
const item = {
|
|
165
|
+
codigo: '001', descricao: '...', ncm: '...', cfop: '5102',
|
|
166
|
+
unidade: 'UN', quantidade: 1, valorUnitario: 100, valorTotal: 100,
|
|
167
|
+
reforma: calcularIBSCBS(100, { pIBSUF: 0.1, pIBSMun: 0.05, pCBS: 0.9 }),
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const xml = service.gerarXml({ ...documento, itens: [item] });
|
|
171
|
+
// XML contém <IBSCBS> no item e <IBSCBSTot> nos totais
|
|
172
|
+
// Não use validarXsd:true com reforma até o schema PL_010 estar embutido
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Cancelamento / substituição NFS-e
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
await service.cancelar({
|
|
179
|
+
numeroNfse: '2026000001',
|
|
180
|
+
cnpjPrestador: '...',
|
|
181
|
+
inscricaoMunicipal: '...',
|
|
182
|
+
codigoMunicipio: '3550308',
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
await service.substituir({
|
|
186
|
+
numeroNfseSubstituida: '2026000001',
|
|
187
|
+
cnpjPrestador: '...',
|
|
188
|
+
inscricaoMunicipal: '...',
|
|
189
|
+
codigoMunicipio: '3550308',
|
|
190
|
+
documentoSubstituto: { /* novo RPS */ },
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### DANFE / DANFCE
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
import { DanfeService } from 'ghinfe';
|
|
198
|
+
|
|
199
|
+
const danfe = new DanfeService();
|
|
200
|
+
const { html } = await danfe.gerarDanfe(xmlNfe, { protocolo: '...' });
|
|
201
|
+
const { html: cupom } = await danfe.gerarDanfce(xmlNfce, { qrCodeUrl: '...' });
|
|
202
|
+
// Salve o HTML e imprima / “Salvar como PDF” no navegador
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Consulta status SEFAZ
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
import { NFeService, XsdValidationError } from 'ghinfe';
|
|
209
|
+
|
|
210
|
+
const service = new NFeService({ validarXsd: true });
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
service.validarXsd(xml, { preAssinatura: true });
|
|
214
|
+
} catch (error) {
|
|
215
|
+
if (error instanceof XsdValidationError) console.error(error.erros);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Schemas oficiais em `schemas/nfe/PL_009_V4/`.
|
|
220
|
+
|
|
221
|
+
### NFC-e (modelo 65)
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
import { NFCeService } from 'ghinfe';
|
|
225
|
+
|
|
226
|
+
const service = new NFCeService({ mock: true });
|
|
227
|
+
|
|
228
|
+
const documento = {
|
|
229
|
+
ambiente: 2,
|
|
230
|
+
ide: { uf: 'SP', codigoMunicipio: '3550308', serie: 1, numero: 1 },
|
|
231
|
+
emitente: { cnpj: '...', razaoSocial: '...', ie: '...', crt: '1', endereco: { /* ... */ } },
|
|
232
|
+
itens: [{ codigo: '001', descricao: '...', ncm: '...', cfop: '5102', unidade: 'UN', quantidade: 1, valorUnitario: 10, valorTotal: 10 }],
|
|
233
|
+
csc: { idCSC: '000001', codigo: 'SEU-CSC-SEFAZ' },
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const xml = service.gerarXml(documento);
|
|
237
|
+
// QR Code v3 é adicionado após assinatura:
|
|
238
|
+
const { xml: xmlCompleto, qrCode } = service.gerarXmlAssinado(documento, { pfx, senha });
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### DC-e — Declaração de Conteúdo eletrônica (modelo 99)
|
|
242
|
+
|
|
243
|
+
Para remessa de bens por pessoas físicas ou não contribuintes do ICMS. Layout 1.00 (PL_DCe_v1.00a + NT 2024.001), validado contra o XSD oficial em `schemas/dce/`.
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
import { DCeService, DCE_TIPO_EMITENTE, DCE_MODALIDADE_TRANSPORTE } from 'ghinfe';
|
|
247
|
+
|
|
248
|
+
const service = new DCeService();
|
|
249
|
+
|
|
250
|
+
const documento = {
|
|
251
|
+
ambiente: 2,
|
|
252
|
+
ide: { uf: 'SP', serie: 1, numero: 42, tipoEmitente: DCE_TIPO_EMITENTE.MARKETPLACE },
|
|
253
|
+
emitente: { cpf: '...', razaoSocial: '...', endereco: { /* ... */ } },
|
|
254
|
+
marketplace: { cnpj: '...', razaoSocial: '...', site: 'www.exemplo.com.br' },
|
|
255
|
+
destinatario: { cpf: '...', razaoSocial: '...', endereco: { /* ... */ } },
|
|
256
|
+
itens: [{ descricao: 'LIVRO USADO', ncm: '49019900', quantidade: 2, valorUnitario: 35.5 }],
|
|
257
|
+
transporte: { modalidade: DCE_MODALIDADE_TRANSPORTE.CORREIOS },
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const xml = service.gerarXml(documento, { validarXsd: true });
|
|
261
|
+
const { xml: xmlAssinado, chaveAcesso, qrCode } = service.gerarXmlAssinado(documento, { pfx, senha });
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
- `tipoEmitente` define o grupo obrigatório: `fisco` (0), `marketplace` (1), nenhum na emissão própria (2), `transportadora` (3) ou `ect` (4). O CNPJ desse emissor compõe a chave de acesso.
|
|
265
|
+
- Em homologação, `dest/xNome` recebe automaticamente o literal exigido pela SEFAZ.
|
|
266
|
+
- Contingência off-line (`ide.tipoEmissao: 2`): o QR Code leva o parâmetro `sign`, por isso use `gerarXmlAssinado`.
|
|
267
|
+
|
|
268
|
+
#### Comunicação com a SEFAZ (autorizador SEFA-PR, atende todas as UFs)
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
const service = new DCeService({ certificado: { pfx, senha }, ambiente: 2 });
|
|
272
|
+
|
|
273
|
+
await service.consultarStatus(); // { emOperacao: true, cStat: '107', ... }
|
|
274
|
+
|
|
275
|
+
const resultado = await service.emitir(documento); // lança SefazError se rejeitada
|
|
276
|
+
resultado.retorno.protocolo; // nProt
|
|
277
|
+
resultado.retorno.xmlProc; // dceProc (DC-e + protDCe) — guarde este XML
|
|
278
|
+
|
|
279
|
+
await service.consultar(resultado.chaveAcesso); // cStat 100 (autorizada) / 101 (cancelada)
|
|
280
|
+
|
|
281
|
+
await service.cancelar({ // até 24h após a autorização
|
|
282
|
+
chaveAcesso: resultado.chaveAcesso,
|
|
283
|
+
protocolo: resultado.retorno.protocolo,
|
|
284
|
+
justificativa: 'Motivo com no minimo 15 caracteres',
|
|
285
|
+
emitente: { cpf: '...' }, // mesmo usuário emitente da DC-e
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
- TLS mútuo com o certificado A1; a raiz ICP-Brasil v10 (`src/sefaz/ca/`) é adicionada às CAs do Node, sem desligar a verificação do servidor.
|
|
290
|
+
- `emitir(documento, { compactar: true })` usa `dceAutorizacaoZip` (GZip + Base64).
|
|
291
|
+
- Emissão própria (`tipoEmitente: 2`) só é aceita para não contribuintes do ICMS; contribuintes recebem a rejeição 812.
|
|
292
|
+
- Certificado em PEM (`cert.pem` + `key.pem`): `criarPfxDePem(certPem, keyPem, senha)` gera o PFX em memória.
|
|
293
|
+
- Testes em homologação: `npm run example:dce-homologacao -- status` (veja as variáveis no topo de `examples/dce-homologacao.js`).
|
|
294
|
+
|
|
295
|
+
#### DACE — Declaração Auxiliar de Conteúdo eletrônica
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
import { DaceService } from 'ghinfe';
|
|
299
|
+
|
|
300
|
+
const dace = new DaceService();
|
|
301
|
+
const { html, folhas } = await dace.gerar(xmlDceProc); // completa (A4, com itens)
|
|
302
|
+
const { html: etiqueta } = await dace.gerar(xmlDceProc, { modelo: 'resumida' }); // sem itens, 10×15 cm
|
|
303
|
+
|
|
304
|
+
// ou direto do resultado da emissão
|
|
305
|
+
const { html: dace2 } = await service.gerarDace(resultado);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
- Segue o Manual DC-e — Anexo II: chave em blocos de 4 dígitos, código de barras CODE-128C (SVG, sem dependência) e QR Code do `infDCeSupl`.
|
|
309
|
+
- Folhas adicionais repetem cabeçalho, código de barras, chave e remetente; ajuste com `itensPrimeiraFolha` / `itensDemaisFolhas`.
|
|
310
|
+
- Homologação: "EMITIDA EM HOMOLOGAÇÃO" em marca d'água e nas informações complementares. Contingência: "EMITIDA EM CONTINGÊNCIA" no protocolo.
|
|
311
|
+
- CPF mascarado por padrão (`123.***.***-09`, recomendação LGPD da NT 2024.001); use `mascararCpf: false` para exibir completo.
|
|
312
|
+
- Exige o protocolo de autorização (use o `dceProc`), exceto em contingência.
|
|
313
|
+
|
|
314
|
+
### 2. Assinar com certificado A1
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
import fs from 'fs';
|
|
318
|
+
|
|
319
|
+
const pfx = fs.readFileSync('./certs/certificado.pfx');
|
|
320
|
+
const xmlAssinado = service.gerarXmlAssinado(documento, {
|
|
321
|
+
pfx,
|
|
322
|
+
senha: process.env.PFX_PASSWORD,
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### 3. Enviar para SEFAZ (mock em desenvolvimento)
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
const service = new NFeService({ mock: true });
|
|
330
|
+
|
|
331
|
+
const resultado = await service.emitir(documento, { pfx, senha: '...' });
|
|
332
|
+
|
|
333
|
+
if (resultado.retorno.autorizado) {
|
|
334
|
+
console.log('Protocolo:', resultado.retorno.protocolo);
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### 4. Persistir no banco (Sequelize)
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
const payload = service.toPersistencePayload(resultado);
|
|
342
|
+
|
|
343
|
+
await NotaFiscal.create({
|
|
344
|
+
chave_acesso: payload.chave_acesso,
|
|
345
|
+
xml_nfe: payload.xml_nfe,
|
|
346
|
+
xml_protocolo: payload.xml_protocolo,
|
|
347
|
+
protocolo: payload.protocolo,
|
|
348
|
+
status: payload.status,
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### 5. Cancelar NF-e
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
const resultado = await service.cancelar({
|
|
356
|
+
chaveAcesso: '35260712345678000199550010000000011000000011',
|
|
357
|
+
cnpj: '12345678000199',
|
|
358
|
+
uf: 'SP',
|
|
359
|
+
protocolo: '135260000000001',
|
|
360
|
+
justificativa: 'Cancelamento por erro de digitacao no pedido',
|
|
361
|
+
}, { pfx, senha });
|
|
362
|
+
|
|
363
|
+
console.log(resultado.retorno.cStat); // '135' — evento registrado
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 6. Carta de Correção (CC-e)
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
const resultado = await service.cartaCorrecao({
|
|
370
|
+
chaveAcesso: '...',
|
|
371
|
+
cnpj: '12345678000199',
|
|
372
|
+
uf: 'SP',
|
|
373
|
+
sequencia: 1,
|
|
374
|
+
correcao: 'Correcao do endereco de entrega: Rua Nova, 500',
|
|
375
|
+
}, { pfx, senha });
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### 7. Fila assíncrona (Bull + Redis)
|
|
379
|
+
|
|
380
|
+
```javascript
|
|
381
|
+
import { NFeQueue } from 'ghinfe';
|
|
382
|
+
|
|
383
|
+
const queue = new NFeQueue({
|
|
384
|
+
redis: { host: '127.0.0.1', port: 6379 },
|
|
385
|
+
nfeOptions: { mock: true },
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
await queue.adicionarEmissao({ documento, certificado: { pfx, senha } });
|
|
389
|
+
|
|
390
|
+
queue.onCompleted(async (resultado) => {
|
|
391
|
+
await NotaFiscal.create(service.toPersistencePayload(resultado));
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Tratamento de erros SEFAZ
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
import { SefazError } from 'ghinfe';
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
await service.enviar(xmlAssinado, chaveAcesso);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
if (error instanceof SefazError) {
|
|
404
|
+
console.error(`Rejeição ${error.cStat}: ${error.xMotivo}`);
|
|
405
|
+
// 204 = duplicidade, 225 = schema, 280 = certificado...
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## API de testes (Swagger)
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
npm start
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
| URL | Descrição |
|
|
417
|
+
|-----|-----------|
|
|
418
|
+
| http://localhost:3333/docs | Swagger UI interativo |
|
|
419
|
+
| http://localhost:3333/guia/developer-guide.html | Guia HTML do desenvolvedor |
|
|
420
|
+
| http://localhost:3333/health | Health check |
|
|
421
|
+
|
|
422
|
+
### Endpoints
|
|
423
|
+
|
|
424
|
+
- `GET /sefaz/endpoints/:uf?ambiente=2` — URLs SEFAZ por UF
|
|
425
|
+
- `GET /sefaz/ufs` — Lista UFs suportadas
|
|
426
|
+
- `POST /nfse/cancelar-mock` — Cancela NFS-e (mock)
|
|
427
|
+
- `POST /nfse/substituir-mock` — Substitui NFS-e (mock)
|
|
428
|
+
- `POST /danfe` — Gera DANFE/DANFCE (JSON ou `?format=html`)
|
|
429
|
+
- `GET /sefaz/status/:uf?cenario=ok` — Consulta status SEFAZ (mock)
|
|
430
|
+
- `GET /nfse/layouts` — Layouts NFS-e suportados
|
|
431
|
+
- `POST /reforma/calcular` — Calcula IBS/CBS + fragmento XML
|
|
432
|
+
- `POST /nfse/xml?layout=ginfes` — Gera XML RPS NFS-e
|
|
433
|
+
- `POST /nfse/enviar-mock` — Emite NFS-e mock
|
|
434
|
+
- `GET /nfse/municipios` — Municípios configurados
|
|
435
|
+
- `POST /nfe/xml?validarXsd=true` — Gera XML com validação XSD
|
|
436
|
+
- `POST /nfe/validar-xsd` — Valida XML existente
|
|
437
|
+
- `POST /nfce/xml` — Gera XML NFC-e (modelo 65)
|
|
438
|
+
- `POST /nfce/enviar-mock` — Envia NFC-e mock
|
|
439
|
+
- `POST /nfe/xml` — Gera XML a partir do JSON
|
|
440
|
+
- `POST /nfe/enviar-mock?cenario=autorizado` — Fluxo completo mock
|
|
441
|
+
- `POST /nfe/cancelar-mock` — Cancelamento simulado
|
|
442
|
+
- `POST /nfe/cce-mock` — Carta de correção simulada
|
|
443
|
+
- `GET /nfe/cenarios-mock` — Lista cenários de teste
|
|
444
|
+
|
|
445
|
+
## Exemplos CLI
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
npm run example:nfe # Gera XML e simula retorno
|
|
449
|
+
npm run example:mock # Testa cenários SEFAZ mock
|
|
450
|
+
npm run example:endpoints # Endpoints SEFAZ por UF
|
|
451
|
+
npm run example:reforma-xml # NF-e com IBSCBS no XML
|
|
452
|
+
npm run example:nfse-eventos # Cancelamento / substituição NFS-e
|
|
453
|
+
npm run example:danfe # Gera HTML em tmp/
|
|
454
|
+
npm run example:dce # Gera DC-e (modelo 99) e valida XSD
|
|
455
|
+
npm run example:dce-homologacao -- status # DC-e real em homologação (requer certificado)
|
|
456
|
+
npm run example:dace # Gera DACE completa e resumida em tmp/
|
|
457
|
+
npm run example:status # Status SEFAZ mock
|
|
458
|
+
npm run example:layouts # ABRASF / GINFES / Betha / ISSNet
|
|
459
|
+
npm run example:reforma # Cálculo IBS/CBS
|
|
460
|
+
npm run example:nfse # NFS-e mock
|
|
461
|
+
npm run example:nfce # Gera NFC-e modelo 65
|
|
462
|
+
npm run example:xsd # Valida XML contra XSD
|
|
463
|
+
npm run example:eventos # Cancelamento e CC-e mock
|
|
464
|
+
npm run schemas:download # Baixa schemas XSD da SEFAZ
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Arquitetura
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
┌─────────────┐ ┌──────────────┐ ┌───────────────┐ ┌────────────┐
|
|
471
|
+
│ Seu App │────▶│ NFeService │────▶│ NFeXmlService │────▶│ XML NF-e │
|
|
472
|
+
│ (Sequelize) │ │ (orquestrador)│ └───────────────┘ └────────────┘
|
|
473
|
+
└─────────────┘ │ │────▶│ NFeSignService│────▶│ XML Assinado│
|
|
474
|
+
│ │ │ └───────────────┘ └────────────┘
|
|
475
|
+
│ │ │────▶│ NFeSoapService│────▶│ SEFAZ/Mock │
|
|
476
|
+
▼ └──────────────┘ └───────────────┘ └────────────┘
|
|
477
|
+
┌─────────────┐
|
|
478
|
+
│ NFeQueue │ Bull/Redis — processamento assíncrono
|
|
479
|
+
└─────────────┘
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Roadmap
|
|
483
|
+
|
|
484
|
+
- [ ] Validação XSD PL_010 completa (quando SEFAZ publicar pacote estável)
|
|
485
|
+
- [ ] Mais municípios / provedores NFS-e
|
|
486
|
+
- [ ] PDF nativo (puppeteer opcional) no DanfeService
|
|
487
|
+
- [ ] Assinatura XML de cancelamento NFS-e por layout
|
|
488
|
+
|
|
489
|
+
## Licença
|
|
490
|
+
|
|
491
|
+
MIT — veja [LICENSE](LICENSE).
|