Java tutorial
/* * GovPay - Porta di Accesso al Nodo dei Pagamenti SPC * http://www.gov4j.it/govpay * * Copyright (c) 2014-2017 Link.it srl (http://www.link.it). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package it.govpay.core.utils.client; import it.govpay.core.utils.GovpayConfig; import it.govpay.core.utils.GpContext; import it.govpay.core.utils.GpThreadLocal; import it.govpay.core.utils.JaxbUtils; import it.govpay.core.utils.client.handler.IntegrationContext; import it.govpay.core.utils.client.handler.IntegrationOutHandler; import it.govpay.model.Applicazione; import it.govpay.model.Connettore; import it.govpay.model.Intermediario; import it.govpay.model.Connettore.EnumAuthType; import it.govpay.model.Connettore.EnumSslType; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.security.KeyStore; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.xml.bind.JAXBElement; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.openspcoop2.utils.logger.beans.Message; import org.openspcoop2.utils.logger.beans.Property; import org.openspcoop2.utils.logger.constants.MessageType; public class BasicClient { private static Logger log = LogManager.getLogger(); public class ClientException extends Exception { private static final long serialVersionUID = 1L; public ClientException(String message, Exception e) { super(message, e); } public ClientException(Exception e) { super(e); } public ClientException(String string) { super(string); } } protected static Map<String, SSLContext> sslContexts = new HashMap<String, SSLContext>(); protected URL url = null; protected SSLContext sslContext; protected boolean ishttpBasicEnabled = false, isSslEnabled = false; protected String httpBasicUser, httpBasicPassword; protected String errMsg; protected String destinatario; protected String mittente; protected TipoDestinatario tipoDestinatario; public enum TipoConnettore { VERIFICA, NOTIFICA; } public enum TipoDestinatario { APPLICAZIONE, INTERMEDIARIO; } protected BasicClient(Intermediario intermediario) throws ClientException { this("I_" + intermediario.getCodIntermediario(), intermediario.getConnettorePdd()); errMsg = "Pdd dell'intermediario (" + intermediario.getCodIntermediario() + ")"; mittente = intermediario.getDenominazione(); destinatario = "NodoDeiPagamentiDellaPA"; } protected BasicClient(Applicazione applicazione, TipoConnettore tipoConnettore) throws ClientException { this("A_" + tipoConnettore + applicazione.getCodApplicazione(), tipoConnettore == TipoConnettore.NOTIFICA ? applicazione.getConnettoreNotifica() : applicazione.getConnettoreVerifica()); GpThreadLocal.get().getIntegrationCtx().setApplicazione(applicazione); errMsg = tipoConnettore.toString() + " dell'applicazione (" + applicazione.getCodApplicazione() + ")"; mittente = "GovPay"; destinatario = applicazione.getCodApplicazione(); } private BasicClient(String bundleKey, Connettore connettore) throws ClientException { if (connettore == null) { throw new ClientException("Connettore non configurato"); } try { this.url = new URL(connettore.getUrl()); } catch (Exception e) { throw new ClientException("La URL del connettore " + errMsg + " non e' valida: " + e); } sslContext = sslContexts.get(bundleKey); if (connettore.getTipoAutenticazione().equals(EnumAuthType.SSL)) { isSslEnabled = true; if (sslContext == null) { try { FileInputStream finKeyStore = null; FileInputStream finTrustStore = null; KeyManager[] km = null; TrustManager[] tm = null; // Autenticazione CLIENT if (connettore.getTipoSsl().equals(EnumSslType.CLIENT)) { if (connettore.getSslKsType() == null || connettore.getSslKsLocation() == null || connettore.getSslKsPasswd() == null || connettore.getSslPKeyPasswd() == null) throw new ClientException( "Configurazione SSL Client del connettore " + errMsg + " incompleta."); KeyStore keystore = KeyStore.getInstance(connettore.getSslKsType()); // JKS,PKCS12,jceks,bks,uber,gkr finKeyStore = new FileInputStream(connettore.getSslKsLocation()); keystore.load(finKeyStore, connettore.getSslKsPasswd().toCharArray()); KeyManagerFactory keyManagerFactory = KeyManagerFactory .getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keystore, connettore.getSslPKeyPasswd().toCharArray()); km = keyManagerFactory.getKeyManagers(); } if (connettore.getSslTsType() == null || connettore.getSslTsLocation() == null || connettore.getSslTsPasswd() == null || connettore.getSslType() == null) throw new ClientException( "Configurazione SSL Server del connettore " + errMsg + " incompleta."); // Autenticazione SERVER KeyStore truststore = KeyStore.getInstance(connettore.getSslTsType()); // JKS,PKCS12,jceks,bks,uber,gkr finTrustStore = new FileInputStream(connettore.getSslTsLocation()); truststore.load(finTrustStore, connettore.getSslTsPasswd().toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(truststore); tm = trustManagerFactory.getTrustManagers(); // Creo contesto SSL sslContext = SSLContext.getInstance(connettore.getSslType()); sslContext.init(km, tm, null); sslContexts.put(bundleKey, sslContext); } catch (Exception e) { throw new ClientException(e); } } } if (connettore.getTipoAutenticazione().equals(EnumAuthType.HTTPBasic)) { ishttpBasicEnabled = true; httpBasicUser = connettore.getHttpUser(); httpBasicPassword = connettore.getHttpPassw(); } } public byte[] sendXml(JAXBElement<?> body, boolean isAzioneInUrl) throws ClientException { return send(false, null, body, null, isAzioneInUrl); } private void invokeOutHandlers() throws ClientException { try { List<String> outHandlers = GovpayConfig.getInstance().getOutHandlers(); if (outHandlers != null && !outHandlers.isEmpty()) { IntegrationContext ic = GpThreadLocal.get().getIntegrationCtx(); log.debug("Applicazione al messaggio degli handlers configurati..."); for (String handler : outHandlers) { Class<?> c = Class.forName(handler); IntegrationOutHandler instance = (IntegrationOutHandler) c.newInstance(); log.debug("Applicazione al messaggio dell'handler [" + handler + "]..."); instance.invoke(ic); log.debug("Applicazione al messaggio dell'handler [" + handler + "] completata con successo"); } log.debug("Applicazione al messaggio degli handlers configurati completata con successo"); } else { log.debug("Nessun handler configurato"); } } catch (Exception e) { throw new ClientException( "Errore durante l'applicazione al messaggio degli handlers configurati: " + e.getMessage(), e); } } public byte[] sendSoap(String azione, JAXBElement<?> body, Object header, boolean isAzioneInUrl) throws ClientException { return send(true, azione, body, header, isAzioneInUrl); } private byte[] send(boolean soap, String azione, JAXBElement<?> body, Object header, boolean isAzioneInUrl) throws ClientException { // Creazione Connessione int responseCode; HttpURLConnection connection = null; byte[] msg = null; GpContext ctx = GpThreadLocal.get(); String urlString = url.toExternalForm(); if (isAzioneInUrl) { if (!urlString.endsWith("/")) urlString = urlString.concat("/"); try { url = new URL(urlString.concat(azione)); } catch (MalformedURLException e) { throw new ClientException("Url di connessione malformata: " + urlString.concat(azione), e); } } try { Message requestMsg = new Message(); requestMsg.setType(MessageType.REQUEST_OUT); connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); if (soap) { connection.setRequestProperty("SOAPAction", "\"" + azione + "\""); requestMsg.addHeader(new Property("SOAPAction", "\"" + azione + "\"")); } requestMsg.setContentType("text/xml"); connection.setRequestProperty("Content-Type", "text/xml"); connection.setRequestMethod("POST"); // Imposta Contesto SSL se attivo if (sslContext != null) { HttpsURLConnection httpsConn = (HttpsURLConnection) connection; httpsConn.setSSLSocketFactory(sslContext.getSocketFactory()); HostNameVerifierDisabled disabilitato = new HostNameVerifierDisabled(); httpsConn.setHostnameVerifier(disabilitato); } // Imposta l'autenticazione HTTP Basic se attiva if (ishttpBasicEnabled) { Base64 base = new Base64(); String encoding = new String(base.encode((httpBasicUser + ":" + httpBasicPassword).getBytes())); connection.setRequestProperty("Authorization", "Basic " + encoding); requestMsg.addHeader(new Property("Authorization", "Basic " + encoding)); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (soap) { SOAPUtils.writeMessage(body, header, baos); } else { JaxbUtils.marshal(body, baos); } ctx.getIntegrationCtx().setMsg(baos.toByteArray()); invokeOutHandlers(); if (log.getLevel().isMoreSpecificThan(Level.TRACE)) { StringBuffer sb = new StringBuffer(); for (String key : connection.getRequestProperties().keySet()) { sb.append("\n\t" + key + ": " + connection.getRequestProperties().get(key)); } sb.append("\n" + new String(ctx.getIntegrationCtx().getMsg())); log.trace(sb.toString()); } requestMsg.setContent(ctx.getIntegrationCtx().getMsg()); ctx.getContext().getRequest().setOutDate(new Date()); ctx.getContext().getRequest().setOutSize(Long.valueOf(ctx.getIntegrationCtx().getMsg().length)); ctx.log(requestMsg); connection.getOutputStream().write(ctx.getIntegrationCtx().getMsg()); } catch (Exception e) { throw new ClientException(e); } try { responseCode = connection.getResponseCode(); ctx.getTransaction().getServer().setTransportCode(Integer.toString(responseCode)); } catch (Exception e) { throw new ClientException(e); } Message responseMsg = new Message(); responseMsg.setType(MessageType.RESPONSE_IN); for (String key : connection.getHeaderFields().keySet()) { if (connection.getHeaderFields().get(key) != null) { if (key == null) responseMsg .addHeader(new Property("Status-line", connection.getHeaderFields().get(key).get(0))); else if (connection.getHeaderFields().get(key).size() == 1) responseMsg.addHeader(new Property(key, connection.getHeaderFields().get(key).get(0))); else responseMsg.addHeader( new Property(key, ArrayUtils.toString(connection.getHeaderFields().get(key)))); } } try { if (responseCode < 300) { try { if (connection.getInputStream() == null) { return null; } msg = connection.getInputStream() != null ? IOUtils.toByteArray(connection.getInputStream()) : new byte[] {}; if (msg.length > 0) responseMsg.setContent(msg); return msg; } catch (Exception e) { throw new ClientException("Messaggio di risposta non valido", e); } } else { try { msg = connection.getErrorStream() != null ? IOUtils.toByteArray(connection.getErrorStream()) : new byte[] {}; responseMsg.setContent(msg); } catch (IOException e) { msg = ("Impossibile serializzare l'ErrorStream della risposta: " + e).getBytes(); } finally { log.warn("Errore nell'invocazione del Nodo dei Pagamenti [HTTP Response Code " + responseCode + "]\nRisposta: " + new String(msg)); } throw new ClientException("Ricevuto [HTTP " + responseCode + "]"); } } finally { if (responseMsg != null) { ctx.getContext().getResponse().setInDate(new Date()); ctx.getContext().getResponse().setInSize((long) responseMsg.getContent().length); ctx.log(responseMsg); } if (log.getLevel().isMoreSpecificThan(Level.TRACE) && connection != null && connection.getHeaderFields() != null) { StringBuffer sb = new StringBuffer(); for (String key : connection.getHeaderFields().keySet()) { sb.append("\n\t" + key + ": " + connection.getHeaderField(key)); } sb.append("\n" + new String(msg)); log.trace(sb.toString()); } } } public static boolean cleanCache(String bundleKey) { return sslContexts.remove(bundleKey) != null; } public static boolean cleanCache() { sslContexts = new HashMap<String, SSLContext>(); return true; } }