Skip to content

Commit 3f2e9e6

Browse files
authored
Release 3.1.1 (#106)
2 parents 9fb16ad + 0ce5e1e commit 3f2e9e6

17 files changed

+128
-81
lines changed

.github/CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @unzerdev/merchantconnectivity

.github/workflows/maven.yml renamed to .github/workflows/unit.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
33

4-
name: Java CI with Maven
4+
name: Unit tests
55

66
on:
77
pull_request:

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres
77
to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
88

9+
## [3.1.1][3.1.1]
10+
11+
This release updates dependencies with security issues
12+
13+
### Changed
14+
15+
* Upgraded Apache HttpClient from version 4 to version 5.
16+
* Made `HttpCommunicationException` unchecked exception.
17+
* Updated `jackson-core` dependency.
18+
919
## [3.1.0][3.1.0]
1020

1121
This release introduces Unzer PayPal Express in Java SDK.
@@ -315,6 +325,8 @@ This release brings Unzer Paylater Invoice payment type support to Java SDK.
315325
* Remove deprecated classes
316326
* RestCommunication
317327

328+
[3.1.1]: http://github.com/unzerdev/java-sdk/compare/3.1.0..3.1.1
329+
318330
[3.1.0]: http://github.com/unzerdev/java-sdk/compare/3.0.0..3.1.0
319331

320332
[3.0.0]: http://github.com/unzerdev/java-sdk/compare/1.3.0.0..3.0.0

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Java 1.8 or later.
1414
<dependency>
1515
<groupId>com.unzer.payment</groupId>
1616
<artifactId>java-sdk</artifactId>
17-
<version>3.1.0</version>
17+
<version>3.1.1</version>
1818
</dependency>
1919
```
2020

pom.xml

+7-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.unzer.payment</groupId>
88
<artifactId>java-sdk</artifactId>
9-
<version>3.1.0</version>
9+
<version>3.1.1</version>
1010
<name>Unzer Java SDK</name>
1111
<description>Unzer Java SDK provides an easy way to connect to the Unzer Rest API.</description>
1212
<url>https://docs.unzer.com/</url>
@@ -41,9 +41,9 @@
4141
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
4242
<additionalparam>-Xdoclint:none</additionalparam>
4343
<skip.dependency.check>true</skip.dependency.check>
44-
<log4j.version>2.18.0</log4j.version>
45-
<jackson.version>2.14.0-rc1</jackson.version>
46-
<junit.version>5.9.0</junit.version>
44+
<log4j.version>2.19.0</log4j.version>
45+
<jackson.version>2.14.1</jackson.version>
46+
<junit.version>5.9.1</junit.version>
4747
<system-stubs.version>2.0.1</system-stubs.version>
4848
</properties>
4949

@@ -236,7 +236,6 @@
236236
<excludes>
237237
<exclude>**/*.md</exclude>
238238
<exclude>**/*.xml</exclude>
239-
<exclude>selenium/**</exclude>
240239
<exclude>src/test/resources/**</exclude>
241240
<exclude>src/main/resources/**</exclude>
242241
</excludes>
@@ -285,14 +284,12 @@
285284
<artifactId>jaxb-api</artifactId>
286285
<version>2.3.1</version>
287286
</dependency>
288-
289287
<dependency>
290-
<groupId>org.apache.httpcomponents</groupId>
291-
<artifactId>httpclient</artifactId>
292-
<version>4.5.13</version>
288+
<groupId>org.apache.httpcomponents.client5</groupId>
289+
<artifactId>httpclient5</artifactId>
290+
<version>5.2.1</version>
293291
</dependency>
294292

295-
296293
<!-- Test dependencies -->
297294
<dependency>
298295
<groupId>org.junit.jupiter</groupId>

src/main/java/com/unzer/payment/AbstractPayment.java

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public abstract class AbstractPayment implements PaymentType {
3838
private Metadata metadata;
3939
private String basketId;
4040
private Basket basket;
41+
@Deprecated
4142
private transient Unzer unzer;
4243

4344
@Deprecated

src/main/java/com/unzer/payment/communication/AbstractUnzerRestCommunication.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424

2525
import javax.xml.bind.DatatypeConverter;
2626
import java.io.UnsupportedEncodingException;
27+
import java.net.URISyntaxException;
2728
import java.util.ArrayList;
2829
import java.util.List;
2930
import java.util.Locale;
3031
import java.util.Objects;
3132

32-
import static org.apache.http.HttpHeaders.*;
33+
import static org.apache.hc.core5.http.HttpHeaders.*;
3334

3435
/**
3536
* Template implementation of the {@code UnzerRestCommunication}. You should

src/main/java/com/unzer/payment/communication/HttpCommunicationException.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
/**
1919
* Generic exception for HttpCommunication module
2020
*/
21-
public class HttpCommunicationException extends Exception {
21+
public class HttpCommunicationException extends RuntimeException {
2222

2323
private static final long serialVersionUID = 1L;
2424

src/main/java/com/unzer/payment/communication/UnzerHttpRequest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.unzer.payment.communication;
1717

1818
import java.net.URI;
19+
import java.net.URISyntaxException;
1920

2021
/**
2122
* Abstraction for any http-request executed by the
@@ -26,7 +27,7 @@ public interface UnzerHttpRequest {
2627

2728
void addHeader(String header, String value);
2829

29-
URI getURI();
30+
URI getURI() throws URISyntaxException;
3031

3132
void setContent(String content, String encoding);
3233

src/main/java/com/unzer/payment/communication/impl/HttpClientBasedHttpRequest.java

+23-20
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
package com.unzer.payment.communication.impl;
1717

1818
import com.unzer.payment.communication.UnzerHttpRequest;
19-
import org.apache.http.HttpEntity;
20-
import org.apache.http.HttpEntityEnclosingRequest;
21-
import org.apache.http.client.methods.*;
22-
import org.apache.http.entity.StringEntity;
19+
import org.apache.hc.client5.http.classic.methods.*;
20+
import org.apache.hc.core5.http.ClassicHttpRequest;
21+
import org.apache.hc.core5.http.ContentType;
22+
import org.apache.hc.core5.http.io.entity.StringEntity;
2323

2424
import java.net.URI;
25+
import java.net.URISyntaxException;
2526

2627
/**
2728
* Implementation of the {@code UnzerHttpRequest} wrapping an apache
@@ -35,19 +36,17 @@
3536
*/
3637
public class HttpClientBasedHttpRequest implements UnzerHttpRequest {
3738

38-
protected HttpUriRequest request;
39+
protected ClassicHttpRequest request;
3940
protected UnzerHttpMethod method;
4041

4142
/**
4243
* Creates a {@code HttpClientBasedHttpRequest} wrapping a
4344
* {@code HttpUriRequest} defined by the given {@code UnzerHttpMethod}.
4445
*
45-
* @param uri
46-
* - the RUI of the request
47-
* @param method
48-
* - the {@code UnzerHttpMethod} representing one of
49-
* {@code HttpGet}, {@code HttpPost}, {@code HttpPut},
50-
* {@code HttpDelete}
46+
* @param uri - the RUI of the request
47+
* @param method - the {@code UnzerHttpMethod} representing one of
48+
* {@code HttpGet}, {@code HttpPost}, {@code HttpPut},
49+
* {@code HttpDelete}
5150
*/
5251
public HttpClientBasedHttpRequest(String uri, UnzerHttpMethod method) {
5352
this.method = method;
@@ -77,24 +76,28 @@ public void addHeader(String header, String value) {
7776
}
7877

7978
/**
80-
* Returns the wrapped {@code HttpUriRequest} to be passed to the {@code HttpClient} within the {@code HttpClientBasedRestCommunication} implementation.
81-
* @return - the the wrapped {@code HttpUriRequest}
79+
* Returns the wrapped {@code HttpUriRequest} to be passed to the {@code HttpClient} within the {@code HttpClientBasedRestCommunication} implementation.
80+
*
81+
* @return - the the wrapped {@code HttpUriRequest}
8282
*/
83-
public HttpUriRequest getRequest() {
83+
public ClassicHttpRequest getRequest() {
8484
return request;
8585
}
8686

8787
@Override
88-
public URI getURI() {
89-
return request.getURI();
88+
public URI getURI() throws URISyntaxException {
89+
return request.getUri();
9090
}
9191

9292
@Override
9393
public void setContent(String content, String encoding) {
94-
if (request instanceof HttpEntityEnclosingRequest) {
95-
HttpEntity entity = new StringEntity(content, encoding);
96-
((HttpEntityEnclosingRequest) request).setEntity(entity);
97-
}
94+
StringEntity entity = new StringEntity(
95+
content,
96+
ContentType.APPLICATION_JSON,
97+
encoding,
98+
false
99+
);
100+
request.setEntity(entity);
98101
}
99102

100103
@Override

src/main/java/com/unzer/payment/communication/impl/HttpClientBasedRestCommunication.java

+34-19
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,36 @@
1919
import com.unzer.payment.communication.HttpCommunicationException;
2020
import com.unzer.payment.communication.UnzerHttpRequest;
2121
import com.unzer.payment.communication.UnzerHttpResponse;
22-
import org.apache.http.ParseException;
23-
import org.apache.http.client.methods.CloseableHttpResponse;
24-
import org.apache.http.impl.client.CloseableHttpClient;
25-
import org.apache.http.impl.client.HttpClientBuilder;
26-
import org.apache.http.impl.client.HttpClients;
27-
import org.apache.http.util.EntityUtils;
22+
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
23+
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
24+
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
25+
import org.apache.hc.client5.http.impl.classic.HttpClients;
26+
import org.apache.hc.core5.http.ParseException;
27+
import org.apache.hc.core5.http.io.entity.EntityUtils;
2828
import org.apache.logging.log4j.LogManager;
2929
import org.apache.logging.log4j.Logger;
3030

3131
import java.io.IOException;
32+
import java.net.URISyntaxException;
3233
import java.util.Locale;
3334

3435
/**
3536
* Reference implementation of the {@code UnzerRestCommunication}, based on apaches {@code HttpClient}.
36-
*
3737
*/
3838
public class HttpClientBasedRestCommunication extends AbstractUnzerRestCommunication {
3939

4040
private static final Logger logger = LogManager.getLogger(HttpClientBasedRestCommunication.class);
4141

4242
public HttpClientBasedRestCommunication() {
43-
this(null,null);
43+
this(null, null);
4444
}
4545

4646
public HttpClientBasedRestCommunication(Locale locale) {
4747
this(locale, null);
48-
}
48+
}
4949

50-
public HttpClientBasedRestCommunication(Locale locale, String clientIp) {
51-
super(locale, clientIp);
50+
public HttpClientBasedRestCommunication(Locale locale, String clientIp) {
51+
super(locale, clientIp);
5252
}
5353

5454
@Override
@@ -77,14 +77,28 @@ protected UnzerHttpResponse doExecute(UnzerHttpRequest request) throws HttpCommu
7777
if (!(request instanceof HttpClientBasedHttpRequest)) {
7878
throw new IllegalArgumentException("Request is not an instance of HttpClientBasedHttpRequest");
7979
}
80-
CloseableHttpResponse response = null;
80+
8181
try {
82-
response = getHttpClient().execute(((HttpClientBasedHttpRequest) request).getRequest());
83-
return new UnzerHttpResponse(EntityUtils.toString(response.getEntity()),
84-
response.getStatusLine().getStatusCode());
85-
} catch (IOException |ParseException e) {
86-
throw new HttpCommunicationException(
87-
"Error communicating to " + request.getURI() + ": Detail: " + e.getMessage());
82+
request.getURI();
83+
} catch (URISyntaxException e) {
84+
throw new IllegalArgumentException("Request URI is not correct", e);
85+
}
86+
87+
CloseableHttpResponse response = null;
88+
try (CloseableHttpClient client = createClient()) {
89+
response = client.execute(((HttpClientBasedHttpRequest) request).getRequest());
90+
return new UnzerHttpResponse(EntityUtils.toString(response.getEntity()), response.getCode());
91+
} catch (IOException | ParseException e) {
92+
try {
93+
throw new HttpCommunicationException(String.format(
94+
"Error communicating to %s: Detail: %s",
95+
request.getURI().toString(),
96+
e.getMessage()
97+
));
98+
} catch (URISyntaxException ex) {
99+
// happens never, because uri validation happens in the beginning of this method
100+
throw new RuntimeException(ex);
101+
}
88102
} finally {
89103
if (response != null) {
90104
try {
@@ -96,7 +110,8 @@ protected UnzerHttpResponse doExecute(UnzerHttpRequest request) throws HttpCommu
96110
}
97111
}
98112

99-
private CloseableHttpClient getHttpClient() {
113+
@Deprecated
114+
private CloseableHttpClient createClient() {
100115
HttpClientBuilder builder = HttpClients.custom().useSystemProperties();
101116
return builder.build();
102117
}

src/main/java/com/unzer/payment/util/ApplePayAdapterUtil.java

+29-14
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,19 @@
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper;
1919
import com.unzer.payment.ApplePaySession;
20-
import org.apache.http.HttpEntity;
21-
import org.apache.http.client.methods.CloseableHttpResponse;
22-
import org.apache.http.client.methods.HttpPost;
23-
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
24-
import org.apache.http.entity.ContentType;
25-
import org.apache.http.entity.StringEntity;
26-
import org.apache.http.impl.client.CloseableHttpClient;
27-
import org.apache.http.impl.client.HttpClients;
28-
import org.apache.http.util.EntityUtils;
20+
import org.apache.hc.client5.http.classic.methods.HttpPost;
21+
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
22+
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
23+
import org.apache.hc.client5.http.impl.classic.HttpClients;
24+
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
25+
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
26+
import org.apache.hc.client5.http.ssl.HttpsSupport;
27+
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
28+
import org.apache.hc.core5.http.ContentType;
29+
import org.apache.hc.core5.http.HttpEntity;
30+
import org.apache.hc.core5.http.ParseException;
31+
import org.apache.hc.core5.http.io.entity.EntityUtils;
32+
import org.apache.hc.core5.http.io.entity.StringEntity;
2933

3034
import javax.net.ssl.KeyManagerFactory;
3135
import javax.net.ssl.SSLContext;
@@ -71,18 +75,26 @@ public static void setCustomAppleValidationUrls(List<String> appleUrls) {
7175
urls = new HashSet<>(appleUrls);
7276
}
7377

74-
public static String validateApplePayMerchant(String merchantValidationURL, ApplePaySession applePaySession, KeyManagerFactory keyManagerFactory, TrustManagerFactory trustManagerFactory) throws IOException, NoSuchAlgorithmException, KeyManagementException, URISyntaxException {
78+
public static String validateApplePayMerchant(
79+
String merchantValidationURL,
80+
ApplePaySession applePaySession,
81+
KeyManagerFactory keyManagerFactory,
82+
TrustManagerFactory trustManagerFactory
83+
) throws IOException, NoSuchAlgorithmException, KeyManagementException, URISyntaxException, ParseException {
7584
ObjectMapper mapper = new ObjectMapper();
7685
SSLConnectionSocketFactory sslsf = setupSSLSocketFactory(keyManagerFactory, trustManagerFactory);
7786
String response = "";
7887

88+
89+
HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(sslsf).build();
90+
7991
if (doesUrlContainValidDomainName(merchantValidationURL)) {
80-
try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
92+
try (CloseableHttpClient client = HttpClients.custom().setConnectionManager(cm).build()) {
8193
HttpPost post = new HttpPost(merchantValidationURL);
8294
StringEntity reqEntity = new StringEntity(mapper.writeValueAsString(applePaySession), ContentType.APPLICATION_JSON);
8395
post.setEntity(reqEntity);
8496

85-
CloseableHttpResponse res = httpclient.execute(post);
97+
CloseableHttpResponse res = client.execute(post);
8698
HttpEntity entity = res.getEntity();
8799
response = EntityUtils.toString(entity, "UTF-8");
88100
EntityUtils.consume(entity);
@@ -98,11 +110,14 @@ public static boolean doesUrlContainValidDomainName(String merchantValidationURL
98110
return urls.contains(merchantValidationUrlDomain);
99111
}
100112

101-
private static SSLConnectionSocketFactory setupSSLSocketFactory(KeyManagerFactory keyManagerFactory, TrustManagerFactory trustManagerFactory) throws KeyManagementException, NoSuchAlgorithmException {
113+
private static SSLConnectionSocketFactory setupSSLSocketFactory(
114+
KeyManagerFactory keyManagerFactory,
115+
TrustManagerFactory trustManagerFactory
116+
) throws KeyManagementException, NoSuchAlgorithmException {
102117
SSLContext sslcontext = SSLContext.getInstance("TLS");
103118
sslcontext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
104119

105-
return new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
120+
return new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null, HttpsSupport.getDefaultHostnameVerifier());
106121
}
107122

108123
private static String getPlainDomainName(String url) throws URISyntaxException {

0 commit comments

Comments
 (0)