Skip to content

Commit

Permalink
Merge pull request #1156 from Adyen/automation/release
Browse files Browse the repository at this point in the history
Release v22.0.0-beta
  • Loading branch information
AdyenAutomationBot committed Oct 23, 2023
2 parents c99ba89 + c6d37d7 commit b960881
Show file tree
Hide file tree
Showing 394 changed files with 11,864 additions and 3,858 deletions.
17 changes: 10 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ payment: smallServiceName=PaymentApi
recurring: spec=RecurringService-v68
recurring: smallServiceName=RecurringApi
payout: spec=PayoutService-v68
management: spec=ManagementService-v1
management: spec=ManagementService-v3
balanceplatform: spec=BalancePlatformService-v2
transfers: spec=TransferService-v3
transfers: spec=TransferService-v4
legalentitymanagement: spec=LegalEntityService-v3
# Classic Platforms
marketpayaccount: spec=AccountService-v6
Expand All @@ -46,9 +46,9 @@ marketpaywebhooks: spec=MarketPayNotificationService-v6
acswebhooks: spec=BalancePlatformAcsNotification-v1
configurationwebhooks: spec=BalancePlatformConfigurationNotification-v1
reportwebhooks: spec=BalancePlatformReportNotification-v1
transferwebhooks: spec=BalancePlatformTransferNotification-v3
transferwebhooks: spec=BalancePlatformTransferNotification-v4
# Management Webhooks
managementwebhooks: spec=ManagementNotificationService-v1
managementwebhooks: spec=ManagementNotificationService-v3
# Disputes
disputes: spec=DisputeService-v30
disputes: smallServiceName=DisputesApi
Expand All @@ -67,7 +67,8 @@ $(modelGen): target/spec $(openapi-generator-jar)
--library $(library) \
--global-property modelDocs=false \
--global-property modelTests=false \
--inline-schema-name-mappings DonationPaymentRequest_paymentMethod=CheckoutPaymentMethod \
--inline-schema-name-mappings PaymentRequest_paymentMethod=CheckoutPaymentMethod \
--inline-schema-name-mappings DonationPaymentRequest_paymentMethod=DonationPaymentMethod \
--additional-properties=dateLibrary=java8 \
--additional-properties=openApiNullable=false \
--additional-properties=resourceClass=$(resourceClass)Resource
Expand Down Expand Up @@ -97,7 +98,8 @@ $(bigServices): target/spec $(openapi-generator-jar)
--api-name-suffix Api \
--global-property modelDocs=false \
--global-property modelTests=false \
--inline-schema-name-mappings DonationPaymentRequest_paymentMethod=CheckoutPaymentMethod \
--inline-schema-name-mappings PaymentRequest_paymentMethod=CheckoutPaymentMethod \
--inline-schema-name-mappings DonationPaymentRequest_paymentMethod=DonationPaymentMethod \
--additional-properties=dateLibrary=java8 \
--additional-properties=openApiNullable=false
mv $(output)/$(models)/$@ $(models)/$@
Expand All @@ -124,7 +126,8 @@ $(singleFileServices): target/spec $(openapi-generator-jar)
--api-name-suffix Api \
--global-property modelDocs=false \
--global-property modelTests=false \
--inline-schema-name-mappings DonationPaymentRequest_paymentMethod=CheckoutPaymentMethod \
--inline-schema-name-mappings PaymentRequest_paymentMethod=CheckoutPaymentMethod \
--inline-schema-name-mappings DonationPaymentRequest_paymentMethod=DonationPaymentMethod \
--additional-properties=dateLibrary=java8 \
--additional-properties=openApiNullable=false \
--additional-properties=smallServiceName=$(smallServiceName)
Expand Down
91 changes: 67 additions & 24 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<groupId>com.adyen</groupId>
<artifactId>adyen-java-api-library</artifactId>
<packaging>jar</packaging>
<version>21.6.0</version>
<version>22.0.0-beta</version>
<name>Adyen Java API Library</name>
<description>Adyen API Client Library for Java</description>
<url>https://github.com/adyen/adyen-java-api-library</url>
Expand Down
16 changes: 5 additions & 11 deletions src/main/java/com/adyen/Client.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.adyen;

import com.adyen.enums.Environment;
import com.adyen.enums.Region;
import com.adyen.httpclient.AdyenHttpClient;
import com.adyen.httpclient.ClientInterface;

import java.security.KeyStore;
import javax.net.ssl.SSLContext;

public class Client {
private ClientInterface httpClient;
private Config config;
public static final String LIB_NAME = "adyen-java-api-library";
public static final String LIB_VERSION = "21.6.0";
public static final String LIB_VERSION = "22.0.0-beta";
public static final String TERMINAL_API_ENDPOINT_TEST = "https://terminal-api-test.adyen.com";
public static final String TERMINAL_API_ENDPOINT_LIVE = "https://terminal-api-live.adyen.com";

Expand All @@ -32,17 +31,12 @@ public Client(String username, String password, Environment environment, String
* Use this constructor to create client for client certificate authentication along with API key.
* Note: Client certificate authentication is only applicable for PAL and Checkout services in LIVE,
* Other services will just use API key for authentication.
* @param trustStore Trust store containing server certificate
* @param clientKeyStore Client Key store containing client certificate and key
* @param clientKeyStorePassword Password for client key store
* @param sslContext {@link SSLContext} for client certificate authentication
* @param apiKey Adyen API Key
* @param region Data center region (EU/US/AU), default EU if not provided
*/
public Client(KeyStore trustStore, KeyStore clientKeyStore, String clientKeyStorePassword, String apiKey, Region region) {
public Client(SSLContext sslContext, String apiKey) {
this(apiKey, Environment.LIVE);
this.config.setClientKeyStorePassword(clientKeyStorePassword);
this.config.setClientKeyStore(clientKeyStore);
this.config.setTrustKeyStore(trustStore);
this.config.setSSLContext(sslContext);
}

public Client(String username, String password, Environment environment, String liveEndpointUrlPrefix, String applicationName) {
Expand Down
87 changes: 27 additions & 60 deletions src/main/java/com/adyen/Config.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
package com.adyen;

import com.adyen.enums.Environment;
import com.adyen.util.CertificateUtil;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

public class Config {
protected String username;
Expand All @@ -28,13 +21,9 @@ public class Config {
//Terminal API Specific
protected String terminalApiCloudEndpoint;
protected String terminalApiLocalEndpoint;
protected Certificate terminalCertificate;

// Client certificate authentication
protected KeyStore trustKeyStore;
protected KeyStore clientKeyStore;
protected String clientKeyStorePassword;
protected String liveEndpointUrlPrefix;
protected SSLContext sslContext;
protected HostnameVerifier hostnameVerifier;

public Config() {
// do nothing
Expand Down Expand Up @@ -112,59 +101,37 @@ public void setReadTimeoutMillis(int readTimeoutMillis) {
this.readTimeoutMillis = readTimeoutMillis;
}

public Certificate getTerminalCertificate() {
return terminalCertificate;
}

public void setTerminalCertificate(Certificate terminalCertificate) {
this.terminalCertificate = terminalCertificate;
}

public void setTerminalCertificate(String terminalCertificatePath) throws FileNotFoundException, CertificateException {
this.terminalCertificate = CertificateUtil.loadCertificate(terminalCertificatePath);
}

public void setTerminalCertificate(InputStream terminalCertificateStream) throws CertificateException {
this.terminalCertificate = CertificateUtil.loadCertificate(terminalCertificateStream);
}

public KeyStore getTrustKeyStore() {
return trustKeyStore;
}

public void setTrustKeyStore(KeyStore trustKeyStore) {
this.trustKeyStore = trustKeyStore;
}

public void setTrustKeyStore(String trustKeyStorePath, String keyStoreType, String password) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
this.trustKeyStore = CertificateUtil.loadKeyStore(trustKeyStorePath, keyStoreType, password);
}

public KeyStore getClientKeyStore() {
return clientKeyStore;
public String getLiveEndpointUrlPrefix() {
return this.liveEndpointUrlPrefix;
}

public void setClientKeyStore(KeyStore clientKeyStore) {
this.clientKeyStore = clientKeyStore;
public void setLiveEndpointUrlPrefix(String liveEndpointUrlPrefix) {
this.liveEndpointUrlPrefix = liveEndpointUrlPrefix;
}

public void setClientKeyStore(String clientKeyStorePath, String keyStoreType, String clientKeyStorePassword) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
this.clientKeyStorePassword = clientKeyStorePassword;
this.clientKeyStore = CertificateUtil.loadKeyStore(clientKeyStorePath, keyStoreType, clientKeyStorePassword);
public SSLContext getSSLContext() {
return sslContext;
}

public String getClientKeyStorePassword() {
return clientKeyStorePassword;
/**
* Sets the {@link SSLContext} for the {@link com.adyen.httpclient.AdyenHttpClient}.
*
* @param sslContext The {@link SSLContext}
*/
public void setSSLContext(SSLContext sslContext) {
this.sslContext = sslContext;
}

public void setClientKeyStorePassword(String clientKeyStorePassword) {
this.clientKeyStorePassword = clientKeyStorePassword;
public HostnameVerifier getHostnameVerifier() {
return hostnameVerifier;
}

public String getLiveEndpointUrlPrefix() {
return this.liveEndpointUrlPrefix;
}
public void setLiveEndpointUrlPrefix(String liveEndpointUrlPrefix) {
this.liveEndpointUrlPrefix = liveEndpointUrlPrefix;
/**
* Sets the {@link HostnameVerifier} for the {@link com.adyen.httpclient.AdyenHttpClient}.
*
* @param hostnameVerifier The {@link HostnameVerifier}
* @see com.adyen.httpclient.TerminalLocalAPIHostnameVerifier
*/
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
}
}
88 changes: 7 additions & 81 deletions src/main/java/com/adyen/httpclient/AdyenHttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
import com.adyen.Client;
import com.adyen.Config;
import com.adyen.constants.ApiConstants;
import com.adyen.enums.Environment;
import com.adyen.model.RequestOptions;
import com.adyen.terminal.security.TerminalCommonNameValidator;
import org.apache.commons.codec.binary.Base64;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
Expand All @@ -41,22 +39,16 @@
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.ssl.SSLContexts;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.TimeUnit;

Expand All @@ -74,9 +66,6 @@
public class AdyenHttpClient implements ClientInterface {

private static final String CHARSET = "UTF-8";
private static final String TERMINAL_CERTIFICATE_ALIAS = "TerminalCertificate";
private static final String SSL = "SSL";
private static final String TLSV1_2 = "TLSv1.2";
private Proxy proxy;

public Proxy getProxy() {
Expand Down Expand Up @@ -203,14 +192,13 @@ private URI createUri(String endpoint, Map<String, String> params) throws HTTPCl
}
}

private CloseableHttpClient createCloseableHttpClient(Config config) throws HTTPClientException {
if (config.getClientKeyStore() != null && config.getTrustKeyStore() != null) {
return createHttpClientWithSocketFactory(getClientCertificateAuthSSLContext(config));
private CloseableHttpClient createCloseableHttpClient(Config config) {
SSLContext sslContext = config.getSSLContext();
if (sslContext == null) {
sslContext = SSLContexts.createDefault();
}
if (config.getTerminalCertificate() != null) {
return createHttpClientWithSocketFactory(getTerminalCertificateSocketFactory(config));
}
return HttpClients.createSystem();
HostnameVerifier hostnameVerifier = config.getHostnameVerifier();
return createHttpClientWithSocketFactory(new SSLConnectionSocketFactory(sslContext, hostnameVerifier));
}

private CloseableHttpClient createHttpClientWithSocketFactory(SSLConnectionSocketFactory socketFactory) {
Expand All @@ -221,68 +209,6 @@ private CloseableHttpClient createHttpClientWithSocketFactory(SSLConnectionSocke
.build();
}

private SSLConnectionSocketFactory getTerminalCertificateSocketFactory(Config config) throws HTTPClientException {
try {
// Create new KeyStore for the terminal certificate
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry(TERMINAL_CERTIFICATE_ALIAS, config.getTerminalCertificate());

TrustManagerFactory trustFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustManagers = trustFactory.getTrustManagers();

// Install the terminal certificate trust manager
SSLContext sc = SSLContext.getInstance(SSL);
sc.init(null, trustManagers, new java.security.SecureRandom());

return new SSLConnectionSocketFactory(sc, createHostnameVerifier(config.getEnvironment()));
} catch (GeneralSecurityException | IOException e) {
throw new HTTPClientException("Error loading certificate from path", e);
}
}

private SSLConnectionSocketFactory getClientCertificateAuthSSLContext(Config config) throws HTTPClientException {
try {
char[] password = null;
if (config.getClientKeyStorePassword() != null && !config.getClientKeyStorePassword().isEmpty()) {
password = config.getClientKeyStorePassword().toCharArray();
}

// Create a TrustManager that trusts the CAs in our Trust KeyStore
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(config.getTrustKeyStore());

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(config.getClientKeyStore(), password);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance(TLSV1_2);
context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
return new SSLConnectionSocketFactory(context);
} catch (Exception e) {
throw new HTTPClientException("Error creating SSL Context", e);
}
}

private HostnameVerifier createHostnameVerifier(final Environment environment) {
return (host, session) -> {
try {
if (session.getPeerCertificates() != null && session.getPeerCertificates().length > 0) {
// Assume the first certificate is the leaf, since chain will be ordered, according to Java documentation:
// https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
X509Certificate certificate = (X509Certificate) session.getPeerCertificates()[0];
return TerminalCommonNameValidator.validateCertificate(certificate, environment);
}
return false;
} catch (SSLPeerUnverifiedException e) {
e.printStackTrace();
return false;
}
};
}

/**
* Sets content type
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.adyen.httpclient;

import com.adyen.enums.Environment;
import com.adyen.terminal.security.TerminalCommonNameValidator;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import java.security.cert.X509Certificate;

public final class TerminalLocalAPIHostnameVerifier implements HostnameVerifier {
private final Environment environment;

public TerminalLocalAPIHostnameVerifier(Environment environment) {
this.environment = environment;
}

@Override
public boolean verify(String hostname, SSLSession session) {
try {
if (session.getPeerCertificates() != null && session.getPeerCertificates().length > 0) {
// Assume the first certificate is the leaf, since chain will be ordered, according to Java documentation:
// https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
X509Certificate certificate = (X509Certificate) session.getPeerCertificates()[0];
return TerminalCommonNameValidator.validateCertificate(certificate, environment);
}
return false;
} catch (SSLPeerUnverifiedException e) {
e.printStackTrace();
return false;
}
}
}

0 comments on commit b960881

Please sign in to comment.