Alguem comunica com o ws da nfe usando node?

25 respostas Resolvido
nodejsjavascript
thimor

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

Tiago_Backes1

Olá, conseguiu solucionar esse problema?

thimor

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

Tiago_Backes1

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!

thimor

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.

Tiago_Backes1
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.

thimor

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.

Tiago_Backes1

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>
thimor

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

thimor

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

Tiago_Backes1

Ajustei e testei. Ainda XML mal formado.

Tiago_Backes1

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>
thimor

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

gcrozariol

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.

thimor

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.

pablogeokar

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.

pablogeokar

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

Vinicius_Caetano

coloca a opção strictSSL como false

thimor

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

pablogeokar

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<<<');
  })

})
Matheus_Molin

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,
        }),
      })
lucashpmelo

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