简体   繁体   English

Paypal Sandbox API:javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure

[英]Paypal Sandbox API: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

I am getting an exception while using PayPal MassPay API in sandbox mode. 我在沙盒模式下使用PayPal MassPay API时遇到异常。

The same code worked earlier, now it is giving me an SSLHandshakeException . 相同的代码早先工作,现在它给了我一个SSLHandshakeException I think this is because of PayPal's latest SSL certification updates. 我认为这是因为PayPal最新的SSL认证更新。 Could someone can help me fix this issue? 有人可以帮我解决这个问题吗?

The following is my exception log: 以下是我的异常日志:

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

The issue is that PayPal recently (19th or 20th of Jan) switched the sandbox to TLS 1.2 and do not support TLS 1 anymore. 问题是PayPal最近(1月19日或20日)将沙箱切换到TLS 1.2并且不再支持TLS 1。 I guess that you are running on Java SE 7 or older. 我猜你是在Java SE 7或更早版本上运行的。 If you search the net a bit you will find this: 如果您在网上搜索一下,您会发现:

Although SunJSSE in the Java SE 7 release supports TLS 1.1 and TLS 1.2, neither version is enabled by default for client connections. 虽然Java SE 7发行版中的SunJSSE支持TLS 1.1和TLS 1.2,但默认情况下不会为客户端连接启用任何版本。 Some servers do not implement forward compatibility correctly and refuse to talk to TLS 1.1 or TLS 1.2 clients. 某些服务器无法正确实现前向兼容性,并拒绝与TLS 1.1或TLS 1.2客户端通信。 For interoperability, SunJSSE does not enable TLS 1.1 or TLS 1.2 by default for client connections. 对于互操作性,SunJSSE默认情况下不为客户端连接启用TLS 1.1或TLS 1.2。

Link 链接

To enable TLS 1.2 you can use the following setting of the VM: -Dhttps.protocols=TLSv1.1,TLSv1.2 Then it will work. 要启用TLS 1.2,您可以使用以下VM设置: -Dhttps.protocols=TLSv1.1,TLSv1.2然后它将起作用。

If you want to see more details about the handshake you can use this VM option: -Djavax.net.debug=all 如果要查看有关握手的更多详细信息,可以使用此VM选项: -Djavax.net.debug=all

Then you may confirm that TLS 1.2 is disabled if you see something like this: 然后,如果您看到以下内容,则可以确认已禁用TLS 1.2:

*** ClientHello, TLSv1

After the server response is read the exception will be thrown. 读取服务器响应后,将抛出异常。 Java 8 has no such problem because TLS 1.2 is enabled by default. Java 8没有这样的问题,因为默认情况下启用了TLS 1.2。

Currently only the sandbox is affected. 目前只有沙箱受到影响。 You can read on PayPal's site: 您可以在PayPal的网站上阅读:

PayPal is updating its services to require TLS v1.2 for all HTTPS connections on June 17, 2016. After that date, all TLS v1.0 and TLS v1.1 API connections will be refused. PayPal正在更新其服务,以便在2016年6月17日对所有HTTPS连接要求TLS v1.2。在该日期之后,将拒绝所有TLS v1.0和TLS v1.1 API连接。

Most likely this will be postponed even more. 最有可能的是,这将推迟更多。

You may reproduce the problem and experiment with this simple throw-away code: 您可以重现问题并尝试使用这个简单的丢弃代码:

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();

http-bio-9090-exec-1, RECV TLSv1 ALERT: fatal, handshake_failure http-bio-9090-exec-1,RECV TLSv1警告:致命,握手_失败

Looks like you're using an older version of TLS. 看起来你正在使用旧版本的TLS。 PayPal recently (a few days ago) made a change to their sandbox to require all connections be done over HTTP 1.1 and TLS 1.2. PayPal最近(几天前)对他们的沙箱进行了更改,要求通过HTTP 1.1和TLS 1.2完成所有连接。 Try setting your code to use the newer version of TLS (1.2) and see if that helps. 尝试设置您的代码以使用较新版本的TLS(1.2),看看是否有帮助。 Apparently it's worked for a lot of people on here. 显然它对很多人来说都很有用。

Link to the change description on PayPal dev blog 链接到PayPal开发博客上的更改说明

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

I have been dealing with the same problem (Paypal TLS 1.2 Vs JRE 1.6) this week. 本周我一直在处理同样的问题(Paypal TLS 1.2 Vs JRE 1.6)。 After some crazy hours, I managed to solve the problem using BouncyCastle and a some code I am not proud of (just as a patch. lasting solution will be upgrading to JRE 1.8). 经过一段疯狂的时间后,我设法使用BouncyCastle和一些我并不自豪的代码来解决问题(就像补丁一样。持久解决方案将升级到JRE 1.8)。

BouncyCastle dependency: BouncyCastle依赖:

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

My working code: 我的工作代码:

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;
    }
}

}

如果要从Web服务或JAVA中的独立应用程序调用https请求,请使用以下行使其工作:

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

我的问题是我安装了java 7所以我升级到java 8并且瞧,异常不存在了:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SSL javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure - SSL javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure - javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure Java:javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure - Java: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure java 1.7_45 - javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure java 1.7_45 ChangeCipherSpec - javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure - ChangeCipherSpec - javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure javax.net.ssl.SSLHandshakeException:收到致命警报:仅在服务器中握手失败 - javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure only in server 获取javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure错误 - Getting javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure Error 获取 javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure - Getting javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 收到致命警报:handshake_failure:javax.net.ssl.SSLHandshakeException - Received fatal alert: handshake_failure : javax.net.ssl.SSLHandshakeException notnoop java-apns抛出javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure - notnoop java-apns throw javax.net.ssl.SSLHandshakeException:Received fatal alert: handshake_failure
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM