@useinvio/nfse-sdk 0.3.0 → 1.0.1
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 +46 -3
- package/examples/README.md +12 -0
- package/examples/client-resource.ts +50 -0
- package/examples/emit-homologation.ts +54 -0
- package/examples/generate-dps-xml.ts +43 -0
- package/examples/handle-errors.ts +24 -0
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -4,9 +4,21 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@useinvio/nfse-sdk)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
|
|
7
|
+
[Website](https://sdk.useinvio.com/)
|
|
8
|
+
|
|
9
|
+
<img width="959" height="296" alt="image" src="https://github.com/user-attachments/assets/d6c45737-e7ca-4ea7-a06f-d93b7c16e4f0" />
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
7
13
|
SDK TypeScript para integração com a **NFS-e Nacional** (SEFIN).
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
Transforme JSON em DPS/NFS-e, assine com XMLDSIG, compacte em GZip/Base64 e transmita por mTLS sem escrever XML fiscal na mão.
|
|
16
|
+
|
|
17
|
+
O SDK cuida da camada protocolar: certificado A1, montagem de DPS, validações estruturais, assinatura XML, compactação, envio, consulta e normalização de rejeições da SEFIN. A aplicação [...]
|
|
18
|
+
|
|
19
|
+
**Para quem é:** ERPs, SaaS financeiros, plataformas de cobrança, contabilidades digitais e times Node.js/TypeScript que precisam integrar com a NFS-e Nacional.
|
|
20
|
+
|
|
21
|
+
**O que ele não é:** um motor fiscal, consultor tributário ou substituto da validação contábil do seu produto.
|
|
10
22
|
|
|
11
23
|
---
|
|
12
24
|
|
|
@@ -14,6 +26,7 @@ Cuida de todo o protocolo de comunicação: certificado A1, assinatura XML (XMLD
|
|
|
14
26
|
|
|
15
27
|
- [Instalação](#instalação)
|
|
16
28
|
- [Quick start](#quick-start)
|
|
29
|
+
- [Por que usar](#por-que-usar)
|
|
17
30
|
- [Escolhendo o ponto de entrada](#escolhendo-o-ponto-de-entrada)
|
|
18
31
|
- [Cliente orientado a recursos](#cliente-orientado-a-recursos)
|
|
19
32
|
- [Certificado A1](#certificado-a1)
|
|
@@ -28,6 +41,8 @@ Cuida de todo o protocolo de comunicação: certificado A1, assinatura XML (XMLD
|
|
|
28
41
|
- [Referência da API](#referência-da-api)
|
|
29
42
|
- [Desenvolvimento](#desenvolvimento)
|
|
30
43
|
- [Publicação no npm](#publicação-no-npm)
|
|
44
|
+
- [Divulgação e exemplos](#divulgação-e-exemplos)
|
|
45
|
+
- [Assistente GPT](#assistente-gpt)
|
|
31
46
|
|
|
32
47
|
---
|
|
33
48
|
|
|
@@ -102,6 +117,17 @@ try {
|
|
|
102
117
|
|
|
103
118
|
---
|
|
104
119
|
|
|
120
|
+
## Por que usar
|
|
121
|
+
|
|
122
|
+
- Entrada JSON tipada para construir DPS no layout nacional.
|
|
123
|
+
- Assinatura XMLDSIG, GZip/Base64 e mTLS encapsulados em uma API Node.js.
|
|
124
|
+
- Erros oficiais da SEFIN preservados em formato estruturado.
|
|
125
|
+
- Builder separado para inspecionar ou salvar o XML antes de transmitir.
|
|
126
|
+
- Cliente `NfseClient` para configurar certificado, ambiente e defaults uma vez.
|
|
127
|
+
- Validação explícita de campos fiscais obrigatórios, sem defaults silenciosos.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
105
131
|
## Escolhendo o ponto de entrada
|
|
106
132
|
|
|
107
133
|
| Situação | O que usar |
|
|
@@ -247,7 +273,7 @@ await emitirNfse(dpsXml, pfx, { dpsId: 'DPS0001', ambiente: 'restrita' });
|
|
|
247
273
|
Use quando a aplicação mantém os perfis de prestador e serviço e quer que a SDK monte o XML.
|
|
248
274
|
|
|
249
275
|
Para a referência completa de campos aceitos no JSON, consulte [JSON_MAPPING.md](./JSON_MAPPING.md).
|
|
250
|
-
O builder valida formatos e combinações mínimas antes de gerar XML, mas não escolhe códigos fiscais por você. Campos como `tributacaoMunicipal` e `totTrib` precisam ser informados
|
|
276
|
+
O builder valida formatos e combinações mínimas antes de gerar XML, mas não escolhe códigos fiscais por você. Campos como `tributacaoMunicipal` e `totTrib` precisam ser informados explicita[...]
|
|
251
277
|
|
|
252
278
|
```ts
|
|
253
279
|
import { emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
|
|
@@ -480,7 +506,7 @@ npm run build # compila para dist/
|
|
|
480
506
|
npm test # build + tipos + testes unitários
|
|
481
507
|
```
|
|
482
508
|
|
|
483
|
-
`npm test` também valida uma DPS gerada contra os XSD oficiais em `schemas/nfse/v1.01/Schemas/1.01`. Para compatibilidade com `xmllint`, o teste corrige em uma cópia temporária a âncora regex
|
|
509
|
+
`npm test` também valida uma DPS gerada contra os XSD oficiais em `schemas/nfse/v1.01/Schemas/1.01`. Para compatibilidade com `xmllint`, o teste corrige em uma cópia temporária a âncora regex[...]
|
|
484
510
|
|
|
485
511
|
### Uso local em outro projeto
|
|
486
512
|
|
|
@@ -510,9 +536,26 @@ O pacote usa `publishConfig.access = public`, necessário para publicar um pacot
|
|
|
510
536
|
|
|
511
537
|
---
|
|
512
538
|
|
|
539
|
+
## Divulgação e exemplos
|
|
540
|
+
|
|
541
|
+
- Exemplos copiáveis ficam em [`examples/`](./examples).
|
|
542
|
+
- Material de lançamento, mensagens para redes e prompt de landing page ficam em [`docs/launch.md`](./docs/launch.md).
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## Assistente GPT
|
|
547
|
+
|
|
548
|
+
Para criar um GPT que ajude outros devs a implementar e documentar esta SDK, use:
|
|
549
|
+
|
|
550
|
+
- [`docs/gpt-assistant.md`](./docs/gpt-assistant.md): configuracao completa do GPT, instrucoes copiaveis, starters e testes de preview.
|
|
551
|
+
- [`docs/gpt-knowledge.md`](./docs/gpt-knowledge.md): resumo compacto para subir como arquivo de Knowledge.
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
513
555
|
## Princípios de design
|
|
514
556
|
|
|
515
557
|
- Sem dependência de banco de dados, config de aplicação ou estado de tenant.
|
|
516
558
|
- Funções pequenas, testáveis e reutilizáveis.
|
|
517
559
|
- Erros oficiais da SEFIN são preservados na íntegra, não engolidos.
|
|
518
560
|
- O SDK transporta declarações fiscais; não valida se estão contabilmente corretas.
|
|
561
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
Copyable entry points for common NFS-e Nacional flows.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
- [`generate-dps-xml.ts`](./generate-dps-xml.ts): build an unsigned DPS XML from JSON.
|
|
8
|
+
- [`emit-homologation.ts`](./emit-homologation.ts): emit in the restricted/sandbox SEFIN environment.
|
|
9
|
+
- [`client-resource.ts`](./client-resource.ts): use `NfseClient` with certificate and defaults configured once.
|
|
10
|
+
- [`handle-errors.ts`](./handle-errors.ts): normalize SEFIN rejection details for your application.
|
|
11
|
+
|
|
12
|
+
The examples assume Node.js 20+ and a valid A1/PFX certificate. They are intentionally explicit about fiscal fields; the SDK does not infer municipal taxation, withholding, CST or total tax burden.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { NfseClient } from '@useinvio/nfse-sdk';
|
|
2
|
+
|
|
3
|
+
const client = new NfseClient({
|
|
4
|
+
environment: 'sandbox',
|
|
5
|
+
certificate: {
|
|
6
|
+
content: process.env.NFSE_CERTIFICATE_BASE64!,
|
|
7
|
+
password: process.env.NFSE_CERTIFICATE_PASSWORD!,
|
|
8
|
+
},
|
|
9
|
+
defaults: {
|
|
10
|
+
prestador: {
|
|
11
|
+
cnpj: '12345678000195',
|
|
12
|
+
tpInsc: '2',
|
|
13
|
+
cLocEmi: '4106902',
|
|
14
|
+
serie: '1601',
|
|
15
|
+
opSimpNac: '1',
|
|
16
|
+
regEspTrib: '0',
|
|
17
|
+
},
|
|
18
|
+
servico: {
|
|
19
|
+
cTribNac: '010201',
|
|
20
|
+
xDescServ: 'Desenvolvimento de software',
|
|
21
|
+
cLocPrestacao: '4106902',
|
|
22
|
+
cNBS: '115022000',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const invoice = await client.invoices.create({
|
|
28
|
+
emissao: {
|
|
29
|
+
nDPS: '2',
|
|
30
|
+
valores: { vServ: '1000.00' },
|
|
31
|
+
tomador: {
|
|
32
|
+
CPF: '00000000000',
|
|
33
|
+
xNome: 'Cliente Exemplo',
|
|
34
|
+
},
|
|
35
|
+
tributacaoMunicipal: {
|
|
36
|
+
tribISSQN: '3',
|
|
37
|
+
tpRetISSQN: '1',
|
|
38
|
+
},
|
|
39
|
+
tributacaoFederal: {
|
|
40
|
+
piscofins: { CST: '07' },
|
|
41
|
+
},
|
|
42
|
+
totTrib: {
|
|
43
|
+
pTotTribFed: '0.00',
|
|
44
|
+
pTotTribEst: '0.00',
|
|
45
|
+
pTotTribMun: '5.00',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(invoice.chaveAcesso);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { EmitirNotaError, emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
|
|
2
|
+
|
|
3
|
+
const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
|
|
4
|
+
|
|
5
|
+
const nota: DpsJsonRequest = {
|
|
6
|
+
ambiente: 'restrita',
|
|
7
|
+
prestador: {
|
|
8
|
+
cnpj: '12345678000195',
|
|
9
|
+
tpInsc: '2',
|
|
10
|
+
cLocEmi: '4106902',
|
|
11
|
+
serie: '1601',
|
|
12
|
+
opSimpNac: '1',
|
|
13
|
+
regEspTrib: '0',
|
|
14
|
+
},
|
|
15
|
+
servico: {
|
|
16
|
+
cTribNac: '010201',
|
|
17
|
+
xDescServ: 'Desenvolvimento de software',
|
|
18
|
+
cLocPrestacao: '4106902',
|
|
19
|
+
cNBS: '115022000',
|
|
20
|
+
},
|
|
21
|
+
emissao: {
|
|
22
|
+
nDPS: '1',
|
|
23
|
+
dhEmi: '2026-06-15T10:30:00-03:00',
|
|
24
|
+
dCompet: '2026-06-01',
|
|
25
|
+
valores: { vServ: '1500.00' },
|
|
26
|
+
tributacaoMunicipal: {
|
|
27
|
+
tribISSQN: '3',
|
|
28
|
+
cPaisResult: 'BR',
|
|
29
|
+
tpRetISSQN: '1',
|
|
30
|
+
},
|
|
31
|
+
tributacaoFederal: {
|
|
32
|
+
piscofins: { CST: '07' },
|
|
33
|
+
},
|
|
34
|
+
totTrib: {
|
|
35
|
+
pTotTribFed: '0.00',
|
|
36
|
+
pTotTribEst: '0.00',
|
|
37
|
+
pTotTribMun: '5.00',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const resultado = await emitirNfse(nota, pfx);
|
|
44
|
+
console.log(resultado.chaveAcesso);
|
|
45
|
+
console.log(resultado.nfseXml);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (!(error instanceof EmitirNotaError)) throw error;
|
|
48
|
+
|
|
49
|
+
console.error(`Emissao rejeitada pela SEFIN: HTTP ${error.status}`);
|
|
50
|
+
for (const rejeicao of error.erros) {
|
|
51
|
+
console.error(`${rejeicao.Codigo}: ${rejeicao.Descricao}`);
|
|
52
|
+
if (rejeicao.Complemento) console.error(rejeicao.Complemento);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { buildDpsFromJson, type DpsJsonRequest } from '@useinvio/nfse-sdk';
|
|
2
|
+
|
|
3
|
+
const nota: DpsJsonRequest = {
|
|
4
|
+
ambiente: 'restrita',
|
|
5
|
+
prestador: {
|
|
6
|
+
cnpj: '12345678000195',
|
|
7
|
+
tpInsc: '2',
|
|
8
|
+
cLocEmi: '4106902',
|
|
9
|
+
serie: '1601',
|
|
10
|
+
opSimpNac: '1',
|
|
11
|
+
regEspTrib: '0',
|
|
12
|
+
},
|
|
13
|
+
servico: {
|
|
14
|
+
cTribNac: '010201',
|
|
15
|
+
xDescServ: 'Desenvolvimento de software',
|
|
16
|
+
cLocPrestacao: '4106902',
|
|
17
|
+
cNBS: '115022000',
|
|
18
|
+
},
|
|
19
|
+
emissao: {
|
|
20
|
+
nDPS: '1',
|
|
21
|
+
dhEmi: '2026-06-15T10:30:00-03:00',
|
|
22
|
+
dCompet: '2026-06-01',
|
|
23
|
+
valores: { vServ: '1500.00' },
|
|
24
|
+
tributacaoMunicipal: {
|
|
25
|
+
tribISSQN: '3',
|
|
26
|
+
cPaisResult: 'BR',
|
|
27
|
+
tpRetISSQN: '1',
|
|
28
|
+
},
|
|
29
|
+
tributacaoFederal: {
|
|
30
|
+
piscofins: { CST: '07' },
|
|
31
|
+
},
|
|
32
|
+
totTrib: {
|
|
33
|
+
pTotTribFed: '0.00',
|
|
34
|
+
pTotTribEst: '0.00',
|
|
35
|
+
pTotTribMun: '5.00',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const { id, xml } = buildDpsFromJson(nota);
|
|
41
|
+
|
|
42
|
+
console.log(id);
|
|
43
|
+
console.log(xml);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { EmitirNotaError, emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
|
|
2
|
+
|
|
3
|
+
async function emitWithStructuredErrors(nota: DpsJsonRequest) {
|
|
4
|
+
const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
return await emitirNfse(nota, pfx);
|
|
8
|
+
} catch (error) {
|
|
9
|
+
if (!(error instanceof EmitirNotaError)) throw error;
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
rejected: true,
|
|
13
|
+
status: error.status,
|
|
14
|
+
dpsId: error.dpsId,
|
|
15
|
+
errors: error.erros.map((rejeicao) => ({
|
|
16
|
+
code: rejeicao.Codigo,
|
|
17
|
+
message: rejeicao.Descricao,
|
|
18
|
+
detail: rejeicao.Complemento,
|
|
19
|
+
})),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void emitWithStructuredErrors({} as DpsJsonRequest);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinvio/nfse-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "TypeScript SDK for Brazil's national NFS-e: JSON to DPS/XML, XMLDSIG, GZip/Base64, mTLS and SEFIN errors.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"dist/*.d.ts",
|
|
17
17
|
"dist/*.js",
|
|
18
18
|
"dist/*.js.map",
|
|
19
|
+
"docs/*.md",
|
|
20
|
+
"examples/*.ts",
|
|
21
|
+
"examples/README.md",
|
|
19
22
|
"README.md",
|
|
20
23
|
"JSON_MAPPING.md",
|
|
21
24
|
"LICENSE"
|
|
@@ -29,9 +32,18 @@
|
|
|
29
32
|
"keywords": [
|
|
30
33
|
"nfse",
|
|
31
34
|
"nfs-e",
|
|
35
|
+
"nfs-e-nacional",
|
|
32
36
|
"nota-fiscal",
|
|
37
|
+
"nota-fiscal-servico",
|
|
38
|
+
"dps",
|
|
33
39
|
"sefin",
|
|
34
|
-
"sped"
|
|
40
|
+
"sped",
|
|
41
|
+
"xml-dsig",
|
|
42
|
+
"xmldsig",
|
|
43
|
+
"mtls",
|
|
44
|
+
"typescript",
|
|
45
|
+
"brazil",
|
|
46
|
+
"erp"
|
|
35
47
|
],
|
|
36
48
|
"repository": {
|
|
37
49
|
"type": "git",
|