[RESOLVIDO]Enviar Nota Fiscal para várias empresas (keystore em cache da JVM)

22 respostas
G

Prezados, bom dia.

preciso da ajuda de vocês, fiz um sistema de envio de nota fiscal em Maker (gerador de código Java), funciona beleza, mas quando tento enviar uma NF diferente(ex: mandei a nf da matriz e tento enviar a nota fiscal para uma filial) da erro na autenticação, isso porque a JVM guarda o último keystore enviado… se eu reiniciar o tomcat eu consigo enviar normalmente. Existe uma forma de contornoar essa situação? alguma função em Java que consiga retirar o keystore guardado em cache sem que eu precise reiniciar o tomcat?
Desde já agradeço pela atenção!

22 Respostas

A

Dê uma olhada no meu blog, eu coloquei uma resolução para este problema : http://alesaudate.com.

[]´s

G

Colega, Asaudade.

BLz, estou dando uma olhada qualquer dúvida espero poder contar com sua ajuda novamente.
desde já te agradeço pela dica.

para os que estão com o mesmo problema o link é: http://alesaudate.com/2010/08/09/how-to-dynamically-select-a-certificate-alias-when-invoking-web-services/
vou ver se resolvo meu problema e posto o resultado aqui

G

Asaudate,

Você utilizou Jboss, sabe dizer se isso é válido para o Tomcat? porque é nele que enfreto esse problema.

A

Basta que você coloque as libs do JAX-WS no diretório de lib´s do Tomcat. (eu usei a RI, que dá pra baixar em https://jax-ws.dev.java.net/2.1.1/index.html).

[]´s

G

Pessoal, alguém sabe como faço para limpar as propriedades da JVM? descobri o erro da minha aplicação, a função para remover na verdade não remove. estou fazendo da seguinte forma:

System.getProperties().remove(“key”);
e também usei System.clearProperty(“key”);

mas n removeram nada.

Asaudate, vc é a minha referência nessa parada, se puder dar uma força mais uma vez… hehehe

A

System.getProperties().remove(“key”); funciona pra mim. Que parâmetro você está querendo remover?? E como você seta, via parâmetro da VM, mesmo, ou via programação?

[]´s

G

Asaudate, Bom dia.

cara seguinte, ontem remexi nesse trem e percebi o seguinte… a função que estou utilizando aqui no Maker envia a NF da seguinte forma:

primeira ela da System.setProperty(javax.net.ssl.keyStore, MinhavariavelKeystore);  para guardar os dados no sistema;

em seguida ela utiliza uma classe espicífica pra realizar o envio e depos limpa as propriedades do sistema com

System.getProperties().remove(key);

Quando vi isso pensei que a função n tivesse funcionando, mas coloquei uma série de labels no jsp e percebi que ele está limpando mesmo as propriedades do sistema.
Sendo assim a única solução que consigo pensar é mudar a função e tentar passar esses dados a partir de uma variável e não pegando do sistema, como está sendo feito atualmente.
O problema ainda maior é que a classe q a função importa para enviar os dados pra prefeitura, está num .class e não tenho acesso ao código. vou pesquisar por uma função que realize o envio da NF para o webservice, mas já pergunto se é obrigatório os dados estarem nas propriedades do sistema ou se eles podem ficar numa variável como penso em fazer?
No aguardo, e mais uma vez agradeço a ajuda que tem me dado.(desesperado aqui no trampo p resolver esse negócio, projeto no final e só dependendo desse pepino… affs)

G
alguém sabe me dizer onde encontro um material sobre as bibliotecas:

import org.apache.axis.client.Stub;

import org.apache.axis.wsdl.gen.NoopFactory;

import org.apache.axis.wsdl.symbolTable.<em>;

import org.apache.axis.wsdl.toJava.</em>;

dei uma olhada no google mas n achei nada útil, preciso entender como isso funciona para tentar gerar uma classe que envie o XML para o webservice e me de um retorno.

G

Pessoal, estou tendo problemas para definir o serviço de envio da nota, no seguinte trecho do código

javax.xml.ws.Service service = javax.xml.ws.Service.create(new java.net.URL(url), new javax.xml.namespace.QName(namespace, serviceName));

apresenta o erro:
javax.xml.ws.WebServiceException: The following WSDL exception occurred: WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure

alguém já passou por isso?

G

Código inteiro do erro:

Exceção Gerada:
javax.xml.ws.WebServiceException: The following WSDL exception occurred: WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:170) at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:67) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.setupWsdlDefinition(ServiceDescriptionImpl.java:507) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.(ServiceDescriptionImpl.java:128) at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:101) at org.apache.axis2.jaxws.description.DescriptionFactory.createServiceDescription(DescriptionFactory.java:67) at org.apache.axis2.jaxws.spi.ServiceDelegate.(ServiceDelegate.java:84) at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:45) at javax.xml.ws.Service.(Service.java:33) at javax.xml.ws.Service.create(Service.java:85) at wfr.com.systems.system_tif.rules.WebrunFunctions.ebfWSCallSSL(WebrunFunctions.java:11323) at wfr.com.systems.system_tif.rules.EnviaLoteNfseWs.run(EnviaLoteNfseWs.java:102) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.callRule(WFRRule.java:661) at wfr.com.systems.system_tif.rules.MontaXml.run(MontaXml.java:165) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.call(WFRRule.java:1779) at wfr.rules.WFRRule.call(WFRRule.java:53) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269) at java.util.concurrent.FutureTask.run(FutureTask.java:123) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595) Caused by: WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure: at org.apache.axis2.jaxws.util.WSDL4JWrapper.(WSDL4JWrapper.java:184) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.setupWsdlDefinition(ServiceDescriptionImpl.java:489) … 20 more

Causa:
WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure: at org.apache.axis2.jaxws.util.WSDL4JWrapper.(WSDL4JWrapper.java:184) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.setupWsdlDefinition(ServiceDescriptionImpl.java:489) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.(ServiceDescriptionImpl.java:128) at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:101) at org.apache.axis2.jaxws.description.DescriptionFactory.createServiceDescription(DescriptionFactory.java:67) at org.apache.axis2.jaxws.spi.ServiceDelegate.(ServiceDelegate.java:84) at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:45) at javax.xml.ws.Service.(Service.java:33) at javax.xml.ws.Service.create(Service.java:85) at wfr.com.systems.system_tif.rules.WebrunFunctions.ebfWSCallSSL(WebrunFunctions.java:11323) at wfr.com.systems.system_tif.rules.EnviaLoteNfseWs.run(EnviaLoteNfseWs.java:102) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.callRule(WFRRule.java:661) at wfr.com.systems.system_tif.rules.MontaXml.run(MontaXml.java:165) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.call(WFRRule.java:1779) at wfr.rules.WFRRule.call(WFRRule.java:53) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269) at java.util.concurrent.FutureTask.run(FutureTask.java:123) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595)

estou há dois dias tentando encontrar a causa, mas não identifico, já olhei na documentação do Service.create e ele recebe de fato dois parametros, a URL e o QName com nome do servico e namespace. o engraçado é que tirando a URL e passando apenas o QName ele para de dar erro, mas não posso deixar assim porque sem a url do wsdl as funções de envio não funcionarão.

G

Andei pesquisando sobre o erro acima e me parece que no momento do service.create é feita uma requisicao com o wsdl e em webservices que exigem autenticacao é necessário que seja informado o keystore.
Bem assim é a programação, resolvendo um problema e aparecendo outro, a saga da NF parece n ter fim.

Amigos, o erro agora é : java.io.IOException: Keystore was tampered with, or password was incorrect

ele ocorre nessa parte do codigo:

SSLSocketFactoryGenerator sslFactory = new SSLSocketFactoryGenerator(alias.toString(), fileKeyStore.toString(), filepfx.toString(), passKeyStore.toString(), passpfx.toString());

javax.net.ssl.SSLSocketFactory socketFactory = null;

try{
socketFactory = sslFactory.getSSLSocketFactory();
}catch (Exception e){
return new Variant(e.toString());
}

O código do SSLSocketFactoryGenerator me foi cedido pelo nosso amigo Alexandre(que tem me ajudado ate aqui). segue código:
package raneves.generator;

import incode.tifs.AliasSelectorKeyManager;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.logging.Logger;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;

public class SSLSocketFactoryGenerator {

	private String alias = null;
	private String keyStore = null;
	private String trustStore = null;

	public SSLSocketFactoryGenerator (String alias, String keyStore, String trustStore, String keyStorePass, String trustStorePass) {
		if (alias == null)
			throw new IllegalArgumentException("The alias may not be null");
		this.alias = alias;
		this.keyStore = keyStore;
		this.trustStore = trustStore;

	}

	public SSLSocketFactory getSSLSocketFactory() throws IOException, GeneralSecurityException {

		KeyManager[] keyManagers = getKeyManagers();
		TrustManager[] trustManagers =getTrustManagers();

		//For each key manager, check if it is a X509KeyManager (because we will override its 		//functionality
		for (int i=0; i<keyManagers.length; i++) {
			if (keyManagers[i] instanceof X509KeyManager) {
				keyManagers[i]=new AliasSelectorKeyManager((X509KeyManager)keyManagers[i], alias);
			}
      		}

		SSLContext context=SSLContext.getInstance("SSL");
		context.init(keyManagers, trustManagers, null);

		SSLSocketFactory ssf=context.getSocketFactory();
    		return ssf;
  	}	

	public String getKeyStorePassword() {
		return "keyStorePassword";
	}

	public String getTrustStorePassword() {
		return "trustStorePassword";
	}

	public String getKeyStore() {
		return keyStore;
	}

	public String getTrustStore() {

		return trustStore;
	}

	private KeyManager[] getKeyManagers()
	throws IOException, GeneralSecurityException
	{

		//Init a key store with the given file.

		String alg=KeyManagerFactory.getDefaultAlgorithm();
		KeyManagerFactory kmFact=KeyManagerFactory.getInstance(alg);

		FileInputStream fis=new FileInputStream(getKeyStore());
		KeyStore ks=KeyStore.getInstance("jks");
		ks.load(fis, getKeyStorePassword().toCharArray());
		fis.close();

		//Init the key manager factory with the loaded key store
		kmFact.init(ks,  getKeyStorePassword().toCharArray());

		KeyManager[] kms=kmFact.getKeyManagers();
		return kms;
	}

	protected TrustManager[] getTrustManagers() throws IOException, GeneralSecurityException
	{

		String alg=TrustManagerFactory.getDefaultAlgorithm();
		TrustManagerFactory tmFact=TrustManagerFactory.getInstance(alg);

		FileInputStream fis=new FileInputStream(getTrustStore());
		KeyStore ks=KeyStore.getInstance("jks");
		ks.load(fis, getTrustStorePassword().toCharArray());
		fis.close();

		tmFact.init(ks);

		TrustManager[] tms=tmFact.getTrustManagers();
		return tms;
	}
}
olhando o código uma coisa que n entendi foi porque vc(alexandre) pega a senha como parametro mas n seta ela na construtora.
G

Prezados,

Creio que o erro está neste trecho:

FileInputStream fis=new FileInputStream("C:\\Program Files\\emp.keystore");
		KeyStore ks=KeyStore.getInstance("jks");
		ks.load(fis, getKeyStorePassword().toCharArray());
		fis.close();

por alguma razão ele n consegue carregar o ks.load

G

Prezados,

identifiquei o problema, era a instancia que estava setando errado. ali deve-se passar o .pfx e a minha instancia que é PKCS12.

O problema agora é pra converter uma string para o tipo SOAPMessage:

java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(arguments.getBytes());

javax.xml.soap.SOAPMessage messageInput = null;

try {

messageInput = javax.xml.soap.MessageFactory.newInstance().createMessage(new javax.xml.soap.MimeHeaders(), bais);

}catch (Exception e){
    return new Variant(e.toString());
}

o alerta da exceção diz:

org.apache.axiom.soap.SOAPProcessingException: First Element must contain the local name, Envelope , but found cabecalho
:shock: :shock: :shock: :?:

G

Prezados, ao que parece é necessário inserir uma tag(algumas na verdade) no XML. googlando encontrei algo assim:

<?xml version="1.0" encoding="UTF-8"?>
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote">
<soap:Body>
 <mh:getBookPrice>
 <isbn xsi:type="xsd:string">[telefone removido] </isbn>
</mh:getBookPrice>
</soap:Body></soap:Envelope>

todo o conteudo do meu XML deve ir dentro da soap:body?

:roll: :roll: :roll: :roll: :roll:

G

coloquei o conteúdo do xml dentro da tag soap:Body e me retorna o erro:

avax.xml.soap.SOAPException: org.apache.axiom.om.OMException: com.ctc.wstx.exc.WstxParsingException: Illegal processing instruction target (“xml”); xml (case insensitive) is reserved by the specs.
at [row,col {unknown-source}]: [2,86]

alguém sabe como preparar o XML para esse formato SOAPMessage :?: :?: :?: :?: :?: :?: :?:

G

o problema estava na tag <?xml version="1.0" encoding="UTF-8"?> que era declarada duas vezes.

agora, quando tento enviar uzando:

javax.xml.soap.SOAPMessage response = message.invoke(messageInput); me vem o erro:

javax.xml.ws.soap.SOAPFaultException: Cannot find dispatch method for {http://www.abrasf.org.br/nfse.xsd}GerarNfseEnvio

hoje é meu ultimo dia para finalizar essa NF, caso contrário no mínimo tomarei uma bronca do patrão e no máximo serei demitido :frowning: se alguém puder me ajudar eu serei eternamente grato, venho buscando solução no google, mas ainda n compreende o motivo do erro, parece ser algo relacionado ao targetNameSpace do wsdl da prefeitura, mas ainda n sei como definir esse parametro no meu XML.

G
Graças a dica do Saudate consegui gerar meu XML corretamente. Agora só me falta verificar o retorno, alguém sabe como faço para converter a variável response em uma string? ou mesmo ler o retorno do xml com ela?
javax.xml.ws.Dispatch<javax.xml.soap.SOAPMessage> message = service.createDispatch(new javax.xml.namespace.QName(namespace.toString(), portName.toString()), javax.xml.soap.SOAPMessage.class, javax.xml.ws.Service.Mode.MESSAGE);


javax.xml.soap.SOAPMessage response = message.invoke(messageInput);

:?: :?: :?:

G

Alexandre,

Quando vou definir o servico me vinha o erro de Received fatal alert: handshake_failure

lendo diversos foruns me lembro que encontrei um falando que no momento em que o serviço é criado se o servidor exigir autenticação como é o caso da NFSe da prefeitura é necessário informar o keystore, daí eu setei na system e parou o erro, agora consegui enviar o XML sem problemas, mas quando mudo de empresa e keystore me vem o mesmo erro que dava na função que usava anteriormente “Erro na Autenticação”

qual a forma de contornar esse Received fatal alert: handshake_failure? sem ter de setar o keystore na system?

G

o problema está nessa linha javax.xml.ws.Service.create(new java.net.URL(url.toString()), new javax.xml.namespace.QName(namespace.toString(), serviceName.toString()));

quando o service.create é criado nessa construtora ele já faz o acesso com webservice, e como o da prefeitura requer o PFX eu preciso passar ele de alguma maneira, só consegui via system.
se eu jogar o link no browser ele vai me pedir o PFX tambem e se n informar ele me da o mesmo erro
[b]O sistema remoto SSL não conseguiu negociar um conjunto aceitável de parâmetros de segurança.

(Código do erro: ssl_error_handshake_failure_alert)
[/b]

deve haver uma forma de informar esse pfx sem ter de setar na system…

G

putz, o problema persiste. observando a exceção gerada, quando o service.create é chamado ele tenta acessar o webservice pela classe WSDL4JWrapper e como o wsdl é SSL ele exige um certificado, só não entendo como informar para essa classe o caminho para o keystore, quando seto na system ele deve aceitar pq o default deve ser pegar de la.

OBS: na verdade eu nem entendo porque/como o WSDL4JWrapper identifica os propriedades que são setadas na system.
Deve haver uma forma de resolver isso, MAS qual? só o saudate me ajuda, ninguém mais nesse forum diz nada. Please, Help-me!!!

G

Visitantes, boa tarde.

Consegui resolver o problema!!!
tive que fazer uso do pacote axis.
segue link: http://code.google.com/p/axis-ssl/

Vlw ao Amigo Alessandro Medis e Alexandre Saudate pelas dicas!!!

A

ola asaudate
por acaso vc tirou o seu site do ar? tem abrir e não da…
estou com o mesmo caso… tenho 2 certificados (PKCS12) para usar no mesmo sistema de forma dinamica…
pelo que vc falou, vc tem a solução para isso né?

valeo
abraco

Criado 15 de setembro de 2010
Ultima resposta 9 de nov. de 2010
Respostas 22
Participantes 3