Skip to main content

MVP Example

This page shows the minimal working implementation of the Mobile SDK — a complete example that integrates card payments, Google Pay, 3D Secure authentication, a loading overlay, and payment result display within a single Activity.

The goal is to provide a clear starting point when integrating the SDK into your own application. Detailed descriptions of individual components and configuration options can be found in the following sections of the documentation.

What the MVP includes

  • Session initialization (ComgateSecureSession) including 3D Secure configuration
  • A form with Secure Fields for card payment (card number, expiry date, CVV, cardholder name)
  • Card payment button (SecurePayButton)
  • Google Pay button (SecureGooglePayButton)
  • Loading overlay (SecureLoadingOverlay)
  • Payment result display (SecurePaymentStatusView)

Source code

package cz.comgate.mvpdemo

import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color as ComposeColor
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import cz.comgate.sdk.ComgateSecureSession
import cz.comgate.sdk.PaymentParams
import cz.comgate.sdk.PaymentResult
import cz.comgate.sdk.compose.*
import cz.comgate.sdk.threeds.ThreeDSConfig
import cz.comgate.sdk.threeds.ThreeDSToolbarStyle
import cz.comgate.sdk.threeds.ThreeDSUiCustomization
import cz.comgate.sdk.ui.SecureLoadingOverlay

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
// Create the session and release it when the screen is disposed.
val session = remember {
try { createSession() }
catch (e: Exception) { Log.e("ComgateMvp", "createSession crashed", e); null }
}
if (session != null) {
DisposableEffect(session) { onDispose { session.dispose() } }
PaymentScreen(session)
} else {
Text("Initialization failed", color = ComposeColor.Red, modifier = Modifier.padding(20.dp))
}
}
}
}

private fun createSession() = ComgateSecureSession(
checkoutId = "<CHECKOUT_ID>",
context = applicationContext,
devMode = false,
googleMerchantId = "<GOOGLE_MERCHANT_ID>",
googleMerchantName = "<MERCHANT_NAME>",
threeDSConfig = ThreeDSConfig(
uiCustomization = ThreeDSUiCustomization(
toolbarStyle = ThreeDSToolbarStyle(
headerText = "<APP_NAME>"
)
),
challengeTimeoutMinutes = 5
),
lifecycleOwner = this,
onInitialized = { result ->
result.onSuccess { Log.i("ComgateMvp", "Session initialized") }
result.onFailure { Log.e("ComgateMvp", "Init failed: ${it.message}", it) }
}
)
}

@Composable
private fun PaymentScreen(session: ComgateSecureSession) {
val panState = rememberSecurePanFieldState()
val expiryState = rememberSecureExpiryFieldState()
val cvvState = rememberSecureCvvFieldState()
val fullNameState = rememberSecureFullNameFieldState()
// Data collector handles all secure fields including cardholder name.
val collector = rememberSecureDataCollector(panState = panState, expiryState = expiryState, cvvState = cvvState, fullNameState = fullNameState, session = session)

val statusState = rememberPaymentStatusState()
statusState.translation = session.translation

val params: () -> PaymentParams = {
PaymentParams(email = "test@example.com", price = 100, curr = "CZK", country = "CZ", label = "Test payment", refId = "mvp-001")
}

// Shared result handler for both card and Google Pay payments.
fun handleResult(result: PaymentResult) {
statusState.showStatus(result)
Log.i("ComgateMvp", "Payment: $result")
}

val activity = LocalContext.current as AppCompatActivity
// Overlay automatically shows a loader while payment is being processed.
DisposableEffect(session) {
val overlay = SecureLoadingOverlay().apply { setup(session, activity) }
onDispose { overlay.detach() }
}

Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(start = 20.dp, end = 20.dp, bottom = 20.dp, top = 60.dp)) {
SecureFullNameField(state = fullNameState, modifier = Modifier.fillMaxWidth())
Spacer(Modifier.height(12.dp))
SecurePanField(state = panState, modifier = Modifier.fillMaxWidth())
Spacer(Modifier.height(12.dp))
SecureExpiryField(state = expiryState, modifier = Modifier.fillMaxWidth())
Spacer(Modifier.height(12.dp))
SecureCvvField(state = cvvState, modifier = Modifier.fillMaxWidth())
Spacer(Modifier.height(24.dp))
SecurePayButton(
session = session, collector = collector,
onPaymentResult = { handleResult(it) },
paymentParamsProvider = params,
modifier = Modifier.fillMaxWidth().height(52.dp)
)
Spacer(Modifier.height(16.dp))
SecureGooglePayButton(
session = session,
onPaymentResult = { handleResult(it) },
paymentParamsProvider = params,
modifier = Modifier.fillMaxWidth().height(48.dp)
)
Spacer(Modifier.height(16.dp))
SecurePaymentStatusView(state = statusState, modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp))
}
}