Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package checkout.checkout_android;

import static checkout.checkout_android.Constants.PUBLIC_KEY_CVV_TOKENIZATION;
import static checkout.checkout_android.Constants.REGIONAL_SUBDOMAIN;

import android.app.AlertDialog;
import android.os.Bundle;
Expand Down Expand Up @@ -51,7 +52,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
setupObservers();

// Create cvvComponentApi
CVVComponentApi cvvComponentApi = CVVComponentApiFactory.create(PUBLIC_KEY_CVV_TOKENIZATION, Environment.SANDBOX, this);
CVVComponentApi cvvComponentApi = CVVComponentApiFactory.create(PUBLIC_KEY_CVV_TOKENIZATION, Environment.SANDBOX, this, REGIONAL_SUBDOMAIN);

// initialise CVVTokenizationResultHandler for tokenization
resultHandler = result -> {
Expand Down
10 changes: 7 additions & 3 deletions app/src/main/java/checkout/checkout_android/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ public class Constants {
/**
* Replace with public key from Hub in Sandbox Environment
*/
public static final String PUBLIC_KEY = "pk_test_b37b8b6b-fc9a-483f-a77e-3386b606f90e";
public static final String PUBLIC_KEY = "pk_sbox_dheqoi7tqn2jcvbn55sa2czwu42";

/**
* Replace with public key from Hub in Sandbox Environment, testing key for CVV Tokenization
*/
public static final String PUBLIC_KEY_CVV_TOKENIZATION = "pk_6b30805a-1f3b-4c63-8b75-eb3030109173";
public static final String PUBLIC_KEY_CVV_TOKENIZATION = "pk_sbox_dheqoi7tqn2jcvbn55sa2czwu42";
/**
* Replace with Secret key from Hub in Sandbox Environment
*/
public static final String SECRET_KEY = "sk_test_568e6077-a08f-4692-9237-cc6c48dcf6aa";
public static final String SECRET_KEY = "sk_sbox_cqc26o3haljkwuns6xcfcmf2vmu";
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
/**
* Replace with subdomain value, testing key for base url regional subdomain prefix
*/
public static final String REGIONAL_SUBDOMAIN = "global";
/**
* Replace with Success/Failure Urls from Hub in Sandbox Environment
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package checkout.checkout_android;

import static checkout.checkout_android.Constants.REGIONAL_SUBDOMAIN;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.os.Bundle;
Expand All @@ -18,6 +20,8 @@
import com.checkout.threedsecure.model.ThreeDSResult;
import com.checkout.tokenization.model.TokenDetails;

import java.util.Collections;

import checkout.checkout_android.utils.PaymentUtil;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
Expand Down Expand Up @@ -93,7 +97,11 @@ private PaymentFormConfig providePaymentFormConfig() {
this,
Constants.ENVIRONMENT,
new PaymentFormStyle(),
mPaymentFlowHandler);
mPaymentFlowHandler,
Collections.emptyList(),
null,
REGIONAL_SUBDOMAIN
);
}

private void displayMessage(String title, String message, boolean exitScreen) {
Expand Down
51 changes: 31 additions & 20 deletions checkout/src/main/java/com/checkout/CheckoutApiServiceFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.checkout.base.model.Environment
import com.checkout.logging.EventLoggerProvider
import com.checkout.logging.Logger
import com.checkout.logging.model.LoggingEvent
import com.checkout.logging.utils.toBaseUrl
import com.checkout.network.OkHttpProvider
import com.checkout.risk.FramesOptions
import com.checkout.threedsecure.Executor
Expand Down Expand Up @@ -40,6 +41,7 @@ public object CheckoutApiServiceFactory {
publicKey: String,
environment: Environment,
context: Context,
baseUrlPrefix: String? = null,
): CheckoutApiService {
val logger = EventLoggerProvider.provide()
logger.setup(context, environment)
Expand All @@ -51,7 +53,7 @@ public object CheckoutApiServiceFactory {
)

return CheckoutApiClient(
provideTokenRepository(context, publicKey, environment),
provideTokenRepository(context, publicKey, environment, baseUrlPrefix),
provideThreeDSExecutor(logger),
)
}
Expand All @@ -60,25 +62,34 @@ public object CheckoutApiServiceFactory {
context: Context,
publicKey: String,
environment: Environment,
): TokenRepository = TokenRepositoryImpl(
networkApiClient = provideNetworkApiClient(publicKey, environment.url),
cardToTokenRequestMapper = CardToTokenRequestMapper(),
cvvToTokenNetworkRequestMapper = CVVToTokenNetworkRequestMapper(),
cardTokenizationNetworkDataMapper = CardTokenizationNetworkDataMapper(),
validateTokenizationDataUseCase = ValidateTokenizationDataUseCase(
CardValidatorFactory.createInternal(),
AddressValidator(),
PhoneValidator(),
AddressToAddressValidationRequestDataMapper(),
),
validateCVVTokenizationDataUseCase = ValidateCVVTokenizationDataUseCase(
CVVComponentValidatorFactory.create(),
),
logger = TokenizationEventLogger(EventLoggerProvider.provide()),
publicKey = publicKey,
cvvTokenizationNetworkDataMapper = CVVTokenizationNetworkDataMapper(),
riskSdkUseCase = RiskSdkUseCase(environment, context, publicKey, riskSDKFramesOptions, RiskInstanceProvider),
)
baseUrlPrefix: String?,
): TokenRepository {
return TokenRepositoryImpl(
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
networkApiClient = provideNetworkApiClient(publicKey, environment.toBaseUrl(baseUrlPrefix)),
cardToTokenRequestMapper = CardToTokenRequestMapper(),
cvvToTokenNetworkRequestMapper = CVVToTokenNetworkRequestMapper(),
cardTokenizationNetworkDataMapper = CardTokenizationNetworkDataMapper(),
validateTokenizationDataUseCase = ValidateTokenizationDataUseCase(
CardValidatorFactory.createInternal(),
AddressValidator(),
PhoneValidator(),
AddressToAddressValidationRequestDataMapper(),
),
validateCVVTokenizationDataUseCase = ValidateCVVTokenizationDataUseCase(
CVVComponentValidatorFactory.create(),
),
logger = TokenizationEventLogger(EventLoggerProvider.provide()),
publicKey = publicKey,
cvvTokenizationNetworkDataMapper = CVVTokenizationNetworkDataMapper(),
riskSdkUseCase = RiskSdkUseCase(
environment,
context,
publicKey,
riskSDKFramesOptions,
RiskInstanceProvider,
),
)
}

private fun provideNetworkApiClient(
publicKey: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.checkout.base.model

import com.checkout.base.util.EnvironmentConstants

public enum class Environment(public val url: String) {
PRODUCTION(EnvironmentConstants.PRODUCTION_SERVER_URL),
SANDBOX(EnvironmentConstants.SANDBOX_SERVER_URL),
public enum class Environment {
PRODUCTION,
SANDBOX,
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
package com.checkout.logging.utils

import com.checkout.base.model.Environment
import com.checkout.base.util.EnvironmentConstants.PRODUCTION_SERVER_URL
import com.checkout.base.util.EnvironmentConstants.SANDBOX_SERVER_URL

internal fun Environment.toBaseUrl(baseUrlPrefix: String? = null) = when (this) {
Environment.PRODUCTION -> baseUrlPrefix?.baseUrlPrefixValidator()?.let {
"https://$baseUrlPrefix.api.checkout.com/tokens"
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
} ?: PRODUCTION_SERVER_URL
Environment.SANDBOX -> baseUrlPrefix?.baseUrlPrefixValidator()?.let {
"https://$baseUrlPrefix.api.sandbox.checkout.com/tokens"
} ?: SANDBOX_SERVER_URL
}
Comment thread
zane-smith-cko marked this conversation as resolved.
internal fun Environment.toLoggingEnvironment() = when (this) {
Environment.PRODUCTION -> com.checkout.eventlogger.Environment.PRODUCTION
Environment.SANDBOX -> com.checkout.eventlogger.Environment.SANDBOX
}

internal fun Environment.toLoggingName() = when (this) {
Environment.PRODUCTION -> "production"
Environment.SANDBOX -> "sandbox"
Environment.PRODUCTION ->
"production"
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
Environment.SANDBOX ->
"sandbox"
}

private fun String?.baseUrlPrefixValidator() = this
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
?.takeIf {
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
prefix ->
prefix.all { char -> char.isLetterOrDigit() } && prefix.isNotEmpty()
}
Comment thread
zane-smith-cko marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal class CheckoutApiServiceFactoryTest {
val mockEnvironment = Environment.SANDBOX

// When
CheckoutApiServiceFactory.create("", mockEnvironment, mockContext)
CheckoutApiServiceFactory.create("", mockEnvironment, mockContext, null)

// Then
verify { mockLogger.setup(eq(mockContext), eq(mockEnvironment)) }
Expand Down
93 changes: 93 additions & 0 deletions checkout/src/test/java/com/checkout/EnvironmentExtensionTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.checkout

import com.checkout.base.model.Environment
import com.checkout.base.util.EnvironmentConstants
import com.checkout.base.util.EnvironmentConstants.PRODUCTION_SERVER_URL
import com.checkout.logging.utils.toBaseUrl
import org.junit.Assert.assertEquals
import org.junit.Test

internal class EnvironmentExtensionTest {

@Test
fun `when toBaseUrl PRODUCTION with null subDomainPrefix returns production server URL`() {
val result = Environment.PRODUCTION.toBaseUrl(null)
assertEquals(EnvironmentConstants.PRODUCTION_SERVER_URL, result)
}

@Test
fun `when toBaseUrl PRODUCTION with no subDomainPrefix argument returns production server URL`() {
val result = Environment.PRODUCTION.toBaseUrl()
assertEquals(EnvironmentConstants.PRODUCTION_SERVER_URL, result)
}

@Test
fun `when toBaseUrl PRODUCTION with subDomainPrefix returns custom production URL`() {
val result = Environment.PRODUCTION.toBaseUrl("custom")
assertEquals("https://custom.api.checkout.com/tokens", result)
}

@Test
fun `when toBaseUrl PRODUCTION with alphanumeric subDomainPrefix returns custom production URL`() {
val result = Environment.PRODUCTION.toBaseUrl("mySubdomain123")
assertEquals("https://mySubdomain123.api.checkout.com/tokens", result)
}

@Test
fun `when toBaseUrl SANDBOX with null subDomainPrefix returns sandbox server URL`() {
val result = Environment.SANDBOX.toBaseUrl(null)
assertEquals(EnvironmentConstants.SANDBOX_SERVER_URL, result)
}

@Test
fun `when toBaseUrl SANDBOX with no subDomainPrefix argument returns sandbox server URL`() {
val result = Environment.SANDBOX.toBaseUrl()
assertEquals(EnvironmentConstants.SANDBOX_SERVER_URL, result)
}

@Test
fun `when toBaseUrl SANDBOX with subDomainPrefix returns custom sandbox URL`() {
val result = Environment.SANDBOX.toBaseUrl("custom")
assertEquals("https://custom.api.sandbox.checkout.com/tokens", result)
}

@Test
fun `when toBaseUrl SANDBOX with alphanumeric subDomainPrefix returns custom sandbox URL`() {
val result = Environment.SANDBOX.toBaseUrl("test99")
assertEquals("https://test99.api.sandbox.checkout.com/tokens", result)
}

@Test
fun `when toBaseUrl with empty string subDomainPrefix uses default URL for production`() {
val result = Environment.PRODUCTION.toBaseUrl("")
assertEquals("https://api.checkout.com/tokens", result)
}

@Test
fun `toBaseUrl PRODUCTION returns default URL for any non-alphanumeric prefix`() {
Comment thread
zane-smith-cko marked this conversation as resolved.
val invalidPrefixList = listOf(
"invalid_prefix",
"invalid-prefix",
"invalid.prefix",
Comment thread
zane-smith-cko marked this conversation as resolved.
"invalid@prefix",
"invalid!prefix",
"invalid#prefix",
"invalid\$prefix",
"invalid%prefix",
"invalid^prefix",
"invalid&prefix",
"invalid*prefix",
"invalid(prefix",
"invalid)prefix",
"invalid prefix",
)

invalidPrefixList.forEach { invalidPrefix ->
val result = Environment.PRODUCTION.toBaseUrl(invalidPrefix)
assertEquals(
PRODUCTION_SERVER_URL,
result,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.checkout.base.model.Environment
import com.checkout.example.frames.paymentformstyling.PaymentFormConstants
import com.checkout.example.frames.styling.CustomCVVInputFieldStyle
import com.checkout.example.frames.ui.utils.PUBLIC_KEY_CVV_TOKENIZATION
import com.checkout.example.frames.ui.utils.REGIONAL_SUBDOMAIN
import com.checkout.example.frames.ui.viewmodel.CVVTokenizationViewModel
import com.checkout.frames.cvvinputfield.CVVComponentApiFactory
import com.checkout.frames.cvvinputfield.api.CVVComponentApi
Expand All @@ -35,6 +36,7 @@ fun CVVTokenizationScreen(navController: NavHostController) {
publicKey = PUBLIC_KEY_CVV_TOKENIZATION,
environment = Environment.SANDBOX,
context = LocalContext.current,
baseUrlPrefix = REGIONAL_SUBDOMAIN,
)

val visaMediator = createMediator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import com.checkout.example.frames.ui.theme.FramesTheme
import com.checkout.example.frames.ui.theme.GrayColor
import com.checkout.example.frames.ui.utils.PromptUtils
import com.checkout.example.frames.ui.utils.PromptUtils.neutralButton
import com.checkout.example.frames.ui.utils.REGIONAL_SUBDOMAIN
import com.checkout.tokenization.model.GooglePayTokenRequest

@Suppress("MagicNumber", "LongMethod")
Expand Down Expand Up @@ -223,6 +224,7 @@ fun invokeCheckoutSDKToGenerateTokenForGooglePay(context: Context) {
"pk_test_6e40a700-d563-43cd-89d0-f9bb17d35e73",
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
Environment.SANDBOX,
context,
REGIONAL_SUBDOMAIN,
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.checkout.example.frames.paymentformstyling.CustomPaymentFormTheme
import com.checkout.example.frames.ui.utils.ENVIRONMENT
import com.checkout.example.frames.ui.utils.PUBLIC_KEY
import com.checkout.example.frames.ui.utils.PrefillDataHelper
import com.checkout.example.frames.ui.utils.REGIONAL_SUBDOMAIN
import com.checkout.frames.api.PaymentFlowHandler
import com.checkout.frames.api.PaymentFormMediator
import com.checkout.frames.screen.paymentform.model.PaymentFormConfig
Expand Down Expand Up @@ -50,6 +51,7 @@ fun Navigator(
publicKey = PUBLIC_KEY,
context = context,
environment = ENVIRONMENT,
baseUrlPrefix = REGIONAL_SUBDOMAIN,
paymentFlowHandler = object : PaymentFlowHandler {
override fun onSubmit() {
/*Intentionally left empty*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ val ENVIRONMENT: Environment = Environment.SANDBOX
/**
* Replace with public key from Hub in Sandbox Environment
*/
const val PUBLIC_KEY = "pk_test_b37b8b6b-fc9a-483f-a77e-3386b606f90e"
const val PUBLIC_KEY = "pk_sbox_dheqoi7tqn2jcvbn55sa2czwu42"

/**
* Replace with public key from Hub in Sandbox Environment, testing key for CVV Tokenization
*/
const val PUBLIC_KEY_CVV_TOKENIZATION = "pk_6b30805a-1f3b-4c63-8b75-eb3030109173"
const val PUBLIC_KEY_CVV_TOKENIZATION = "pk_sbox_dheqoi7tqn2jcvbn55sa2czwu42"

/**
* Replace with Secret key from Hub in Sandbox Environment
* Replace with subdomain value, testing key for base url regional subdomain prefix
*/
const val SECRET_KEY = "sk_test_568e6077-a08f-4692-9237-cc6c48dcf6aa"
const val REGIONAL_SUBDOMAIN = "global"

/**
* Replace with Success/Failure Urls from Hub in Sandbox Environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ public object CVVComponentApiFactory {
* @param publicKey - used for client-side authentication in the SDK
* @param environment - [Environment] represent the environment for tokenization
* @param context - represent the application context
* @param baseUrlPrefix - an optional alphanumeric prefix used to route requests to a specific regional or merchant-specific subdomain (e.g., "msdd"). Must be alphanumeric.
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
*/
@JvmStatic
public fun create(
publicKey: String,
environment: Environment,
context: Context,
baseUrlPrefix: String? = null,
): CVVComponentApi {
return InternalCVVComponentApi(publicKey, environment, context)
return InternalCVVComponentApi(publicKey, environment, context, baseUrlPrefix)
}
}
Loading
Loading