diff --git a/button-merchant/src/main/java/com/usebutton/merchant/ButtonApiImpl.java b/button-merchant/src/main/java/com/usebutton/merchant/ButtonApiImpl.java index 1c2fb52..cf18a6c 100644 --- a/button-merchant/src/main/java/com/usebutton/merchant/ButtonApiImpl.java +++ b/button-merchant/src/main/java/com/usebutton/merchant/ButtonApiImpl.java @@ -82,7 +82,7 @@ public PostInstallLink getPendingLink(String applicationId, @Nullable String adv requestBody.put("signals", new JSONObject(signalsMap)); ApiRequest apiRequest = new ApiRequest.Builder(ApiRequest.RequestMethod.POST, - "/v1/web/deferred-deeplink") + "/v1/app/deferred-deeplink") .setBody(requestBody) .build(); diff --git a/button-merchant/src/main/java/com/usebutton/merchant/ButtonInternalImpl.java b/button-merchant/src/main/java/com/usebutton/merchant/ButtonInternalImpl.java index 6f4b938..c3ea935 100644 --- a/button-merchant/src/main/java/com/usebutton/merchant/ButtonInternalImpl.java +++ b/button-merchant/src/main/java/com/usebutton/merchant/ButtonInternalImpl.java @@ -30,6 +30,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; +import android.util.Log; import com.usebutton.merchant.exception.ApplicationIdNotFoundException; import com.usebutton.merchant.module.Features; @@ -38,6 +39,7 @@ import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; /** * ButtonInternalImpl class should implement everything needed for {@link ButtonMerchant} @@ -47,6 +49,8 @@ final class ButtonInternalImpl implements ButtonInternal { + private static final String TAG = ButtonMerchant.class.getSimpleName(); + /** * A list of {@link ButtonMerchant.AttributionTokenListener}. All listeners will be notified of * a token change via the @@ -68,12 +72,21 @@ final class ButtonInternalImpl implements ButtonInternal { */ private final AtomicBoolean hasReceivedDirectDeeplink = new AtomicBoolean(); + private static final Pattern APP_ID_PATTERN = Pattern.compile("^app-[0-9a-zA-Z]+$"); + ButtonInternalImpl(Executor executor) { this.attributionTokenListeners = new ArrayList<>(); this.executor = executor; } public void configure(ButtonRepository buttonRepository, String applicationId) { + if (!APP_ID_PATTERN.matcher(applicationId).matches()) { + Log.e(TAG, "Application ID [" + applicationId + "] is not valid. " + + "You can find your Application ID in the dashboard by logging in at" + + " https://app.usebutton.com/"); + return; + } + buttonRepository.setApplicationId(applicationId); } diff --git a/button-merchant/src/main/java/com/usebutton/merchant/ButtonMerchant.java b/button-merchant/src/main/java/com/usebutton/merchant/ButtonMerchant.java index 611afd1..06b0504 100644 --- a/button-merchant/src/main/java/com/usebutton/merchant/ButtonMerchant.java +++ b/button-merchant/src/main/java/com/usebutton/merchant/ButtonMerchant.java @@ -51,7 +51,8 @@ private ButtonMerchant() { static ButtonInternal buttonInternal = new ButtonInternalImpl(executor); private static ExecutorService executorService = Executors.newSingleThreadExecutor(); - private static final String BASE_URL = "https://api.usebutton.com"; + private static final String BASE_URL = "https://mobileapi.usebutton.com"; + static final String FMT_BASE_URL_APP_ID = "https://%s.mobileapi.usebutton.com"; /** * Configures {@link ButtonMerchant} with your application Id. diff --git a/button-merchant/src/main/java/com/usebutton/merchant/ConnectionManagerImpl.java b/button-merchant/src/main/java/com/usebutton/merchant/ConnectionManagerImpl.java index ebc3ce9..1c47ba7 100644 --- a/button-merchant/src/main/java/com/usebutton/merchant/ConnectionManagerImpl.java +++ b/button-merchant/src/main/java/com/usebutton/merchant/ConnectionManagerImpl.java @@ -67,7 +67,8 @@ final class ConnectionManagerImpl implements ConnectionManager { private String applicationId; - private final String baseUrl; + @VisibleForTesting + String baseUrl; private final String userAgent; private final PersistenceManager persistenceManager; @@ -90,6 +91,9 @@ static ConnectionManager getInstance(String baseUrl, String userAgent, @Override public void setApplicationId(String applicationId) { this.applicationId = applicationId; + + // Update the endpoint to the App ID flavor + baseUrl = String.format(ButtonMerchant.FMT_BASE_URL_APP_ID, applicationId); } @Override diff --git a/button-merchant/src/test/java/com/usebutton/merchant/ButtonApiImplTest.java b/button-merchant/src/test/java/com/usebutton/merchant/ButtonApiImplTest.java index f31a4bf..d3f0e34 100644 --- a/button-merchant/src/test/java/com/usebutton/merchant/ButtonApiImplTest.java +++ b/button-merchant/src/test/java/com/usebutton/merchant/ButtonApiImplTest.java @@ -107,7 +107,7 @@ public void getPendingLink_validateRequest() throws Exception { JSONObject signals = body.getJSONObject("signals"); assertEquals(apiRequest.getRequestMethod(), ApiRequest.RequestMethod.POST); - assertEquals(apiRequest.getPath(), "/v1/web/deferred-deeplink"); + assertEquals(apiRequest.getPath(), "/v1/app/deferred-deeplink"); // request body assertEquals("valid_application_id", body.getString("application_id")); diff --git a/button-merchant/src/test/java/com/usebutton/merchant/ButtonInternalImplTest.java b/button-merchant/src/test/java/com/usebutton/merchant/ButtonInternalImplTest.java index 149f555..6a9a55a 100644 --- a/button-merchant/src/test/java/com/usebutton/merchant/ButtonInternalImplTest.java +++ b/button-merchant/src/test/java/com/usebutton/merchant/ButtonInternalImplTest.java @@ -50,6 +50,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; public class ButtonInternalImplTest { @@ -67,8 +68,18 @@ public void setUp() { public void configure_saveApplicationIdInMemory() { ButtonRepository buttonRepository = mock(ButtonRepository.class); - buttonInternal.configure(buttonRepository, "valid_application_id"); - verify(buttonRepository).setApplicationId("valid_application_id"); + buttonInternal.configure(buttonRepository, "app-abcdef1234567890"); + + verify(buttonRepository).setApplicationId("app-abcdef1234567890"); + } + + @Test + public void configure_invalidAppId_shouldNotConfigure() { + ButtonRepository buttonRepository = mock(ButtonRepository.class); + + buttonInternal.configure(buttonRepository, "invalid_application_id"); + + verifyZeroInteractions(buttonRepository); } @Test diff --git a/button-merchant/src/test/java/com/usebutton/merchant/ConnectionManagerImplTest.java b/button-merchant/src/test/java/com/usebutton/merchant/ConnectionManagerImplTest.java index 4c2a506..a967095 100644 --- a/button-merchant/src/test/java/com/usebutton/merchant/ConnectionManagerImplTest.java +++ b/button-merchant/src/test/java/com/usebutton/merchant/ConnectionManagerImplTest.java @@ -53,7 +53,8 @@ public class ConnectionManagerImplTest { private static final String VALID_UA = "valid_user_agent"; - private ConnectionManagerImpl connectionManager; + private String url; + private ConnectionManager connectionManager; private PersistenceManager persistenceManager; private MockWebServer server = new MockWebServer(); @@ -62,7 +63,7 @@ public void setUp() throws Exception { server.start(); HttpUrl baseUrl = server.url(""); - String url = baseUrl.url().toString(); + url = baseUrl.url().toString(); url = url.substring(0, url.length() - 1); persistenceManager = mock(PersistenceManager.class); @@ -74,6 +75,16 @@ public void tearDown() throws Exception { server.close(); } + @Test + public void setApplicationId_shouldUpdateEndpoint() { + connectionManager = new ConnectionManagerImpl(url, VALID_UA, persistenceManager); + + connectionManager.setApplicationId("valid_app_id"); + + String expectedUrl = String.format(ButtonMerchant.FMT_BASE_URL_APP_ID, "valid_app_id"); + assertEquals(expectedUrl, ((ConnectionManagerImpl) connectionManager).baseUrl); + } + @Test(expected = ButtonNetworkException.class) public void executeRequest_invalidUrl_shouldThrowError() throws Exception { String url = "invalid_link"; @@ -257,6 +268,7 @@ public void executeRequest_shouldIncludeSessionId() throws Exception { public void executeRequest_shouldIncludeApplicationId() throws Exception { String applicationId = "valid_application_id"; connectionManager.setApplicationId(applicationId); + ((ConnectionManagerImpl) connectionManager).baseUrl = url; server.enqueue(new MockResponse().setResponseCode(200).setBody("{}")); connectionManager.executeRequest(new ApiRequest.Builder(ApiRequest.RequestMethod.POST,