SPRING BOOT - Invio fattura test webservice - Internal Error

Ciao a tutti.
Sono più di due settimane che cerco di far funzionare il sistema e non sono riuscito ancora a fare niente. Siamo partiti da un progetto vuoto Spring Boot.

Ho generato le due chiavi (2 key e i corrispettivi csr) dal server dove andremo ad installare il sistema, le ho “conciliate” con i due certificati “cer” (client e server) scaricati dal primo step e poi, tramite keytool, le ho aggiunte al keystore.jks.
I certificati caentrate.der, CAEntrateTest.cer e testservizi.fatturapa.it.cer sono stati aggiunti nel truststore.jks.

Ho provato ad installare il certificato client sul browser e riesco a vedere il messaggio di benvenuto accendendo a https://testservizi.fatturapa.it/ricevi_file

Genero la request xml e tramite Postman contatto il mio webservice.
Poi contatto il WS di test ma l’unica risposta che ricevo è un Internal Error e non so dove sbaglio.

Questo è il codice dell’endpoint:

@PayloadRoot(namespace = NAMESPACE_TRASMISSIONE, localPart = RICEVI_FILE)
@ResponsePayload
public JAXBElement<RispostaSdIRiceviFileType> riceviFile(@RequestPayload JAXBElement<FileSdIBaseType> request)
		throws IOException {
	sendNotificationMail(null, TrasmissioneEndpoint.class.getSimpleName(), RICEVI_FILE, request.getValue());

	RispostaSdIRiceviFileType response = null;
	webServiceTemplate.setDefaultUri("https://testservizi.fatturapa.it/ricevi_file");
	
	ObjectFactory factory = new ObjectFactory();

	FileSdIBaseType sdIAccoglienza = factory.createFileSdIAccoglienza(request.getValue()).getValue();
	sdIAccoglienza.setNomeFile("esempio_fattura_IT01234567890_FPA01.xml");
	FileDataSource source = new FileDataSource(
			"C:\\workspace\\ws-fattura\\complete\\src\\main\\resources\\esempio_fattura_IT01234567890_FPA01.xml.zip");
	sdIAccoglienza.setFile(new DataHandler(source));

	try {
		response = (RispostaSdIRiceviFileType) webServiceTemplate.marshalSendAndReceive(sdIAccoglienza,
				new SoapActionCallback("http://www.fatturapa.it/TrasmissioneFatture/ricevi_file"));

	} catch (Exception e) {
		e.printStackTrace();
		sendErrorNotificationMail(null, RICEVI_FILE, e);
	}
	return factory.createRispostaSdIRiceviFile(response);

}

Log della request:

2018-11-13 11:59:15,885 o.s.w.c.c.WebServiceTemplate Opening [org.springframework.ws.transport.http.HttpComponentsConnection@9537925] to [https://testservizi.fatturapa.it/ricevi_file]
2018-11-13 11:59:15,894 o.s.w.c.M.sent Sent request [SaajSoapMessage {http://www.fatturapa.gov.it/sdi/ws/trasmissione/v1.0/types}fileSdIBaseType]
2018-11-13 11:59:16,363 o.s.w.c.M.received Received response [SaajSoapMessage {http://schemas.xmlsoap.org/soap/envelope/}Fault] for request [SaajSoapMessage {http://www.fatturapa.gov.it/sdi/ws/trasmissione/v1.0/types}fileSdIBaseType]
2018-11-13 11:59:20,443 o.s.w.c.c.WebServiceTemplate Received Fault message for request [SaajSoapMessage {http://www.fatturapa.gov.it/sdi/ws/trasmissione/v1.0/types}fileSdIBaseType]

Questo il log dell’Exception

org.springframework.ws.soap.client.SoapFaultClientException: Internal Error
        at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:38)
        at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:830)
        at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:624)
        at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
        at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
        at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:383)
        at com.csteam.fatturapa.endpoint.TrasmissioneEndpoint.riceviFile(TrasmissioneEndpoint.java:79)

Sono riuscito ad effettuare l’invio!
Ho dovuto aggiungere nella classe FileSdIBaseType, nell’annotation @XmlRootElement il name in questo modo:

@XmlRootElement(name = “fileSdIAccoglienza”, namespace = “http://www.fatturapa.gov.it/sdi/ws/trasmissione/v1.0/types”)

Ho anche settato a “true” il Mtom nel marshaller

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

  marshaller.setContextPaths("it.gov.fatturapa.sdi.ws.ricezione.v1_0.types",
  		"it.gov.fatturapa.sdi.ws.trasmissione.v1_0.types");

  marshaller.afterPropertiesSet();
  marshaller.setMtomEnabled(true);

Di seguito il metodo riceviFile con le ultime modifiche:

@PayloadRoot(namespace = NAMESPACE_TRASMISSIONE, localPart = RICEVI_FILE)
@ResponsePayload
public JAXBElement riceviFile(@RequestPayload JAXBElement request)
throws IOException {
sendNotificationMail(null, TrasmissioneEndpoint.class.getSimpleName(), RICEVI_FILE, request.getValue());

  JAXBElement<RispostaSdIRiceviFileType> response = null;
  
  String defaultUri = "https://testservizi.fatturapa.it/ricevi_file";
  webServiceTemplate.setDefaultUri(defaultUri);
  
  ObjectFactory factory = new ObjectFactory();

  FileSdIBaseType sdIAccoglienza = factory.createFileSdIAccoglienza(request.getValue()).getValue();
  sdIAccoglienza.setNomeFile("esempio_fattura_IT01234567890_FPA01.xml");
  FileDataSource source = new FileDataSource(
  		"C:\\workspace\\ws-fattura\\complete\\src\\main\\resources\\esempio_fattura_IT01234567890_FPA01.xml");
  sdIAccoglienza.setFile(new DataHandler(source));
  
  try {
  	response = (JAXBElement<RispostaSdIRiceviFileType>) webServiceTemplate.marshalSendAndReceive(sdIAccoglienza,
  			new SoapActionCallback("ricevi_file"));

  } catch (Exception e) {
  	e.printStackTrace();
  	sendErrorNotificationMail(null, RICEVI_FILE, e);
  }
  return response;

}

Ciao Gianluca e ciao a tutta la Community,

Sto cercando di tirare su il sistema di invio con Spring Boot anche io, ma sono bloccato sull’errore 403… ho provato anche a creare il keystore.jks e il truststore.jks come hai scritto te ma ancora niente!!

Probabilmente non ho ben capito come creare keystore/truststore con i vari certificati che mi hanno rilasciato.

posto anche il codice della configurazione spring boot e della chiamata a ricevi file.

Configurazione:

@Bean
Jaxb2Marshaller jaxb2Marshaller() {
  Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
  jaxb2Marshaller.setContextPath("it.sogei.service.sdi.ricevifile");
  return jaxb2Marshaller;
}

@Bean
public WebServiceTemplate webServiceTemplate() throws Exception {
  WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
  webServiceTemplate.setMarshaller(jaxb2Marshaller());
  webServiceTemplate.setUnmarshaller(jaxb2Marshaller());
  webServiceTemplate.setDefaultUri(defaultUri);
  webServiceTemplate.setMessageSender(httpComponentsMessageSender());

  return webServiceTemplate;
}

@Bean
public HttpComponentsMessageSender httpComponentsMessageSender() throws Exception {
  HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
  httpComponentsMessageSender.setHttpClient(httpClient());

  return httpComponentsMessageSender;
}
@Bean
public HttpClient httpClient() throws Exception {
  return HttpClientBuilder.create().setSSLSocketFactory(sslConnectionSocketFactory())
      .addInterceptorFirst(new RemoveSoapHeadersInterceptor()).build();
}
@Bean
public SSLConnectionSocketFactory sslConnectionSocketFactory() throws Exception {
  return new SSLConnectionSocketFactory(sslContext(), NoopHostnameVerifier.INSTANCE);
}
@Bean
public SSLContext sslContext() throws Exception {
  return SSLContextBuilder.create()
	  .loadKeyMaterial(keyStore.getFile(), trustStorePassword.toCharArray(), trustStorePassword.toCharArray())
      .loadTrustMaterial(trustStore.getFile(), trustStorePassword.toCharArray()).build();
}

Metodo che effettua la chiamata

@Autowired
private WebServiceTemplate webServiceTemplate;

@SuppressWarnings("unchecked")
public RispostaSdIRiceviFileType riceviFile(String nome, byte[] fileByte) {
    ObjectFactory factory = new ObjectFactory();
    FileSdIType file = factory.createFileSdIType();
    file.setNomeFile(nome);
    file.setFile(new DataHandler(new ByteArrayDataSource(fileByte)));
    JAXBElement<FileSdIType> request = factory.createFileSdI(file);
    try {
    	JAXBElement<RispostaSdIRiceviFileType> response = 
    			(JAXBElement<RispostaSdIRiceviFileType>) webServiceTemplate.marshalSendAndReceive(request);
    	 System.out.println(response.getValue().getErrore().value());
         System.out.println(response.getValue().getDataOraRicezione());
         System.out.println(response.getValue().getIdentificativoSdI());
         return response.getValue();
    } catch (Exception e) {
		System.out.println(e.getMessage());
	}
   return null;
  }

Ringrazio in anticipo se qualcuno ha qualche dritta da darmi !

Ciao Claudio,
allora innanzitutto assicurati di aver caricato i certificati giusti nel truststore e keystore. Ci ho perso dei giorni! Dei certificati “server” te ne puoi fregare, nel keystore basta mettere solo quello client.

Nel bean di JAXB2 io ho inserito questi context:
marshaller.setContextPaths("it.gov.fatturapa.sdi.ws.ricezione.v1_0.types", "it.gov.fatturapa.sdi.ws.trasmissione.v1_0.types", "it.gov.agenziaentrate.ivaservizi.docs.wsdl.trasmissionefile.v2", "it.gov.agenziaentrate.ivaservizi.docs.xsd.fatture.v1");

Il metodo di ricezione l’ho inserito in una classe con l’annotation @Endpoint e l’ho impostato in questo modo:
@SoapAction("http://www.fatturapa.it/RicezioneFatture/RiceviFattureSdI") @ResponsePayload public JAXBElement<RispostaRiceviFattureType> riceviFattureSdI( @RequestPayload JAXBElement<FileSdIConMetadatiType> request) {

Il resto della configurazione mi sembra uguale alla mia.
Spero che questo possa esserti d’aiuto.

Ciao Gianluca,
Sei un grande!

Finalmente oggi siamo riusciti a sbloccare la situazione del 403 e sempre grazie a te anche il 500!!

Ora passiamo ai servizi da esporre! ci aggiorniamo!

Buona serata
Claudio

Bella lee :smiley:

Per la ricevuta delle notifiche (sia di scarto che di consegna e tutte le altre) il metodo è molto semplice in quanto il parametro in ricezione è lo stesso:

@SoapAction(value = "http://www.fatturapa.it/TrasmissioneFatture/RicevutaConsegna") @PayloadRoot(namespace = NAMESPACE_TRASMISSIONE, localPart = RICEVUTA_CONSEGNA) @ResponsePayload public void ricevutaConsegna(@RequestPayload JAXBElement<FileSdIType> request) {

Dove
NAMESPACE_TRASMISSIONE = http://www.fatturapa.gov.it/sdi/ws/trasmissione/v1.0/types
e
RICEVUTA_CONSEGNA = "RicevutaConsegna"

Nella notifica di mancata consegna (e nelle altre) cambia solo il SoapAction
@SoapAction(value = "http://www.fatturapa.it/TrasmissioneFatture/NotificaMancataConsegna")

Buona serata :slight_smile: