Java SDK
Introduction
To understand how to use this SDK it is best to read the following documentation:
API Reference
This SDK wraps the Acquiring API and (amongst other things) exposes the responses of the webservice calls as Java objects. Understanding the Acquiring API will help you understand these SDK objects as well.
The explanation of all the various
features
we offer
This page will help you understand the global flow when interacting with the Acquiring API using the Java SDK.
Introduction
To understand how to use this SDK it is best to read the following documentation:
API Reference
This SDK wraps the Acquiring API and (amongst other things) exposes the responses of the webservice calls as Java objects. Understanding the Acquiring API will help you understand these SDK objects as well.The explanation of all the various features we offer
This page will help you understand the global flow when interacting with the Acquiring API using the Java SDK.
The Java SDK helps you to communicate with the Acquiring API . More specifically, it offers a fluent Java API that provides access to all the functionality of the RESTful Acquiring API. Below, we discuss the following topics in detail.
Initialization of the SDK
Exceptions
Logging
SSL Certificates
Advanced use: Connection pooling
Advanced use: Customization of the communication
Advanced use: Using system properties
The source code of the SDK is available on Github . There you can find installation instructions.
The API documentation of the latest version of the SDK is available here . For a specific major version, replace latest with the actual version in format <major>.x .
Initialization of the Java SDK
All Java code snippets presented in the API Reference assume you have initialized the Java SDK before using them in your Development Environment. This section details how to initialize SDK.
Initializing is simple, and requires only one key task: use our Factory class to create an instance of Client , which contains the actual methods to communicate with the Acquiring API.
The Factory needs the following input information to provide you with an initialized Client :
A URI to the property file with your connection configuration
The OAuth2 client ID and secret
The property file should contain the following keys:
acquiring.api.integrator=<your company name>
acquiring.api.endpoint.host=api.preprod.acquiring.worldline-solutions.com
acquiring.api.authorizationType=OAuth2
acquiring.api.oauth2.tokenUri=https://auth-test-eu-west-1.aws.bambora.com/connect/token
acquiring.api.connectTimeout=5000 # use -1 for no timeout
acquiring.api.socketTimeout=300000 # use -1 for no timeout
acquiring.api.maxConnections=10 # to support 10 concurrent connections
We recommend you to to keep the timeout values at these values. See API endpoints for the possible hosts and token URIs.
If a proxy should be used, the property file should additionally contain the following key(s):
acquiring.api.proxy.uri=<URL to the proxy host including leading http:// or https://>
# omit the following two lines if no proxy authentication is required
acquiring.api.proxy.username=<username for the proxy>
acquiring.api.proxy.password=<password for the proxy>
You can create an instance of Client using the Factory with this code snippet:
Client client = Factory.createClient(propertiesUrl.toURI(), "oauth2ClientId", "oauth2ClientSecret");
This Client instance offers connection pooling and can be reused for multiple concurrent API calls. Once it is no longer used it should be closed.
Client implements java.io.Closeable , which allows it to be used in try-with-resources statements introduced in Java 7.
Connection management
The Java SDK by default uses Apache HttpClient for setting up connections to the RESTful Server API. Although this works out-of-the-box for most, sometimes its connection pool contains connections that no longer work due to the basic limitations of the blocking I/O model. See section 2.3.3 of Connection management for more information.
Therefore, it is recommended to periodically evict expired HTTP connections. With the SDK, this can be done by periodically (e.g. every 10 seconds) calling method closeExpiredConnections of a Client object.
Because the Java SDK can be used in a multitude of environments, the SDK cannot spawn a thread itself to perform this periodic call. Instead, you should create a scheduled job that runs at a regular interval that performs this cleanup. How this scheduled job should be created depends on the platform that the SDK is used in. Please refer to your platform documentation for instructions on how to create scheduled jobs.
Exceptions
All calls can throw one of the following runtime exceptions:
A ValidationException if the request was not correct and couldn't be processed (HTTP status code 400)
An AuthorizationException if the request was not allowed or your credentials are incorrect/expired (HTTP status code 401 or 403)
An IdempotenceException if an idempotent request caused a conflict (HTTP status code 409)
A ReferenceException if an object was attempted to be referenced that doesn't exist or has been removed, or there was a conflict (HTTP status code 404, 409 or 410)
A PlatformException if something went wrong on the Acquiring platform. The Acquiring platform was unable to process a message from a downstream system, or the service that you're trying to reach is temporary unavailable (HTTP status code 500, 502 or 503)
An ApiException if the RESTful Server API returned any other error
Below is an example of how a payment response can be handled:
try {
ApiPaymentResponse response = client.v1()
.acquirer(acquiredId)
.merchants(merchantId)
.payments()
.processPayment(request);
} catch (ValidationException e) {
System.err.println("Input validation error: " + e.getDetail());
} catch (AuthorizationException e) {
System.err.println("Authorization error: " + e.getDetail());
} catch (ReferenceException e) {
System.err.println("Incorrect object reference: " + e.getDetail());
} catch (PlatformException e) {
System.err.println("Error occurred at Worldline or a downstream partner: " + e.getDetail());
} catch (ApiException e) {
System.err.println("Worldline error:" + e.getStatusCode() + ", " + e.getDetail());
}
Exception overview
The following table is a summary that shows when each of these exceptions will be thrown:
HTTP status code |
Meaning |
Description |
Exception Type |
---|---|---|---|
200 |
Successful |
Your request was processed correctly |
N/A |
201 |
Created |
Your request was processed correctly and a new resource was created. The URI of this created resource is returned in the Location header of the response. |
N/A |
204 |
No Content |
Your request was processed correctly |
N/A |
400 |
Bad Request |
Your request is not correct and can't be processed. Please correct the mistake and try again. |
ValidationException |
403 |
Not Authorized |
You're trying to do something that is not allowed or that you're not authorized to do. |
AuthorizationException |
404 |
Not Found |
The object you were trying to access could not be found on the server. |
ReferenceException |
409 |
Conflict |
Your idempotent request resulted in a conflict. The first request has not finished yet. |
IdempotenceException |
409 |
Conflict |
Your request resulted in a conflict. Either you submitted a duplicate request or you're trying to create something with a duplicate key. |
ReferenceException |
500 |
Internal Server Error |
Something went wrong on the platform. |
PlatformException |
502 |
Bad Gateway |
The platform was unable to process a message from a downstream partner/acquirer. |
PlatformException |
503 |
Service Unavailable |
The service that you're trying to reach is temporarily unavailable. Please try again later. |
PlatformException |
other |
Unexpected error |
An unexpected error has occurred |
ApiException |
HTTP status code 401 responses are automatically handled by the SDK and will not result in an exception if your OAuth2 credentials are valid. The SDK will automatically try to renew the access token if it gets such a response.
Logging
The Java SDK supports logging of requests, responses and exceptions of the API communication.
In order to start using the logging feature, an implementation of the CommunicatorLogger interface should be provided. The SDK provides two example implementations for logging to System.out ( SysOutCommunicatorLogger ) and logging to a java.util.logging.Logger ( JdkCommunicatorLogger ).
Logging can be enabled by calling the enableLogging method on a Client object, and providing the logger as an argument. The logger can subsequently be disabled by calling the disableLogging method.
When logged messages contain sensitive data, this data is obfuscated.
The following code exemplifies the use of adding a logger:
Client client = Factory.createClient(propertiesUrl.toURI(), "oauth2ClientId", "oauth2ClientSecret");
CommunicatorLogger logger = new JdkCommunicatorLogger(Logger.getLogger(...), Level.INFO);
client.enableLogging(logger);
//... Do some calls
client.disableLogging();
Installing SSL certificates
Not all versions of Java support the SSL certificates of the Acquiring platform out-of-the-box. If a CommunicationException wrapped around a javax.net.ssl.SSLHandshakeException is thrown when trying to communicate with the Server API, you must manually install an SSL certificate. Following is the procedure for most Java implementations:
Open the correct API Endpoint in your browser; ignore the 404 error.
Export the root certificate (Trustwave / SecureTrust CA) from your browser to a Base64 encoded X.509 (*.CER) file.
From the command line, go to the /lib/security directory of the JRE to use and execute the following command:
keytool -import -keystore cacerts -alias securetrustca -file <path to exported certificate>
The default password for OpenJDK and Oracle's JDK and JRE is changeit . For other vendors, please check the vendor's documentation. When prompted to trust the certificate, type yes and press Enter .
Any "Alias already exists" error can be ignored. This implies that the root certificate entry already exists.
The new certificate will not be automatically picked up by the running JVM. The JVM needs to be restarted.
The cacerts key store is specific to the JRE it was bundled with. Do not copy this file when upgrading the Java version. Instead, the above procedure needs to be followed every time a new Java version is installed.
The aforementioned instructions have been successfully tested on OpenJDK and Oracle's JDK. If there are issues installing SSL certificates, please refer to your Java vendor's documentation.
Advanced use: Connection pooling
A Client created using the Factory class from a properties file or CommunicatorConfiguration object will use its own connection pool. If multiple clients should share a single connection pool, the Factory class should be used to first create a shared Communicator , then to create Client instances that use that Communicator :
Communicator communicator = Factory.createCommunicator(propertiesUrl.toURI(), "oauth2ClientId", "oauth2ClientSecret");
// create one or more clients using the shared communicator
Client client = Factory.createClient(communicator);
Instead of closing these Client instances, you should instead close the Communicator when it is no longer needed. This will close all Client instances that use the Communicator .
If instead, one of the Client instances is closed, the Communicator will be closed as well. As a result, all other Client instances that use the Communicator will also be closed. Attempting to use a closed Client or Communicator will result in an error.
Just like Client , Communicator implements java.io.Closeable , and can therefore also be used in try-with-resources statements introduced in Java 7.
Connection management
Just like Client , Communicator also has method closeExpiredConnections that can be used to evict expired HTTP connections. You can call this method on the Communicator instead of on any of the Client instances. The effect will be the same.
Advanced use: Customization of the communication
A Client uses a Communicator to communicate with the RESTful Server API. A Communicator contains all the logic to transform a request object to a HTTP request and a HTTP response to a response object. If needed, you can extend this class. To instantiate a Client that uses your own implementation of Communicator you can use the following code snippet:
Communicator communicator = new YourCommunicator();
Client client = Factory.createClient(communicator
However, for most customizations you do not have to extend Communicator . The functionality of the Communicator is built on the following:
The RESTful Server API endpoint URI.
A Connection , which represents one or more HTTP connections to the Worldline server.
An Authenticator , which is used to sign your requests.
A MetadataProvider , which constructs the header with metadata of your server that is sent in requests for BI and fraud prevention purposes.
A Marshaller , which is used to marshal and unmarshal request and response objects to and from JSON.
For your convenience, a CommunicatorBuilder is provided to easily replace one or more of these components. For example, to instantiate a Client that uses your own implementation of Connection , you can use the following code snippet:
Connection connection = new YourConnection();
Communicator communicator = Factory.createCommunicatorBuilder(propertiesUrl.toURI(), "oauth2ClientId", "oauth2ClientSecret")
.withConnection(connection)
.build();
Client client = Factory.createClient(communicator);
Connection management
Calling closeExpiredConnections on a Client or a Communicator object only works if the Connection implements PooledConnection , otherwise these methods do nothing. If you write a custom Connection that uses a pool of HTTP connections, implement PooledConnection instead.
Logging
To facilitate implementing logging in a custom Connection , the SDK provides utility classes RequestLogMessageBuilder and ResponseLogMessageBuilder . These can be used to easily construct request and response messages. For instance:
// In the below code, logger is the CommunicatorLogger set using enableLogging.
// Note that it may be null if enableLogging is not called.
String requestId = UUID.randomUUID().toString();
RequestLogMessageBuilder requestLogMessageBuilder =
new RequestLogMessageBuilder(requestId, method, uri);
// add request headers to requestLogMessageBuilder
// if present, set the request body on requestLogMessageBuilder
logger.log(requestLogMessageBuilder.getMessage());
long startTime = System.currentTimeMillis();
// send the request
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
int statusCode = ...;
// note: the duration is optional
ResponseLogMessageBuilder responseLogMessageBuilder =
new ResponseLogMessageBuilder(requestId, statusCode, duration);
// add response headers to responseLogMessageBuilder
// if present, set the response body on responseLogMessageBuilder
logger.log(responseLogMessageBuilder.getMessage());
Advanced use: Using system properties
Proxy
The SDK provides basic support for HTTP proxies by specifying the proxy in the property file used for initializing the SDK. If this is not sufficient it is also possible to use Java's proxying mechanism instead. Note that java.net.Authenticator is needed for authentication.