Thursday, 23 October 2014

Paypal sandbox SSL exception & SSL 3.0 Protocol Vulnerability

Problem

Connection to Paypal sandbox was broken on/after 13th of October and the SSL exception below was thrown from Paypal core Java client.

Caused by: javax.net.ssl.SSLException: Unsupported record version Unknown-0.0
                at com.ibm.jsse2.b.b(b.java:102)
                at com.ibm.jsse2.b.a(b.java:212)
                at com.ibm.jsse2.SSLSocketImpl.a(SSLSocketImpl.java:814)
                at com.ibm.jsse2.SSLSocketImpl.h(SSLSocketImpl.java:704)
                at com.ibm.jsse2.SSLSocketImpl.a(SSLSocketImpl.java:12)
                at com.ibm.jsse2.SSLSocketImpl.startHandshake(SSLSocketImpl.java:498)
                at com.ibm.net.ssl.www2.protocol.https.c.afterConnect(c.java:59)
                at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:31)
                at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
                at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
                at com.ibm.net.ssl.www2.protocol.https.b.getResponseCode(b.java:91)
                at com.paypal.core.HttpConnection.execute(HttpConnection.java:93)
                at com.paypal.core.APIService.makeRequestUsing(APIService.java:176)
                at com.paypal.core.BaseService.call(BaseService.java:258)
                at urn.ebay.api.PayPalAPI.PayPalAPIInterfaceServiceService.setExpressCheckout(PayPalAPIInterfaceServiceService.java:2196)
                at urn.ebay.api.PayPalAPI.PayPalAPIInterfaceServiceService.setExpressCheckout(PayPalAPIInterfaceServiceService.java:2148)

Fix

Paypal sandbox was updated on/around 13th of October to disable SSLv3 and enable TLS instead as a response to POODLE Security Vulnerability. This change on their side mandates replacing Paypal client Jars to latest version especially paypal-core which needs to be on version 1.6.4 at least as it has the necessary code change to initialize a TLS connection.

To prepare a fix, you need to build new jars from Paypal GitHub links provided below:

Paypal SDK Core Java
Paypal Merchant SDK Java

For quick testing, you can use the two jars below which I build myself:

Download PayPal Merchant SDK
Download Paypal SDK Core Java

Remarks

  • The issues above were encountered while using Paypal Mercahant SDK and don't know if their newer library (REST SDK) had a similar issue or not

Warning !

  • The jars provided above are for quick testing only and for use on a test non-live environment
  • Never deploy a payment related jar from untrusted source (like myself). Once you are sure the jars fixes your problem, please contact Paypal to prepare a new jar for you or do it yourself and build their code available on GitHub.



Friday, 17 October 2014

Tip for handling exceptions in WebSphere Commerce


Overview

When integrating with 3rd party jar files (e.g. Paypal as shown in examples below), it is important when catching exceptions thrown by those jars, to include the original exception (known as cause) when throwing an application specific exception.

In sample code given below, the first method will throw PayPalException and just the exception message while the second code sample will include the original exception itself too.

What difference will that make ? if you face a problem on production, a stack trace similar to the one given below will show up, but the second code sample will show more details which are marked in red in stack trace.

As you can see from the stack trace, you will get more details on what happened within your 3rd party jar files and if you have to contact their support team, you are able to give them a proper exception stack trace that helps them (and subsequently yourself too) to identify the problem and advise you with proper fix.

Sample code

private SetExpressCheckoutResponseType callPayPalSetExpressCheckOut(SetExpressCheckoutReq setExpressCheckoutReq,
PayPalAPIInterfaceServiceService service) throws PayPalException {
final String METHOD_NAME = "callPayPalSetExpressCheckOut()";
LOGGER.entering(CLASSNAME, METHOD_NAME);

String responseToken = null;
SetExpressCheckoutResponseType setExpressCheckoutResponse;
try {
//Execute the API operation and obtain the response.
setExpressCheckoutResponse = service.setExpressCheckout(setExpressCheckoutReq);
} catch (Exception ex) {
throw new PayPalException(CLASSNAME, METHOD_NAME, ex.getMessage());
}

LOGGER.exiting(CLASSNAME, METHOD_NAME);
return setExpressCheckoutResponse;
}

private SetExpressCheckoutResponseType callPayPalSetExpressCheckOut(SetExpressCheckoutReq setExpressCheckoutReq,
PayPalAPIInterfaceServiceService service) throws PayPalException {

final String METHOD_NAME = "callPayPalSetExpressCheckOut()";
LOGGER.entering(CLASSNAME, METHOD_NAME);

String responseToken = null;
SetExpressCheckoutResponseType setExpressCheckoutResponse;
try {
//Execute the API operation and obtain the response.
setExpressCheckoutResponse = service.setExpressCheckout(setExpressCheckoutReq);
} catch (Exception ex) {
throw new PayPalException(CLASSNAME, METHOD_NAME, ex.getMessage(),ex);
}

LOGGER.exiting(CLASSNAME, METHOD_NAME);
return setExpressCheckoutResponse;
}

Stacktrace

 com.tmpl.commerce.payment.exceptions.PayPalException: Unsupported record version Unknown-0.0
at com.tmpl.commerce.payment.paypal.request.PayPalECPaymentRequestHandler.callPayPalSetExpressCheckOut(PayPalECPaymentRequestHandler.java:457)
at com.tmpl.commerce.payment.paypal.request.PayPalECPaymentRequestHandler.setExpressCheckOut(PayPalECPaymentRequestHandler.java:107)
at com.tmpl.commerce.payment.paypal.processor.PayPalECService.setExpressCheckOut(PayPalECService.java:84)
at com.tmpl.commerce.payment.paypal.commands.PayPalECRequestCmdImpl.performExecute(PayPalECRequestCmdImpl.java:174)
at com.ibm.commerce.command.ECCommandTarget.executeCommand(ECCommandTarget.java:157)
at com.ibm.ws.cache.command.CommandCache.executeCommand(CommandCache.java:332)
at com.ibm.websphere.command.CacheableCommandImpl.execute(CacheableCommandImpl.java:166)
at com.ibm.commerce.command.AbstractECTargetableCommand.execute(AbstractECTargetableCommand.java:236)
at com.ibm.commerce.component.BaseComponentImpl.executeCommand(BaseComponentImpl.java:202)
at com.ibm.commerce.component.WebAdapterComponentImpl.executeCommand(WebAdapterComponentImpl.java:46)
at com.ibm.commerce.component.objimpl.WebAdapterServiceBeanBase.executeCommand(WebAdapterServiceBeanBase.java:58)
at com.ibm.commerce.component.objects.EJSLocalStatelessWebAdapterService_ce749a4a.executeCommand(EJSLocalStatelessWebAdapterService_ce749a4a.java:31)
at com.ibm.commerce.component.objects.WebAdapterServiceAccessBean.executeCommand(WebAdapterServiceAccessBean.java:160)
at com.ibm.commerce.webcontroller.WebControllerHelper.executeCommand(WebControllerHelper.java:2778)
at com.ibm.commerce.struts.AjaxAction.invokeService(AjaxAction.java:501)
at com.ibm.commerce.struts.AjaxAction.executeAction(AjaxAction.java:312)
at com.ibm.commerce.struts.AjaxAction.execute(AjaxAction.java:125)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at com.ibm.commerce.struts.ECActionServlet.processRequest(ECActionServlet.java:231)
at com.ibm.commerce.struts.ECActionServlet.doPost(ECActionServlet.java:186)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
at com.ibm.commerce.struts.ECActionServlet.service(ECActionServlet.java:739)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at com.ibm.ws.cache.servlet.ServletWrapper.serviceProxied(ServletWrapper.java:307)
at com.ibm.ws.cache.servlet.CacheHook.handleFragment(CacheHook.java:576)
at com.ibm.ws.cache.servlet.CacheHook.handleServlet(CacheHook.java:250)
at com.ibm.ws.cache.servlet.ServletWrapper.service(ServletWrapper.java:259)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1667)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1602)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:149)
at com.ibm.commerce.campaigns.filter.CampaignsFilter.doFilter(CampaignsFilter.java:148)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125)
at com.ibm.commerce.likeminds.filter.LikeMindsFilter.doFilter(LikeMindsFilter.java:183)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125)
at com.ibm.commerce.dynacache.filter.CacheFilter$1.run(CacheFilter.java:390)
at com.ibm.commerce.dynacache.filter.CacheFilter.doFilter(CacheFilter.java:553)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125)
at com.ibm.commerce.webcontroller.RuntimeServletFilter.doFilterAction(RuntimeServletFilter.java:736)
at com.ibm.commerce.webcontroller.RuntimeServletFilter.access$0(RuntimeServletFilter.java:523)
at com.ibm.commerce.webcontroller.RuntimeServletFilter$1.run(RuntimeServletFilter.java:433)
at com.ibm.commerce.webcontroller.RuntimeServletFilter.doFilter(RuntimeServletFilter.java:458)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:80)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:939)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:507)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:181)
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:91)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:878)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1592)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:191)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:453)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:515)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:306)
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:84)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1656)
Caused by: javax.net.ssl.SSLException: Unsupported record version Unknown-0.0
at com.ibm.jsse2.b.b(b.java:102)
at com.ibm.jsse2.b.a(b.java:212)
at com.ibm.jsse2.SSLSocketImpl.a(SSLSocketImpl.java:814)
at com.ibm.jsse2.SSLSocketImpl.h(SSLSocketImpl.java:704)
at com.ibm.jsse2.SSLSocketImpl.a(SSLSocketImpl.java:12)
at com.ibm.jsse2.SSLSocketImpl.startHandshake(SSLSocketImpl.java:498)
at com.ibm.net.ssl.www2.protocol.https.c.afterConnect(c.java:59)
at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:31)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
at com.ibm.net.ssl.www2.protocol.https.b.getResponseCode(b.java:91)
at com.paypal.core.HttpConnection.execute(HttpConnection.java:93)
at com.paypal.core.APIService.makeRequestUsing(APIService.java:176)
at com.paypal.core.BaseService.call(BaseService.java:258)
at urn.ebay.api.PayPalAPI.PayPalAPIInterfaceServiceService.setExpressCheckout(PayPalAPIInterfaceServiceService.java:2196)
at urn.ebay.api.PayPalAPI.PayPalAPIInterfaceServiceService.setExpressCheckout(PayPalAPIInterfaceServiceService.java:2148)
at com.tmpl.commerce.payment.paypal.request.PayPalECPaymentRequestHandler.callPayPalSetExpressCheckOut(PayPalECPaymentRequestHandler.java:455)
... 68 more