1. java
  2. android
  3. c#
  4. .net
  5. javascript
  6. php
  7. jquery
  8. html
  9. sql

Erro ocasional ao transmitir NFCe nos novos webservices da Sefaz do RS - Connection reset

Tenho um sistema de emissão de NFe e NFCe que usamos para vários clientes do RS. Há alguns meses a sefaz daqui andou mudando a estrutura dos webservices, então eles também disponibilizaram novas URL's para acesso ao serviço (as antigas continuam funcionando até final de 2015). Já baixei a cadeia de certificados e importei em nosso repositório de certificados confiáveis. Fiz alguns testes e tive o seguinte problema: As vezes funciona e as vezes não! As vezes eu mando 5 notas e todas são emitidas sem problema nenhum, e do nada começa a dar erro ao conectar ao WS. O erro que acontece (quando acontece) é o seguinte:

INFO (11:19:42,368) - Unable to sendViaPost to url[https://nfce-homologacao.sefazrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao.asmx]java.net.SocketException: Connection reset

Achei que pudesse ser algo no meu provedor de internet, porém tentei colocar em alguns clientes e ocorre o mesmo problema. As vezes da certo e em outras da esse erro.

Com a URL antiga funcionava tudo 100%, isso era quando a URL antiga servia tanto pra NFe quanto pra NFCe. Agora com as novas eles separaram os serviços, e a nova da NFe funciona perfeitamente, o problema está apenas na NFCe.

Falei com o pessoal da sefaz e segundo eles não é problema com eles. Porém, não souberam informar o por que de as vezes a conexão não ser aceita. Também acredito não ser problema em meu código, visto que as vezes funciona. Mas aí já não posso ter tanta certeza. Alguém sabe o que poderia estar acontecendo?

RESOLVIDO

Graças ao Leandro Kersting, consegui resoler o problema. Estou usando o axis como cliente, e uso uma socket factory personalizada. Segue o código dessa factory, onde a diferença pra resolver o problema foi setar TLSv1 nessa linha SSLContext sslContext = SSLContext.getInstance("TLSv1");, que antes tinha apenas "TLS" no parametro:

import java.io.IOException;  
import java.net.InetAddress;  
import java.net.InetSocketAddress;  
import java.net.Socket;  
import java.net.SocketAddress;  
import java.net.UnknownHostException;  
import java.security.KeyManagementException;  
import java.security.KeyStore;  
import java.security.KeyStoreException;  
import java.security.NoSuchAlgorithmException;  
import java.security.Principal;  
import java.security.PrivateKey;  
import java.security.cert.CertificateException;  
import java.security.cert.X509Certificate;  

import javax.net.SocketFactory;  
import javax.net.ssl.KeyManager;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.TrustManager;  
import javax.net.ssl.TrustManagerFactory;  
import javax.net.ssl.X509KeyManager;  
import org.apache.commons.httpclient.params.HttpConnectionParams;  
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;  

public class SocketFactoryDinamico implements ProtocolSocketFactory {  
    private SSLContext ssl = null;  
    private X509Certificate certificate;  
    private PrivateKey privateKey;

    public SocketFactoryDinamico(X509Certificate certificate,  
            PrivateKey privateKey) {  
        this.certificate = certificate;  
        this.privateKey = privateKey;  
    }  

    private SSLContext createSSLContext() {  
        try {  
            KeyManager[] keyManagers = createKeyManagers();  
            TrustManager[] trustManagers = createTrustManagers();  
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(keyManagers, trustManagers, null);  

            return sslContext;  
        } catch (KeyManagementException | KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
            throw new RuntimeException(e);
        }
    }  

    private SSLContext getSSLContext() {  
        if (ssl == null) {  
            ssl = createSSLContext();  
        }  
        return ssl;  
    }  

    public Socket createSocket(String host, int port, InetAddress localAddress,  
            int localPort, HttpConnectionParams params){
        Socket socket=null;
        try{
            if (params == null) {  
                throw new IllegalArgumentException("Parameters may not be null");  
            }
            int timeout = params.getConnectionTimeout();
            SocketFactory socketfactory = getSSLContext().getSocketFactory();
            if (timeout == 0) {  
                return socketfactory.createSocket(host, port, localAddress,  
                        localPort);  
            }  

            socket = socketfactory.createSocket();
            SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);  
            SocketAddress remoteaddr = new InetSocketAddress(host, port);  
            socket.bind(localaddr);
            socket.connect(remoteaddr, timeout);
        }catch(Exception e){
            throw new RuntimeException(e);
        }

        return socket;  
    }  

    public Socket createSocket(String host, int port, InetAddress clientHost,  
            int clientPort) throws IOException, UnknownHostException {  
        return getSSLContext().getSocketFactory().createSocket(host, port,  
                clientHost, clientPort);  
    }  

    public Socket createSocket(String host, int port) throws IOException,  
            UnknownHostException {  
        return getSSLContext().getSocketFactory().createSocket(host, port);  
    }  

    public Socket createSocket(Socket socket, String host, int port,  
            boolean autoClose) throws IOException, UnknownHostException {  
        return getSSLContext().getSocketFactory().createSocket(socket, host,  
                port, autoClose);  
    }  

    public KeyManager[] createKeyManagers() {  
        HSKeyManager keyManager = new HSKeyManager(certificate, privateKey);  

        return new KeyManager[] { keyManager };  
    }  

    public TrustManager[] createTrustManagers() throws KeyStoreException,  
            NoSuchAlgorithmException, CertificateException, IOException {  
        KeyStore trustStore = KeyStore.getInstance("JKS");  

        trustStore.load(SocketFactoryDinamico.class.getResourceAsStream("/br/com/atualy/nfce/webservices/NFeCacerts"), "changeit".toCharArray());
        TrustManagerFactory trustManagerFactory = TrustManagerFactory  
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());  
        trustManagerFactory.init(trustStore);
        return trustManagerFactory.getTrustManagers();  
    }  

    class HSKeyManager implements X509KeyManager {  

        private X509Certificate certificate;  
        private PrivateKey privateKey;  

        public HSKeyManager(X509Certificate certificate, PrivateKey privateKey) {  
            this.certificate = certificate;  
            this.privateKey = privateKey;  
        }  

        public String chooseClientAlias(String[] arg0, Principal[] arg1,  
                Socket arg2) {  
            return certificate.getIssuerDN().getName();  
        }  

        public String chooseServerAlias(String arg0, Principal[] arg1,  
                Socket arg2) {  
            return null;  
        }  

        public X509Certificate[] getCertificateChain(String arg0) {  
            return new X509Certificate[] { certificate };  
        }  

        public String[] getClientAliases(String arg0, Principal[] arg1) {  
            return new String[] { certificate.getIssuerDN().getName() };  
        }  

        public PrivateKey getPrivateKey(String arg0) {  
            return privateKey;  
        }  

        public String[] getServerAliases(String arg0, Principal[] arg1) {  
            return null;  
        }  
    }

}

E é assim que eu seto ela na conexão, toda vez que chamo um WS da sefaz:

SocketFactoryDinamico socketFactoryDinamico = new SocketFactoryDinamico(Pkcs11Provider.certificate, Pkcs11Provider.privateKey);

Protocol protocol = new Protocol("https", socketFactoryDinamico, SSL_PORT);
Protocol.registerProtocol("https", protocol);
  • Já faz algum tempo que não trabalho com NFe, CTe, NFCe, etc... mas pelo seu log acredito que não utilize Axis nem JAX-WS certo? você faz suas conexões com SOAPMessages? ou esta abrindo um HTTPConnection na mão mesmo? geralmente isso é erro de socket não encerrado em uma requisição e outra, você tem uma SocketFactory implementada?

    Dilnei Cunha   10 de jul de 2015
  • Como agora estão usando balanceador de carga, talvez algum estagiário não tenha feito o serviço dele (kkkkkk), mas vamos conversar direto quem sabe podemos nos ajudar. Me manda um Mensagem Privada, ou add no skype. depois quando resolvermos o problema postamos a solução aqui. Abraços

    Leandro Kersting de Freitas   10 de jul de 2015
  • Dilnei Cunha, pois então, também estou passando por esse problema no momento, e no meu caso não é Socket aberto,(não encontrei nenhuma aberto nos meus testes), porem os mesmos testes rodam perfeitamente nos outros endpoints, O wsdl é exatamente o mesmo, entre o nf-e e nfc-e a unica coisa que muda é o endpoint. Tem alguma ideia? O que você acha que poderia ser alem do socket? Abraços valeu. \o/

    Leandro Kersting de Freitas   10 de jul de 2015
  • Ola Leandro, eu estava analisando seus logs e depois que li seu post eu preciso eu fazer uns testes antes de qualquer coisa rsrsrsrsr, muito estranho o que vocês estão passando, vou tentar ajudar e volto aqui para postar.

    Dilnei Cunha   10 de jul de 2015
  • Obrigado Dilnei, qualquer ajuda é bem vinda, talvez alguma configuração extra para a chamada, chequei a trocar o tamanho do header de 4k para 8k, 20k ... mas também não resolveu. Pela minha experiencia, quando agente fica dando voltas num bug assim, sempre é algo bem basico e trivial, mas está me deixando louco aqui. kkkk. Valeu qualquer dica é bem vinda, acho que vou acender umas velas aqui e rezar. kkkkk

    Leandro Kersting de Freitas   10 de jul de 2015
Mostrar todos os 8 comentários>
  1. Você vai ver essas setas em qualquer página de pergunta. Com elas, você pode dizer se uma pergunta ou uma resposta foram relevantes ou não.
  2. Edite sua pergunta ou resposta caso queira alterar ou adicionar detalhes.
  3. Caso haja alguma dúvida sobre a pergunta, adicione um comentário. O espaço de respostas deve ser utilizado apenas para responder a pergunta.
  4. Se o autor da pergunta marcar uma resposta como solucionada, esta marca aparecerá.
  5. Clique aqui para mais detalhes sobre o funcionamento do GUJ!

1 resposta

Não é a resposta que estava procurando? Procure outras perguntas com as tags java ou faça a sua própria pergunta.