web-dev-qa-db-fra.com

API Paypal Sandbox: javax.net.ssl.SSLHandshakeException: Alerte irrécupérable reçue: handshake_failure

Je reçois une exception lorsque j'utilise Paypal MassPay API en mode bac à sable.

Le même code fonctionnait plus tôt, maintenant il me donne une SSLHandshakeException. Je pense que cela est dû aux dernières mises à jour de la certification SSL de Paypal. Quelqu'un peut-il m'aider à résoudre ce problème?

Voici mon journal des exceptions:

http-bio-9090-exec-1, READ: TLSv1 Alert, length = 2
http-bio-9090-exec-1, RECV TLSv1 ALERT:  fatal, handshake_failure
http-bio-9090-exec-1, called closeSocket()
http-bio-9090-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
com.Paypal.core.rest.PayPalRESTException: Received fatal alert: handshake_failure
    at com.Paypal.core.rest.PayPalResource.execute(PayPalResource.Java:374)
    at com.Paypal.core.rest.PayPalResource.configureAndExecute(PayPalResource.Java:225)
    at com.Paypal.sdk.openidconnect.Tokeninfo.createFromAuthorizationCode(Tokeninfo.Java:245)
    at com.oldwallet.controllers.CouponPaymentController.redeemed(CouponPaymentController.Java:321)
    at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.Java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.Java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.Java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.Java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.Java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.Java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:953)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:844)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.Java:829)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:728)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:305)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:222)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:123)
    at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:472)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:171)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:99)
    at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:953)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:408)
    at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1008)
    at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:589)
    at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:310)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
    at Java.lang.Thread.run(Thread.Java:745)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at Sun.security.ssl.Alerts.getSSLException(Alerts.Java:192)
    at Sun.security.ssl.Alerts.getSSLException(Alerts.Java:154)
    at Sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.Java:1959)
    at Sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.Java:1077)
    at Sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.Java:1312)
    at Sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1339)
    at Sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1323)
    at Sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.Java:563)
    at Sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.Java:185)
    at Sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.Java:1300)
    at Java.net.HttpURLConnection.getResponseCode(HttpURLConnection.Java:468)
    at Sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.Java:338)
    at com.Paypal.core.HttpConnection.execute(HttpConnection.Java:93)
    at com.Paypal.core.rest.PayPalResource.execute(PayPalResource.Java:367)
    ... 36 more
14
Syam Danda

Le problème est que Paypal (le 19 ou le 20 janvier) a récemment basculé le bac à sable vers TLS 1.2 et ne prend plus en charge TLS 1. Je suppose que vous utilisez Java SE 7 ou une version antérieure. Si vous recherchez un peu le net, vous trouverez ceci:

Bien que SunJSSE dans la version Java SE 7 prenne en charge TLS 1.1 et TLS 1.2, aucune version n'est activée par défaut pour les connexions client. Certains serveurs n’implémentent pas correctement la compatibilité en aval et refuser de parler aux clients TLS 1.1 ou 1.2. Pour l'interopérabilité, SunJSSE n'active pas TLS 1.1 ou TLS 1.2 par défaut pour le client les liaisons.

Lien

Pour activer TLS 1.2, vous pouvez utiliser le paramètre suivant de la VM: -Dhttps.protocols=TLSv1.1,TLSv1.2 Ensuite, cela fonctionnera.

Si vous voulez voir plus de détails sur la poignée de main, vous pouvez utiliser cette option VM: -Djavax.net.debug=all

Ensuite, vous pouvez confirmer que TLS 1.2 est désactivé si vous voyez quelque chose comme ceci:

*** ClientHello, TLSv1

Une fois la réponse du serveur lue, l'exception sera levée. Java 8 n'a pas ce problème car TLS 1.2 est activé par défaut.

Actuellement, seul le bac à sable est affecté. Vous pouvez lire sur le site de Paypal:

Paypal met à jour ses services pour exiger TLS v1.2 pour tous les protocoles HTTPS connexions le 17 juin 2016. Après cette date, toutes les versions TLS v1.0 et TLS Les connexions à l'API v1.1 seront refusées.

Très probablement, cela sera reporté encore plus.

Vous pouvez reproduire le problème et expérimenter avec ce code jetable simple:

URL sandbox = new URL("https://api.sandbox.Paypal.com/v1/oauth2/token");
URLConnection yc = sandbox.openConnection();

BufferedReader in = new BufferedReader(new InputStreamReader(
    yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
   System.out.println(inputLine);
in.close();
22
Lachezar Balev

http-bio-9090-exec-1, ALERTE RECV TLSv1: fatal, handshake_failure

On dirait que vous utilisez une ancienne version de TLS. Paypal a récemment (il y a quelques jours) modifié son sandbox pour exiger que toutes les connexions soient effectuées via HTTP 1.1 et TLS 1.2. Essayez de définir votre code pour utiliser la nouvelle version de TLS (1.2) et voyez si cela vous aide. Apparemment, cela a fonctionné pour beaucoup de gens ici.

Lien vers la description de la modification sur le blog paypal dev

https://devblog.Paypal.com/upcoming-security-changes-notice/

4
0kay

Si vous appelez une demande https depuis un service Web ou dans une application autonome en Java, utilisez la ligne suivante pour la faire fonctionner: 

System.setProperty(“https.protocols”, “TLSv1,TLSv1.1,TLSv1.2”);
1
Rohit S

J'ai eu le même problème (Paypal TLS 1.2 vs JRE 1.6) cette semaine. Après quelques heures folles, j'ai réussi à résoudre le problème en utilisant BouncyCastle et un code dont je ne suis pas fier (tout comme un correctif. Une solution durable passera à JRE 1.8).

Dépendance BouncyCastle:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.54</version>
</dependency>

Mon code de travail:

package es.webtools.eencuesta.redsys.component.impl;

import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import Java.net.Socket;
import Java.net.URL;
import Java.net.URLDecoder;
import Java.util.HashMap;
import Java.util.Iterator;
import Java.util.Map;
import Java.util.Map.Entry;

import org.bouncycastle.crypto.tls.CertificateRequest;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.crypto.tls.TlsCredentials;

import es.webtools.eencuesta.common.util.HttpUtils;

public class PayPayAPIHandler {

    public static Map<String, String> doAPIRequest(Map<String, String> paramMap) {

    StringBuilder data = new StringBuilder();
    Iterator<Entry<String, String>> paramIt = paramMap.entrySet().iterator();
    while (paramIt.hasNext()) {
        Entry<String, String> param = paramIt.next();
        data.append(param.getKey()).append("=").append(HttpUtils.encodeUTF8(param.getValue()));
        if (paramIt.hasNext()) {
            data.append("&");
        }
    }

    try {
        URL url = new URL("https://api-3t.sandbox.Paypal.com/nvp");

        // TODO #39 Utilizar HttpConnection (Java 8 implementa TLS 1.2, necesaria para comunicación con Paypal)
        Java.security.SecureRandom secureRandom = new Java.security.SecureRandom();
        Socket socket = new Socket(Java.net.InetAddress.getByName(url.getHost()), 443);
        TlsClientProtocol protocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), secureRandom);
        DefaultTlsClient client = new DefaultTlsClient() {
            public TlsAuthentication getAuthentication() throws IOException {
                TlsAuthentication auth = new TlsAuthentication() {
                    // Capture the server certificate information!
                    public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate) throws IOException {
                    }

                    public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
                        return null;
                    }
                };
                return auth;
            }
        };

        protocol.connect(client);
        Java.io.OutputStream output2 = protocol.getOutputStream();
        output2.write(("POST " + url.getPath() + " HTTP/1.1\r\n").getBytes("UTF-8"));
        output2.write(("Host: " + url.getHost() + "\r\n").getBytes("UTF-8"));
        output2.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
        output2.write(("Content-Length: " + data.length() + "\r\n").getBytes("UTF-8")); // So the server will close socket immediately.
        output2.write("Content-Type:text/plain; charset=UTF-8\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
        output2.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
        output2.write(data.toString().getBytes("UTF-8"));
        output2.flush();

        InputStream input2 = protocol.getInputStream();
        StringBuilder stringBuffer = new StringBuilder();
        try {
            InputStreamReader reader = new InputStreamReader(input2, "UTF-8");
            int ch;
            while ((ch = reader.read()) > -1) {
                stringBuffer.append((char) ch);
            }
            reader.close();
        } catch (Exception e) {
            // Log some messages...
        }

        Map<String, String> result = new HashMap<String, String>();
        String[] lines = stringBuffer.toString().split("\r\n");
        String paramsLine = "";
        for (int i = 0; i < lines.length; i++) {
            if (lines[i].equals("")) {
                paramsLine = lines[i + 1];
                i = lines.length;
            }
        }

        // El contenido de la respuesta vendrá después del salto de linea
        for (String param : paramsLine.split("&")) {
            String[] keyValue = param.split("=");
            result.put(keyValue[0], URLDecoder.decode(keyValue[1], "UTF-8"));
        }

        return result;
    } catch (Exception e) {
        // Log some messages....
        return null;
    }
}

}
1
Basa

Mon problème était que j'avais Java 7 installé alors je suis passé à Java 8 et le tour est joué, l'exception n'était plus là :)

1
joeabala