@useinvio/nfse-sdk 0.2.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/JSON_MAPPING.md +225 -0
- package/LICENSE +21 -0
- package/README.md +512 -0
- package/dist/client.d.ts +39 -0
- package/dist/client.js +77 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -0
- package/dist/dpsJson.d.ts +144 -0
- package/dist/dpsJson.js +252 -0
- package/dist/dpsJson.js.map +1 -0
- package/dist/emissaoNota.d.ts +31 -0
- package/dist/emissaoNota.js +65 -0
- package/dist/emissaoNota.js.map +1 -0
- package/dist/fiscalValidation.d.ts +6 -0
- package/dist/fiscalValidation.js +218 -0
- package/dist/fiscalValidation.js.map +1 -0
- package/dist/gzipB64.d.ts +4 -0
- package/dist/gzipB64.js +10 -0
- package/dist/gzipB64.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/loadPfx.d.ts +18 -0
- package/dist/loadPfx.js +41 -0
- package/dist/loadPfx.js.map +1 -0
- package/dist/sefinClient.d.ts +20 -0
- package/dist/sefinClient.js +117 -0
- package/dist/sefinClient.js.map +1 -0
- package/dist/signXml.d.ts +13 -0
- package/dist/signXml.js +52 -0
- package/dist/signXml.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const OP_SIMP_NAC = new Set(['1', '2', '3']);
|
|
2
|
+
const REG_AP_TRIB_SN = new Set(['1', '2', '3']);
|
|
3
|
+
const REG_ESP_TRIB = new Set(['0', '1', '2', '3', '4', '5', '6', '9']);
|
|
4
|
+
const TRIB_ISSQN = new Set(['1', '2', '3', '4']);
|
|
5
|
+
const TP_IMUNIDADE = new Set(['0', '1', '2', '3', '4', '5']);
|
|
6
|
+
const TP_RET_ISSQN = new Set(['1', '2', '3']);
|
|
7
|
+
const PIS_COFINS_CST = new Set([
|
|
8
|
+
'00',
|
|
9
|
+
'01',
|
|
10
|
+
'02',
|
|
11
|
+
'03',
|
|
12
|
+
'04',
|
|
13
|
+
'05',
|
|
14
|
+
'06',
|
|
15
|
+
'07',
|
|
16
|
+
'08',
|
|
17
|
+
'09',
|
|
18
|
+
'49',
|
|
19
|
+
'50',
|
|
20
|
+
'51',
|
|
21
|
+
'52',
|
|
22
|
+
'53',
|
|
23
|
+
'54',
|
|
24
|
+
'55',
|
|
25
|
+
'56',
|
|
26
|
+
'60',
|
|
27
|
+
'61',
|
|
28
|
+
'62',
|
|
29
|
+
'63',
|
|
30
|
+
'64',
|
|
31
|
+
'65',
|
|
32
|
+
'66',
|
|
33
|
+
'67',
|
|
34
|
+
'70',
|
|
35
|
+
'71',
|
|
36
|
+
'72',
|
|
37
|
+
'73',
|
|
38
|
+
'74',
|
|
39
|
+
'75',
|
|
40
|
+
'98',
|
|
41
|
+
'99',
|
|
42
|
+
]);
|
|
43
|
+
export class DpsFiscalValidationError extends Error {
|
|
44
|
+
issues;
|
|
45
|
+
constructor(issues) {
|
|
46
|
+
super(`JSON da DPS invalido: ${issues.join('; ')}`);
|
|
47
|
+
this.issues = issues;
|
|
48
|
+
this.name = 'DpsFiscalValidationError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function issue(issues, message) {
|
|
52
|
+
issues.push(message);
|
|
53
|
+
}
|
|
54
|
+
function assertPattern(issues, field, value, pattern, example) {
|
|
55
|
+
if (value === undefined || value === '') {
|
|
56
|
+
issue(issues, `${field} e obrigatorio`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!pattern.test(value)) {
|
|
60
|
+
issue(issues, `${field} deve seguir ${example}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function assertEnum(issues, field, value, allowed) {
|
|
64
|
+
if (value === undefined || value === '') {
|
|
65
|
+
issue(issues, `${field} e obrigatorio`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!allowed.has(value)) {
|
|
69
|
+
issue(issues, `${field} deve ser um de: ${Array.from(allowed).join(', ')}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function assertDecimal(issues, field, value) {
|
|
73
|
+
if (value === undefined || value === '')
|
|
74
|
+
return;
|
|
75
|
+
if (!Number.isFinite(Number(value))) {
|
|
76
|
+
issue(issues, `${field} deve ser numerico`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function validatePrestador(issues, prestador) {
|
|
80
|
+
assertPattern(issues, 'prestador.cnpj', prestador.cnpj, /^\d{14}$/, '14 digitos numericos');
|
|
81
|
+
assertPattern(issues, 'prestador.cLocEmi', prestador.cLocEmi, /^\d{7}$/, 'codigo IBGE com 7 digitos');
|
|
82
|
+
assertPattern(issues, 'prestador.serie', prestador.serie, /^\d{1,5}$/, 'serie numerica com ate 5 digitos');
|
|
83
|
+
assertEnum(issues, 'prestador.opSimpNac', prestador.opSimpNac, OP_SIMP_NAC);
|
|
84
|
+
assertEnum(issues, 'prestador.regEspTrib', prestador.regEspTrib, REG_ESP_TRIB);
|
|
85
|
+
if (prestador.regApTribSN !== undefined) {
|
|
86
|
+
assertEnum(issues, 'prestador.regApTribSN', prestador.regApTribSN, REG_AP_TRIB_SN);
|
|
87
|
+
if (prestador.opSimpNac !== '3') {
|
|
88
|
+
issue(issues, 'prestador.regApTribSN so deve ser informado quando prestador.opSimpNac = 3');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function validateServico(issues, servico, emissao) {
|
|
93
|
+
assertPattern(issues, 'servico.cTribNac', servico.cTribNac, /^\d{6}$/, '6 digitos numericos');
|
|
94
|
+
assertPattern(issues, 'servico.cLocPrestacao', emissao.servico?.cLocPrestacao ?? servico.cLocPrestacao, /^\d{7}$/, 'codigo IBGE com 7 digitos');
|
|
95
|
+
const cNBS = emissao.servico?.cNBS ?? servico.cNBS;
|
|
96
|
+
if (cNBS !== undefined) {
|
|
97
|
+
assertPattern(issues, 'servico.cNBS', cNBS, /^\d{9}$/, '9 digitos numericos');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function validatePessoa(issues, field, pessoa) {
|
|
101
|
+
if (!pessoa)
|
|
102
|
+
return;
|
|
103
|
+
const ids = [pessoa.CNPJ, pessoa.CPF, pessoa.NIF, pessoa.cNaoNIF].filter((value) => value !== undefined && value !== '');
|
|
104
|
+
if (ids.length !== 1) {
|
|
105
|
+
issue(issues, `${field} deve informar exatamente um identificador: CNPJ, CPF, NIF ou cNaoNIF`);
|
|
106
|
+
}
|
|
107
|
+
if (!pessoa.xNome) {
|
|
108
|
+
issue(issues, `${field}.xNome e obrigatorio quando ${field} for informado`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function validateTribMun(issues, trib, opSimpNac) {
|
|
112
|
+
if (!trib) {
|
|
113
|
+
issue(issues, 'emissao.tributacaoMunicipal e obrigatorio; a SDK nao assume tribISSQN/tpRetISSQN por default');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
assertEnum(issues, 'emissao.tributacaoMunicipal.tribISSQN', trib.tribISSQN, TRIB_ISSQN);
|
|
117
|
+
assertEnum(issues, 'emissao.tributacaoMunicipal.tpRetISSQN', trib.tpRetISSQN, TP_RET_ISSQN);
|
|
118
|
+
if (trib.tribISSQN === '2') {
|
|
119
|
+
assertEnum(issues, 'emissao.tributacaoMunicipal.tpImunidade', trib.tpImunidade, TP_IMUNIDADE);
|
|
120
|
+
}
|
|
121
|
+
else if (trib.tpImunidade !== undefined) {
|
|
122
|
+
issue(issues, 'emissao.tributacaoMunicipal.tpImunidade so deve ser informado quando tribISSQN = 2');
|
|
123
|
+
}
|
|
124
|
+
if (trib.tribISSQN === '3') {
|
|
125
|
+
assertPattern(issues, 'emissao.tributacaoMunicipal.cPaisResult', trib.cPaisResult, /^[A-Z]{2}$/, 'ISO-3166 alpha-2');
|
|
126
|
+
}
|
|
127
|
+
else if (trib.cPaisResult !== undefined) {
|
|
128
|
+
issue(issues, 'emissao.tributacaoMunicipal.cPaisResult so deve ser informado quando tribISSQN = 3');
|
|
129
|
+
}
|
|
130
|
+
if (opSimpNac === '1' && trib.pAliq !== undefined) {
|
|
131
|
+
issue(issues, 'emissao.tributacaoMunicipal.pAliq nao deve ser informado quando prestador.opSimpNac = 1');
|
|
132
|
+
}
|
|
133
|
+
assertDecimal(issues, 'emissao.tributacaoMunicipal.vBC', trib.vBC);
|
|
134
|
+
assertDecimal(issues, 'emissao.tributacaoMunicipal.pAliq', trib.pAliq);
|
|
135
|
+
assertDecimal(issues, 'emissao.tributacaoMunicipal.vISSQN', trib.vISSQN);
|
|
136
|
+
}
|
|
137
|
+
function validateTotTrib(issues, emissao, opSimpNac) {
|
|
138
|
+
const tot = emissao.totTrib;
|
|
139
|
+
if (!tot) {
|
|
140
|
+
issue(issues, 'emissao.totTrib e obrigatorio; a SDK nao preenche carga tributaria aproximada por default');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const hasExplicitValue = tot.vTotTrib !== undefined ||
|
|
144
|
+
tot.pTotTribFed !== undefined ||
|
|
145
|
+
tot.pTotTribEst !== undefined ||
|
|
146
|
+
tot.pTotTribMun !== undefined ||
|
|
147
|
+
tot.pTotTribSN !== undefined ||
|
|
148
|
+
tot.indTotTrib !== undefined;
|
|
149
|
+
if (!hasExplicitValue) {
|
|
150
|
+
issue(issues, 'emissao.totTrib deve informar vTotTrib, pTotTrib*, pTotTribSN ou indTotTrib');
|
|
151
|
+
}
|
|
152
|
+
if (opSimpNac === '1' && (tot.pTotTribSN !== undefined || tot.indTotTrib !== undefined)) {
|
|
153
|
+
issue(issues, 'emissao.totTrib.pTotTribSN/indTotTrib nao devem ser informados para prestador.opSimpNac = 1');
|
|
154
|
+
}
|
|
155
|
+
assertDecimal(issues, 'emissao.totTrib.vTotTrib', tot.vTotTrib);
|
|
156
|
+
assertDecimal(issues, 'emissao.totTrib.pTotTribFed', tot.pTotTribFed);
|
|
157
|
+
assertDecimal(issues, 'emissao.totTrib.pTotTribEst', tot.pTotTribEst);
|
|
158
|
+
assertDecimal(issues, 'emissao.totTrib.pTotTribMun', tot.pTotTribMun);
|
|
159
|
+
assertDecimal(issues, 'emissao.totTrib.pTotTribSN', tot.pTotTribSN);
|
|
160
|
+
}
|
|
161
|
+
function validateUnsupportedShapes(issues, emissao) {
|
|
162
|
+
if (emissao.tribNac) {
|
|
163
|
+
issue(issues, 'emissao.tribNac ainda nao e suportado; IBS/CBS no layout v1.01 exige o bloco RTC IBSCBS oficial');
|
|
164
|
+
}
|
|
165
|
+
if (emissao.evento) {
|
|
166
|
+
issue(issues, 'emissao.evento ainda nao e suportado; o layout v1.01 exige xNome, dtIni, dtFim e id/endereco');
|
|
167
|
+
}
|
|
168
|
+
if (emissao.obra?.cCM) {
|
|
169
|
+
issue(issues, 'emissao.obra.cCM nao existe no layout v1.01; use cObra/inscImobFisc ou aguarde suporte a cCIB/endereco');
|
|
170
|
+
}
|
|
171
|
+
if (emissao.valores?.vDesc !== undefined || emissao.valores?.vDedRed !== undefined) {
|
|
172
|
+
issue(issues, 'emissao.valores.vDesc/vDedRed ainda nao sao suportados no shape correto do layout v1.01');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function validateComercioExterior(issues, emissao) {
|
|
176
|
+
const comExt = emissao.comercioExterior ?? emissao.comExt;
|
|
177
|
+
if (!comExt)
|
|
178
|
+
return;
|
|
179
|
+
for (const field of ['mdPrestacao', 'vincPrest', 'tpMoeda', 'mecAFComexP', 'mecAFComexT', 'movTempBens', 'mdic']) {
|
|
180
|
+
if (!comExt[field])
|
|
181
|
+
issue(issues, `emissao.comercioExterior.${field} e obrigatorio quando comercioExterior for informado`);
|
|
182
|
+
}
|
|
183
|
+
assertDecimal(issues, 'emissao.comercioExterior.vServMoeda', comExt.vServMoeda ?? emissao.valores?.vServMoeda ?? emissao.vServMoeda);
|
|
184
|
+
}
|
|
185
|
+
function validateTribFed(issues, emissao) {
|
|
186
|
+
const piscofins = emissao.tributacaoFederal?.piscofins;
|
|
187
|
+
if (!piscofins)
|
|
188
|
+
return;
|
|
189
|
+
assertEnum(issues, 'emissao.tributacaoFederal.piscofins.CST', piscofins.CST, PIS_COFINS_CST);
|
|
190
|
+
assertDecimal(issues, 'emissao.tributacaoFederal.piscofins.vBCPisCofins', piscofins.vBCPisCofins);
|
|
191
|
+
assertDecimal(issues, 'emissao.tributacaoFederal.piscofins.pAliqPis', piscofins.pAliqPis);
|
|
192
|
+
assertDecimal(issues, 'emissao.tributacaoFederal.piscofins.pAliqCofins', piscofins.pAliqCofins);
|
|
193
|
+
assertDecimal(issues, 'emissao.tributacaoFederal.piscofins.vPis', piscofins.vPis);
|
|
194
|
+
assertDecimal(issues, 'emissao.tributacaoFederal.piscofins.vCofins', piscofins.vCofins);
|
|
195
|
+
}
|
|
196
|
+
export function validateDpsJsonRequest(request) {
|
|
197
|
+
const issues = [];
|
|
198
|
+
validatePrestador(issues, request.prestador);
|
|
199
|
+
validateServico(issues, request.servico, request.emissao);
|
|
200
|
+
assertPattern(issues, 'emissao.nDPS', request.emissao.nDPS, /^[1-9][0-9]{0,14}$/, '1 a 15 digitos, sem zero inicial');
|
|
201
|
+
if (request.emissao.serie !== undefined) {
|
|
202
|
+
assertPattern(issues, 'emissao.serie', request.emissao.serie, /^\d{1,5}$/, 'serie numerica com ate 5 digitos');
|
|
203
|
+
}
|
|
204
|
+
assertDecimal(issues, 'emissao.valores.vServ', request.emissao.valores?.vServ ?? request.emissao.vServ);
|
|
205
|
+
assertDecimal(issues, 'emissao.valores.vServMoeda', request.emissao.valores?.vServMoeda ?? request.emissao.vServMoeda);
|
|
206
|
+
assertDecimal(issues, 'emissao.valores.cotacao', request.emissao.valores?.cotacao ?? request.emissao.cotacao);
|
|
207
|
+
validatePessoa(issues, 'emissao.tomador', request.emissao.tomador);
|
|
208
|
+
validatePessoa(issues, 'emissao.intermediario', request.emissao.intermediario);
|
|
209
|
+
validateTribMun(issues, request.emissao.tributacaoMunicipal, request.prestador.opSimpNac);
|
|
210
|
+
validateTribFed(issues, request.emissao);
|
|
211
|
+
validateTotTrib(issues, request.emissao, request.prestador.opSimpNac);
|
|
212
|
+
validateComercioExterior(issues, request.emissao);
|
|
213
|
+
validateUnsupportedShapes(issues, request.emissao);
|
|
214
|
+
if (issues.length > 0) {
|
|
215
|
+
throw new DpsFiscalValidationError(issues);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=fiscalValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fiscalValidation.js","sourceRoot":"","sources":["../fiscalValidation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Compacta (GZip) e codifica em Base64 — formato exigido por dpsXmlGZipB64. */
|
|
2
|
+
export declare function gzipBase64(xml: string): string;
|
|
3
|
+
/** Inverso: decodifica Base64 e descompacta GZip (resposta nfseXmlGZipB64). */
|
|
4
|
+
export declare function gunzipBase64(b64: string): string;
|
package/dist/gzipB64.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { gzipSync, gunzipSync } from 'node:zlib';
|
|
2
|
+
/** Compacta (GZip) e codifica em Base64 — formato exigido por dpsXmlGZipB64. */
|
|
3
|
+
export function gzipBase64(xml) {
|
|
4
|
+
return gzipSync(Buffer.from(xml, 'utf-8')).toString('base64');
|
|
5
|
+
}
|
|
6
|
+
/** Inverso: decodifica Base64 e descompacta GZip (resposta nfseXmlGZipB64). */
|
|
7
|
+
export function gunzipBase64(b64) {
|
|
8
|
+
return gunzipSync(Buffer.from(b64, 'base64')).toString('utf-8');
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=gzipB64.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gzipB64.js","sourceRoot":"","sources":["../gzipB64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEjD,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAChE,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NFS-e Nacional SDK.
|
|
3
|
+
*
|
|
4
|
+
* Handles the protocol layer only: mTLS, signing, gzip/base64, send, consult, events.
|
|
5
|
+
* No database, no tenants, no business rules.
|
|
6
|
+
*/
|
|
7
|
+
export { SEFIN_BASE_URL, TP_AMB, DEFAULT_AMBIENTE, resolveSefinBaseUrl } from './config.js';
|
|
8
|
+
export type { Ambiente } from './config.js';
|
|
9
|
+
export { consultarNfse, enviarEvento, extrairErros } from './sefinClient.js';
|
|
10
|
+
export type { SefinErro, SefinResposta } from './sefinClient.js';
|
|
11
|
+
export { buildDpsFromJson, buildDpsId } from './dpsJson.js';
|
|
12
|
+
export type { BuiltDps, ComExt, DpsJsonInput, DpsJsonRequest, EventoServico, Intermediario, Obra, PrestadorProfile, ServicoProfile, Tomador, TotTrib, TribFed, TribMun, TribNac, Valores, } from './dpsJson.js';
|
|
13
|
+
export { DpsFiscalValidationError, validateDpsJsonRequest } from './fiscalValidation.js';
|
|
14
|
+
export { EmitirNotaError, emitirNfse } from './emissaoNota.js';
|
|
15
|
+
export type { EmitirNotaOptions, NotaInput, ResultadoEmissaoNota } from './emissaoNota.js';
|
|
16
|
+
export { NfseClient } from './client.js';
|
|
17
|
+
export type { CreateInvoiceInput, InvoiceResource, NfseCertificateInput, NfseClientDpsDefaults, NfseClientOptions, NfseEnvironment, } from './client.js';
|
|
18
|
+
export { gzipBase64, gunzipBase64 } from './gzipB64.js';
|
|
19
|
+
export { signDps, signEnveloped, verifyDps, withUtf8XmlDeclaration } from './signXml.js';
|
|
20
|
+
export { loadPfxFromBuffer, loadPfx } from './loadPfx.js';
|
|
21
|
+
export type { PfxMaterial } from './loadPfx.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NFS-e Nacional SDK.
|
|
3
|
+
*
|
|
4
|
+
* Handles the protocol layer only: mTLS, signing, gzip/base64, send, consult, events.
|
|
5
|
+
* No database, no tenants, no business rules.
|
|
6
|
+
*/
|
|
7
|
+
export { SEFIN_BASE_URL, TP_AMB, DEFAULT_AMBIENTE, resolveSefinBaseUrl } from './config.js';
|
|
8
|
+
export { consultarNfse, enviarEvento, extrairErros } from './sefinClient.js';
|
|
9
|
+
export { buildDpsFromJson, buildDpsId } from './dpsJson.js';
|
|
10
|
+
export { DpsFiscalValidationError, validateDpsJsonRequest } from './fiscalValidation.js';
|
|
11
|
+
export { EmitirNotaError, emitirNfse } from './emissaoNota.js';
|
|
12
|
+
export { NfseClient } from './client.js';
|
|
13
|
+
export { gzipBase64, gunzipBase64 } from './gzipB64.js';
|
|
14
|
+
export { signDps, signEnveloped, verifyDps, withUtf8XmlDeclaration } from './signXml.js';
|
|
15
|
+
export { loadPfxFromBuffer, loadPfx } from './loadPfx.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAG5F,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG7E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAmB5D,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEzF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAUzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAEzF,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface PfxMaterial {
|
|
2
|
+
/** Chave privada em PEM (PKCS#8/PKCS#1) */
|
|
3
|
+
privateKeyPem: string;
|
|
4
|
+
/** Certificado do titular em PEM */
|
|
5
|
+
certPem: string;
|
|
6
|
+
/** Certificado em DER base64 (sem cabeçalhos PEM), p/ <X509Certificate> */
|
|
7
|
+
certDerBase64: string;
|
|
8
|
+
/** Buffer bruto do .pfx, para uso no handshake mTLS */
|
|
9
|
+
pfxBuffer: Buffer;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Lê um certificado ICP-Brasil A1 (.pfx/PKCS#12) e extrai a chave privada e o
|
|
13
|
+
* certificado do titular. Usado tanto para a assinatura XMLDSIG quanto para o
|
|
14
|
+
* mTLS (via pfxBuffer).
|
|
15
|
+
*/
|
|
16
|
+
/** Load from an in-memory buffer (used for decrypted certs in multi-tenant flow). */
|
|
17
|
+
export declare function loadPfxFromBuffer(pfxBuffer: Buffer, password: string): PfxMaterial;
|
|
18
|
+
export declare function loadPfx(pfxPath: string, password: string): PfxMaterial;
|
package/dist/loadPfx.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import forge from 'node-forge';
|
|
3
|
+
/**
|
|
4
|
+
* Lê um certificado ICP-Brasil A1 (.pfx/PKCS#12) e extrai a chave privada e o
|
|
5
|
+
* certificado do titular. Usado tanto para a assinatura XMLDSIG quanto para o
|
|
6
|
+
* mTLS (via pfxBuffer).
|
|
7
|
+
*/
|
|
8
|
+
/** Load from an in-memory buffer (used for decrypted certs in multi-tenant flow). */
|
|
9
|
+
export function loadPfxFromBuffer(pfxBuffer, password) {
|
|
10
|
+
return parsePfx(pfxBuffer, password);
|
|
11
|
+
}
|
|
12
|
+
export function loadPfx(pfxPath, password) {
|
|
13
|
+
const pfxBuffer = readFileSync(pfxPath);
|
|
14
|
+
return parsePfx(pfxBuffer, password);
|
|
15
|
+
}
|
|
16
|
+
function parsePfx(pfxBuffer, password) {
|
|
17
|
+
const p12Der = forge.util.createBuffer(pfxBuffer.toString('binary'));
|
|
18
|
+
const p12Asn1 = forge.asn1.fromDer(p12Der);
|
|
19
|
+
const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, password);
|
|
20
|
+
// Chave privada
|
|
21
|
+
const keyBags = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag });
|
|
22
|
+
const keyBag = keyBags[forge.pki.oids.pkcs8ShroudedKeyBag]?.[0];
|
|
23
|
+
if (!keyBag?.key)
|
|
24
|
+
throw new Error('Chave privada não encontrada no .pfx (senha incorreta?)');
|
|
25
|
+
const privateKeyPem = forge.pki.privateKeyToPem(keyBag.key);
|
|
26
|
+
// Certificado do titular: o que casa com a chave (não-CA, com o CNPJ)
|
|
27
|
+
const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });
|
|
28
|
+
const certs = certBags[forge.pki.oids.certBag] ?? [];
|
|
29
|
+
const isCa = (b) => {
|
|
30
|
+
const ext = b.cert?.getExtension('basicConstraints');
|
|
31
|
+
return ext?.cA === true;
|
|
32
|
+
};
|
|
33
|
+
const holder = certs.find((b) => b.cert && !isCa(b)) ?? certs[0];
|
|
34
|
+
if (!holder?.cert)
|
|
35
|
+
throw new Error('Certificado do titular não encontrado no .pfx');
|
|
36
|
+
const certPem = forge.pki.certificateToPem(holder.cert);
|
|
37
|
+
const certDer = forge.asn1.toDer(forge.pki.certificateToAsn1(holder.cert)).getBytes();
|
|
38
|
+
const certDerBase64 = forge.util.encode64(certDer);
|
|
39
|
+
return { privateKeyPem, certPem, certDerBase64, pfxBuffer };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=loadPfx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadPfx.js","sourceRoot":"","sources":["../loadPfx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,MAAM,YAAY,CAAC;AAa/B;;;;GAIG;AACH,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAAC,SAAiB,EAAE,QAAgB;IACnE,OAAO,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,QAAgB;IACvD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,QAAQ,CAAC,SAAiB,EAAE,QAAgB;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAE3D,gBAAgB;IAChB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,CAAC,MAAM,EAAE,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7F,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAE5D,sEAAsE;IACtE,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACrD,MAAM,IAAI,GAAG,CAAC,CAAmB,EAAW,EAAE;QAC5C,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,kBAAkB,CAAiC,CAAC;QACrF,OAAO,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC;IAC1B,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,EAAE,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAEpF,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtF,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEnD,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PfxMaterial } from './loadPfx.js';
|
|
2
|
+
import type { Ambiente } from './config.js';
|
|
3
|
+
export interface SefinErro {
|
|
4
|
+
Codigo: string;
|
|
5
|
+
Descricao: string;
|
|
6
|
+
Complemento?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SefinResposta {
|
|
9
|
+
status: number;
|
|
10
|
+
/** Corpo bruto parseado (JSON) */
|
|
11
|
+
body: any;
|
|
12
|
+
}
|
|
13
|
+
/** Normaliza a lista de erros retornada pelo SEFIN em diferentes formatos. */
|
|
14
|
+
export declare function extrairErros(body: any): SefinErro[];
|
|
15
|
+
/** SefinNacional · POST /nfse — transporte baixo nivel de DPS ja compactada em GZip+Base64. */
|
|
16
|
+
export declare function transmitirDpsCompactada(dpsXmlGZipB64: string, pfx: PfxMaterial, ambiente?: Ambiente): Promise<SefinResposta>;
|
|
17
|
+
/** SefinNacional · GET /nfse/{chave} — consulta a NFS-e pela chave de acesso (50 dígitos). */
|
|
18
|
+
export declare function consultarNfse(chave: string, pfx: PfxMaterial, ambiente?: Ambiente): Promise<SefinResposta>;
|
|
19
|
+
/** SefinNacional · POST /nfse/{chave}/eventos — registra evento fiscal da NFS-e. */
|
|
20
|
+
export declare function enviarEvento(pedRegXmlGZipB64: string, pfx: PfxMaterial, chaveAcesso: string, ambiente?: Ambiente): Promise<SefinResposta>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import https from 'node:https';
|
|
2
|
+
import { resolveSefinBaseUrl } from './config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Requisição mTLS de baixo nível ao SefinNacional, retornando o corpo bruto (Buffer).
|
|
5
|
+
* Usa key+cert PEM no handshake (o .pfx legado ICP-Brasil é rejeitado pelo TLS do Node).
|
|
6
|
+
*/
|
|
7
|
+
function sefinRequest(opts, pfx, baseOverride) {
|
|
8
|
+
const url = new URL(`${baseOverride ?? resolveSefinBaseUrl()}${opts.path}`);
|
|
9
|
+
const payload = opts.jsonBody != null ? JSON.stringify(opts.jsonBody) : undefined;
|
|
10
|
+
const headers = {
|
|
11
|
+
Accept: 'application/json',
|
|
12
|
+
};
|
|
13
|
+
if (payload != null) {
|
|
14
|
+
headers['Content-Type'] = 'application/json';
|
|
15
|
+
headers['Content-Length'] = Buffer.byteLength(payload);
|
|
16
|
+
}
|
|
17
|
+
const options = {
|
|
18
|
+
method: opts.method,
|
|
19
|
+
hostname: url.hostname,
|
|
20
|
+
port: url.port || 443,
|
|
21
|
+
path: url.pathname + url.search,
|
|
22
|
+
headers,
|
|
23
|
+
key: pfx.privateKeyPem,
|
|
24
|
+
cert: pfx.certPem,
|
|
25
|
+
rejectUnauthorized: true,
|
|
26
|
+
};
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const req = https.request(options, (res) => {
|
|
29
|
+
const chunks = [];
|
|
30
|
+
res.on('data', (c) => chunks.push(c));
|
|
31
|
+
res.on('end', () => resolve({
|
|
32
|
+
status: res.statusCode ?? 0,
|
|
33
|
+
contentType: String(res.headers['content-type'] ?? ''),
|
|
34
|
+
buffer: Buffer.concat(chunks),
|
|
35
|
+
}));
|
|
36
|
+
});
|
|
37
|
+
req.on('error', reject);
|
|
38
|
+
if (payload != null)
|
|
39
|
+
req.write(payload);
|
|
40
|
+
req.end();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** Parseia o corpo como JSON; mantém texto cru se não for JSON (ex.: 403 HTML). */
|
|
44
|
+
function parseJson(raw) {
|
|
45
|
+
const text = raw.buffer.toString('utf-8');
|
|
46
|
+
try {
|
|
47
|
+
return { status: raw.status, body: text ? JSON.parse(text) : null };
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return { status: raw.status, body: text };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isRecord(value) {
|
|
54
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
55
|
+
}
|
|
56
|
+
function normalizeErro(value) {
|
|
57
|
+
const erro = {
|
|
58
|
+
Codigo: String(value.Codigo ?? value.codigo ?? value.code ?? 'DESCONHECIDO'),
|
|
59
|
+
Descricao: String(value.Descricao ?? value.descricao ?? value.mensagem ?? value.message ?? ''),
|
|
60
|
+
};
|
|
61
|
+
const complemento = value.Complemento ?? value.complemento;
|
|
62
|
+
if (complemento != null)
|
|
63
|
+
erro.Complemento = String(complemento);
|
|
64
|
+
return erro;
|
|
65
|
+
}
|
|
66
|
+
function isSefinSuccessBody(body) {
|
|
67
|
+
return (body.sucesso === true ||
|
|
68
|
+
typeof body.chaveAcesso === 'string' ||
|
|
69
|
+
typeof body.nfseXmlGZipB64 === 'string' ||
|
|
70
|
+
typeof body.idDps === 'string');
|
|
71
|
+
}
|
|
72
|
+
/** Normaliza a lista de erros retornada pelo SEFIN em diferentes formatos. */
|
|
73
|
+
export function extrairErros(body) {
|
|
74
|
+
if (!body)
|
|
75
|
+
return [];
|
|
76
|
+
if (Array.isArray(body))
|
|
77
|
+
return body.map(normalizeErro);
|
|
78
|
+
if (!isRecord(body)) {
|
|
79
|
+
return [{ Codigo: 'DESCONHECIDO', Descricao: String(body) }];
|
|
80
|
+
}
|
|
81
|
+
if (isSefinSuccessBody(body))
|
|
82
|
+
return [];
|
|
83
|
+
if (Array.isArray(body.erros))
|
|
84
|
+
return body.erros.map(normalizeErro);
|
|
85
|
+
if (Array.isArray(body.Erros))
|
|
86
|
+
return body.Erros.map(normalizeErro);
|
|
87
|
+
if (Array.isArray(body.erro))
|
|
88
|
+
return body.erro.map(normalizeErro);
|
|
89
|
+
if (Array.isArray(body.Erro))
|
|
90
|
+
return body.Erro.map(normalizeErro);
|
|
91
|
+
if (body.Codigo || body.codigo) {
|
|
92
|
+
return [normalizeErro(body)];
|
|
93
|
+
}
|
|
94
|
+
return [
|
|
95
|
+
{ Codigo: 'DESCONHECIDO', Descricao: JSON.stringify(body) },
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
/** SefinNacional · POST /nfse — transporte baixo nivel de DPS ja compactada em GZip+Base64. */
|
|
99
|
+
export async function transmitirDpsCompactada(dpsXmlGZipB64, pfx, ambiente) {
|
|
100
|
+
const base = ambiente ? resolveSefinBaseUrl(ambiente) : undefined;
|
|
101
|
+
return parseJson(await sefinRequest({ method: 'POST', path: '/nfse', jsonBody: { dpsXmlGZipB64 } }, pfx, base));
|
|
102
|
+
}
|
|
103
|
+
/** SefinNacional · GET /nfse/{chave} — consulta a NFS-e pela chave de acesso (50 dígitos). */
|
|
104
|
+
export async function consultarNfse(chave, pfx, ambiente) {
|
|
105
|
+
const base = ambiente ? resolveSefinBaseUrl(ambiente) : undefined;
|
|
106
|
+
return parseJson(await sefinRequest({ method: 'GET', path: `/nfse/${chave}` }, pfx, base));
|
|
107
|
+
}
|
|
108
|
+
/** SefinNacional · POST /nfse/{chave}/eventos — registra evento fiscal da NFS-e. */
|
|
109
|
+
export async function enviarEvento(pedRegXmlGZipB64, pfx, chaveAcesso, ambiente) {
|
|
110
|
+
const base = ambiente ? resolveSefinBaseUrl(ambiente) : undefined;
|
|
111
|
+
return parseJson(await sefinRequest({
|
|
112
|
+
method: 'POST',
|
|
113
|
+
path: `/nfse/${chaveAcesso}/eventos`,
|
|
114
|
+
jsonBody: { pedRegXmlGZipB64 },
|
|
115
|
+
}, pfx, base));
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=sefinClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sefinClient.js","sourceRoot":"","sources":["../sefinClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PfxMaterial } from './loadPfx.js';
|
|
2
|
+
/** Garante declaracao XML UTF-8 antes de compactar/enviar para a SEFIN. */
|
|
3
|
+
export declare function withUtf8XmlDeclaration(xml: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Assina (XMLDSIG enveloped) o elemento de nome local `localName`, referenciando
|
|
6
|
+
* seu Id (URI="#<id>"). A <Signature> é inserida como irmã desse elemento.
|
|
7
|
+
* Usado para infDPS (emissão) e infPedReg (eventos/cancelamento).
|
|
8
|
+
*/
|
|
9
|
+
export declare function signEnveloped(xml: string, refId: string, localName: string, pfx: PfxMaterial): string;
|
|
10
|
+
/** Assina a DPS (referência em infDPS). */
|
|
11
|
+
export declare function signDps(xml: string, dpsId: string, pfx: PfxMaterial): string;
|
|
12
|
+
/** Valida uma DPS assinada usando o certificado fornecido. Útil em testes. */
|
|
13
|
+
export declare function verifyDps(signedXml: string, certPem: string): boolean;
|
package/dist/signXml.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SignedXml } from 'xml-crypto';
|
|
2
|
+
import { DOMParser } from '@xmldom/xmldom';
|
|
3
|
+
// Algoritmos observados nas NFS-e reais do Sistema Nacional.
|
|
4
|
+
// Centralizados aqui para troca fácil caso o ambiente exija variantes.
|
|
5
|
+
const SIGNATURE_ALGORITHM = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
|
|
6
|
+
const DIGEST_ALGORITHM = 'http://www.w3.org/2001/04/xmlenc#sha256';
|
|
7
|
+
const CANON_ALGORITHM = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
|
|
8
|
+
const ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature';
|
|
9
|
+
/** Garante declaracao XML UTF-8 antes de compactar/enviar para a SEFIN. */
|
|
10
|
+
export function withUtf8XmlDeclaration(xml) {
|
|
11
|
+
const xmlWithoutDeclaration = xml.replace(/^\uFEFF?\s*<\?xml[^?]*\?>\s*/i, '');
|
|
12
|
+
return `<?xml version="1.0" encoding="UTF-8"?>${xmlWithoutDeclaration}`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Assina (XMLDSIG enveloped) o elemento de nome local `localName`, referenciando
|
|
16
|
+
* seu Id (URI="#<id>"). A <Signature> é inserida como irmã desse elemento.
|
|
17
|
+
* Usado para infDPS (emissão) e infPedReg (eventos/cancelamento).
|
|
18
|
+
*/
|
|
19
|
+
export function signEnveloped(xml, refId, localName, pfx) {
|
|
20
|
+
const xpath = `//*[local-name(.)='${localName}']`;
|
|
21
|
+
const sig = new SignedXml({
|
|
22
|
+
privateKey: pfx.privateKeyPem,
|
|
23
|
+
publicCert: pfx.certPem,
|
|
24
|
+
signatureAlgorithm: SIGNATURE_ALGORITHM,
|
|
25
|
+
canonicalizationAlgorithm: CANON_ALGORITHM,
|
|
26
|
+
});
|
|
27
|
+
sig.addReference({
|
|
28
|
+
xpath,
|
|
29
|
+
transforms: [ENVELOPED, CANON_ALGORITHM],
|
|
30
|
+
digestAlgorithm: DIGEST_ALGORITHM,
|
|
31
|
+
uri: refId,
|
|
32
|
+
});
|
|
33
|
+
// Emite <KeyInfo> com o certificado do titular.
|
|
34
|
+
sig.getKeyInfoContent = () => `<X509Data><X509Certificate>${pfx.certDerBase64}</X509Certificate></X509Data>`;
|
|
35
|
+
sig.computeSignature(xml, { location: { reference: xpath, action: 'after' } });
|
|
36
|
+
return withUtf8XmlDeclaration(sig.getSignedXml());
|
|
37
|
+
}
|
|
38
|
+
/** Assina a DPS (referência em infDPS). */
|
|
39
|
+
export function signDps(xml, dpsId, pfx) {
|
|
40
|
+
return signEnveloped(xml, dpsId, 'infDPS', pfx);
|
|
41
|
+
}
|
|
42
|
+
/** Valida uma DPS assinada usando o certificado fornecido. Útil em testes. */
|
|
43
|
+
export function verifyDps(signedXml, certPem) {
|
|
44
|
+
const doc = new DOMParser().parseFromString(signedXml, 'text/xml');
|
|
45
|
+
const signature = doc.getElementsByTagName('Signature')[0];
|
|
46
|
+
if (!signature)
|
|
47
|
+
throw new Error('Nenhuma <Signature> encontrada no XML');
|
|
48
|
+
const sig = new SignedXml({ publicCert: certPem });
|
|
49
|
+
sig.loadSignature(signature);
|
|
50
|
+
return sig.checkSignature(signedXml);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=signXml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signXml.js","sourceRoot":"","sources":["../signXml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,6DAA6D;AAC7D,uEAAuE;AACvE,MAAM,mBAAmB,GAAG,mDAAmD,CAAC;AAChF,MAAM,gBAAgB,GAAG,yCAAyC,CAAC;AACnE,MAAM,eAAe,GAAG,qDAAqD,CAAC;AAC9E,MAAM,SAAS,GAAG,uDAAuD,CAAC;AAE1E,2EAA2E;AAC3E,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,MAAM,qBAAqB,GAAG,GAAG,CAAC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;IAC/E,OAAO,yCAAyC,qBAAqB,EAAE,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,KAAa,EACb,SAAiB,EACjB,GAAgB;IAEhB,MAAM,KAAK,GAAG,sBAAsB,SAAS,IAAI,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC;QACxB,UAAU,EAAE,GAAG,CAAC,aAAa;QAC7B,UAAU,EAAE,GAAG,CAAC,OAAO;QACvB,kBAAkB,EAAE,mBAAmB;QACvC,yBAAyB,EAAE,eAAe;KAC3C,CAAC,CAAC;IAEH,GAAG,CAAC,YAAY,CAAC;QACf,KAAK;QACL,UAAU,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;QACxC,eAAe,EAAE,gBAAgB;QACjC,GAAG,EAAE,KAAK;KACX,CAAC,CAAC;IAEH,gDAAgD;IAChD,GAAG,CAAC,iBAAiB,GAAG,GAAG,EAAE,CAC3B,8BAA8B,GAAG,CAAC,aAAa,+BAA+B,CAAC;IAEjF,GAAG,CAAC,gBAAgB,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/E,OAAO,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,KAAa,EAAE,GAAgB;IAClE,OAAO,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,SAAS,CAAC,SAAiB,EAAE,OAAe;IAC1D,MAAM,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,GAAG,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACzE,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,GAAG,CAAC,aAAa,CAAC,SAA4B,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC"}
|