Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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?
): CheckoutApiService {
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
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 {
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
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
Comment thread
chintan-soni-cko marked this conversation as resolved.
Outdated
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
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) {
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
Environment.PRODUCTION -> baseUrlPrefix?.baseUrlPrefixValidator()?.let {
"https://${baseUrlPrefix}.api.checkout.com/tokens"
} ?: 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
Expand All @@ -11,3 +22,7 @@ internal fun Environment.toLoggingName() = when (this) {
Environment.PRODUCTION -> "production"
Environment.SANDBOX -> "sandbox"
}

private fun String?.baseUrlPrefixValidator() = this?.takeIf {
prefix -> prefix.all { char -> char.isLetterOrDigit() } && prefix.isNotEmpty()
}
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
92 changes: 92 additions & 0 deletions checkout/src/test/java/com/checkout/EnvironmentExtensionTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
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)
}

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.map { invalidPrefix ->
val result = Environment.PRODUCTION.toBaseUrl(invalidPrefix)
assertEquals(
result,
PRODUCTION_SERVER_URL,
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
)
}
}
}
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 @@ -22,7 +22,8 @@ public object CVVComponentApiFactory {
publicKey: String,
environment: Environment,
context: Context,
baseUrlPrefix: String?,
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
Comment thread
zane-smith-cko marked this conversation as resolved.
Outdated
): CVVComponentApi {
return InternalCVVComponentApi(publicKey, environment, context)
return InternalCVVComponentApi(publicKey, environment, context, baseUrlPrefix)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal class InternalCVVComponentApi(
private val publicKey: String,
private val environment: Environment,
private val context: Context,
private val baseUrlPrefix: String?
) : CVVComponentApi {

override fun createComponentMediator(cvvComponentConfig: CVVComponentConfig) = InternalCVVComponentMediator(
Expand All @@ -19,6 +20,7 @@ internal class InternalCVVComponentApi(
publicKey = publicKey,
environment = environment,
context = context,
baseUrlPrefix = baseUrlPrefix
),
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ internal abstract class FramesDIComponent {
@BindsInstance
fun prefillData(cardHolderName: PrefillData?): Builder

@BindsInstance
fun baseUrlPrefix(baseUrlPrefix: String?): Builder

fun build(): FramesDIComponent
}
}
Loading
Loading