Adyen for Java developers
Tags: java, payment, integration
Published: 2023-05-24 15:00:13

In today's digital age, the ability to connect to different applications through APIs (Application Programming Interfaces) is essential for any modern platform. APIs allow the design of sophisticated workflows, enabling communication between systems that need to exchange data and provide services.

While developers can use different languages and frameworks to directly consume the REST APIs, the adoption of libraries is the most effective path to create friction-less integrations that boost both productivity and developer experience.

In a previous [blog](https://www.adyen.com/blog/adyen-api-libraries) we explained the benefits of using an Adyen API Library. Let’s now explore more specifically the choices and advantages available to Java developers.


> **In this article..**
> …discover the Adyen Java Library, what’s new in the latest release, and how to bootstrap a new application or upgrade an existing one.


## Adyen Java Library
The Adyen Java library is the toolkit provided to Java developers who work or will work with Adyen’s APIs. It enables them to focus on the use cases and its functional aspects while the library takes care of the necessary groundwork such as connection setup, security features (authentication, encryption and tokenization), validation, exception handling, etc…

The library includes a wrapper for each of our public APIs, complete with documentation. Whether you are implementing a payment flow, platform integration, issuing, capital or API management **you only need to use this library**. As you expand the scope of your integration and access new products or services, the library is already set up and the additional code is minimal.

### Benefits
The Java library brings the following advantages typical of the Java ecosystem:

- Easy access, available on Maven central
Usage of packages to ensure encapsulation and avoid name clashing
- Built-in JSON support with Gson
- Custom exception class (ApiException) to provide a consistent exception handling
- Dependency management: use Dependabot or Renovate to be notified when a new Adyen Java Library version is released
- Comprehensive unit testing coverage: check unit tests to see an example of how services are invoked and models are defined
- Built-in HTTP client (with additional proxy support) with the option to override and use your own implementation.

### Supported APIs
All Adyen products are supported in the latest version of the Java library.

- **Online Payments**: everything you need to process payments and any advanced use case: Checkout, Payouts, Recurring Payments
- **Point of Sale**: management of point-of-sale (POS) payment terminals
- **Management**: configuration of company and merchant accounts, stores, payment terminals
- **Platforms and Financial Products**: work with Adyen for Platforms. Account structure, onboarding, payment flows, embedded financial services

### What’s new in the Java library
The Java Library v20 upgrade delivers a lot of new features as well as several significant improvements.

A substantial redesign is perhaps the most noteworthy change, as it brings the library in line with Adyen API catalog and naming conventions. This update enables you to quickly locate the relevant Java service that corresponds to an API (i.e. CheckoutService when using the Checkout API). By maintaining consistency across Adyen documentation, the API Explorer, and code samples, you can easily find the information you need.

Another significant change is the adoption of OpenAPI-driven code generation. Java classes that map the request and response payloads are now generated using OpenAPI Generator, ensuring that the code complies with the contract (i.e. the specification), thus avoiding errors and inconsistencies.

There are other valuable improvements to make sure the library is **comprehensive** (all API versions are updated to the latest release, there is support for Adyen for Platforms and Embedded Financial Services), **fast** (providing built-in methods for JSON processing) and **easy** (adding adapter classes mapping each payment method).

## Getting started
The Adyen Java library requires minimum setup. Make sure you match the pre-requisites (Java 11, a valid API Key), then add the dependency in your Java project with your favorite build tool.

Maven
```
<dependency>
  <groupId>com.adyen</groupId>
  <artifactId>adyen-java-api-library</artifactId>
  <version>20.0.0</ver
```
Gradle

```
dependencies {
  implementation 'com.adyen:adyen-java-api-library:20.0.0'
}
```
Setup the client that will access the Adyen service

```
// Setup Client and Service
Client client = new Client("Your X-API-KEY", Environment.TEST);

// PaymentsApi service
PaymentsApi paymentsApi = new PaymentsApi(client);
```

Use the relevant service and models to access the functionality, for example when using Checkout you can get the list available payment methods:

```
PaymentMethodsRequest paymentMethodsRequest = new PaymentMethodsRequest();
paymentMethodsRequest.setMerchantAccount("YOUR_MERCHANT_ACCOUNT");
PaymentMethodsResponse resp = paymentsApi.paymentMethods(paymentMethodsRequest);

// print available payment methods
resp.getPaymentMethods().stream().forEach(System.out::println);
```
When using the Management API (i.e. generate client Key) the approach is similar:

```
// Management ClientKeyMerchantLevel service
ClientKeyMerchantLevel merchantLevel = new ClientKeyMerchantLevel(client);

// generate Client Key
GenerateClientKeyResponse resp = merchantLevel.generateNewClientKey("YOUR_MERCHANT_ACCOUNT", "YOUR_API_CREDENTIAL_ID");

System.out.println(resp.getClientKey());
```

### Working with webhooks
The Adyen Java library provides support for webhooks, an essential feature of the Adyen platform. The Java library simplifies this by providing a model for the incoming payload (NotificationRequestItem) as well as a helper class (HMACValidator) to validate the HMAC signature.

```
// YOUR_HMAC_KEY from the Customer Area
String hmacKey = "YOUR_HMAC_KEY";
String notificationRequestJson = "NOTIFICATION_REQUEST_JSON";
HMACValidator hmacValidator = new HMACValidator();

NotificationHandler notificationHandler = new NotificationHandler();
NotificationRequest notificationRequest = notificationHandler.handleNotificationJson(notificationRequestJson);

// fetch first (and only) NotificationRequestItem
var notificationRequestItem = notificationRequest.getNotificationItems().stream().findFirst();

if (notificationRequestItem.isPresent()) {
    // Handle the notification
    if ( hmacValidator.validateHMAC(notificationRequestItem, hmacKey) ) {
     // Process the notification based on the eventCode
 // …
    } else {
// Non valid NotificationRequest
 throw new RuntimeError("Invalid HMAC signature");
    }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5k4uv5kp3h3f5v5ngic.png)

Is your application already using the Adyen Java library? Do you want to use this latest version? Then this section is for you.

The Adyen Java Library v20 brings lots of new features but, at the same time, introduces several breaking changes. Although affecting existing working code is never good news, **“breaking by design”** is sometimes necessary. The redesign of the library, the code generation and many other improvements are addressing inconsistencies and removing legacy code.

The new version can better assist you in the implementation of your workflows and use cases, and allow you to easily integrate new products and features as they become available on the Adyen platform.

### Migrating your code
All Java models are created based on the OpenAPI specifications, which results in various modifications such as the relocation and renaming of packages, classes, and fields.

Generic models (i.e. Address, Name, BankAccount, etc..) are no longer shared. Each package defines the models it needs. While this results in some duplication of the Java classes, it ensures a good encapsulation of the services.

Notifications have been renamed to webhooks, for example class GenericNotification is now GenericWebhook (watch out, this class includes constants that might be used by your application) and NotificationHandler has become WebhookHandler.

If you work with the **Checkout API** you need to consider the following changes:

- The single Checkout class has been removed in favor of providing a different service class for each Checkout functionality: PaymentsApi, RecurringApi, ModificationsApi, etc.. Each service corresponds to a functionality (sub-folder) of the Checkout API (see API Explorer) ensuring consistency between the library and the API.
- com.adyen.model.Amount is now com.adyen.model.checkout.Amount
- com.adyen.model.checkout.details.StorePaymentMethodDetails is now com.adyen.model.checkout.StorePaymentMethodDetails
- `PaymentsRequest` has been renamed `PaymentRequest`, `PaymentsResponse` has been renamed `PaymentResponse`
- Several helper methods (setAmountData, setCardData, isAuthorised, getCardHolderName) have been removed to let Java models provide getter/setter methods only, consistently with the OpenAPI specification and the API Explorer documentation.

#### GSON

Another major change is the introduction of GSON as the preferred JSON processing framework. This should be transparent to the application as the library takes care of providing the serialization and deserialization logic that converts JSON payloads into Java objects.

You can find within each model (ie CardDetailsRequest) the methods to perform the JSON processing:

```
public static CardDetailsRequest fromJson(String jsonString) throws IOException {
   return JSON.getGson().fromJson(jsonString, CardDetailsRequest.class);
 }


public String toJson() {
   return JSON.getGson().toJson(this);
 }
}
```
In the case of handling the webhooks you can take advantage of the built-in methods, for example:

```
@PostMapping("/webhooks/notifications")
public ResponseEntity<String> webhooks(@RequestBody  ) throws Exception {
  // from JSON string to object
  var notificationRequest = NotificationRequest.fromJson(json);

  // consume event
```

## Upgrade the Recurring Payment sample
Let’s look at a use case and what should be done when upgrading an existing application to the Adyen Java library v20.

On [GitHub](https://github.com/adyen-examples/adyen-java-spring-online-payments) you can find a Java sample application that demonstrates how to implement payment subscriptions. It is a simplified version of a website that offers a music subscription service. There are 2 flows basically:

- the shopper can purchase a subscription, saving the card details for the recurring payment (aka [Tokenization](https://docs.adyen.com/online-payments/tokenization))
- the site administrator can make payments on behalf of the shopper (for example monthly when the subscription is renewed) and optionally expire the token

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9qlhh2ybm7lcf5cx7ke.jpg)
The first step is to update the dependency version in the application. It uses Gradle therefore we need to change the`adyen-java-library` version in `build.gradle`

```
implementation 'com.adyen:adyen-java-api-library:20.0.0'
```
The new version (as outlined above) has refactored packages and classes, so we need to update several imports and replace the Checkout class with PaymentsApi:

```
import com.adyen.model.checkout.Amount;
import com.adyen.model.checkout.CreateCheckoutSessionRequest;
import com.adyen.model.checkout.CreateCheckoutSessionResponse;
import com.adyen.service.checkout.PaymentsApi;

@RestController
@RequestMapping("/api")
public class SubscriptionResource {

// PaymentsApi service class 
private final PaymentsApi paymentsApi;
// …
```
Other classes and references to update:

- PaymentsRequest and PaymentsResponse have been renamed to PaymentRequest and PaymentResponse: the imports and the class names must be updated
- The class that defines the payment method is now called CheckoutPaymentMethod

The revised code snippet to perform a payment using a token looks like:

```
PaymentRequest paymentRequest = new PaymentRequest();
paymentRequest.setMerchantAccount(“YOUR_MERCHANT_ACCOUNT”);
paymentRequest.setAmount
(new Amount().currency("EUR").value(1199L));
paymentRequest.setReference(orderRef);
paymentRequest.setShopperInteraction(PaymentRequest.ShopperInteractionEnum.CONTAUTH);
paymentRequest.setShopperReference(Storage.SHOPPER_REFERENCE);
paymentRequest.setRecurringProcessingModel(PaymentRequest.RecurringProcessingModelEnum.SUBSCRIPTION);
paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(new StoredPaymentMethodDetails().storedPaymentMethodId(“abc123”));

PaymentResponse response = this.paymentsApi.payments(paymentRequest);
```
Finally we need to update the webhook handler to take advantage of the built-in methods for deserializing the JSON payload into a Java object

```
// processing incoming webhooks
@PostMapping("/webhooks/notifications")
public ResponseEntity<String> webhooks(@RequestBody String json) 
throws Exception {


   // from JSON string to object
   NotificationRequest notificationRequest = NotificationRequest.fromJson(json);


// fetch first (and only) NotificationRequestItem
Optional<NotificationRequestItem> notificationRequestItem = 
notificationRequest.getNotificationItems().stream().findFirst();
if (notificationRequestItem.isPresent()) {
// consume webhooks
// ………
```

## Next steps
It is time to get coding.

For new starters the simplest way to see the Adyen Java library in action is to look at the [Java Spring sample application](https://github.com/adyen-examples/adyen-java-spring-online-payments). The sample uses the Web Drop-in and the Java library to demonstrate the Checkout use case.

Run the application with [one click using Gitpod](https://www.youtube.com/watch?v=0VKnZtiTaHs) and browse through the source code to learn how to obtain the available payment methods, perform the transaction and process the asynchronous event delivered by webhooks.

If you are upgrading an existing application the Upgrade section above will guide you through the changes and how to deal with them. We are of course ready to help you in case something is not clear or needs additional details.

We are looking forward to hearing your feedback about our libraries, what is missing or can be improved. Join our [survey](https://forms.gle/FzyavyxX5S2GGGYr9) and let us know how we can improve them and make your developer experience better.