ghinfe 0.6.0
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 +15 -0
- package/LICENSE +21 -0
- package/README.md +413 -0
- package/docs/developer-guide.html +421 -0
- package/docs/openapi.yaml +428 -0
- package/examples/emitir-nfce.js +51 -0
- package/examples/emitir-nfe.js +83 -0
- package/examples/emitir-nfse.js +46 -0
- package/examples/endpoints-sefaz.js +14 -0
- package/examples/eventos-nfe.js +49 -0
- package/examples/gerar-chave.js +25 -0
- package/examples/gerar-danfe.js +75 -0
- package/examples/layouts-nfse.js +51 -0
- package/examples/mock-sefaz.js +52 -0
- package/examples/nfse-eventos.js +57 -0
- package/examples/reforma-ibscbs.js +27 -0
- package/examples/reforma-nfe-xml.js +52 -0
- package/examples/status-sefaz.js +12 -0
- package/examples/validar-xsd.js +48 -0
- package/package.json +68 -0
- package/schemas/nfe/PL_009_V4/consReciNFe_v4.00.xsd +9 -0
- package/schemas/nfe/PL_009_V4/consSitNFe_v4.00.xsd +9 -0
- package/schemas/nfe/PL_009_V4/consStatServ_v4.00.xsd +9 -0
- package/schemas/nfe/PL_009_V4/enviNFe_v3.10.xsd +9 -0
- package/schemas/nfe/PL_009_V4/enviNFe_v4.00.xsd +9 -0
- package/schemas/nfe/PL_009_V4/inutNFe_v4.00.xsd +9 -0
- package/schemas/nfe/PL_009_V4/leiauteNFe_v4.00.xsd +7339 -0
- package/schemas/nfe/PL_009_V4/nfe_v4.00.xsd +9 -0
- package/schemas/nfe/PL_009_V4/tiposBasico_v4.00.xsd +598 -0
- package/schemas/nfe/PL_009_V4/xmldsig-core-schema_v1.01.xsd +98 -0
- package/scripts/download-schemas.js +39 -0
- package/scripts/test-xsd.js +34 -0
- package/src/api/server.js +316 -0
- package/src/constants/sefaz.js +69 -0
- package/src/danfe/DanfeService.js +205 -0
- package/src/danfe/xml-extract.js +69 -0
- package/src/errors/GhinfeError.js +13 -0
- package/src/errors/SefazError.js +25 -0
- package/src/errors/XsdValidationError.js +15 -0
- package/src/index.js +60 -0
- package/src/nfce/builders/NFCeXmlBuilder.js +178 -0
- package/src/nfce/constants/qrcode.js +26 -0
- package/src/nfce/services/NFCeService.js +188 -0
- package/src/nfce/services/NFCeXmlService.js +38 -0
- package/src/nfce/types/NFCeDocument.js +42 -0
- package/src/nfce/utils/qrcode.utils.js +92 -0
- package/src/nfe/builders/NFeEventoXmlBuilder.js +110 -0
- package/src/nfe/builders/NFeXmlBuilder.js +215 -0
- package/src/nfe/mocks/sefaz-responses.js +195 -0
- package/src/nfe/services/NFeEventoService.js +95 -0
- package/src/nfe/services/NFeService.js +196 -0
- package/src/nfe/services/NFeSignService.js +111 -0
- package/src/nfe/services/NFeSoapService.js +437 -0
- package/src/nfe/services/NFeXmlService.js +41 -0
- package/src/nfe/services/NFeXsdService.js +56 -0
- package/src/nfe/types/NFeDocument.js +92 -0
- package/src/nfe/types/NFeEvento.js +44 -0
- package/src/nfse/NFSeMunicipioResolver.js +42 -0
- package/src/nfse/builders/NFSeEventoXmlBuilder.js +92 -0
- package/src/nfse/builders/NFSeXmlBuilder.js +16 -0
- package/src/nfse/constants/municipios.js +82 -0
- package/src/nfse/layouts/adapters.js +202 -0
- package/src/nfse/mocks/nfse-responses.js +142 -0
- package/src/nfse/services/NFSeService.js +191 -0
- package/src/nfse/services/NFSeSoapService.js +232 -0
- package/src/nfse/services/NFSeXmlService.js +12 -0
- package/src/nfse/types/NFSeDocument.js +54 -0
- package/src/queue/NFCeQueue.js +63 -0
- package/src/queue/NFSeQueue.js +59 -0
- package/src/queue/NFeQueue.js +76 -0
- package/src/reforma/ibscbs.js +175 -0
- package/src/sefaz/SefazEndpointResolver.js +95 -0
- package/src/sefaz/endpoints.registry.js +205 -0
- package/src/shared/fiscal.helpers.js +53 -0
- package/src/utils/certificate.utils.js +47 -0
- package/src/utils/chave.utils.js +117 -0
- package/src/utils/date.utils.js +26 -0
- package/src/utils/xml.utils.js +44 -0
- package/src/validation/XsdValidator.js +114 -0
- package/src/validation/schemas.js +14 -0
package/.env.example
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Redis (Bull queue)
|
|
2
|
+
REDIS_HOST=127.0.0.1
|
|
3
|
+
REDIS_PORT=6379
|
|
4
|
+
# REDIS_PASSWORD=
|
|
5
|
+
|
|
6
|
+
# API de testes / Swagger
|
|
7
|
+
PORT=3333
|
|
8
|
+
|
|
9
|
+
# SEFAZ (produção — use com cuidado)
|
|
10
|
+
# SEFAZ_MOCK=true
|
|
11
|
+
# SEFAZ_ENDPOINT=https://homologacao.nfe.fazenda.sp.gov.br/ws/nfeautorizacao4.asmx
|
|
12
|
+
|
|
13
|
+
# Certificado A1
|
|
14
|
+
# PFX_PATH=./certs/certificado.pfx
|
|
15
|
+
# PFX_PASSWORD=
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Victor Henrique Ghilardi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# GHINFE
|
|
2
|
+
|
|
3
|
+
Biblioteca Node.js para emissão de documentos fiscais eletrônicos brasileiros: **NF-e**, **NFC-e** e **NFS-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
|
+
| IBS/CBS injetado no XML NF-e (item + totais) | ✅ experimental |
|
|
13
|
+
| Cancelamento e substituição NFS-e | ✅ |
|
|
14
|
+
| DANFE / DANFCE (HTML imprimível) | ✅ |
|
|
15
|
+
| Assinatura A1, XSD, multi-UF, filas Bull | ✅ |
|
|
16
|
+
| Injeção completa conforme XSD PL_010 estável | 🔜 |
|
|
17
|
+
|
|
18
|
+
## Estrutura de pastas
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
ghinfe/
|
|
22
|
+
├── docs/
|
|
23
|
+
│ ├── openapi.yaml # Especificação Swagger/OpenAPI
|
|
24
|
+
│ └── developer-guide.html # Guia completo para desenvolvedores
|
|
25
|
+
├── examples/
|
|
26
|
+
│ ├── emitir-nfe.js # Exemplo de geração + mock
|
|
27
|
+
│ └── mock-sefaz.js # Cenários de retorno SEFAZ
|
|
28
|
+
├── src/
|
|
29
|
+
│ ├── api/
|
|
30
|
+
│ │ └── server.js # Servidor Express + Swagger UI
|
|
31
|
+
│ ├── constants/
|
|
32
|
+
│ │ └── sefaz.js # UF, cStat, URLs, versão layout
|
|
33
|
+
│ ├── errors/
|
|
34
|
+
│ │ ├── GhinfeError.js
|
|
35
|
+
│ │ └── SefazError.js # Erros reais da SEFAZ (cStat)
|
|
36
|
+
│ ├── nfe/
|
|
37
|
+
│ │ ├── builders/
|
|
38
|
+
│ │ │ ├── NFeXmlBuilder.js
|
|
39
|
+
│ │ │ └── NFeEventoXmlBuilder.js # Cancelamento, CC-e
|
|
40
|
+
│ │ ├── mocks/
|
|
41
|
+
│ │ │ └── sefaz-responses.js
|
|
42
|
+
│ │ ├── services/
|
|
43
|
+
│ │ │ ├── NFeXmlService.js
|
|
44
|
+
│ │ │ ├── NFeSignService.js
|
|
45
|
+
│ │ │ ├── NFeSoapService.js
|
|
46
|
+
│ │ │ ├── NFeEventoService.js # Eventos SEFAZ
|
|
47
|
+
│ │ │ └── NFeService.js
|
|
48
|
+
│ │ └── types/
|
|
49
|
+
│ │ ├── NFeDocument.js
|
|
50
|
+
│ │ └── NFeEvento.js
|
|
51
|
+
│ ├── sefaz/
|
|
52
|
+
│ │ ├── endpoints.registry.js # URLs por autorizador (SVRS, SP, MG...)
|
|
53
|
+
│ │ └── SefazEndpointResolver.js
|
|
54
|
+
│ ├── nfse/
|
|
55
|
+
│ │ ├── builders/NFSeXmlBuilder.js
|
|
56
|
+
│ │ ├── services/ # NFSeService, NFSeSoapService
|
|
57
|
+
│ │ └── NFSeMunicipioResolver.js
|
|
58
|
+
│ ├── queue/
|
|
59
|
+
│ │ ├── NFeQueue.js
|
|
60
|
+
│ │ ├── NFCeQueue.js
|
|
61
|
+
│ │ └── NFSeQueue.js
|
|
62
|
+
│ ├── utils/
|
|
63
|
+
│ │ ├── certificate.utils.js
|
|
64
|
+
│ │ ├── chave.utils.js # Chave de acesso + DV
|
|
65
|
+
│ │ ├── date.utils.js
|
|
66
|
+
│ │ └── xml.utils.js
|
|
67
|
+
│ └── index.js # Exports públicos
|
|
68
|
+
├── .env.example
|
|
69
|
+
└── package.json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Instalação
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install
|
|
76
|
+
cp .env.example .env
|
|
77
|
+
npm run schemas:download # baixa XSDs se necessário (já inclusos em schemas/)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Uso rápido
|
|
81
|
+
|
|
82
|
+
### 1. Montar o objeto e gerar XML (chave automática)
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
import { NFeService } from 'ghinfe';
|
|
86
|
+
|
|
87
|
+
const service = new NFeService();
|
|
88
|
+
|
|
89
|
+
const documento = {
|
|
90
|
+
// chaveAcesso é opcional — gerada automaticamente
|
|
91
|
+
ambiente: 2,
|
|
92
|
+
ide: { uf: 'SP', codigoMunicipio: '3550308', serie: 1, numero: 1 },
|
|
93
|
+
emitente: { cnpj: '12345678000199', /* ... */ },
|
|
94
|
+
destinatario: { /* ... */ },
|
|
95
|
+
itens: [{ /* ... */ }],
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const xml = service.gerarXml(documento);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 1b. Gerar chave de acesso manualmente
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
import { gerarChaveAcesso, validarChaveAcesso } from 'ghinfe';
|
|
105
|
+
|
|
106
|
+
const chave = gerarChaveAcesso({
|
|
107
|
+
uf: 'SP',
|
|
108
|
+
cnpj: '12345678000199',
|
|
109
|
+
serie: 1,
|
|
110
|
+
numero: 42,
|
|
111
|
+
});
|
|
112
|
+
console.log(validarChaveAcesso(chave)); // true
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Endpoints SEFAZ automáticos (multi-UF)
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
import { SefazEndpointResolver, NFeService } from 'ghinfe';
|
|
119
|
+
|
|
120
|
+
// Por UF — resolve autorizador (SVRS, SP, MG...) automaticamente
|
|
121
|
+
const urls = SefazEndpointResolver.paraNFe('RJ', 2); // homologação
|
|
122
|
+
console.log(urls.endpoint);
|
|
123
|
+
|
|
124
|
+
// No serviço — basta informar UF
|
|
125
|
+
const service = new NFeService({ mock: false, uf: 'SP', ambiente: 2 });
|
|
126
|
+
|
|
127
|
+
// Ou configurar em runtime a partir do documento
|
|
128
|
+
service.configurarUf('MG', 2);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### NFS-e (layouts municipais)
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
import { NFSeService, NFSE_LAYOUTS, NFSeMunicipioResolver } from 'ghinfe';
|
|
135
|
+
|
|
136
|
+
// Layout explícito ou automático pelo município
|
|
137
|
+
const service = new NFSeService({ mock: true, layout: NFSE_LAYOUTS.GINFES });
|
|
138
|
+
const xml = service.gerarXml(documento);
|
|
139
|
+
|
|
140
|
+
// Assinatura A1 do RPS
|
|
141
|
+
const xmlAssinado = service.gerarXmlAssinado(documento, { pfx, senha });
|
|
142
|
+
|
|
143
|
+
// Emissão com assinatura opcional
|
|
144
|
+
const resultado = await service.emitir(documento, { pfx, senha });
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Layouts: `abrasf`, `ginfes`, `betha`, `issnet` — municípios pré-cadastrados em SP, RJ, BH, Curitiba, POA, Floripa, Salvador, Recife, Fortaleza.
|
|
148
|
+
|
|
149
|
+
### Consulta status SEFAZ
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
const service = new NFeService({ mock: true });
|
|
153
|
+
const status = await service.consultarStatus('SP', 2);
|
|
154
|
+
// { emOperacao: true, cStat: '107', xMotivo: 'Serviço em Operação', tMed: '1' }
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Reforma tributária (IBS/CBS no XML)
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
import { NFeService, calcularIBSCBS } from 'ghinfe';
|
|
161
|
+
|
|
162
|
+
const item = {
|
|
163
|
+
codigo: '001', descricao: '...', ncm: '...', cfop: '5102',
|
|
164
|
+
unidade: 'UN', quantidade: 1, valorUnitario: 100, valorTotal: 100,
|
|
165
|
+
reforma: calcularIBSCBS(100, { pIBSUF: 0.1, pIBSMun: 0.05, pCBS: 0.9 }),
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const xml = service.gerarXml({ ...documento, itens: [item] });
|
|
169
|
+
// XML contém <IBSCBS> no item e <IBSCBSTot> nos totais
|
|
170
|
+
// Não use validarXsd:true com reforma até o schema PL_010 estar embutido
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Cancelamento / substituição NFS-e
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
await service.cancelar({
|
|
177
|
+
numeroNfse: '2026000001',
|
|
178
|
+
cnpjPrestador: '...',
|
|
179
|
+
inscricaoMunicipal: '...',
|
|
180
|
+
codigoMunicipio: '3550308',
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await service.substituir({
|
|
184
|
+
numeroNfseSubstituida: '2026000001',
|
|
185
|
+
cnpjPrestador: '...',
|
|
186
|
+
inscricaoMunicipal: '...',
|
|
187
|
+
codigoMunicipio: '3550308',
|
|
188
|
+
documentoSubstituto: { /* novo RPS */ },
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### DANFE / DANFCE
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
import { DanfeService } from 'ghinfe';
|
|
196
|
+
|
|
197
|
+
const danfe = new DanfeService();
|
|
198
|
+
const { html } = await danfe.gerarDanfe(xmlNfe, { protocolo: '...' });
|
|
199
|
+
const { html: cupom } = await danfe.gerarDanfce(xmlNfce, { qrCodeUrl: '...' });
|
|
200
|
+
// Salve o HTML e imprima / “Salvar como PDF” no navegador
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Consulta status SEFAZ
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
import { NFeService, XsdValidationError } from 'ghinfe';
|
|
207
|
+
|
|
208
|
+
const service = new NFeService({ validarXsd: true });
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
service.validarXsd(xml, { preAssinatura: true });
|
|
212
|
+
} catch (error) {
|
|
213
|
+
if (error instanceof XsdValidationError) console.error(error.erros);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Schemas oficiais em `schemas/nfe/PL_009_V4/`.
|
|
218
|
+
|
|
219
|
+
### NFC-e (modelo 65)
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
import { NFCeService } from 'ghinfe';
|
|
223
|
+
|
|
224
|
+
const service = new NFCeService({ mock: true });
|
|
225
|
+
|
|
226
|
+
const documento = {
|
|
227
|
+
ambiente: 2,
|
|
228
|
+
ide: { uf: 'SP', codigoMunicipio: '3550308', serie: 1, numero: 1 },
|
|
229
|
+
emitente: { cnpj: '...', razaoSocial: '...', ie: '...', crt: '1', endereco: { /* ... */ } },
|
|
230
|
+
itens: [{ codigo: '001', descricao: '...', ncm: '...', cfop: '5102', unidade: 'UN', quantidade: 1, valorUnitario: 10, valorTotal: 10 }],
|
|
231
|
+
csc: { idCSC: '000001', codigo: 'SEU-CSC-SEFAZ' },
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const xml = service.gerarXml(documento);
|
|
235
|
+
// QR Code v3 é adicionado após assinatura:
|
|
236
|
+
const { xml: xmlCompleto, qrCode } = service.gerarXmlAssinado(documento, { pfx, senha });
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### 2. Assinar com certificado A1
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
import fs from 'fs';
|
|
243
|
+
|
|
244
|
+
const pfx = fs.readFileSync('./certs/certificado.pfx');
|
|
245
|
+
const xmlAssinado = service.gerarXmlAssinado(documento, {
|
|
246
|
+
pfx,
|
|
247
|
+
senha: process.env.PFX_PASSWORD,
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 3. Enviar para SEFAZ (mock em desenvolvimento)
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
const service = new NFeService({ mock: true });
|
|
255
|
+
|
|
256
|
+
const resultado = await service.emitir(documento, { pfx, senha: '...' });
|
|
257
|
+
|
|
258
|
+
if (resultado.retorno.autorizado) {
|
|
259
|
+
console.log('Protocolo:', resultado.retorno.protocolo);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 4. Persistir no banco (Sequelize)
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
const payload = service.toPersistencePayload(resultado);
|
|
267
|
+
|
|
268
|
+
await NotaFiscal.create({
|
|
269
|
+
chave_acesso: payload.chave_acesso,
|
|
270
|
+
xml_nfe: payload.xml_nfe,
|
|
271
|
+
xml_protocolo: payload.xml_protocolo,
|
|
272
|
+
protocolo: payload.protocolo,
|
|
273
|
+
status: payload.status,
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 5. Cancelar NF-e
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
const resultado = await service.cancelar({
|
|
281
|
+
chaveAcesso: '35260712345678000199550010000000011000000011',
|
|
282
|
+
cnpj: '12345678000199',
|
|
283
|
+
uf: 'SP',
|
|
284
|
+
protocolo: '135260000000001',
|
|
285
|
+
justificativa: 'Cancelamento por erro de digitacao no pedido',
|
|
286
|
+
}, { pfx, senha });
|
|
287
|
+
|
|
288
|
+
console.log(resultado.retorno.cStat); // '135' — evento registrado
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### 6. Carta de Correção (CC-e)
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
const resultado = await service.cartaCorrecao({
|
|
295
|
+
chaveAcesso: '...',
|
|
296
|
+
cnpj: '12345678000199',
|
|
297
|
+
uf: 'SP',
|
|
298
|
+
sequencia: 1,
|
|
299
|
+
correcao: 'Correcao do endereco de entrega: Rua Nova, 500',
|
|
300
|
+
}, { pfx, senha });
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 7. Fila assíncrona (Bull + Redis)
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
import { NFeQueue } from 'ghinfe';
|
|
307
|
+
|
|
308
|
+
const queue = new NFeQueue({
|
|
309
|
+
redis: { host: '127.0.0.1', port: 6379 },
|
|
310
|
+
nfeOptions: { mock: true },
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
await queue.adicionarEmissao({ documento, certificado: { pfx, senha } });
|
|
314
|
+
|
|
315
|
+
queue.onCompleted(async (resultado) => {
|
|
316
|
+
await NotaFiscal.create(service.toPersistencePayload(resultado));
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Tratamento de erros SEFAZ
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
import { SefazError } from 'ghinfe';
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
await service.enviar(xmlAssinado, chaveAcesso);
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (error instanceof SefazError) {
|
|
329
|
+
console.error(`Rejeição ${error.cStat}: ${error.xMotivo}`);
|
|
330
|
+
// 204 = duplicidade, 225 = schema, 280 = certificado...
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## API de testes (Swagger)
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
npm start
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
| URL | Descrição |
|
|
342
|
+
|-----|-----------|
|
|
343
|
+
| http://localhost:3333/docs | Swagger UI interativo |
|
|
344
|
+
| http://localhost:3333/guia/developer-guide.html | Guia HTML do desenvolvedor |
|
|
345
|
+
| http://localhost:3333/health | Health check |
|
|
346
|
+
|
|
347
|
+
### Endpoints
|
|
348
|
+
|
|
349
|
+
- `GET /sefaz/endpoints/:uf?ambiente=2` — URLs SEFAZ por UF
|
|
350
|
+
- `GET /sefaz/ufs` — Lista UFs suportadas
|
|
351
|
+
- `POST /nfse/cancelar-mock` — Cancela NFS-e (mock)
|
|
352
|
+
- `POST /nfse/substituir-mock` — Substitui NFS-e (mock)
|
|
353
|
+
- `POST /danfe` — Gera DANFE/DANFCE (JSON ou `?format=html`)
|
|
354
|
+
- `GET /sefaz/status/:uf?cenario=ok` — Consulta status SEFAZ (mock)
|
|
355
|
+
- `GET /nfse/layouts` — Layouts NFS-e suportados
|
|
356
|
+
- `POST /reforma/calcular` — Calcula IBS/CBS + fragmento XML
|
|
357
|
+
- `POST /nfse/xml?layout=ginfes` — Gera XML RPS NFS-e
|
|
358
|
+
- `POST /nfse/enviar-mock` — Emite NFS-e mock
|
|
359
|
+
- `GET /nfse/municipios` — Municípios configurados
|
|
360
|
+
- `POST /nfe/xml?validarXsd=true` — Gera XML com validação XSD
|
|
361
|
+
- `POST /nfe/validar-xsd` — Valida XML existente
|
|
362
|
+
- `POST /nfce/xml` — Gera XML NFC-e (modelo 65)
|
|
363
|
+
- `POST /nfce/enviar-mock` — Envia NFC-e mock
|
|
364
|
+
- `POST /nfe/xml` — Gera XML a partir do JSON
|
|
365
|
+
- `POST /nfe/enviar-mock?cenario=autorizado` — Fluxo completo mock
|
|
366
|
+
- `POST /nfe/cancelar-mock` — Cancelamento simulado
|
|
367
|
+
- `POST /nfe/cce-mock` — Carta de correção simulada
|
|
368
|
+
- `GET /nfe/cenarios-mock` — Lista cenários de teste
|
|
369
|
+
|
|
370
|
+
## Exemplos CLI
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
npm run example:nfe # Gera XML e simula retorno
|
|
374
|
+
npm run example:mock # Testa cenários SEFAZ mock
|
|
375
|
+
npm run example:endpoints # Endpoints SEFAZ por UF
|
|
376
|
+
npm run example:reforma-xml # NF-e com IBSCBS no XML
|
|
377
|
+
npm run example:nfse-eventos # Cancelamento / substituição NFS-e
|
|
378
|
+
npm run example:danfe # Gera HTML em tmp/
|
|
379
|
+
npm run example:status # Status SEFAZ mock
|
|
380
|
+
npm run example:layouts # ABRASF / GINFES / Betha / ISSNet
|
|
381
|
+
npm run example:reforma # Cálculo IBS/CBS
|
|
382
|
+
npm run example:nfse # NFS-e mock
|
|
383
|
+
npm run example:nfce # Gera NFC-e modelo 65
|
|
384
|
+
npm run example:xsd # Valida XML contra XSD
|
|
385
|
+
npm run example:eventos # Cancelamento e CC-e mock
|
|
386
|
+
npm run schemas:download # Baixa schemas XSD da SEFAZ
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Arquitetura
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
┌─────────────┐ ┌──────────────┐ ┌───────────────┐ ┌────────────┐
|
|
393
|
+
│ Seu App │────▶│ NFeService │────▶│ NFeXmlService │────▶│ XML NF-e │
|
|
394
|
+
│ (Sequelize) │ │ (orquestrador)│ └───────────────┘ └────────────┘
|
|
395
|
+
└─────────────┘ │ │────▶│ NFeSignService│────▶│ XML Assinado│
|
|
396
|
+
│ │ │ └───────────────┘ └────────────┘
|
|
397
|
+
│ │ │────▶│ NFeSoapService│────▶│ SEFAZ/Mock │
|
|
398
|
+
▼ └──────────────┘ └───────────────┘ └────────────┘
|
|
399
|
+
┌─────────────┐
|
|
400
|
+
│ NFeQueue │ Bull/Redis — processamento assíncrono
|
|
401
|
+
└─────────────┘
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Roadmap
|
|
405
|
+
|
|
406
|
+
- [ ] Validação XSD PL_010 completa (quando SEFAZ publicar pacote estável)
|
|
407
|
+
- [ ] Mais municípios / provedores NFS-e
|
|
408
|
+
- [ ] PDF nativo (puppeteer opcional) no DanfeService
|
|
409
|
+
- [ ] Assinatura XML de cancelamento NFS-e por layout
|
|
410
|
+
|
|
411
|
+
## Licença
|
|
412
|
+
|
|
413
|
+
MIT — veja [LICENSE](LICENSE).
|