Alguem comunica com o ws da nfe usando node?

25 respostas Resolvido
nodejsjavascript
T

Ola,

estou tentando fazer um servico para consumir o webservice da sefaz, mas nao estou conseguindo fazer o acesso com o certificado. Ja vi todo o material do node-soap, e na pagina de ajuda deles. Baseado no que li montei esse codigo:

const soap = require('soap');
const fs = require('fs');
const url = 'https://www1.nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx'
const pfxFile = __dirname + '\\certificado.pfx';
const pfxPass = "xxxxxx";
const options = {
  wsdl_options: {
    agentOptions: {
      pfx: pfxFile,
      passphrase: pfxPass,
      securityOptions: 'SSL_OP_NO_SSLv3'
    }
  }
}
soap.createClient(url, options, (err, client) => {
  if (err) {
    return console.log('createClient() erro>>>', err);
  }
  client.setSecurity(
    new soap.ClientSSLSecurityPFX(
      pfxFile,
      pfxPass,
      {
        rejectUnauthorized: false,
        strictSSL: false,
        secureOptions: constants.SSL_OP_NO_TLSv1_2,
        forever: true
      }
    )
  );
  console.log(client.describe());
})

porem quando execute recebo a mensagem de erro:

Error: not enough data
    at Object.createSecureContext (_tls_common.js:271:19)
    at Object.connect (_tls_wrap.js:1583:48)
    at Agent.createConnection (https.js:130:22)
    at Agent.createSocket (_http_agent.js:281:26)
    at Agent.addRequest (_http_agent.js:240:10)
    at new ClientRequest (_http_client.js:296:16)
    at Object.request (https.js:314:10)
    at Request.start (D:\Users\th1m0r\Projetos\aratu-nfe\node_modules\request\request.js:751:32)
    at Request.end (D:\Users\th1m0r\Projetos\aratu-nfe\node_modules\request\request.js:1505:10)
    at end (D:\Users\th1m0r\Projetos\aratu-nfe\node_modules\request\request.js:564:14)
    at Immediate._onImmediate (D:\Users\th1m0r\Projetos\aratu-nfe\node_modules\request\request.js:578:7)
    at processImmediate (internal/timers.js:456:21)

se alguem ja fez essa comunicacao, o que estou fazendo de errado?

[]'s

25 Respostas

T

Olá, conseguiu solucionar esse problema?

T

infelizmente não, mas vou me debruçar sobre isso novamente.

T

Que pena, vou tentar aqui e qualquer avanço eu compartilho.
Uma pergunta… De onde vc tirou que são essas as infos a serem passadas nas options? Pergunto pois o manual da nfe deixa muito a desejar nas informações técnicas. (considere também que não manjo muito de soap).
Caso tenha algum link ou conteúdo que possa me auxiliar nessa empreitada eu agradeço.
Valeu!

T

no manual do node-soap e num artigo que vi na internet. que nao abordava essa questao da conecao SSL com certificado digital. O site da sefaz nao informa muito pq isso varia de acordo com a linguagem de programacao. O webservice so precisa que o certificado seja utilizado como “senha” para abrir a conexao.

T
Solucao aceita

A solução está aí:

var options = {
    wsdl_options: {
      forever: true,
      rejectUnauthorized: false,
      strictSSL: false,
      pfx: fs.readFileSync(__dirname + '/folder/my.pfx'),
      passphrase: 'myPass'
    }
  };
  soap.createClient(myUrl, options, function (err, client) {
    console.log(err);
    console.log(client);
  });

Você deve enviar o conteudo do certificado, não somente o endereço.
E não é necessário o ClientSSLSecurityPFX, basta enviar nas options do http.

T

deu certo mesmo.
conectou
Agora quando tento executar o metodo para verificar o status apresenta que nao localizou o certificado. Mas pelo menos agora conecta no servidor, esta mais facil de solucionar

nfeStatusServicoNF() erro >>> Error: unable to get local issuer certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1501:34)
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:936:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:710:12) {
  code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'
}

valeu ai pela forca.

T

Estranho.

Eu também estou tendo problema, mas ao chamar o metodo nfeDistDFeInteresse.

soap.createClient(url, options, function (err, client){
	if(err){
		return console.log('ERRO1: ', err);
	}
	client.setSecurity(new soap.ClientSSLSecurityPFX(pfxFile, pfxPass));
	client.nfeDistDFeInteresse({nfeDadosMsg: xml}, function(err, result) {
		if(err){
			return console.log('ERRO2: ', err);
		}
		console.log('>>>\n', JSON.stringify(result, null, 4), '\n<<<');
	});
});

Ele chega a chamar e a resposta que tenho é:

{
    "nfeDistDFeInteresseResult": {
        "retDistDFeInt": {
            "attributes": {
                "versao": "1.00"
            },
            "tpAmb": "2",
            "verAplic": "1.2.0",
            "cStat": "243",
            "xMotivo": "Rejeicao: XML mal formado",
            "dhResp": "2020-11-06T17:43:29",
            "ultNSU": "000000000000000",
            "maxNSU": "000000000000000"
        }
    }
}

O XML que estou mandando na requisição provavelmente não está correto, mas não sei qual o problema dele. Tenho bastante dificuldade em entender o manual da nfe.

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soapenvelope">
    <soap12:Header>
        <nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/sce/wsdl/NfeRecepcao2">
            <versaoDados>4.0</versaoDados>
            <cUF>43</cUF>
        </nfeCabecMsg>
    </soap12:Header>
    <soap12:Body>
        <nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2">
            <distDFeInt xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.01">
                <tpAmb>2</tpAmb>
                <cUFAutor>43</cUFAutor>
                <CNPJ>1111111111111111</CNPJ>
                <distNSU>
                    <ultNSU>000000000000001</ultNSU>
                </distNSU>
            </distDFeInt>
        </nfeDadosMsg>
    </soap12:Body>
</soap12:Envelope>
T

Pois é, eu resolvi o meu problema e agora estou com o seu problema, de XML mal formado.

T

pelo xml schema, voce precisa mandar 4.00 e nao 4.0 como voce colocou. ajusta isso ai e testa.

T

Ajustei e testei. Ainda XML mal formado.

T

Mas é só esse mesmo o XML que eu devo enviar?
Eu não preciso assinar o XML? Tipo o exemplo abaixo que peguei no manual da NFE:

<NFe xmlns="http://www.portalfiscal.inf.br/nfe" >
 <infNFe Id="NFe31060243816719000108550000000010001234567897" versao="1.01">
 ...
 </infNFe>
 <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
 <SignedInfo>
 <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
 <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
 <Reference URI="#NFe31060243816719000108550000000010001234567897">
 <Transforms>
 <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
 <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
 </Transforms>
 <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
 <DigestValue>vFL68WETQ+mvj1aJAMDx+oVi928=</DigestValue>
 </Reference>
 </SignedInfo>
 <SignatureValue>IhXNhbdL1F9UGb2ydVc5v/gTB/y6r0KIFaf5evUi1i ...</SignatureValue>
 <KeyInfo>
 <X509Data>
 <X509Certificate>MIIFazCCBFOgAwIBAgIQaHEfNaxSeOEvZGlVDANB ... </X509Certificate>
 </X509Data>
 </KeyInfo>
T

sendo para enviar a nota ela tem que ir assinada, essas comunicacoes nao.

G

Estou tentando fazer essa conexão também, porém estou recebendo status 403 de volta por conta da autenticação. Vocês poderiam me ajudar em como conseguir esse certificado *.pfx?

Muito obrigado!

G

O certificado digital é para pessoas juridicas que emitem nota fiscal, você pode conseguir fazer um pedido para sua empresa.

A assinatura é ± assim:
<SignatureValue> inumeros numeros e letras, etc....</SignatureValue>

E ainda tem o certificado:
<X509Certificate>mais inumeros caracteres</X509Certificate>

Fora algumas outras informações que estão faltando no seu XML, e informações que são devolvidas após o retorno do seu XML do sefaz.

Aconselho pegar um XML de uma nota fiscal válida e ir testando, os schemas são bem complexos e cheio de detalhes, fora os manuais que não são nem um pouco bons ou didáticos.

T

ola, eu apenas segui o codigo e consegui me autenticar. Eu desisti do node, pq achei uma biblioteca opensouce em java, e resolveu meu problema.

P

Pessoal, eu tenho uma dúvida, eu gostaria de saber de vocês se existe alguma solução no node para a autenticação do certificado do tipo token, se existir alguma forma eu gostaria da sugestão de vocês, desde já agradeço.

P

Olá, você conseguiu solucionar o erro ‘UNABLE_TO_GET_ISSUER_CERT_LOCALLY’? estou me batendo aqui também.

V

coloca a opção strictSSL como false

T

passei um tempao fora daqui, mas eu desisti do node. desobri a biblioteca java nfe e to usando spring boot mesmo. nao achei o node legal para aplicacoes complexas

P

Pessoal, depois de bater cabeça por um tempo, eu consegui pegar as ideias de alguns e finalmente consegui botar para rodar, este código funfou 100%

const fs = require('fs');
const soap = require('soap');

const args = {
  distDFeInt: {
    attributes: {
      xmlns: 'http://www.portalfiscal.inf.br/nfe',
      versao: '1.01',
    },
    tpAmb: 1,
    cUFAutor: 29,
    CNPJ: '01234567891231',
    distNSU: {
      ultNSU: '000000000000000'
    }
  }
}

var options = {
  wsdl_options: {
    rejectUnauthorized: false,
    strictSSL: false,
    pfx: fs.readFileSync('./certs/certificadoDB.pfx'),
    passphrase: '1234',
  }
}

const url = 'https://www1.nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx?wsdl';

soap.createClient(url, options, (err, client) => {
  err && console.log('ERRO1', err)

  client.setSecurity(new soap.ClientSSLSecurityPFX('./certs/certificadoDB.pfx', '1234', {
    rejectUnauthorized: false,
    strictSSL: false,
    securityOptions: 'SSL_OP_NO_SSLv3',
    forever: true
  }));

  client.nfeDistDFeInteresse({ nfeDadosMsg: args }, (err, result) => {
    err && console.log('ERRO2', err)

    console.log('>>>\n', JSON.stringify(result, null, 4), '\n<<<');
  })

})
M

Só trazendo aqui uma outra implementação que eu fiz para a nota carioca (prefeitura RJ) utilizando basicamente só o axios (envelopado pela lib easy-soap-request).

const soapRequest = require(easy-soap-request);

const fs = require(fs)

const https = require(https)
const url = <a href="https://homologacao.notacarioca.rio.gov.br/WSNacional/nfse.asmx?WSDL">https://homologacao.notacarioca.rio.gov.br/WSNacional/nfse.asmx?WSDL</a>’;

const headers = {

‘Content-Type’: ‘text/xml; charset=utf-8’,

‘soapAction’: <a href="http://notacarioca.rio.gov.br/CancelarNfse">http://notacarioca.rio.gov.br/CancelarNfse</a>’,

};

// example data
const xml = <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <CancelarNfseRequest xmlns="http://notacarioca.rio.gov.br/"> <inputXML>teste</inputXML> </CancelarNfseRequest> </soap:Body> </soap:Envelope>;

const extraOpts =  {

httpsAgent: new https.Agent({

pfx: fs.readFileSync("./path/to/certificate.pfx"),

passphrase: senhaDoCertificado,

})

}
// usage of module

soapRequest({url, headers, xml, extraOpts}).then(({response: {body, statusCode}}) => {

console.log(body);

}).catch((errorBody) => {

console.error(errorBody);

})

Espero que traga alguma alternativa pra quem estava com o problema. Lidar com esses sistemas antigos pode ser uma dor de cabeça, principalmente pra quem tá usando linguagens mais atuais.

V
Olá, Pablo.

Eu estou fazendo um método parecido para CTe, mas estou sempre tendo este erro:

Error: unable to get local issuer certificate

at TLSSocket.onConnectSecure (_tls_wrap.js:1497:34)

at TLSSocket.emit (events.js:315:20)

at TLSSocket._finishInit (_tls_wrap.js:932:8)

at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:706:12) {

code: UNABLE_TO_GET_ISSUER_CERT_LOCALLY,


Poderia me ajudar?

D

Olá Tiago.

Estou tentando executar esse exemplo e recebo a seguinte mensagem:

Error: unable to get issuer certificate

at TLSSocket.onConnectSecure (node:_tls_wrap:1530:34)

at TLSSocket.emit (node:events:390:28)

at TLSSocket._finishInit (node:_tls_wrap:944:8)

at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:725:12) {

Tentei instalar certificados e o problema continua.
Existe alguma configuração para fazer no firefox ?

G

O que me ajudou foi fazer a requisição via axios, o uso do SoapClient mais atrapalhava do que ajudava

const response = await axios.post(URL, body, {
        headers: {
          'Content-Type': 'text/xml;charset=utf-8',
          SOAPAction: ACTION,
        },
        httpsAgent: new https.Agent({
          pfx: fs.readFileSync(filePathCertificate),
          passphrase: certificatePassphrase,
          rejectUnauthorized: false,
        }),
      })
L

Esse ano eu tive que fazer a integração de um sistema em Node com os WS da Sefaz de Distribuição de DF-e e Evento de Manifestação do Destinatário, então acabei criando uma biblioteca e publiquei no NPM. Para quem quiser testar na sua aplicação ou olhar o código para desenvolver uma solução própria, vou deixar o repositório do GitHub.

Criado 14 de julho de 2020
Ultima resposta 6 de jul. de 2022
Respostas 25
Participantes 11