-
Notifications
You must be signed in to change notification settings - Fork 151
Add Cloud Device API integration tests #1914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,3 +3,4 @@ | |
| **/target/** | ||
| .DS_Store | ||
| .vscode | ||
| src/test/resources/config.properties | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| * Adyen Java API Library | ||
| * | ||
| * Copyright (c) 2025 Adyen B.V. | ||
| * This file is open source and available under the MIT license. | ||
| * See the LICENSE file for more info. | ||
| */ | ||
| package com.adyen; | ||
|
|
||
| import com.adyen.enums.Environment; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.util.Properties; | ||
|
|
||
| /** | ||
| * Base class for Integration tests | ||
| * | ||
| * <p>Define in src/test/resources the configuration for the tests | ||
| * | ||
| * <p>``` ADYEN_API_KEY= ADYEN_MERCHANT_ACCOUNT= ADYEN_TERMINAL_DEVICE_ID= | ||
| * ADYEN_TERMINAL_DEVICE_KEY_IDENTIFIER= ADYEN_TERMINAL_DEVICE_PASSPHRASE= ``` | ||
| */ | ||
| public class BaseIntegrationTest { | ||
|
|
||
| private static Properties properties = null; | ||
|
|
||
| protected Client getClient() { | ||
| return new Client(new Config().apiKey(getApiKey()).environment(Environment.TEST)); | ||
| } | ||
|
|
||
| protected String getApiKey() { | ||
| return getProperty("ADYEN_API_KEY"); | ||
| } | ||
|
|
||
| protected String getMerchantAccount() { | ||
| return getProperty("ADYEN_MERCHANT_ACCOUNT"); | ||
| } | ||
|
|
||
| protected String getTerminalDeviceId() { | ||
| return getProperty("ADYEN_TERMINAL_DEVICE_ID"); | ||
| } | ||
|
|
||
| protected String getTerminalDeviceKeyIdentifier() { | ||
| return getProperty("ADYEN_TERMINAL_DEVICE_KEY_IDENTIFIER"); | ||
| } | ||
|
|
||
| protected String getTerminalDevicePassphrase() { | ||
| return getProperty("ADYEN_TERMINAL_DEVICE_PASSPHRASE"); | ||
| } | ||
|
|
||
| private Properties getProperties() { | ||
| if (properties == null) { | ||
| properties = new Properties(); | ||
| try (InputStream inputStream = | ||
| BaseIntegrationTest.class.getClassLoader().getResourceAsStream("config.properties")) { | ||
| if (inputStream != null) { | ||
| properties.load(inputStream); | ||
| } | ||
| } catch (IOException e) { | ||
| // Do nothing, properties will be empty | ||
| } | ||
| } | ||
|
|
||
| return properties; | ||
| } | ||
|
gcatanese marked this conversation as resolved.
|
||
|
|
||
| private String getProperty(String name) { | ||
| String property = System.getenv(name); | ||
|
|
||
| if (property != null && !property.isEmpty()) { | ||
| return property; | ||
| } | ||
| property = getProperties().getProperty(name); | ||
|
|
||
| if (property == null || property.isEmpty()) { | ||
| throw new RuntimeException("Property " + name + " not defined"); | ||
| } | ||
|
|
||
| return property; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| package com.adyen.service.clouddevice; | ||
|
|
||
| import com.adyen.BaseIntegrationTest; | ||
| import com.adyen.model.clouddevice.*; | ||
| import com.adyen.model.tapi.*; | ||
| import com.adyen.security.clouddevice.EncryptionCredentialDetails; | ||
| import java.math.BigDecimal; | ||
| import java.time.OffsetDateTime; | ||
| import java.time.ZoneOffset; | ||
| import java.util.UUID; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.Disabled; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| /** | ||
| * Verify Terminal integration: tests to send API requests to the Cloud Device API and test the | ||
| * Terminal responds as expected. | ||
| * | ||
| * <p>Don't forget to: | ||
| * | ||
| * <ul> | ||
| * <li>Enable the terminal | ||
| * <li>Enable the test to run (by removing/commenting the {@code @Disabled} annotation) | ||
| * <li>Set required variables by creating {@code src/test/resources/config.properties}: | ||
| * </ul> | ||
| * | ||
| * <pre>{@code | ||
| * # Example of config.properties | ||
| * ADYEN_API_KEY= | ||
| * ADYEN_MERCHANT_ACCOUNT=MyMerchantAccount | ||
| * ADYEN_TERMINAL_DEVICE_ID=V400m-1234567890 | ||
| * ADYEN_TERMINAL_DEVICE_KEY_IDENTIFIER= | ||
| * ADYEN_TERMINAL_DEVICE_PASSPHRASE= | ||
| * }</pre> | ||
| * | ||
| * <ul> | ||
| * <li>Run one test at a time with {@code mvn test -Dtest=CloudDeviceApiTerminalIT#sendSync} | ||
| * <li>Disable the test again | ||
| * </ul> | ||
| */ | ||
| public class CloudDeviceApiTerminalIT extends BaseIntegrationTest { | ||
|
|
||
| @Disabled("Enable when you want to test with the Terminal") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we could use conditional testing? https://docs.junit.org/5.5.0/user-guide/#writing-tests-conditional-execution
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is "special" integration test class, where tests need to be executed one by one (each test will wait for a response from the Terminal). It might be confusing, but it is the only way to test the integration with the POS terminal works.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, let's keep like this. If we have some idea in the future, we can address in a follow-up PR. I don't see it a blocker, so I'm leaving the approval. |
||
| @Test | ||
| public void sendSync() throws Exception { | ||
|
|
||
| CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(getClient()); | ||
|
|
||
| CloudDeviceApiRequest cloudDeviceApiRequest = | ||
| createCloudDeviceAPIPaymentRequest(getTerminalDeviceId()); | ||
|
|
||
| var response = | ||
| cloudDeviceApi.sync(getMerchantAccount(), getTerminalDeviceId(), cloudDeviceApiRequest); | ||
|
|
||
| Assertions.assertNotNull(response); | ||
| Assertions.assertNotNull(response.getSaleToPOIResponse()); | ||
| Assertions.assertEquals(getTerminalDeviceId(), response.getSaleToPOIResponse().getMessageHeader().getPOIID()); | ||
| } | ||
|
|
||
| @Disabled("Enable when you want to test with the Terminal") | ||
| @Test | ||
| public void sendAsync() throws Exception { | ||
|
|
||
| CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(getClient()); | ||
|
|
||
| CloudDeviceApiRequest cloudDeviceApiRequest = | ||
| createCloudDeviceAPIPaymentRequest(getTerminalDeviceId()); | ||
|
|
||
| var response = | ||
| cloudDeviceApi.async(getMerchantAccount(), getTerminalDeviceId(), cloudDeviceApiRequest); | ||
|
|
||
| Assertions.assertNotNull(response); | ||
| Assertions.assertEquals("ok", response.getResult()); | ||
| } | ||
|
|
||
| @Disabled("Enable when you want to test with the Terminal") | ||
| @Test | ||
| public void sendEncryptedSync() throws Exception { | ||
|
|
||
| CloudDeviceApiRequest cloudDeviceApiRequest = | ||
| createCloudDeviceAPIPaymentRequest(getTerminalDeviceId()); | ||
|
|
||
| EncryptionCredentialDetails encryptionCredentialDetails = | ||
| new EncryptionCredentialDetails() | ||
| .adyenCryptoVersion(1) | ||
| .keyIdentifier(getTerminalDeviceKeyIdentifier()) | ||
| .keyVersion(1) | ||
| .passphrase(getTerminalDevicePassphrase()); | ||
|
|
||
| EncryptedCloudDeviceApi encryptedCloudDeviceApi = | ||
| new EncryptedCloudDeviceApi(getClient(), encryptionCredentialDetails); | ||
|
gcatanese marked this conversation as resolved.
|
||
|
|
||
| var response = | ||
| encryptedCloudDeviceApi.sync( | ||
| getMerchantAccount(), getTerminalDeviceId(), cloudDeviceApiRequest); | ||
|
|
||
| Assertions.assertNotNull(response); | ||
| Assertions.assertNotNull(response.getSaleToPOIResponse()); | ||
| Assertions.assertEquals(getTerminalDeviceId(), response.getSaleToPOIResponse().getMessageHeader().getPOIID()); | ||
| } | ||
|
|
||
| @Disabled("Enable when you want to test with the Terminal") | ||
| @Test | ||
| public void getConnectedDevices() throws Exception { | ||
|
|
||
| CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(getClient()); | ||
|
|
||
| var response = cloudDeviceApi.getConnectedDevices(getMerchantAccount()); | ||
|
|
||
| Assertions.assertNotNull(response); | ||
| Assertions.assertNotNull(response.getUniqueDeviceIds()); | ||
| Assertions.assertTrue(response.getUniqueDeviceIds().contains(getTerminalDeviceId())); | ||
| } | ||
|
|
||
| @Disabled("Enable when you want to test with the Terminal") | ||
| @Test | ||
| public void sendEncryptedAsync() throws Exception { | ||
|
|
||
| CloudDeviceApiRequest cloudDeviceApiRequest = | ||
| createCloudDeviceAPIPaymentRequest(getTerminalDeviceId()); | ||
|
|
||
| EncryptionCredentialDetails encryptionCredentialDetails = | ||
| new EncryptionCredentialDetails() | ||
| .adyenCryptoVersion(1) | ||
| .keyIdentifier(getTerminalDeviceKeyIdentifier()) | ||
| .keyVersion(1) | ||
| .passphrase(getTerminalDevicePassphrase()); | ||
|
|
||
| EncryptedCloudDeviceApi encryptedCloudDeviceApi = | ||
| new EncryptedCloudDeviceApi(getClient(), encryptionCredentialDetails); | ||
|
|
||
| var response = | ||
| encryptedCloudDeviceApi.async( | ||
| getMerchantAccount(), getTerminalDeviceId(), cloudDeviceApiRequest); | ||
|
|
||
| Assertions.assertNotNull(response); | ||
| Assertions.assertEquals("ok", response.getResult()); | ||
| } | ||
|
|
||
| protected CloudDeviceApiRequest createCloudDeviceAPIPaymentRequest(String deviceId) { | ||
| SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest(); | ||
|
|
||
| var randomId = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10); | ||
|
|
||
| MessageHeader messageHeader = new MessageHeader(); | ||
| messageHeader.setProtocolVersion("3.0"); | ||
| messageHeader.setMessageClass(MessageClass.SERVICE); | ||
| messageHeader.setMessageCategory(MessageCategory.PAYMENT); | ||
| messageHeader.setMessageType(MessageType.REQUEST); | ||
| messageHeader.setSaleID(randomId); | ||
| messageHeader.setServiceID(randomId); | ||
| messageHeader.setPOIID(deviceId); | ||
|
|
||
| saleToPOIRequest.setMessageHeader(messageHeader); | ||
|
|
||
| PaymentRequest paymentRequest = new PaymentRequest(); | ||
|
|
||
| SaleData saleData = new SaleData(); | ||
| TransactionIDType transactionIdentification = new TransactionIDType(); | ||
| transactionIdentification.setTransactionID(randomId); | ||
| OffsetDateTime timestamp = OffsetDateTime.now(ZoneOffset.UTC); | ||
| transactionIdentification.setTimeStamp(timestamp); | ||
| saleData.setSaleTransactionID(transactionIdentification); | ||
|
|
||
| PaymentTransaction paymentTransaction = new PaymentTransaction(); | ||
| AmountsReq amountsReq = new AmountsReq(); | ||
| amountsReq.setCurrency("EUR"); | ||
| amountsReq.setRequestedAmount(BigDecimal.TEN); | ||
| paymentTransaction.setAmountsReq(amountsReq); | ||
|
|
||
| paymentRequest.setSaleData(saleData); | ||
| paymentRequest.setPaymentTransaction(paymentTransaction); | ||
|
|
||
| saleToPOIRequest.setPaymentRequest(paymentRequest); | ||
|
|
||
| CloudDeviceApiRequest cloudDeviceApiRequest = new CloudDeviceApiRequest(); | ||
| cloudDeviceApiRequest.setSaleToPOIRequest(saleToPOIRequest); | ||
|
|
||
| return cloudDeviceApiRequest; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.