wmixvideo / nfe

Nota Fiscal Eletrônica em Java.
Apache License 2.0
654 stars 377 forks source link

Permitir a utilização de certificados A3 #27

Closed jefperito closed 8 years ago

jefperito commented 9 years ago

Atualmente só existe a possibilidade de utilizar certificados A1

lucasmoreiradev commented 8 years ago

@jefperito @fincatto

Talvez não seria interessante desenvolvermos uma solução para assinar com esses certificados (token, smart cards etc), e sim criar métodos para que a API receba o XML já assinado e só o envie para a SEFAZ, pois a forma de assinar um XML com certificados do tipo A3 depende muito do projeto. Por exemplo, nós temos um projeto Web e desenvolvemos uma comunicação com um sistema Desktop que assina o XML e devolve pra APP Web.

Para não quebrar o código de todos que utilizam a API, poderíamos criar outros métodos públicos que recebem um XML já assinado e apenas o envie para a SEFAZ, como por exemplo:

   // continua do jeito que está hoje sem quebrar o código de ninguém
    public NFLoteEnvioRetorno enviaLote(final NFLoteEnvio lote) throws Exception {
        final String xml = new AssinaturaDigital(this.config).assinarDocumento(lote.toString());
        return enviaLote(xml, lote.getIndicadorProcessamento());
    }
    // novo método que recebe um xml já assinado
    public NFLoteEnvioRetorno enviaLoteAssinado(final String xmlAssinado, NFLoteIndicadorProcessamento indicadorProcessamento) throws Exception {
        return enviaLote(xmlAssinado, indicadorProcessamento);
    }

    private NFLoteEnvioRetorno enviaLote(final String xml, NFLoteIndicadorProcessamento indicadorProcessamento)
            throws XMLStreamException, RemoteException, AxisFault, Exception {

        //Um dia, quando for possivel fazer o envio sincrono, fazer o tratamento de acordo
        //com o segundo parametro

        final OMElement omElement = this.nfeToOMElement(xml);

        final NfeDadosMsg dados = new NfeDadosMsg();
        dados.setExtraElement(omElement);

        final NfeCabecMsgE cabecalhoSOAP = this.getCabecalhoSOAP();

        WSLoteEnvio.LOG.info(omElement);
        final NfeAutorizacaoLoteResult autorizacaoLoteResult = new NfeAutorizacaoStub(NFAutorizador31.valueOfCodigoUF(this.config.getCUF()).getNfeAutorizacao(this.config.getAmbiente())).nfeAutorizacaoLote(dados, cabecalhoSOAP);
        final Persister persister = new Persister(new NFRegistryMatcher());
        final NFLoteEnvioRetorno loteEnvioRetorno = persister.read(NFLoteEnvioRetorno.class, autorizacaoLoteResult.getExtraElement().toString());
        WSLoteEnvio.LOG.info(loteEnvioRetorno.toString());
        return loteEnvioRetorno;
    }

No caso, isso teria de ser feito para todas as operações (CCe, Cancelamento, Inutilizacao...).

De qualquer forma, terei de fazer isso para continuar utilizando a API, pois meu sistema terá de suportar certificados A1 e A3. Gostaria muito de achar uma solução que ajudasse a todos.

O que vocês acham?

daviarimateia93 commented 8 years ago

acho muito valido!!

Enviado do meu iPhone

Em 25 de abr de 2016, às 19:15, Lucas Moreira notifications@github.com escreveu:

@jefperito @fincatto

Talvez não seria interessante desenvolvermos uma solução para assinar com esses certificados (token, smart cards etc), e sim criar métodos para que a API receba o XML já assinado e só o envie para a SEFAZ, pois a forma de assinar um XML com certificados do tipo A3 depende muito do projeto. Por exemplo, nós temos um projeto Web e desenvolvemos uma comunicação com um sistema Desktop que assina o XML e devolve pra APP Web.

Para não quebrar o código de todos que utilizam a API, poderíamos criar outros métodos públicos que recebem um XML já assinado e apenas o envie para a SEFAZ, como por exemplo:

// continua do jeito que está hoje sem quebrar o código de ninguém public NFLoteEnvioRetorno enviaLote(final NFLoteEnvio lote) throws Exception { final String xml = new AssinaturaDigital(this.config).assinarDocumento(lote.toString()); return enviaLote(xml, lote.getIndicadorProcessamento()); } // novo método que recebe um xml já assinado public NFLoteEnvioRetorno enviaLoteAssinado(final String xmlAssinado, NFLoteIndicadorProcessamento indicadorProcessamento) throws Exception { return enviaLote(xmlAssinado, indicadorProcessamento); }

private NFLoteEnvioRetorno enviaLote(final String xml, NFLoteIndicadorProcessamento indicadorProcessamento)
        throws XMLStreamException, RemoteException, AxisFault, Exception {

    //Um dia, quando for possivel fazer o envio sincrono, fazer o tratamento de acordo
    //com o segundo parametro

    final OMElement omElement = this.nfeToOMElement(xml);

    final NfeDadosMsg dados = new NfeDadosMsg();
    dados.setExtraElement(omElement);

    final NfeCabecMsgE cabecalhoSOAP = this.getCabecalhoSOAP();

    WSLoteEnvio.LOG.info(omElement);
    final NfeAutorizacaoLoteResult autorizacaoLoteResult = new NfeAutorizacaoStub(NFAutorizador31.valueOfCodigoUF(this.config.getCUF()).getNfeAutorizacao(this.config.getAmbiente())).nfeAutorizacaoLote(dados, cabecalhoSOAP);
    final Persister persister = new Persister(new NFRegistryMatcher());
    final NFLoteEnvioRetorno loteEnvioRetorno = persister.read(NFLoteEnvioRetorno.class, autorizacaoLoteResult.getExtraElement().toString());
    WSLoteEnvio.LOG.info(loteEnvioRetorno.toString());
    return loteEnvioRetorno;
}

No caso, isso teria de ser feito para todas as operações (CCe, Cancelamento, Inutilizacao...).

De qualquer forma, terei de fazer isso para continuar utilizando a API, pois meu sistema terá de suportar certificados A1 e A3. Gostaria muito de achar uma solução que ajudasse a todos.

O que vocês acham?

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub

fincatto commented 8 years ago

Muito interessante!!! Sempre quisemos fazer uma solução que funcionasse pra ambos mas, como não temos acesso ao certificado A3, não conseguimos desenvolver algo.

2016-04-25 19:27 GMT-03:00 Davi de Sousa Arimateia <notifications@github.com

:

acho muito valido!!

Enviado do meu iPhone

Em 25 de abr de 2016, às 19:15, Lucas Moreira notifications@github.com escreveu:

@jefperito @fincatto

Talvez não seria interessante desenvolvermos uma solução para assinar com esses certificados (token, smart cards etc), e sim criar métodos para que a API receba o XML já assinado e só o envie para a SEFAZ, pois a forma de assinar um XML com certificados do tipo A3 depende muito do projeto. Por exemplo, nós temos um projeto Web e desenvolvemos uma comunicação com um sistema Desktop que assina o XML e devolve pra APP Web.

Para não quebrar o código de todos que utilizam a API, poderíamos criar outros métodos públicos que recebem um XML já assinado e apenas o envie para a SEFAZ, como por exemplo:

// continua do jeito que está hoje sem quebrar o código de ninguém public NFLoteEnvioRetorno enviaLote(final NFLoteEnvio lote) throws Exception { final String xml = new AssinaturaDigital(this.config).assinarDocumento(lote.toString()); return enviaLote(xml, lote.getIndicadorProcessamento()); } // novo método que recebe um xml já assinado public NFLoteEnvioRetorno enviaLoteAssinado(final String xmlAssinado, NFLoteIndicadorProcessamento indicadorProcessamento) throws Exception { return enviaLote(xmlAssinado, indicadorProcessamento); }

private NFLoteEnvioRetorno enviaLote(final String xml, NFLoteIndicadorProcessamento indicadorProcessamento) throws XMLStreamException, RemoteException, AxisFault, Exception {

//Um dia, quando for possivel fazer o envio sincrono, fazer o tratamento de acordo //com o segundo parametro

final OMElement omElement = this.nfeToOMElement(xml);

final NfeDadosMsg dados = new NfeDadosMsg(); dados.setExtraElement(omElement);

final NfeCabecMsgE cabecalhoSOAP = this.getCabecalhoSOAP();

WSLoteEnvio.LOG.info(omElement); final NfeAutorizacaoLoteResult autorizacaoLoteResult = new NfeAutorizacaoStub(NFAutorizador31.valueOfCodigoUF(this.config.getCUF()).getNfeAutorizacao(this.config.getAmbiente())).nfeAutorizacaoLote(dados, cabecalhoSOAP); final Persister persister = new Persister(new NFRegistryMatcher()); final NFLoteEnvioRetorno loteEnvioRetorno = persister.read(NFLoteEnvioRetorno.class, autorizacaoLoteResult.getExtraElement().toString()); WSLoteEnvio.LOG.info(loteEnvioRetorno.toString()); return loteEnvioRetorno; } No caso, isso teria de ser feito para todas as operações (CCe, Cancelamento, Inutilizacao...).

De qualquer forma, terei de fazer isso para continuar utilizando a API, pois meu sistema terá de suportar certificados A1 e A3. Gostaria muito de achar uma solução que ajudasse a todos.

O que vocês acham?

— You are receiving this because you are subscribed to this thread.

Reply to this email directly or view it on GitHub

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-214549890

jefperito commented 8 years ago

A solução parece boa e bem simples.

caiocteodoro commented 8 years ago

@fauker @jefperito @fincatto

Preciso utilizar a biblioteca com certificado A3, e a proposta do fauker provavelmente é uma boa idéia. Como está o andamento dessa alteração? Precisam de alguma ajuda? Como utilizo a biblioteca seria muito bom colaborar.

jefperito commented 8 years ago

Estamos no momento adicionando algumas funcionalidades (Carregamento de certificados de forma dinâmica, geração da chave de forma automática, suporte a NFC-e, etc...), essa pretende entrar ir também.

lucasmoreiradev commented 8 years ago

@caiocteodoro ainda será implementado. Estamos terminando algumas pendências aqui no projeto.

caiocteodoro commented 8 years ago

Valeu @fauker @jefperito, qualquer coisa estou a disposição para ajudar.

jefperito commented 8 years ago

@fauker e outros,

Criei um método, WsFacade:enviaLoteAssinado, verifiquem se isso é o suficiente para envio de lotes assinados por A3.

jefperito commented 8 years ago

usem a versao 1.1.14-SNAPSHOT, Quando for lançada, provável não será 1.1.14 pois houve quebra de interface de algumas coisas.

fincatto commented 8 years ago

Possivelmente lançaremos como 1.2.0-RELEASE, pois houveram quebras necessárias para usar o certificado dinamicamente. Se houverem pull requests a serem feitos, peço que o façam antes da liberação da 1.2, que aí já incluímos tudo. Se precisarem de mais tempo, é só avisar que seguramos. Att.

On Mon, May 2, 2016 at 10:49 AM, Jeferson Viana Perito < notifications@github.com> wrote:

usem a versao 1.1.14-SNAPSHOT, Quando for lançada, provável não será 1.1.14 pois houve quebra de interface de algumas coisas.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216240331

lucasmoreiradev commented 8 years ago

@jefperito isso! teria de ter um método de receber o XML já assinado dessa forma mesmo! Aí teríamos de fazer isso pra todos os métodos de comunicação com a SEFAZ (eventos, inutilização etc), porque pelo o que eu vi, em todos os casos, o XML é assinado e enviado de uma vez só.

jefperito commented 8 years ago

é, eu vi aqui que ele é assinado tambem no cancelamento, carta correcao, e inutilização

jefperito commented 8 years ago

Adicionei tambem nos eventos.

caiocteodoro commented 8 years ago

Ta ficando top as alterações, já estou ate fazendo uns testes aqui... Mas pelo que percebi a gente tem que ter a chave publica para fazer o envio e as consultas na SEFAZ. E a chave privada é utilizada para assinar os eventos de envio, cancelamento, correção e inutilização. Tenho um exemplo de como carregar o certificado A3 feito no fórum javac, onde carrega o KS dessa maneira:

KeyStore ks = KeyStore.getInstance("PKCS11");

A classe NFSocketFactory que carrega o certificado A1 tem o seguinte carregamento: final KeyStore ks = KeyStore.getInstance("PKCS12"); --linha 73

Pelo que andei lendo o "PKCS12" é o arquivo que já contém a chave publica e privada do certificado digital e o "PKCS11" é o formato utilizado pelo A3.

Deveria a classe NFSocketFactory comportar o tipo PKCS11?

lucasmoreiradev commented 8 years ago

@jefperito massa! farei alguns testes hoje à noite com o certificado A3.

@caiocteodoro dessa forma vc consegue carregar o certificado, mas em uma aplicação Desktop. Em uma aplicação Web vc não vai conseguir carregar a KeyStore da máquina do usuário logado, concorda? Essa biblioteca não conhece quem a está utilizando (se é web, desktop etc). Pra ficar bem flexível, a ideia é que ela receba um XML já assinado (não importa de onde) e se comunique com a SEFAZ.

caiocteodoro commented 8 years ago

@fauker até o ponto de enviar p xml assinado está ok. Tenho uma aplicação WEB que gera o xml com a biblioteca e outra aplicação que está lendo o xml e assinando. Mas para qualquer ação com a sefaz tem que ter um certificado carregado. Como seria o procedimento?

lucasmoreiradev commented 8 years ago

Mas pelo que percebi a gente tem que ter a chave publica para fazer o envio e as consultas na SEFAZ.

Acho que você se refere à cadeia de certificados que precisamos informar ao consumirmos um WS da SEFAZ. No meu caso, eu gerei essa cadeia de certificados com seguinte tutorial, joguei-a na pasta resources do meu projeto e passei o caminho dela pra minha classe de configuração.

Seria isso?

caiocteodoro commented 8 years ago

A cadeia de certificados está ok, mas como o projeto é web não estou conseguindo entender como vamos informar o "certificado (byte[])" no projeto já que este é do tipo A3?

caiocteodoro commented 8 years ago

"Talvez não seria interessante desenvolvermos uma solução para assinar com esses certificados (token, smart cards etc), e sim criar métodos para que a API receba o XML já assinado e só o envie para a SEFAZ, pois a forma de assinar um XML com certificados do tipo A3 depende muito do projeto. Por exemplo, nós temos um projeto Web e desenvolvemos uma comunicação com um sistema Desktop que assina o XML e devolve pra APP Web."

@fauker

A sua aplicação WEB recebe o xml assinado e faz a comunicação com a SEFAZ? Ou é sua aplicação Desktop que assina e comunica com a SEFAZ e sua aplicação WEB somente recebe a resposta dessa comunicação?

Porque sem o certificado informado sua aplicação web não consegue se comunicar com a SEFAZ.

lucasmoreiradev commented 8 years ago

@caiocteodoro aquela classe de configuração (passar os bytes do certificado e tals) só tem como com o A1. Aí com o A3 provavelmente teria que passar um null, não sei. Hoje a noite farei alguns testes com a implementação do @jefperito para ver como vai funcionar.

Na minha aplicação, que é Web, o usuário poderá fazer o upload do certificado A1 (que aí sim poderei passar os bytes para a classe de configuração) ou ter o certificado A3.

No caso do A3, a solução foi criar uma app desktop que somente assine o XML e devolva pra app web enviar pra SEFAZ.

Respondendo a sua pergunta: qnd o certificado do usuário é do tipo A1, tudo é feito na Web. Quando é A3, preciso assinar o XML com um app desktop e devolver pra app Web terminar o processo.

caiocteodoro commented 8 years ago

@fauker

Eu já tenho o xml de EnvioLote assinado pela minha aplicação desktop com o certificado A3.

E a minha aplicação WEB está encarrega de fazer o envio desse lote, como fica a classe NfeConfig na aplicação WEb? No método que deve retornar o certificado "public byte[] getCertificado()"?

Se passar null da erro na classe NFSocketFactory ao tentar carregar um certificado que não exite.

fincatto commented 8 years ago

Quem sabe uma solução possa ser desenvolvida. Você poderia postar o codigo de como você assina usando um A3, nessa sua app desktop? Att, Diego

2016-05-02 16:21 GMT-03:00 Lucas Moreira notifications@github.com:

@caiocteodoro https://github.com/caiocteodoro aquela classe de configuração (passar os bytes do certificado e tals) só tem como com o A1.

Na minha aplicação, que é Web, o usuário poderá fazer o upload do certificado A1 (que aí sim poderei passar os bytes para a classe de configuração) ou ter o certificado A3.

No caso do A3, a solução foi criar uma app desktop que somente assine o XML e devolva pra app web enviar pra SEFAZ.

Respondendo a sua pergunta: qnd o certificado do usuário é do tipo A1, tudo é feito na Web. Quando é A3, preciso assinar o XML com um app desktop e devolver pra app Web terminar o processo.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216334973

lucasmoreiradev commented 8 years ago

@caiocteodoro pois é! isso que eu vou testar à noite.

@fincatto , no meu caso, a app Desktop utiliza a classe AssinaturaDigital aqui da lib, mas com uma modificação:

    public String assinarDocumento(final String conteudoXml, final String nomeCertificado) throws Exception {
        KeyStore ks = FabricaKeyStore.obterKeyStore();
        ks.load(null, null);

        KeyStore.PrivateKeyEntry keyEntry = null;
        Enumeration<String> aliasesEnum = ks.aliases();
        while (aliasesEnum.hasMoreElements()) {
            aliasesEnum.nextElement();
            if (ks.isKeyEntry(nomeCertificado)) {
                keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(
                        nomeCertificado,
                        new KeyStore.PasswordProtection("".toCharArray()));
                break;
            }
        }

        if(keyEntry == null){
            throw new CertificadoNaoConectadoException("Token n�o conectado.");
        }

        final XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
//à partir daqui, tudo igual
caiocteodoro commented 8 years ago

@fincatto @fauker

Uso um exemplo do fórum javac

Carrega o certificado A3

private void loadCertificates(String senha,  
            XMLSignatureFactory signatureFactory) throws Exception {  

        /** 
         * Para Certificados A3 Cartao usar: SmartCard.cfg; 
         * Para Certificados A3 Token usar: Token.cfg; 
         */  
        Provider provider = new sun.security.pkcs11.SunPKCS11("SmartCard.cfg");  
        Security.addProvider(provider);   

        KeyStore ks = KeyStore.getInstance("pkcs11", provider);  
        try {  
            ks.load(null, senha.toCharArray());  
        } catch (IOException e) {  
            throw new Exception("Senha do Certificado Digital incorreta ou Certificado inválido.");  
        }  

        KeyStore.PrivateKeyEntry pkEntry = null;  
        Enumeration<String> aliasesEnum = ks.aliases();  
        while (aliasesEnum.hasMoreElements()) {  
            String alias = (String) aliasesEnum.nextElement();  
            if (ks.isKeyEntry(alias)) {  
                pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias,  
                        new KeyStore.PasswordProtection(senha.toCharArray()));  
                privateKey = pkEntry.getPrivateKey();  
                break;  
            }  
        }  

        X509Certificate cert = (X509Certificate) pkEntry.getCertificate();  
        info("SubjectDN: " + cert.getSubjectDN().toString());  

        KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();  
        List<X509Certificate> x509Content = new ArrayList<X509Certificate>();  

        x509Content.add(cert);  
        X509Data x509Data = keyInfoFactory.newX509Data(x509Content);  
        keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));  
    }  

Lista as notas a serem assinadas

    public String assinaEnviNFe(String xml, String senha) throws Exception {  
        Document document = documentFactory(xml);    

        XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");    

        ArrayList<Transform> transformList = signatureFactory(signatureFactory);    

        loadCertificates(senha, signatureFactory);    

        for (int i = 0; i < document.getDocumentElement().getElementsByTagName(NFE).getLength(); i++) {    
            try {  
                assinarNFe(signatureFactory, transformList, privateKey, keyInfo, document, i);    
            } catch(Exception e)  {  
                continue;  
            }  
        }    

        return outputXML(document);  
    } 

Assina as notas

    private void assinarNFe(XMLSignatureFactory fac,  
            ArrayList<Transform> transformList, PrivateKey privateKey,  
            KeyInfo ki, Document document, int indexNFe) throws Exception {  

        NodeList elements = document.getElementsByTagName("infNFe");  
        org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(indexNFe);  
        String id = el.getAttribute("Id");  

        Reference ref = fac.newReference("#" + id,  
                fac.newDigestMethod(DigestMethod.SHA1, null), transformList,  
                null, null);  

        SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(  
                CanonicalizationMethod.INCLUSIVE,  
                (C14NMethodParameterSpec) null), fac  
                .newSignatureMethod(SignatureMethod.RSA_SHA1, null),  
                Collections.singletonList(ref));  

        XMLSignature signature = fac.newXMLSignature(si, ki);  

        DOMSignContext dsc = new DOMSignContext(privateKey, document.getDocumentElement().getElementsByTagName(NFE).item(indexNFe));  
        signature.sign(dsc);  
    } 
fincatto commented 8 years ago

Pelo que pude perceber numa analise rápida, a única coisa que muda é o carregamento do KeyStore, é isso mesmo?

caiocteodoro commented 8 years ago

Parece que sim, mas o que está complicando é fazer a aplicação WEB enviar o xml assinado pela aplicação desktop.

fincatto commented 8 years ago

Se você passar nulo e usar o método que o @jefperito criou, ainda ocorre o erro? Se sim, em que momento ocorre o erro?

caiocteodoro commented 8 years ago

O erro ocorre na classe NFSocketFactory, no método createKeyManagers na linha 72. No qual executa essa linha de comando:

try (InputStream certificado = new ByteArrayInputStream(config.getCertificado())) {

caiocteodoro commented 8 years ago

se deixar o método dessa maneira:

    private KeyManager[] createKeyManagers(final NFeConfig config) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
        if(config.getCertificado() != null){
            try (InputStream certificado = new ByteArrayInputStream(config.getCertificado())) {
                final KeyStore ks = KeyStore.getInstance("PKCS12");
                ks.load(certificado, config.getCertificadoSenha().toCharArray());

                final String alias = NFSocketFactory.getAlias(ks);
                final X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);
                final PrivateKey privateKey = (PrivateKey) ks.getKey(alias, config.getCertificadoSenha().toCharArray());
                return new KeyManager[] { new HSKeyManager(certificate, privateKey) };
            }
        }else{
            return null;
        }
    }

Vai passar tranquilamente mas vai gerar erro na classe NfeAutorizacaoStub linha 248, segue o erro:

org.apache.axis2.AxisFault: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430)
    at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:78)
    at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84)
    at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
    at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
    at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
    at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:621)
    at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:193)
    at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404)
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231)
    at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443)
    at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406)
    at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
    at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
    at com.fincatto.nfe310.webservices.gerado.NfeAutorizacaoStub.nfeAutorizacaoLote(NfeAutorizacaoStub.java:248)
    at com.fincatto.nfe310.webservices.WSLoteEnvio.comunicaLote(WSLoteEnvio.java:110)
    at com.fincatto.nfe310.webservices.WSLoteEnvio.enviaLoteAssinado(WSLoteEnvio.java:46)
    at com.fincatto.nfe310.webservices.WSFacade.enviaLoteAssinado(WSFacade.java:64)
    at agely.nucleo.nfe.teste.Main.main(Main.java:79)
Caused by: com.ctc.wstx.exc.WstxIOException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1692)
    at com.ctc.wstx.sw.BaseStreamWriter.close(BaseStreamWriter.java:288)
    at org.apache.axiom.util.stax.wrapper.XMLStreamWriterWrapper.close(XMLStreamWriterWrapper.java:46)
    at org.apache.axiom.om.impl.MTOMXMLStreamWriter.close(MTOMXMLStreamWriter.java:222)
    at org.apache.axiom.om.impl.llom.OMSerializableImpl.serializeAndConsume(OMSerializableImpl.java:192)
    at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:74)
    ... 21 more
Caused by: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.security.ssl.SSLSocketImpl.checkEOF(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.checkWrite(Unknown Source)
    at sun.security.ssl.AppOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.write(Unknown Source)
    at org.apache.commons.httpclient.ChunkedOutputStream.flushCacheWithAppend(ChunkedOutputStream.java:121)
    at org.apache.commons.httpclient.ChunkedOutputStream.write(ChunkedOutputStream.java:179)
    at com.ctc.wstx.io.UTF8Writer.flush(UTF8Writer.java:96)
    at com.ctc.wstx.sw.BufferingXmlWriter.flush(BufferingXmlWriter.java:214)
    at com.ctc.wstx.sw.BufferingXmlWriter.close(BufferingXmlWriter.java:194)
    at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1690)
    ... 26 more
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source)
    at sun.security.ssl.AppOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.write(Unknown Source)
    at org.apache.commons.httpclient.ChunkedOutputStream.flushCacheWithAppend(ChunkedOutputStream.java:121)
    at org.apache.commons.httpclient.ChunkedOutputStream.write(ChunkedOutputStream.java:179)
    at com.ctc.wstx.io.UTF8Writer.write(UTF8Writer.java:139)
    at com.ctc.wstx.sw.BufferingXmlWriter.writeRaw(BufferingXmlWriter.java:259)
    at com.ctc.wstx.sw.BufferingXmlWriter.writeCharacters(BufferingXmlWriter.java:543)
    at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:509)
    at org.apache.axiom.util.stax.wrapper.XMLStreamWriterWrapper.writeCharacters(XMLStreamWriterWrapper.java:100)
    at org.apache.axiom.om.impl.MTOMXMLStreamWriter.writeCharacters(MTOMXMLStreamWriter.java:325)
    at org.apache.axiom.om.impl.llom.OMTextImpl.writeOutput(OMTextImpl.java:249)
    at org.apache.axiom.om.impl.llom.OMTextImpl.internalSerialize(OMTextImpl.java:400)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.om.impl.llom.OMSerializableImpl.serialize(OMSerializableImpl.java:120)
    at org.apache.axiom.om.impl.llom.OMSerializableImpl.serialize(OMSerializableImpl.java:108)
    at com.fincatto.nfe310.webservices.gerado.NfeAutorizacaoStub$NfeDadosMsg.serialize(NfeAutorizacaoStub.java:1457)
    at com.fincatto.nfe310.webservices.gerado.NfeAutorizacaoStub$NfeDadosMsg.serialize(NfeAutorizacaoStub.java:1432)
    at org.apache.axis2.databinding.ADBDataSource.serialize(ADBDataSource.java:90)
    at org.apache.axiom.om.impl.llom.OMSourcedElementImpl.internalSerialize(OMSourcedElementImpl.java:638)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:563)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846)
    at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.serializeInternally(SOAPEnvelopeImpl.java:267)
    at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:229)
    at org.apache.axiom.om.impl.llom.OMSerializableImpl.serializeAndConsume(OMSerializableImpl.java:188)
    ... 22 more
Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
waldandrade commented 8 years ago

Tenho um código de assinatura de certificado A3 utilizando a biblioteca ... vou tentar enviar de alguma forma para vocês para que alguém inclua na biblioteca.

Tenho um sistema WEB ... e já tenho +/- uma estrutura feita em cima desta biblioteca, que fiz com algumas gambiarras ... mas funciona.

2016-05-03 7:51 GMT-03:00 caiocteodoro notifications@github.com:

se deixar o método dessa maneira:

private KeyManager[] createKeyManagers(final NFeConfig config) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
    if(config.getCertificado() != null){
        try (InputStream certificado = new ByteArrayInputStream(config.getCertificado())) {
            final KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(certificado, config.getCertificadoSenha().toCharArray());

            final String alias = NFSocketFactory.getAlias(ks);
            final X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);
            final PrivateKey privateKey = (PrivateKey) ks.getKey(alias, config.getCertificadoSenha().toCharArray());
            return new KeyManager[] { new HSKeyManager(certificate, privateKey) };
        }
    }else{
        return null;
    }
}

Vai passar tranquilamente mas vai gerar erro na classe NfeAutorizacaoStub, seque o erro:

org.apache.axis2.AxisFault: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:78) at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84) at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499) at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114) at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096) at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398) at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:621) at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:193) at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231) at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443) at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406) at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229) at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165) at com.fincatto.nfe310.webservices.gerado.NfeAutorizacaoStub.nfeAutorizacaoLote(NfeAutorizacaoStub.java:248) at com.fincatto.nfe310.webservices.WSLoteEnvio.comunicaLote(WSLoteEnvio.java:110) at com.fincatto.nfe310.webservices.WSLoteEnvio.enviaLoteAssinado(WSLoteEnvio.java:46) at com.fincatto.nfe310.webservices.WSFacade.enviaLoteAssinado(WSFacade.java:64) at agely.nucleo.nfe.teste.Main.main(Main.java:79) Caused by: com.ctc.wstx.exc.WstxIOException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1692) at com.ctc.wstx.sw.BaseStreamWriter.close(BaseStreamWriter.java:288) at org.apache.axiom.util.stax.wrapper.XMLStreamWriterWrapper.close(XMLStreamWriterWrapper.java:46) at org.apache.axiom.om.impl.MTOMXMLStreamWriter.close(MTOMXMLStreamWriter.java:222) at org.apache.axiom.om.impl.llom.OMSerializableImpl.serializeAndConsume(OMSerializableImpl.java:192) at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:74) ... 21 more Caused by: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at sun.security.ssl.SSLSocketImpl.checkEOF(Unknown Source) at sun.security.ssl.SSLSocketImpl.checkWrite(Unknown Source) at sun.security.ssl.AppOutputStream.write(Unknown Source) at java.io.BufferedOutputStream.flushBuffer(Unknown Source) at java.io.BufferedOutputStream.write(Unknown Source) at org.apache.commons.httpclient.ChunkedOutputStream.flushCacheWithAppend(ChunkedOutputStream.java:121) at org.apache.commons.httpclient.ChunkedOutputStream.write(ChunkedOutputStream.java:179) at com.ctc.wstx.io.UTF8Writer.flush(UTF8Writer.java:96) at com.ctc.wstx.sw.BufferingXmlWriter.flush(BufferingXmlWriter.java:214) at com.ctc.wstx.sw.BufferingXmlWriter.close(BufferingXmlWriter.java:194) at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1690) ... 26 more Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at sun.security.ssl.Alerts.getSSLException(Unknown Source) at sun.security.ssl.Alerts.getSSLException(Unknown Source) at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source) at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source) at sun.security.ssl.AppOutputStream.write(Unknown Source) at java.io.BufferedOutputStream.flushBuffer(Unknown Source) at java.io.BufferedOutputStream.write(Unknown Source) at org.apache.commons.httpclient.ChunkedOutputStream.flushCacheWithAppend(ChunkedOutputStream.java:121) at org.apache.commons.httpclient.ChunkedOutputStream.write(ChunkedOutputStream.java:179) at com.ctc.wstx.io.UTF8Writer.write(UTF8Writer.java:139) at com.ctc.wstx.sw.BufferingXmlWriter.writeRaw(BufferingXmlWriter.java:259) at com.ctc.wstx.sw.BufferingXmlWriter.writeCharacters(BufferingXmlWriter.java:543) at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:509) at org.apache.axiom.util.stax.wrapper.XMLStreamWriterWrapper.writeCharacters(XMLStreamWriterWrapper.java:100) at org.apache.axiom.om.impl.MTOMXMLStreamWriter.writeCharacters(MTOMXMLStreamWriter.java:325) at org.apache.axiom.om.impl.llom.OMTextImpl.writeOutput(OMTextImpl.java:249) at org.apache.axiom.om.impl.llom.OMTextImpl.internalSerialize(OMTextImpl.java:400) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:556) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.om.impl.llom.OMSerializableImpl.serialize(OMSerializableImpl.java:120) at org.apache.axiom.om.impl.llom.OMSerializableImpl.serialize(OMSerializableImpl.java:108) at com.fincatto.nfe310.webservices.gerado.NfeAutorizacaoStub$NfeDadosMsg.serialize(NfeAutorizacaoStub.java:1457) at com.fincatto.nfe310.webservices.gerado.NfeAutorizacaoStub$NfeDadosMsg.serialize(NfeAutorizacaoStub.java:1432) at org.apache.axis2.databinding.ADBDataSource.serialize(ADBDataSource.java:90) at org.apache.axiom.om.impl.llom.OMSourcedElementImpl.internalSerialize(OMSourcedElementImpl.java:638) at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:563) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:846) at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.serializeInternally(SOAPEnvelopeImpl.java:267) at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:229) at org.apache.axiom.om.impl.llom.OMSerializableImpl.serializeAndConsume(OMSerializableImpl.java:188) ... 22 more Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216494024

Waldney Souza de Andrade compengi engenharia & sistemas waldney.andrade@gmail.com waldney.andrade@gmail.com

+55(84)8894-3405 +55(84)9447-7354

waldandrade commented 8 years ago

Tem algumas coisas a mais que tem que ajustar Fincatto ....

waldandrade commented 8 years ago
    /**
     *
     * @param args
     * Teste de execuзгo com xml exemplo.
     */
    public static void main(String[] args) {

        String xmlNaoAssinado = "<?xml version=\"1.0\" encoding=\"utf-8\"?><NFe xmlns=\"http://www.portalfiscal.inf.br/nfe\"><infNFe Id=\"NFe43120103987283000133550010000006241607910981\" versao=\"3.00\"><ide><cUF>43</cUF><cNF>60791098</cNF><natOp>5.101 - VENDA</natOp><indPag>1</indPag><mod>55</mod><serie>1</serie><nNF>624</nNF><dEmi>2012-01-25</dEmi><tpNF>1</tpNF><cMunFG>4313409</cMunFG><tpImp>1</tpImp><tpEmis>1</tpEmis><cDV>1</cDV><tpAmb>2</tpAmb><finNFe>1</finNFe><procEmi>0</procEmi><verProc>2.02</verProc></ide><emit><CNPJ>03987283000133</CNPJ><xNome>MINHA EMPRESA TESTE LTDA.</xNome><xFant>MINHA EMPRESA FANTASIA TESTE</xFant><enderEmit><xLgr>RUA TESTE</xLgr><nro>123</nro><xBairro>CENTRO</xBairro><cMun>4312345</cMun><xMun>PORTO ALEGRE</xMun><UF>RS</UF><CEP>93000000</CEP> <cPais>1058</cPais><xPais>BRASIL</xPais><fone>5111223344</fone></enderEmit><IE>0868689965</IE><CRT>1</CRT></emit><dest><CNPJ>99999999000191</CNPJ><xNome>NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL</xNome><enderDest><xLgr>AV. DOS TESTES</xLgr><nro>202</nro><xBairro>CENTRO</xBairro><cMun>4369854</cMun><xMun>PORTO ALEGRE</xMun><UF>RS</UF><CEP>93000000</CEP><cPais>1058</cPais><xPais>BRASIL</xPais></enderDest><IE>ISENTO</IE></dest><det nItem=\"1\"><prod><cProd>15036</cProd><cEAN/><xProd>PRODUTO TESTE REF 123123</xProd><NCM>84123123</NCM><CFOP>5101</CFOP><uCom>UN</uCom><qCom>1.0000</qCom><vUnCom>590.0000</vUnCom><vProd>590.00</vProd><cEANTrib/><uTrib>UN</uTrib><qTrib>1.0000</qTrib><vUnTrib>590.0000</vUnTrib><indTot>1</indTot></prod><imposto><ICMS><ICMSSN101><orig>0</orig><CSOSN>101</CSOSN><pCredSN>2.82</pCredSN><vCredICMSSN>16.64</vCredICMSSN></ICMSSN101></ICMS><PIS><PISOutr><CST>99</CST><vBC>0.00</vBC><pPIS>0.00</pPIS><vPIS>0.00</vPIS></PISOutr></PIS><COFINS><COFINSOutr><CST>99</CST><vBC>0.00</vBC><pCOFINS>0.00</pCOFINS><vCOFINS>0.00</vCOFINS></COFINSOutr></COFINS></imposto></det><total><ICMSTot><vBC>0.00</vBC><vICMS>0.00</vICMS><vBCST>0.00</vBCST><vST>0.00</vST><vProd>590.00</vProd><vFrete>0.00</vFrete><vSeg>0.00</vSeg><vDesc>0.00</vDesc><vII>0.00</vII><vIPI>0.00</vIPI><vPIS>0.00</vPIS><vCOFINS>0.00</vCOFINS><vOutro>0.00</vOutro><vNF>590.00</vNF></ICMSTot></total><transp><modFrete>1</modFrete></transp><cobr><dup><nDup>624</nDup><dVenc>2013-02-08</dVenc><vDup>590.00</vDup></dup></cobr><infAdic><infCpl>TESTE DE INFORMACOES ADICIONAIS</infCpl></infAdic></infNFe></NFe>";
        /**
         * Teste com senha que deve ser passada por parвmetro
         */
        String password = "21902190";
        /**
         * Tipo do certificado que deve ser passada por parвmetro.
         */
        String tipoCertificado = "A3";

        /**
         * Modelo do certificado que deve ser passado por parвmetro ... a aplicaзгo tem modelos padrхes que grava na raiz do usuбrio caso nгo exista o arquivo.
         * Mas o desenvolvedor por tanto criar outros nomes, quando personalizar os arquivos de configuraзгo. e colocalos na raiz do usuбrio do sistema operacional.
         * no caso abaixo, se nгo existir o arquivo Smartcard.cfg na pasta raiz, o sistema possui um modelo que aponta para a pasta system32 no caso do windows, e um modelo que aponta para /opt/foo/lib/libpkcs11.so no caso do linux.
         * em outros sistemas operacionais o responsavel deverб personalizar o arquivo para apontar para a biblioteca pksc11 correspondente.
         */
        String modeloCertificado = "Smartcard";

        /**
         * Esse cуdigo cria automaticamente o arquivo cacerts na raiz do usuбrio caso o arquivo nгo exista, й importante sempre procurar adicionar no cуdigo os UFs para as quais deseja comunicar-se.
         * no caso abaixo
         * й gerado os cacerts para todos os endereзos a seguir:
         * get("homnfe.sefaz.am.gov.br", 443, ks);
            get("hnfe.sefaz.ba.gov.br", 443, ks);
            get("nfeh.sefaz.ce.gov.br", 443, ks);
            get("homolog.sefaz.go.gov.br", 443, ks);
            get("hnfe.fazenda.mg.gov.br", 443, ks);
            get("homologacao.nfe.ms.gov.br", 443, ks);
            get("homologacao.sefaz.mt.gov.br", 443, ks);
            get("nfehomolog.sefaz.pe.gov.br", 443, ks);
            get("homologacao.nfe2.fazenda.pr.gov.br", 443, ks);
            get("homologacao.nfe.sefaz.rs.gov.br", 443, ks);
            get("homologacao.nfe.fazenda.sp.gov.br", 443, ks);
            get("hom.nfe.fazenda.gov.br", 443, ks);
            get("hom.sefazvirtual.fazenda.gov.br", 443, ks);
            get("homologacao.nfe.sefazvirtual.rs.gov.br", 443, ks);

         */

        String codigoEstado = "24";
        String ambiente = "2";

        File cacerts = GerarCacertsNfe.gerarCacertsNfe("changeit", Servico.DemaisServicos, NFAmbiente.valueOfCodigo(ambiente),  NFUnidadeFederativa.valueOfCodigo(codigoEstado));

        /**
         * Abaixo definimos as propriedades necessбrias para a assinatura e em sequкncia assinamos o conteъdo utilizando o cуdigo da biblioteca Fincatto.
         * Caso nгo aja arquivo de configuraзгo ele serб criado.
         */
        try {
            SystemPropertyManager.setProperties(TipoCertificado.valueOfCodigo(tipoCertificado), password, null, null, modeloCertificado);
            System.out.println("3");
            System.out.println(new AssinaturaDigitalApplet(password).assinarDocumento(xmlNaoAssinado));
        } catch (Exception e) {
            // TODO: handle exception
            //JOptionPane.showMessageDialog(this, e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(new Frame(), e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
        }

    }

Classes auxiliares

CertificadoWindows.java


package br.com.ceramic.assinador.util;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import br.com.ceramic.assinador.classes.Certificado;

public class CertificadoWindows {
    private KeyStore keyStore;

    /**
     * Recupera a lista de certificados digitais instalados no Windows,
     * com as informaушes do certificado, ver a classe Certificado.
     * @return
     * @throws KeyStoreException
     * @throws NoSuchProviderException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     */
    public List<Certificado> listaCertificadoDisponiveis() throws KeyStoreException,
            NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException {
        List<Certificado> listCertificado = new ArrayList<Certificado>();

        Enumeration<String> al = getKeyStore().aliases();
        while (al.hasMoreElements()) {
            String alias = al.nextElement();
            if (getKeyStore().containsAlias(alias)) {
                X509Certificate cert = (X509Certificate) getKeyStore().getCertificate(alias);
                if (cert != null) {
                    Certificado certificado = new Certificado();
                    certificado.setEmitidoPara(extractDN(cert.getSubjectDN()));
                    certificado.setAlias(alias);
                    certificado.setValidoDe(cert.getNotBefore());
                    certificado.setValidoAte(cert.getNotAfter());

                    listCertificado.add(certificado);
                }
            }
        }

        return listCertificado;
    }

    /**
     * Extrai o Common Name (CN) do certificado. O Common Name do certificado
     * ж utilizado para exibir o nome do proprietрrio do certificado, ou seja,
     * para qual pessoa ou empresa o certificado foi emitido.
     * @param subjectDN
     * @return
     */
    private String extractDN(Principal subjectDN) {
        if (subjectDN != null) {
            String dn = subjectDN.toString();
            dn = dn.substring(dn.indexOf("CN=") + 3, dn.indexOf(","));
            return dn;
        }
        return null;
    }

    /**
     * Cria o KeyStore de acesso ao Repositorio de Certificados do
     * Windows.
     * @return
     * @throws KeyStoreException
     * @throws NoSuchProviderException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     */
    public KeyStore getKeyStore() throws KeyStoreException, NoSuchProviderException,
            NoSuchAlgorithmException, CertificateException, IOException {
        if (keyStore == null) {
            keyStore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
            keyStore.load(null, null);
        }
        return keyStore;
    }

}

GerarCacertsNfe.java


package br.com.ceramic.assinador.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class GerarCacertsNfe {
    private static final String JSSECACERTS = "NFeCacerts";
    private static final int TIMEOUT_WS = 30;

    public static boolean existeCacerts(){
        File file = new File(JSSECACERTS);
        if (file.isFile() == false) {
            char SEP = File.separatorChar;
            File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");
            file = new File(dir, JSSECACERTS);
            if (file.isFile() == false) {
                file = new File(dir, "cacerts");
                return file.isFile();
            }else{
                return true;
            }
        }else{
            return true;
        }
    }

    //Try to save cacerts at database instead of System.getProperty("java.home") + SEP + "lib" + SEP + "security"
    public static File gerarCacertsNfe(String pass){
        File file = null;
        try {
            //try changeit
            char[] passphrase = pass.toCharArray();

            file = new File(JSSECACERTS);
            if (file.isFile() == false) {
                char SEP = File.separatorChar;
                File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");
                file = new File(dir, JSSECACERTS);
                if (file.isFile() == false) {
                    file = new File(dir, "cacerts");
                }
            }

            info("| Loading KeyStore " + file + "...");
            InputStream in = new FileInputStream(file);
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(in, passphrase);
            in.close();

            /**
             * AM - 2.00: homnfe.sefaz.am.gov.br
             * BA - 2.00: hnfe.sefaz.ba.gov.br
             * CE - 2.00: nfeh.sefaz.ce.gov.br
             * GO - 2.00: homolog.sefaz.go.gov.br
             * MG - 2.00: hnfe.fazenda.mg.gov.br
             * MS - 2.00: homologacao.nfe.ms.gov.br
             * MT - 2.00: homologacao.sefaz.mt.gov.br
             * PE - 2.00: nfehomolog.sefaz.pe.gov.br
             * PR - 2.00: homologacao.nfe2.fazenda.pr.gov.br
             * RS - 2.00: homologacao.nfe.sefaz.rs.gov.br
             * SP - 2.00: homologacao.nfe.fazenda.sp.gov.br
             * SCAN - 2.00: hom.nfe.fazenda.gov.br
             * SVAN - 2.00: hom.sefazvirtual.fazenda.gov.br
             * SVRS - 2.00: homologacao.nfe.sefazvirtual.rs.gov.br
             */
            get("homnfe.sefaz.am.gov.br", 443, ks);
            get("hnfe.sefaz.ba.gov.br", 443, ks);
            get("nfeh.sefaz.ce.gov.br", 443, ks);
            get("homolog.sefaz.go.gov.br", 443, ks);
            get("hnfe.fazenda.mg.gov.br", 443, ks);
            get("homologacao.nfe.ms.gov.br", 443, ks);
            get("homologacao.sefaz.mt.gov.br", 443, ks);
            get("nfehomolog.sefaz.pe.gov.br", 443, ks);
            get("homologacao.nfe2.fazenda.pr.gov.br", 443, ks);
            get("homologacao.nfe.sefaz.rs.gov.br", 443, ks);
            get("homologacao.nfe.fazenda.sp.gov.br", 443, ks);
            get("hom.nfe.fazenda.gov.br", 443, ks);
            get("hom.sefazvirtual.fazenda.gov.br", 443, ks);
            get("homologacao.nfe.sefazvirtual.rs.gov.br", 443, ks);

            File cafile = new File(JSSECACERTS);
            OutputStream out = new FileOutputStream(cafile);
            ks.store(out, passphrase);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return file;
    }

    public static void get(String host, int port, KeyStore ks) throws Exception {
        SSLContext context = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);
        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
        context.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory factory = context.getSocketFactory();

        info("| Opening connection to " + host + ":" + port + "...");
        SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
        socket.setSoTimeout(TIMEOUT_WS * 1000);
        try {
            info("| Starting SSL handshake...");
            socket.startHandshake();
            socket.close();
            info("| No errors, certificate is already trusted");
        } catch (SSLHandshakeException e) {
            /**
             * PKIX path building failed:
             * sun.security.provider.certpath.SunCertPathBuilderException:
             * unable to find valid certification path to requested target
             * Nгo tratado, pois sempre ocorre essa exceзгo quando o cacerts
             * nao esta gerado.
             */
        } catch (SSLException e) {
            error("| " + e.toString());
        }

        X509Certificate[] chain = tm.chain;
        if (chain == null) {
            info("| Could not obtain server certificate chain");
        }

        info("| Server sent " + chain.length + " certificate(s):");
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = chain[i];
            sha1.update(cert.getEncoded());
            md5.update(cert.getEncoded());

            String alias = host + "-" + (i);
            ks.setCertificateEntry(alias, cert);
            info("| Added certificate to keystore '" + JSSECACERTS + "' using alias '" + alias + "'");
        }
    }

    private static class SavingTrustManager implements X509TrustManager {
        private final X509TrustManager tm;
        private X509Certificate[] chain;

        SavingTrustManager(X509TrustManager tm) {
            this.tm = tm;
        }

        public X509Certificate[] getAcceptedIssuers() {
            throw new UnsupportedOperationException();
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            throw new UnsupportedOperationException();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            this.chain = chain;
            tm.checkServerTrusted(chain, authType);
        }
    }

    private static void info(String log) {
        System.out.println("INFO: " + log);
    }

    private static void error(String log) {
        System.out.println("ERROR: " + log);
    }

}

SystemPropertyManager.java

package br.com.ceramic.assinador.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Provider;
import java.security.Security;

import javax.swing.JOptionPane;

import org.apache.commons.lang3.SystemUtils;

import br.com.ceramic.assinador.classes.TipoCertificado;
import br.com.ceramic.assinador.classes.TipoCertificadoA3;

public class SystemPropertyManager {

    public static void setProperties(TipoCertificado tipoCertificado, String pass, File cacerts, File clientCert, String certTipo) throws Exception{

        System.clearProperty("javax.net.ssl.keyStore");
        System.clearProperty("javax.net.ssl.keyStorePassword");
        System.clearProperty("javax.net.ssl.trustStore");

        switch (tipoCertificado) {
        case A1:
            System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
            System.setProperty("javax.net.ssl.keyStore", clientCert.getAbsolutePath());
            System.setProperty("javax.net.ssl.keyStorePassword", pass);
            System.setProperty("javax.net.ssl.trustStoreType", "JKS");
            System.setProperty("javax.net.ssl.trustStorePassword", pass);
            System.setProperty("javax.net.ssl.trustStore", cacerts.getAbsolutePath());
            break;
        case A3:

            //String configName;
            //if(SystemUtils.IS_OS_WINDOWS){
            //    configName = "c:\\pkcs11"+certTipo+".cfg";
            //}else{
            //    configName = "/opt/bar/cfg/pkcs11"+certTipo+".cfg";
            //}
            String configName = System.getProperty("user.home") + File.separatorChar + "" + certTipo+".cfg";
            System.out.println(configName);
            File file = new File(configName);
            if(file.isFile()){
                Provider p = new sun.security.pkcs11.SunPKCS11(configName);
                Security.addProvider(p);
            }else{

                TipoCertificadoA3 tipoCertificadoA3 = TipoCertificadoA3.valueOfCodigo(certTipo);

                if(tipoCertificadoA3 != null){
                    File fileConfig = null;
                    if(SystemUtils.IS_OS_WINDOWS){
                        fileConfig = new File("win/"+certTipo+".cfg");

                    }else if(SystemUtils.IS_OS_LINUX){
                        fileConfig = new File("linux/"+certTipo+".cfg");
                    }else{
                        //Editar arquivo de configuraзгo manualmente indicando o local do dll, e indicar o nome do arquivo no cadastro da cerвmica.
                        throw new Exception("Sistema operaзгo ainda nгo suportado pelo sistema! Contate o suporte!");
                    }

                    InputStream in = new FileInputStream(fileConfig);
                    OutputStream out = new FileOutputStream(file);           // Transferindo bytes de entrada para saнda
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();

                    Provider p = new sun.security.pkcs11.SunPKCS11(file.getAbsolutePath());
                    Security.addProvider(p);

                }else{
                    throw new Exception("Arquivo de configuraзгo nгo existe em '"+configName+", e nгo configuraзгo nгo й reconhecida pelo sistema'!");
                }
            }

        }

    }

}

TipoCertificado.java

package br.com.ceramic.assinador.classes;

/**
 * Created by Waldney on 26/03/2015.
 */
public enum TipoCertificado {

    A1("A1"),
    A3("A3");

    private final String codigo;

    private TipoCertificado(final String codigo) {
        this.codigo = codigo;
    }

    public String getCodigo() {
        return this.codigo;
    }

    public static TipoCertificado valueOfCodigo(final String codigo) {
        for (TipoCertificado tipoCertificado : TipoCertificado.values()) {
            if (tipoCertificado.getCodigo().equalsIgnoreCase(codigo)) {
                return tipoCertificado;
            }
        }
        return null;
    }

}

TipoCertificadoA3.java

package br.com.ceramic.assinador.classes;

public enum TipoCertificadoA3 {

    Smartcard("Smartcard"),
    Safenet("Safenet"),
    Aladdin("Aladdin"),
    pronova("pronova");

    private final String codigo;

    private TipoCertificadoA3(final String codigo) {
        this.codigo = codigo;
    }

    public String getCodigo() {
        return this.codigo;
    }

    public static TipoCertificadoA3 valueOfCodigo(final String codigo) {
        for (TipoCertificadoA3 tipoCertificadoA3 : TipoCertificadoA3.values()) {
            if (tipoCertificadoA3.getCodigo().equalsIgnoreCase(codigo)) {
                return tipoCertificadoA3;
            }
        }
        return null;
    }

}

Classe alterada e renomeada da biblioteca para suportar as alterações exclusivas para certificado A3 AssinaturaDigitalApplet.java


package com.fincatto.nfe310.assinatura;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JOptionPane;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class AssinaturaDigitalApplet {
    private static final String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
    private static final String[] ELEMENTOS_ASSINAVEIS = new String[] { "infEvento", "infCanc", "infNFe", "infInut" };
    /**
     * final KeyStore keyStore = KeyStore.getInstance("PKCS12");
     */
    private final KeyStore keyStore;
    private final String password;

    public AssinaturaDigitalApplet(final KeyStore keyStore, String password) {
        this.keyStore = keyStore;
        this.password = password;
    }

    /**
     *
     * @param file
     * @param password
     * @throws Exception
     *
     * Cerrega o certificado do tipo A1 utilizando um arquivo JKS
     */
    public AssinaturaDigitalApplet(final File file, String password) throws Exception{

        this.keyStore = KeyStore.getInstance("PKCS12");
        try (InputStream certificadoStream = new FileInputStream(file)) {
            keyStore.load(certificadoStream, password.toCharArray());
        }
        this.password = password;
    }

    /**
     *
     * @param password
     * Exclusivo para certificado A3
     */
    public AssinaturaDigitalApplet(String password) throws IOException, NoSuchAlgorithmException, CertificateException, KeyStoreException, UnrecoverableKeyException{

        this.password = password;

        this.keyStore = KeyStore.getInstance("PKCS11");
        keyStore.load(null, this.password.toCharArray());

    }

    public boolean isValida(final InputStream xmlStream) throws Exception {
        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);

        final Document document = dbf.newDocumentBuilder().parse(xmlStream);
        final NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
        if (nodeList.getLength() == 0) {
            throw new Exception("Năo foi encontrada a assinatura do XML.");
        }

        final String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
        final XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());
        final DOMValidateContext validateContext = new DOMValidateContext(new X509KeySelector(), nodeList.item(0));

        for (final String tag : AssinaturaDigitalApplet.ELEMENTOS_ASSINAVEIS) {
            final NodeList elements = document.getElementsByTagName(tag);
            if (elements.getLength() > 0) {
                validateContext.setIdAttributeNS((Element) elements.item(0), null, "Id");
            }
        }

        return signatureFactory.unmarshalXMLSignature(validateContext).validate(validateContext);
    }

    public String assinarDocumento(final String conteudoXml) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, ParserConfigurationException, IOException, SAXException, KeyStoreException, UnrecoverableEntryException, MarshalException, XMLSignatureException, TransformerException {

        final KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(keyStore.aliases().nextElement(), new KeyStore.PasswordProtection(this.password.toCharArray()));
        final XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");

        final List<Transform> transforms = new ArrayList<>(2);
        transforms.add(signatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
        transforms.add(signatureFactory.newTransform(AssinaturaDigitalApplet.C14N_TRANSFORM_METHOD, (TransformParameterSpec) null));

        final KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
        final X509Data x509Data = keyInfoFactory.newX509Data(Collections.singletonList((X509Certificate) keyEntry.getCertificate()));
        final KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));

        final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);

        final Document document = documentBuilderFactory.newDocumentBuilder().parse(IOUtils.toInputStream(conteudoXml));

        for (final String elementoAssinavel : AssinaturaDigitalApplet.ELEMENTOS_ASSINAVEIS) {
            final NodeList elements = document.getElementsByTagName(elementoAssinavel);
            for (int i = 0; i < elements.getLength(); i++) {
                final Element element = (Element) elements.item(i);
                final String id = element.getAttribute("Id");
                element.setIdAttribute("Id", true);

                final Reference reference = signatureFactory.newReference("#" + id, signatureFactory.newDigestMethod(DigestMethod.SHA1, null), transforms, null, null);
                final SignedInfo signedInfo = signatureFactory.newSignedInfo(signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(reference));

                final XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
                signature.sign(new DOMSignContext(keyEntry.getPrivateKey(), element.getParentNode()));
            }
        }
        return this.converteDocumentParaXml(document);
    }

    private String converteDocumentParaXml(final Document document) throws TransformerFactoryConfigurationError, TransformerException, IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            final Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            transformer.transform(new DOMSource(document), new StreamResult(outputStream));
            return outputStream.toString(Charsets.UTF_8.name());
        }
    }
}
waldandrade commented 8 years ago

Atualmente utilizo outra arquitetura .... mas a estrutura é essa mesma.

Na minha arquitetura atual ... monitoro uma pasta de xml não assinados em busca de arquivos .xml, assino automaticamente e salvo o arquivo em uma segunda pasta de xml assinado.

Não fiz ainda o método de envio, mas consiste em salvar o xml em uma pasta monitorada, e que faz o envio, e salva o retorno em outra pasta.

caiocteodoro commented 8 years ago

@fauker @jefperito @fincatto

Pelo que andei pesquisando para o certificado A3 seria melhor fazer a assinatura e comunicação com a SEFAZ pelo desktop.

Fiz algumas alterações para o certificado A3. Não precisou alterar muito, foram essas as classes:

Tive sucesso com os serviços (consultaStatus,enviaLote,consultaLote), vou melhorar o código e se tiverem interesse posso envia-las.

fincatto commented 8 years ago

Com certeza! Se for possivel, faça um PR em um branch para testarmos e validarmos a solução. Vai ser muito bom poder suportar os certificados A3. Att, Diego

2016-05-03 16:57 GMT-03:00 caiocteodoro notifications@github.com:

@fauker https://github.com/fauker @jefperito https://github.com/jefperito @fincatto https://github.com/fincatto

Pelo que andei pesquisando para o certificado A3 seria melhor fazer a assinatura e comunicação com a SEFAZ pelo desktop.

Fiz algumas alterações para o certificado A3. Não precisou alterar muito, foram essas as classes:

  • NFeConfig
  • AssinaturaDigital
  • NFTipoCertificado (Nova)
  • NFSocketFactory
  • WSLoteEnvio
  • WSCartaCorrecao
  • WSCancelamento
  • WSInutilizacao

Tive sucesso com os serviços (consultaStatus,enviaLote,consultaLote), vou melhor o código e se tiverem interesse posso envia-las.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216646570

waldandrade commented 8 years ago

Exatamente, só é realmente interessante fazer essa parte de assinatura e comunicação via desktop.

A arquitetura que fiz divide o projeto em duas partes ... um monitor que vai ficar observando algumas pastas procurando por arquivos .xml, e uma segunda parte é o que salvar os xmls nas pastas e capturar delas.

Em 3 de maio de 2016 17:11, Diego Fincatto notifications@github.com escreveu:

Com certeza! Se for possivel, faça um PR em um branch para testarmos e validarmos a solução. Vai ser muito bom poder suportar os certificados A3. Att, Diego

2016-05-03 16:57 GMT-03:00 caiocteodoro notifications@github.com:

@fauker https://github.com/fauker @jefperito https://github.com/jefperito @fincatto https://github.com/fincatto

Pelo que andei pesquisando para o certificado A3 seria melhor fazer a assinatura e comunicação com a SEFAZ pelo desktop.

Fiz algumas alterações para o certificado A3. Não precisou alterar muito, foram essas as classes:

  • NFeConfig
  • AssinaturaDigital
  • NFTipoCertificado (Nova)
  • NFSocketFactory
  • WSLoteEnvio
  • WSCartaCorrecao
  • WSCancelamento
  • WSInutilizacao

Tive sucesso com os serviços (consultaStatus,enviaLote,consultaLote), vou melhor o código e se tiverem interesse posso envia-las.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216646570

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216650519

Waldney Souza de Andrade compengi engenharia & sistemas waldney.andrade@gmail.com waldney.andrade@gmail.com

+55(84)8894-3405 +55(84)9447-7354

caiocteodoro commented 8 years ago

@fincatto

teitei fazer um PR, mas acho que não fui muito bem sucedido (rsrsrs) qualquer coisa é só me avisar que te envio as classes e você mesmo pode fazer.

fincatto commented 8 years ago

Não consegui ver ainda, mas, se ficar em duvida, manda um patch mesmo que eu aplico aqui. []s

2016-05-04 14:19 GMT-03:00 caiocteodoro notifications@github.com:

@fincatto https://github.com/fincatto

teitei fazer um PR, mas acho que não fui muito bem sucedido (rsrsrs) qualquer coisa é só me avisar que te envio as classes e você mesmo pode fazer.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216937796

waldandrade commented 8 years ago

Boa tarde,

alguém poderia me informar em que ponto estamos com relação a esse ticket? Vi que outro ticket foi criado, e meio que me perdi.

Em 4 de maio de 2016 14:24, Diego Fincatto notifications@github.com escreveu:

Não consegui ver ainda, mas, se ficar em duvida, manda um patch mesmo que eu aplico aqui. []s

2016-05-04 14:19 GMT-03:00 caiocteodoro notifications@github.com:

@fincatto https://github.com/fincatto

teitei fazer um PR, mas acho que não fui muito bem sucedido (rsrsrs) qualquer coisa é só me avisar que te envio as classes e você mesmo pode fazer.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216937796

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216939151

Waldney Souza de Andrade compengi engenharia & sistemas waldney.andrade@gmail.com waldney.andrade@gmail.com

+55(84)8894-3405 +55(84)9447-7354

caiocteodoro commented 8 years ago

@waldandrade

Adicionei as modificações e fiz um PR.

waldandrade commented 8 years ago

@caiocteodoro

Baixei a versão do seu PR para testar... você conseguiu assinar/enviar com essas alterações? Se sim, tem como prover algumas instruções?

2016-05-04 16:03 GMT-03:00 caiocteodoro notifications@github.com:

@waldandrade https://github.com/waldandrade

Adicionei as modificações e fiz um PR.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216968169

Waldney Souza de Andrade compengi engenharia & sistemas waldney.andrade@gmail.com waldney.andrade@gmail.com

+55(84)8894-3405 +55(84)9447-7354

caiocteodoro commented 8 years ago

A unica coisa que muda é na classe Nfeconfig, onde temos mais 2 parâmetros. Basta informar o tipo de certificado A1 ou A3 (se A3 qual o tipo smartcard ou token). Ficando assim:

public class NfeConfig implements NFeConfig{
    @Override
    public NFTipoCertificado getTipoCertificado() {
        // TODO Auto-generated method stub
        return NFTipoCertificado.A3;
    }

    @Override
    public NFTipoCertificadoA3 getTipoCertificadoA3() {
        // TODO Auto-generated method stub
        return NFTipoCertificadoA3.SMARTCARD;
    }

    @Override
    public NFAmbiente getAmbiente() {
        // TODO Auto-generated method stub
        return NFAmbiente.HOMOLOGACAO;
    }

    @Override
    public byte[] getCertificado() throws IOException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public byte[] getCadeiaCertificados() throws IOException {
        // TODO Auto-generated method stub
        return Files.readAllBytes(Paths.get(new File("NFeCacerts").getPath()));
    }

    @Override
    public String getCertificadoSenha() {
        // TODO Auto-generated method stub
        return "senhaCertificadoDigitalA3";
    }

    @Override
    public String getCadeiaCertificadosSenha() {
        // TODO Auto-generated method stub
        return "changeit";
    }

    @Override
    public NFUnidadeFederativa getCUF() {
        // TODO Auto-generated method stub
        return NFUnidadeFederativa.valueOf("MG");
    }

    @Override
    public NFTipoEmissao getTipoEmissao() {
        // TODO Auto-generated method stub
        return NFTipoEmissao.EMISSAO_NORMAL;
    }

    @Override
    public String getSSLProtocolo() {
        // TODO Auto-generated method stub
        return "TLSv1";
    }

    @Override
    public Integer getCodigoSegurancaContribuinteID() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getCodigoSegurancaContribuinte() {
        // TODO Auto-generated method stub
        return null;
    }
}
waldandrade commented 8 years ago

Bom noite/dia ....

Sucesso amigo! @caiocteodoro

O envio do lote da nota fiscal está ok com certificado A3 ... estou subindo minha aplicação que usa esta biblioteca,

e monitora as pastas do google drive ... será útil para alguém que quiser fazer um emissor sem a necessidade de estar com o certificado na máquina.

2016-05-04 16:36 GMT-03:00 caiocteodoro notifications@github.com:

A unica coisa que muda é na classe Nfeconfig, onde temos mais 2 parâmetros. Basta informar o tipo de certificado A1 ou A3 (se A3 qual o tipo smartcard ou token). Ficando assim:

public class NfeConfig implements NFeConfig{ @Override public NFTipoCertificado getTipoCertificado() { // TODO Auto-generated method stub return NFTipoCertificado.A3; }

@Override
public NFTipoCertificadoA3 getTipoCertificadoA3() {
    // TODO Auto-generated method stub
    return NFTipoCertificadoA3.SMARTCARD;
}

@Override
public NFAmbiente getAmbiente() {
    // TODO Auto-generated method stub
    return NFAmbiente.HOMOLOGACAO;
}

@Override
public byte[] getCertificado() throws IOException {
    // TODO Auto-generated method stub
    return null;
}

@Override
public byte[] getCadeiaCertificados() throws IOException {
    // TODO Auto-generated method stub
    return Files.readAllBytes(Paths.get(new File("NFeCacerts").getPath()));
}

@Override
public String getCertificadoSenha() {
    // TODO Auto-generated method stub
    return "senhaCertificadoDigitalA3";
}

@Override
public String getCadeiaCertificadosSenha() {
    // TODO Auto-generated method stub
    return "changeit";
}

@Override
public NFUnidadeFederativa getCUF() {
    // TODO Auto-generated method stub
    return NFUnidadeFederativa.valueOf("MG");
}

@Override
public NFTipoEmissao getTipoEmissao() {
    // TODO Auto-generated method stub
    return NFTipoEmissao.EMISSAO_NORMAL;
}

@Override
public String getSSLProtocolo() {
    // TODO Auto-generated method stub
    return "TLSv1";
}

@Override
public Integer getCodigoSegurancaContribuinteID() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public String getCodigoSegurancaContribuinte() {
    // TODO Auto-generated method stub
    return null;
}

}

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-216976973

Waldney Souza de Andrade compengi engenharia & sistemas waldney.andrade@gmail.com waldney.andrade@gmail.com

+55(84)8894-3405 +55(84)9447-7354

caiocteodoro commented 8 years ago

Que bom meu caro @waldandrade, que tipo de A3 você utilizou? Aqui fiz o teste em um smartCard!

caiocteodoro commented 8 years ago

@fincatto

Notei que deu algum erro no meu PR e não consegui entender o por que. Quando der uma olhada me fala que arrumo.

caiocteodoro commented 8 years ago

Só para complementar. Acabei de testar em um token da sefenet 5100 e os procedimentos foram executados com sucesso!!!

waldandrade commented 8 years ago

Bom dia @caiocteodoro

Vamos fazer um multirão hoje. Kkk

O meu é um Smartcard... da Serasa Experien. Funcionou perfeitamente a assinatura e envio.

Mas não consegui consultar a nota, para armazenar a nota processada e posteriormente testar cancelamento, correção, etc

Se pudesse me ajudar nisso.... ficaria grato e conseguiria te ajudar com maior prontidão. Em 05/05/2016 07:52, "caiocteodoro" notifications@github.com escreveu:

Só para complementar. Acabei de testar em um token da sefenet 5100 e os procedimentos foram executados com sucesso!!!

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-217124017

waldandrade commented 8 years ago

Então já está enviando pelo SmartCard e por token.

Precisamos testar os demais procedimentos Em 05/05/2016 09:03, "Waldney Andrade" waldney.andrade@gmail.com escreveu:

Bom dia @caiocteodoro

Vamos fazer um multirão hoje. Kkk

O meu é um Smartcard... da Serasa Experien. Funcionou perfeitamente a assinatura e envio.

Mas não consegui consultar a nota, para armazenar a nota processada e posteriormente testar cancelamento, correção, etc

Se pudesse me ajudar nisso.... ficaria grato e conseguiria te ajudar com maior prontidão. Em 05/05/2016 07:52, "caiocteodoro" notifications@github.com escreveu:

Só para complementar. Acabei de testar em um token da sefenet 5100 e os procedimentos foram executados com sucesso!!!

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-217124017

caiocteodoro commented 8 years ago

Acabei de testar e todos os serviços que precisam ser assinados e os que não precisam obtiveram sucesso.

Em 5 de maio de 2016 09:07, waldandrade notifications@github.com escreveu:

Então já está enviando pelo SmartCard e por token.

Precisamos testar os demais procedimentos

Em 05/05/2016 09:03, "Waldney Andrade" waldney.andrade@gmail.com escreveu:

Bom dia @caiocteodoro

Vamos fazer um multirão hoje. Kkk

O meu é um Smartcard... da Serasa Experien. Funcionou perfeitamente a assinatura e envio.

Mas não consegui consultar a nota, para armazenar a nota processada e posteriormente testar cancelamento, correção, etc

Se pudesse me ajudar nisso.... ficaria grato e conseguiria te ajudar com maior prontidão. Em 05/05/2016 07:52, "caiocteodoro" notifications@github.com escreveu:

Só para complementar. Acabei de testar em um token da sefenet 5100 e os procedimentos foram executados com sucesso!!!

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-217124017

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/wmixvideo/nfe/issues/27#issuecomment-217137239