From 36aa00c6606f0d322d73538eb106119cb05f4ca7 Mon Sep 17 00:00:00 2001 From: gcatanese Date: Fri, 27 Mar 2026 12:39:51 +0100 Subject: [PATCH 1/4] Include Device API in createBaseURL logic --- src/main/java/com/adyen/Service.java | 15 ++++ src/test/java/com/adyen/ServiceTest.java | 59 ++++++++++++++ .../clouddevice/CloudDeviceApiTest.java | 80 +++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/src/main/java/com/adyen/Service.java b/src/main/java/com/adyen/Service.java index 65b60a53f..19e562973 100644 --- a/src/main/java/com/adyen/Service.java +++ b/src/main/java/com/adyen/Service.java @@ -21,6 +21,7 @@ package com.adyen; import com.adyen.enums.Environment; +import com.adyen.enums.Region; /** * A generic service that provides shared functionality for all API services. It handles client and @@ -139,6 +140,20 @@ protected String createBaseURL(String url) { } } + if (url.contains("device-api-")) { + if (config.getTerminalApiRegion() == null + || config.getTerminalApiRegion().equals(Region.EU)) { + return url.replaceFirst( + "https://device-api-test.adyen.com", "https://device-api-live.adyen.com"); + } else { + return url.replaceFirst( + "https://device-api-test.adyen.com", + String.format( + "https://device-api-live-%s.adyen.com", + config.getTerminalApiRegion().name().toLowerCase())); + } + } + return url.replaceFirst("-test", "-live"); } } diff --git a/src/test/java/com/adyen/ServiceTest.java b/src/test/java/com/adyen/ServiceTest.java index 70a0d69e1..0ce36f37e 100644 --- a/src/test/java/com/adyen/ServiceTest.java +++ b/src/test/java/com/adyen/ServiceTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import com.adyen.enums.Environment; +import com.adyen.enums.Region; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -122,4 +123,62 @@ public void testLiveRecurringUrlWithoutPrefix() { assertThrows(IllegalArgumentException.class, () -> service.createBaseURL(testUrl)); assertEquals("please provide a live url prefix in the client", e.getMessage()); } + + @Test + public void testDeviceApiTestEnvironment() { + config.setEnvironment(Environment.TEST); + String testUrl = "https://device-api-test.adyen.com/device/v1"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(testUrl, actualUrl); + } + + @Test + public void testDeviceApiLiveUrlDefaultRegion() { + String testUrl = "https://device-api-test.adyen.com/device/v1"; + String expectedUrl = "https://device-api-live.adyen.com/device/v1"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testDeviceApiLiveUrlEuRegion() { + config.setTerminalApiRegion(Region.EU); + String testUrl = "https://device-api-test.adyen.com/device/v1"; + String expectedUrl = "https://device-api-live.adyen.com/device/v1"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testDeviceApiLiveUrlAuRegion() { + config.setTerminalApiRegion(Region.AU); + String testUrl = "https://device-api-test.adyen.com/device/v1"; + String expectedUrl = "https://device-api-live-au.adyen.com/device/v1"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testDeviceApiLiveUrlUsRegion() { + config.setTerminalApiRegion(Region.US); + String testUrl = "https://device-api-test.adyen.com/device/v1"; + String expectedUrl = "https://device-api-live-us.adyen.com/device/v1"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testDeviceApiLiveUrlApseRegion() { + config.setTerminalApiRegion(Region.APSE); + String testUrl = "https://device-api-test.adyen.com/device/v1"; + String expectedUrl = "https://device-api-live-apse.adyen.com/device/v1"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(expectedUrl, actualUrl); + } } diff --git a/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java b/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java index a79859458..fc7adc3bd 100644 --- a/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java +++ b/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java @@ -1,12 +1,17 @@ package com.adyen.service.clouddevice; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.verify; import com.adyen.BaseTest; import com.adyen.Client; +import com.adyen.Config; import com.adyen.constants.ApiConstants; +import com.adyen.enums.Environment; +import com.adyen.enums.Region; import com.adyen.model.clouddevice.*; import com.adyen.model.tapi.*; +import java.lang.reflect.Field; import java.math.BigDecimal; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -16,6 +21,81 @@ public class CloudDeviceApiTest extends BaseTest { + @Test + public void baseUrlOnTest() throws NoSuchFieldException, IllegalAccessException { + Client client = new Client(new Config().apiKey("test").environment(Environment.TEST)); + + CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); + // get field by reflection (it is protected) + Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); + baseURLField.setAccessible(true); + String baseURL = (String) baseURLField.get(cloudDeviceApi); + assertEquals( + String.format("https://device-api-test.adyen.com/v%s", CloudDeviceApi.API_VERSION), + baseURL); + } + + @Test + public void baseUrlOnLive() throws NoSuchFieldException, IllegalAccessException { + Client client = new Client(new Config().apiKey("test").environment(Environment.LIVE)); + + CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); + // get field by reflection (it is protected) + Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); + baseURLField.setAccessible(true); + String baseURL = (String) baseURLField.get(cloudDeviceApi); + assertEquals( + String.format("https://device-api-live.adyen.com/v%s", CloudDeviceApi.API_VERSION), + baseURL); + } + + @Test + public void baseUrlOnLivePreservesVersionPath() + throws NoSuchFieldException, IllegalAccessException { + Client client = new Client(new Config().apiKey("test").environment(Environment.LIVE)); + + CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); + Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); + baseURLField.setAccessible(true); + String baseURL = (String) baseURLField.get(cloudDeviceApi); + // The live base URL must retain the /v1 path so that resource paths are correct + assertEquals( + String.format("https://device-api-live.adyen.com/v%s", CloudDeviceApi.API_VERSION), + baseURL); + } + + @Test + public void baseUrlOnLiveWithEuRegion() throws NoSuchFieldException, IllegalAccessException { + Client client = + new Client( + new Config().apiKey("test").environment(Environment.LIVE).terminalApiRegion(Region.EU)); + + CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); + // get field by reflection (it is protected) + Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); + baseURLField.setAccessible(true); + String baseURL = (String) baseURLField.get(cloudDeviceApi); + assertEquals( + String.format("https://device-api-live.adyen.com/v%s", CloudDeviceApi.API_VERSION), + baseURL); + } + + @Test + public void baseUrlOnLiveWithRegion() throws NoSuchFieldException, IllegalAccessException { + Client client = + new Client( + new Config().apiKey("test").environment(Environment.LIVE).terminalApiRegion(Region.US)); + + CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); + // get field by reflection (it is protected) + Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); + baseURLField.setAccessible(true); + String baseURL = (String) baseURLField.get(cloudDeviceApi); + assertEquals( + String.format("https://device-api-live-us.adyen.com/v%s", CloudDeviceApi.API_VERSION), + baseURL); + } + @Test public void sendSync() throws Exception { Client client = createMockClientFromFile("mocks/clouddevice/payment-sync-success.json"); From e3c2f12fb8380ac89ac8e62caf481d6ff532dba8 Mon Sep 17 00:00:00 2001 From: gcatanese Date: Tue, 31 Mar 2026 10:55:47 +0200 Subject: [PATCH 2/4] Remove reflection in CloudDeviceApiTest, use direct protected field access Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- .../clouddevice/CloudDeviceApiTest.java | 42 +++++-------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java b/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java index fc7adc3bd..3b5988a16 100644 --- a/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java +++ b/src/test/java/com/adyen/service/clouddevice/CloudDeviceApiTest.java @@ -11,7 +11,6 @@ import com.adyen.enums.Region; import com.adyen.model.clouddevice.*; import com.adyen.model.tapi.*; -import java.lang.reflect.Field; import java.math.BigDecimal; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -22,78 +21,57 @@ public class CloudDeviceApiTest extends BaseTest { @Test - public void baseUrlOnTest() throws NoSuchFieldException, IllegalAccessException { + public void baseUrlOnTest() { Client client = new Client(new Config().apiKey("test").environment(Environment.TEST)); CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); - // get field by reflection (it is protected) - Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); - baseURLField.setAccessible(true); - String baseURL = (String) baseURLField.get(cloudDeviceApi); assertEquals( String.format("https://device-api-test.adyen.com/v%s", CloudDeviceApi.API_VERSION), - baseURL); + cloudDeviceApi.baseURL); } @Test - public void baseUrlOnLive() throws NoSuchFieldException, IllegalAccessException { + public void baseUrlOnLive() { Client client = new Client(new Config().apiKey("test").environment(Environment.LIVE)); CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); - // get field by reflection (it is protected) - Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); - baseURLField.setAccessible(true); - String baseURL = (String) baseURLField.get(cloudDeviceApi); assertEquals( String.format("https://device-api-live.adyen.com/v%s", CloudDeviceApi.API_VERSION), - baseURL); + cloudDeviceApi.baseURL); } @Test - public void baseUrlOnLivePreservesVersionPath() - throws NoSuchFieldException, IllegalAccessException { + public void baseUrlOnLivePreservesVersionPath() { Client client = new Client(new Config().apiKey("test").environment(Environment.LIVE)); CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); - Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); - baseURLField.setAccessible(true); - String baseURL = (String) baseURLField.get(cloudDeviceApi); - // The live base URL must retain the /v1 path so that resource paths are correct assertEquals( String.format("https://device-api-live.adyen.com/v%s", CloudDeviceApi.API_VERSION), - baseURL); + cloudDeviceApi.baseURL); } @Test - public void baseUrlOnLiveWithEuRegion() throws NoSuchFieldException, IllegalAccessException { + public void baseUrlOnLiveWithEuRegion() { Client client = new Client( new Config().apiKey("test").environment(Environment.LIVE).terminalApiRegion(Region.EU)); CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); - // get field by reflection (it is protected) - Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); - baseURLField.setAccessible(true); - String baseURL = (String) baseURLField.get(cloudDeviceApi); assertEquals( String.format("https://device-api-live.adyen.com/v%s", CloudDeviceApi.API_VERSION), - baseURL); + cloudDeviceApi.baseURL); } @Test - public void baseUrlOnLiveWithRegion() throws NoSuchFieldException, IllegalAccessException { + public void baseUrlOnLiveWithRegion() { Client client = new Client( new Config().apiKey("test").environment(Environment.LIVE).terminalApiRegion(Region.US)); CloudDeviceApi cloudDeviceApi = new CloudDeviceApi(client); - // get field by reflection (it is protected) - Field baseURLField = CloudDeviceApi.class.getDeclaredField("baseURL"); - baseURLField.setAccessible(true); - String baseURL = (String) baseURLField.get(cloudDeviceApi); assertEquals( String.format("https://device-api-live-us.adyen.com/v%s", CloudDeviceApi.API_VERSION), - baseURL); + cloudDeviceApi.baseURL); } @Test From bd9a34c1a678c08d84460112690dc5d976803bbd Mon Sep 17 00:00:00 2001 From: gcatanese Date: Tue, 31 Mar 2026 11:01:34 +0200 Subject: [PATCH 3/4] Use url reassignment in device-api block for consistency with other blocks Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- src/main/java/com/adyen/Service.java | 16 +++++++++------- src/test/java/com/adyen/ServiceTest.java | 9 +++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/adyen/Service.java b/src/main/java/com/adyen/Service.java index 19e562973..0e52eb3b5 100644 --- a/src/main/java/com/adyen/Service.java +++ b/src/main/java/com/adyen/Service.java @@ -143,14 +143,16 @@ protected String createBaseURL(String url) { if (url.contains("device-api-")) { if (config.getTerminalApiRegion() == null || config.getTerminalApiRegion().equals(Region.EU)) { - return url.replaceFirst( - "https://device-api-test.adyen.com", "https://device-api-live.adyen.com"); + url = + url.replaceFirst( + "https://device-api-test.adyen.com", "https://device-api-live.adyen.com"); } else { - return url.replaceFirst( - "https://device-api-test.adyen.com", - String.format( - "https://device-api-live-%s.adyen.com", - config.getTerminalApiRegion().name().toLowerCase())); + url = + url.replaceFirst( + "https://device-api-test.adyen.com", + String.format( + "https://device-api-live-%s.adyen.com", + config.getTerminalApiRegion().name().toLowerCase())); } } diff --git a/src/test/java/com/adyen/ServiceTest.java b/src/test/java/com/adyen/ServiceTest.java index 0ce36f37e..62de0e616 100644 --- a/src/test/java/com/adyen/ServiceTest.java +++ b/src/test/java/com/adyen/ServiceTest.java @@ -181,4 +181,13 @@ public void testDeviceApiLiveUrlApseRegion() { String actualUrl = service.createBaseURL(testUrl); assertEquals(expectedUrl, actualUrl); } + + @Test + public void testDeviceApiCustomDomainFallsBackToGenericReplacement() { + String testUrl = "https://my-proxy-test.example.com/device-api-v1/path"; + String expectedUrl = "https://my-proxy-live.example.com/device-api-v1/path"; + + String actualUrl = service.createBaseURL(testUrl); + assertEquals(expectedUrl, actualUrl); + } } From 7df232627ec437caeecbb67be012d8bf069ae878 Mon Sep 17 00:00:00 2001 From: gcatanese Date: Tue, 31 Mar 2026 12:10:15 +0200 Subject: [PATCH 4/4] Consolidate Device API region tests into a @ParameterizedTest with @MethodSource Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- src/test/java/com/adyen/ServiceTest.java | 56 +++++++----------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/src/test/java/com/adyen/ServiceTest.java b/src/test/java/com/adyen/ServiceTest.java index 62de0e616..8d1a0a08d 100644 --- a/src/test/java/com/adyen/ServiceTest.java +++ b/src/test/java/com/adyen/ServiceTest.java @@ -4,8 +4,12 @@ import com.adyen.enums.Environment; import com.adyen.enums.Region; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; /** Tests for {@link Service#createBaseURL(String)}. */ public class ServiceTest extends BaseTest { @@ -133,50 +137,20 @@ public void testDeviceApiTestEnvironment() { assertEquals(testUrl, actualUrl); } - @Test - public void testDeviceApiLiveUrlDefaultRegion() { - String testUrl = "https://device-api-test.adyen.com/device/v1"; - String expectedUrl = "https://device-api-live.adyen.com/device/v1"; - - String actualUrl = service.createBaseURL(testUrl); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testDeviceApiLiveUrlEuRegion() { - config.setTerminalApiRegion(Region.EU); - String testUrl = "https://device-api-test.adyen.com/device/v1"; - String expectedUrl = "https://device-api-live.adyen.com/device/v1"; - - String actualUrl = service.createBaseURL(testUrl); - assertEquals(expectedUrl, actualUrl); + static Stream deviceApiRegionToLiveUrl() { + return Stream.of( + Arguments.of(null, "https://device-api-live.adyen.com/device/v1"), + Arguments.of(Region.EU, "https://device-api-live.adyen.com/device/v1"), + Arguments.of(Region.AU, "https://device-api-live-au.adyen.com/device/v1"), + Arguments.of(Region.US, "https://device-api-live-us.adyen.com/device/v1"), + Arguments.of(Region.APSE, "https://device-api-live-apse.adyen.com/device/v1")); } - @Test - public void testDeviceApiLiveUrlAuRegion() { - config.setTerminalApiRegion(Region.AU); - String testUrl = "https://device-api-test.adyen.com/device/v1"; - String expectedUrl = "https://device-api-live-au.adyen.com/device/v1"; - - String actualUrl = service.createBaseURL(testUrl); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testDeviceApiLiveUrlUsRegion() { - config.setTerminalApiRegion(Region.US); - String testUrl = "https://device-api-test.adyen.com/device/v1"; - String expectedUrl = "https://device-api-live-us.adyen.com/device/v1"; - - String actualUrl = service.createBaseURL(testUrl); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testDeviceApiLiveUrlApseRegion() { - config.setTerminalApiRegion(Region.APSE); + @ParameterizedTest + @MethodSource("deviceApiRegionToLiveUrl") + public void testDeviceApiLiveUrlPerRegion(Region region, String expectedUrl) { + config.setTerminalApiRegion(region); String testUrl = "https://device-api-test.adyen.com/device/v1"; - String expectedUrl = "https://device-api-live-apse.adyen.com/device/v1"; String actualUrl = service.createBaseURL(testUrl); assertEquals(expectedUrl, actualUrl);