Adyen Java API Library
repository·main·Indexed 40 days ago
https://github.com/adyen/adyen-java-api-libraryThe official Java client library for integrating with Adyen's payment and financial services APIs. Supports Java 11 or later and is available on Maven Central (version 43.1.0). Provides tools for initializing clients via API keys or Basic Auth, handling API errors with ApiException, parsing and validating notification webhooks using HMACValidator, and integrating in-person payments via the Cloud Device and Terminal APIs.
What's inside Adyen
- The Adyen Java API Library is the officially supported Java library for interacting with Adyen's APIs. It is available on Maven Central.
Cloud device API model package and naming conventions
mainThe Cloud device API uses models generated from OpenAPI specifications located in the
com.adyen.model.tapipackage, whereas the Terminal (Cloud) API uses hand-crafted models incom.adyen.model.nexo.Key changes include:
- Enum Naming: Most enums in the Cloud device API drop the
Typesuffix (e.g.,MessageCategoryTypebecomesMessageCategory). - Model Renaming: Some classes are renamed to match OpenAPI specs (e.g.,
TransactionIdentificationbecomesTransactionIDType). - Setter/Getter Naming: Accessors for attributes starting with acronyms like
POIchange casing (e.g.,getPOITransactionID()becomesgetPoITransactionID()).
- Enum Naming: Most enums in the Cloud device API drop the
Use Jackson serialization and fluent setters in Cloud device API
mainThe Cloud device API (
tapimodels) uses Jackson annotations (@JsonProperty) instead of Gson. The models include built-infromJson()andtoJson()methods for easy serialization. Additionally, thetapimodels support a fluent API for object construction, which is not available in the oldernexomodels.// Serialization/Deserialization String json = saleToPOIRequest.toJson(); SaleToPOIRequest request = SaleToPOIRequest.fromJson(jsonString); // Fluent API for building objects MessageHeader messageHeader = new MessageHeader() .protocolVersion("3.0") .messageClass(MessageClass.SERVICE) .messageCategory(MessageCategory.PAYMENT) .messageType(MessageType.REQUEST) .saleID("001") .serviceID("001");Use the Local Terminal API with Encryption
mainFor Local Terminal API integrations, you must provide encryption details and handle SSL/TLS.
- Setup SSL: Load the Adyen root certificate into a
KeyStore, initialize aTrustManagerFactory, and create anSSLContext. - Configure Client: Set the
terminalApiLocalEndpoint(the terminal's IP) and provide theSSLContextand aTerminalLocalAPIHostnameVerifierto theConfigobject. - Security Key: Create a
SecurityKeyobject with yourkeyIdentifierandpassphrase. - Initialize Service: Use
TerminalLocalAPI(client, securityKey)to make requests.
// Import the required classes import com.adyen.Client; import com.adyen.Config; import com.adyen.enums.Environment; import com.adyen.httpclient.TerminalLocalAPIHostnameVerifier; import com.adyen.service.TerminalLocalAPI; import com.adyen.model.terminal.security.*; import com.adyen.model.terminal.*; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import java.security.KeyStore; import java.security.SecureRandom; // Create a KeyStore for the terminal certificate KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("adyenRootCertificate", adyenRootCertificate); // Create a TrustManagerFactory that trusts the CAs in our KeyStore TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); // Create an SSLContext with the desired protocol that uses our TrustManagers SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); // Configure a client for TerminalLocalAPI Config config = new Config(); config.setEnvironment(Environment.TEST); config.setTerminalApiLocalEndpoint("https://" + terminalIpAddress); // IP address of your terminal config.setSSLContext(sslContext); config.setHostnameVerifier(new TerminalLocalAPIHostnameVerifier(Environment.TEST)); Client client = new Client(config); // Create your SecurityKey object used for encrypting the payload SecurityKey securityKey = new SecurityKey(); securityKey.setKeyVersion(1); securityKey.setAdyenCryptoVersion(1); securityKey.setKeyIdentifier("keyIdentifier"); securityKey.setPassphrase("passphrase"); // Use TerminalLocalAPI TerminalLocalAPI terminalLocalAPI = new TerminalLocalAPI(client, securityKey); TerminalAPIResponse terminalAPIResponse = terminalLocalAPI.request(terminalAPIRequest);- Setup SSL: Load the Adyen root certificate into a
Migrate from Terminal (Cloud) API to Cloud device API
mainWhen migrating from the legacy
TerminalCloudAPIto the newCloudDeviceApi, several key changes in the service layer, model packages, and data types must be addressed.Key Changes
- Service Class: Replace
TerminalCloudAPIwithCloudDeviceApi. - Model Package: Move from
com.adyen.model.nexo.*tocom.adyen.model.tapi.*. - Request Structure: The
CloudDeviceApi.sync()method now requiresmerchantAccountanddeviceIdas explicit parameters, rather than setting thePOIIDinside theMessageHeader. - Data Types: Many fields have transitioned from legacy types (like
XMLGregorianCalendar) to modern Java types likeOffsetDateTimeandLocalDate.
Implementation Example
import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.service.clouddevice.CloudDeviceApi; import com.adyen.model.clouddevice.CloudDeviceApiRequest; import com.adyen.model.clouddevice.CloudDeviceApiResponse; import com.adyen.model.tapi.*; Client client = new Client("Your X-API-KEY", Environment.TEST); CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest(); MessageHeader messageHeader = new MessageHeader() .protocolVersion("3.0") .messageClass(MessageClass.SERVICE) .messageCategory(MessageCategory.PAYMENT) .messageType(MessageType.REQUEST) .saleID("001") .serviceID("001"); saleToPOIRequest.setMessageHeader(messageHeader); PaymentRequest paymentRequest = new PaymentRequest(); SaleData saleData = new SaleData(); TransactionIDType transactionIDType = new TransactionIDType() .transactionID("001") .timeStamp(OffsetDateTime.now(ZoneOffset.UTC)); saleData.setSaleTransactionID(transactionIDType); PaymentTransaction paymentTransaction = new PaymentTransaction(); AmountsReq amountsReq = new AmountsReq() .currency("EUR") .requestedAmount(BigDecimal.ONE); paymentTransaction.setAmountsReq(amountsReq); paymentRequest.setSaleData(saleData); paymentRequest.setPaymentTransaction(paymentTransaction); saleToPOIRequest.setPaymentRequest(paymentRequest); CloudDeviceApiRequest cloudDeviceApiRequest = new CloudDeviceApiRequest(); cloudDeviceApiRequest.setSaleToPOIRequest(saleToPOIRequest); // Note: POIID is set automatically from the deviceId parameter CloudDeviceApiResponse response = cloudDeviceApi.sync( "myMerchant", "P400Plus-123456789", cloudDeviceApiRequest);- Service Class: Replace
Troubleshoot HMAC signature calculation with HMAC Tools
mainThe
tools/hmacdirectory contains scripts to calculate the HMAC signature of a webhook payload. These tools are useful for troubleshooting signature mismatches.Important: Ensure you use the specific HMAC key that was used to generate the signature associated with the payload in your JSON file.
To ensure compatibility, check
tools/hmac/pom.xmlto confirm which version of the Adyen Java API library the tools are using.Install the Adyen Java API Library via Maven
mainTo use the Adyen Java API library in your project, add the following dependency to your
pom.xmlfile. Ensure you are using Java 11 or later.Prerequisites
- An Adyen account
- An API key
- Java 11 or later
<dependency> <groupId>com.adyen</groupId> <artifactId>adyen-java-api-library</artifactId> <version>43.1.0</version> </dependency>Integrate In-person payments
mainTo build in-person payment integrations that accept global and local payment methods, you can use either the Cloud Device API or the Terminal API.
Cloud Device API (Recommended)
For In-Person Payments, the recommended approach is using the Cloud device API. Detailed usage instructions can be found in the
doc/CloudDeviceApi.mdfile within this repository.Terminal API
The Terminal API allows you to send and receive messages via two communication methods:
- Local communications: Your POS system sends requests directly to the terminal's IP address over your local network, receiving results synchronously.
- Cloud communications: Uses the internet to access cloud
/syncand/asyncendpoints.
Note: It is recommended to adopt the Cloud device API instead of using the Terminal API's cloud communication endpoints. Detailed instructions for the Terminal API are available in
doc/TerminalApi.md.Secure Cloud device communication with EncryptedCloudDeviceApi
mainTo protect communication between your integration and the cloud, use
EncryptedCloudDeviceApi. This class encrypts request and response payloads.- Setup: Obtain
EncryptionCredentialDetailsfrom your Terminal configuration in the Adyen Customer Area. - Usage: Instantiate
EncryptedCloudDeviceApiwith yourClientand the credentials. Use it exactly like the standardCloudDeviceApi(e.g., calling.sync()). - Decryption: For asynchronous integrations, use the
decryptNotification(payload)method to decrypt the JSON payload of event notifications.
// Encryption credentials from the Terminal configuration on CA EncryptionCredentialDetails encryptionCredentialDetails = new EncryptionCredentialDetails() .adyenCryptoVersion(1) .keyIdentifier("CryptoKeyIdentifier12345") .keyVersion(1) .passphrase("p@ssw0rd123456"); // Use EncryptedCloudDeviceApi instead of CloudDeviceApi EncryptedCloudDeviceApi encryptedCloudDeviceApi = new EncryptedCloudDeviceApi(client, encryptionCredentialDetails); CloudDeviceApiResponse response = encryptedCloudDeviceApi.sync( "TestMerchantAccount", "V400m-123456789", cloudDeviceApiRequest); System.out.println(response); // Decrypting an async notification payload var payload = "..."; var decryptedPayload = encryptedCloudDeviceApi.decryptNotification(payload); System.out.println(decryptedPayload);- Setup: Obtain
Configure a Proxy connection
mainTo use a proxy, inject a custom
AdyenHttpClientinto yourClientinstance. If your proxy requires authentication, it is recommended to set the proxy settings as system properties rather than mixing approaches.// Set http proxy AdyenHttpClient adyenHttpClientWithProxy = new AdyenHttpClient(); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("PROXY_HOST", PROXY_PORT)); adyenHttpClientWithProxy.setProxy(proxy); client.setHttpClient(adyenHttpClientWithProxy); // For authenticated proxies, use system properties: System.setProperty("https.proxyHost", "129.0.0.1"); System.setProperty("https.proxyPort", "3128"); System.setProperty("https.proxyUser", "squid"); System.setProperty("https.proxyPassword", "ward");// Import the required classes import com.adyen.httpclient.AdyenHttpClient; import java.net.InetSocketAddress; import java.net.Proxy; // Set http proxy AdyenHttpClient adyenHttpClientWithProxy = new AdyenHttpClient(); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("PROXY_HOST", PROXY_PORT)); adyenHttpClientWithProxy.setProxy(proxy); client.setHttpClient(adyenHttpClientWithProxy);Parse and validate Notification Webhooks
mainTo process incoming webhooks, use the
WebhookHandlerto parse the JSON payload into aNotificationRequest. For security, always validate the HMAC signature usingHMACValidatorand the HMAC key from your Adyen Customer Area.Standard Webhook Parsing
import java.util.List; import com.adyen.util.HMACValidator; import com.adyen.notification.WebhookHandler; import com.adyen.model.notification.NotificationRequest; import com.adyen.model.notification.NotificationRequestItem; // YOUR_HMAC_KEY from the Customer Area String hmacKey = "YOUR_HMAC_KEY"; // The webhook payload String notificationRequestJson = "NOTIFICATION_REQUEST_JSON"; HMACValidator hmacValidator = new HMACValidator(); WebhookHandler webhookHandler = new WebhookHandler(); NotificationRequest notificationRequest = webhookHandler.handleNotificationJson(notificationRequestJson); // fetch first (and only) NotificationRequestItem var notificationRequestItem = notificationRequest.getNotificationItems().stream().findFirst(); if (notificationRequestItem.isPresent()) { var item = notificationRequestItem.get(); // validate the HMAC signature if (hmacValidator.validateHMAC(item, hmacKey)) { // Process the notification based on the eventCode // ... } else { throw new RuntimeException("Invalid HMAC signature"); } }Banking or Management Webhooks
For Banking or Management webhooks, validate the signature using the
hmacsignatureheader and the raw payload, then use the specific handler (ConfigurationWebhooksHandlerorManagementWebhooksHandler) to extract the event data.// Import the required classes import java.util.List; import com.adyen.util.HMACValidator; import com.adyen.notification.WebhookHandler; import com.adyen.model.notification.NotificationRequest; import com.adyen.model.notification.NotificationRequestItem; // YOUR_HMAC_KEY from the Customer Area String hmacKey = "YOUR_HMAC_KEY"; // The webhook payload String notificationRequestJson = "NOTIFICATION_REQUEST_JSON"; HMACValidator hmacValidator = new HMACValidator(); WebhookHandler webhookHandler = new WebhookHandler(); NotificationRequest notificationRequest = webhookHandler.handleNotificationJson(notificationRequestJson); // fetch first (and only) NotificationRequestItem var notificationRequestItem = notificationRequest.getNotificationItems().stream().findFirst(); if (notificationRequestItem.isPresent()) { var item = notificationRequestItem.get(); // validate the HMAC signature if (hmacValidator.validateHMAC(item, hmacKey)) { // Process the notification based on the eventCode log.info("Received webhook with event {} : \n" + "Merchant Reference: {}\n" + "Alias : {}\n" + "PSP reference : {}", item.getEventCode(), item.getMerchantReference(), item.getAdditionalData().get("alias"), item.getPspReference()); } else { // Non valid NotificationRequest throw new RuntimeException("Invalid HMAC signature"); } }Initialize the Client using Basic Authentication
mainYou can initialize the
Clientusing a username and password for Basic Auth. You can optionally provide a prefix and an application name.// Setup Client and Service passing prefix Client client = new Client("YOUR_USERNAME", "YOUR_PASSWORD", Environment.LIVE, "mycompany123"); // Or setup Client and Service passing prefix and application name //Client client = new Client("YOUR_USERNAME", "YOUR_PASSWORD", Environment.LIVE, "mycompany123", "YOUR_APPLICATION_NAME"); PaymentLinksApi paymentLinksApi = new PaymentLinksApi(client);// Setup Client and Service passing prefix Client client = new Client("YOUR_USERNAME", "YOUR_PASSWORD", Environment.LIVE, "mycompany123"); // Or setup Client and Service passing prefix and application name //Client client = new Client("YOUR_USERNAME", "YOUR_PASSWORD", Environment.LIVE, "mycompany123", "YOUR_APPLICATION_NAME"); PaymentLinksApi paymentLinksApi = new PaymentLinksApi(client);