Certificado digital NFe 2.0

Bom dia pessoal.

Confesso que tem, e vi bastante coisa não só aqui no forum, mas em outros links sobre certificado digital. Estou bastante confuso, e não sai do lugar ainda.
Estou trabalhando no desenvolvimento da NFe (Nota Fiscal eletronica, versão 2.0) para um cliente, vou resumir o que fiz até agora.

  • Baixei o manual de integração do site da receita.
  • Criei as classes (NFe, InfNfe, Imposto, Produto…etc…etc…) para a geração dos arquivos xml.
  • Consegui o certificado digital A1 do cliente pra fazer a assinatura do arquivo xml.
  • Fiz a validação e assinatura do arquivo xml.
    Beleza, até aqui tive sucesso.

Agora estou apanhando há dois dias com a comunicação com o WebService da receita.
Não sei bem como funciona isso:

Vi em muitos lugares que tem que baixar os WSDL da receita e gerar as classes java (não fiz ainda), outros dizem que não é preciso, dá pra chamar o serviço direto na receita, acessando por exemplo:

WebService.callWebService("https://homologacao.nfe.fazenda.sp.gov.br/nfeweb/services/nferecepcao.asmx?WSDL", WebService.nfeRecepcaoLote2, msgXml);

Quando eu faço assim, eu tenho esse erro:

        javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

pelo que entendi, o certificado digital não foi encontrado. Pois bem, eu já tenho o certificado digital que obtive do cliente, certo? Então abri meu navegador, no meu caso o FireFox e acessei : https://homologacao.nfe.fazenda.sp.gov.br/nfeweb/services/nferecepcao.asmx?WSDL
e adicionei o cerificado (quando acessei já apareceu a janela pedindo o certificado), daí apareceu a “estrutura” do WSDL, que é um xml.

Dúvida: Por que na aplicação aparece o erro?

Vi ainda que tem que gerar um keystore pra este arquivo .pfx, usar uns System.setProperty e tals, mas to muito confuso.

Se alguém puder me ajudar, por favor, não sei como continuar o meu desenvolvimento.

Ainda na luta.

Outra tentativa.
Criei a classe de Verificação do status do serviço a partir do WSDL baixado da receita.


import br.inf.portalfiscal.nfe.wsdl.nfestatusservico.NfeStatusServico;
import br.inf.portalfiscal.nfe.wsdl.nfestatusservico.NfeStatusServicoSoap;
import java.security.Security;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class Main {

    public static void main(String[] args) {

        String nfeCabecMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                + "<cabecMsg xmlns=\"http://www.portalfiscal.inf.br/nfe\" "
                + "versao=\"1.02\">" + "<versaoDados>1.07</versaoDados>"
                + "</cabecMsg>";

        String nfeDadosMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                + "<consStatServ " + " versao=\"1.07\""
                + " xmlns=\"http://www.portalfiscal.inf.br/nfe\">"
                + "<tpAmb>2</tpAmb>" + "<cUF>35</cUF>"
                + "<xServ>STATUS</xServ>" + "</consStatServ>";

        System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

        System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
        System.setProperty("javax.net.ssl.keyStore", "/aquivo.pfx");
        System.setProperty("javax.net.ssl.keyStorePassword", "senha");

        System.setProperty("javax.net.ssl.trustStoreType", "JKS");
        System.setProperty("javax.net.ssl.trustStore", "arquivo.jks");
        System.setProperty("javax.net.ssl.trustStorePassword", "senha");

//        NfeStatusServico service = new NfeStatusServicoLocator();
        NfeStatusServico service = new NfeStatusServico();
        try {
            NfeStatusServicoSoap nfeStatus = service.getNfeStatusServicoSoap();
            System.out.println(nfeStatus.nfeStatusServicoNF(nfeCabecMsg, nfeDadosMsg));//nessa linha gera a Exception
        } catch (Throwable e1) {
            e1.printStackTrace();
        }
    }

O arquivo.jks eu gerei a partir do arquivo.pfx, não sei esse procedimento está correto.

Os erros aparentemente são os mesmos:

com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:121)
        at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:142)
        at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:83)
        at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:105)
        at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
        at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
        at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
        at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
        at com.sun.xml.internal.ws.client.Stub.process(Stub.java:211)
        at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:124)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:98)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
        at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
        at $Proxy28.nfeStatusServicoNF(Unknown Source)
        at javaapplication9.Main.main(Main.java:51)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1665)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:258)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:252)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1165)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:610)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:546)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:913)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1158)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1185)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1169)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:440)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:979)
        at com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl.getOutputStream(HttpsURLConnectionOldImpl.java:220)
        at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:109)
        ... 14 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:324)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:224)
        at sun.security.validator.Validator.validate(Validator.java:235)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:147)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:230)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1144)
        ... 26 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:197)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:319)
        ... 32 more

Desculpa a insistência, mas alguém tem uma luz?
Continuo pesquisando.

Abraço.

Estou exatamente com o mesmo problema a varios dias. Nao sei mais o que fazer. Já li e reli milhares de instrucoes na web e nada deu certo até agora. Alguem tem alguma luz por favor…

Alcir,

Eu ainda estou descobrindo algumas coisas, dentre elas, uma informação que encontrei aqui mesmo no forum foi que, precisa setar o certificado do cliente e da receita na sua aplicação.
O meu ficou assim:

System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
        // certificado do cliente, no meu caso é um certificado do tipo A1
        System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
        System.setProperty("javax.net.ssl.keyStore", "certificado.pfx");
        System.setProperty("javax.net.ssl.keyStorePassword", "senha");

        // certificado da receita. Aqui voce tem que fazer a importação do certificado por um navegador de internet, eu fiz pelo FireFox no menu Editar->Preferencias->Certificados, nessa
 //janela eu fui em servidores->adicionar exceção e coloquei o link da receita (não me lembro qual foi). Daí vai aparecer a cadeia de certificados, voce seleciona e exporta-os.
// depois disso eu segui as instruções deste link http://www.java-samples.com/showtutorial.php?tutorialid=210
        System.setProperty("javax.net.ssl.trustStoreType", "JKS");
        System.setProperty("javax.net.ssl.trustStore", "certificado.jks");
        System.setProperty("javax.net.ssl.trustStorePassword", "senha");

Segui este link : http://www.java-samples.com/showtutorial.php?tutorialid=210
Ainda não resolvi todos os problemas, mas estamos caminhando.
Abraço

Edifran,

muitissimo obrigado pelo seu rápido retorno. Com sua resposta eu pude avancar grandemente no que estava fazendo.

Que Deus lhe retibua em dobro, te abençoando e a sua familia tambem.

Fique com Ele.

Abraços.

Caros,
podem me ajudar por favor a resolver um problema com o certificado A1?
ja estamos com XML montado, com toads as classes necessarias.
Porém, precisamos assinar o XML com o certificado, e eu não encontro em lugar nenhum como se faz isso.

Obrigado!