Skip to main content

Kartové údaje

Kartové platby prebiehajú prostredníctvom zabezpečených vstupných komponentov — Secure Fields. Tieto komponenty zaisťujú bezpečné zadávanie, validáciu a ochranu kartových údajov. Hostiteľská aplikácia nikdy nemá prístup k citlivým údajom v nechránenej podobe.

Secure Fields​

Knižnica poskytuje štyri komponenty na zadávanie údajov v platobnom formulári:

SecurePanField​

Pole na zadanie čísla karty (PAN — Primary Account Number).

  • Prijíma iba číslice
  • Automaticky detekuje kartovú sieť (Visa, Mastercard)
  • Formátuje číslo karty s mezerami dle kartové siete (napr. 4111 1111 1111 1111)
  • Omezuje délku vstupu podle detekované kartové siete
  • Validuje číslo karty pomocou Luhnovho algoritmu
  • Podporuje systémový autofill
  • Sprístupňuje vlastnosť last4 — posledné 4 číslice karty (bezpečné na zobrazenie v UI)
import cz.comgate.sdk.compose.*

val panState = rememberSecurePanFieldState()

SecurePanField(
state = panState,
modifier = Modifier.fillMaxWidth()
)

SecureExpiryField​

Pole na zadanie dátumu expirácie karty.

  • Prijíma iba číslice
  • Automaticky formátuje vstup v tvare MM/YY
  • Validuje mesiac (1–12) a kontroluje, či karta nie je expirovaná
  • Podporuje autofill vo formátoch MMYY aj MMYYYY
val expiryState = rememberSecureExpiryFieldState()

SecureExpiryField(
state = expiryState,
modifier = Modifier.fillMaxWidth()
)

SecureCvvField​

Pole na zadanie bezpečnostného kódu karty (CVV/CVC).

  • Prijíma iba číslice
  • Dĺžka sa automaticky prispôsobuje detekovanej kartovej sieti
  • Validuje minimálnu požadovanú dĺžku
val cvvState = rememberSecureCvvFieldState()

SecureCvvField(
state = cvvState,
modifier = Modifier.fillMaxWidth()
)

SecureFullNameField​

Pole na zadanie mena a priezviska platiteľa.

  • Prijíma textový vstup (vrátane mezer)
  • Podporuje systémový autofill mena
  • Je validné pri neprázdnej hodnote
  • Po pripojení k ComgateSecureSession sa jeho hodnota automaticky použije ako fullName
import androidx.compose.runtime.DisposableEffect
import cz.comgate.sdk.compose.*

val fullNameState = rememberSecureFullNameFieldState()

DisposableEffect(session) {
fullNameState.attachTo(session)
onDispose { fullNameState.detachFrom(session) }
}

SecureFullNameField(
state = fullNameState,
modifier = Modifier.fillMaxWidth()
)
Informácie

PaymentParams.fullName má vždy prednosť pred hodnotou zo SecureFullNameField — ak je fullName v PaymentParams vyplnený, pole SecureFullNameField nie je vyžadované. Ak je fullName prázdny, použije sa hodnota z pripojeného poľa. Ak sú prázdne obidve, platba zlyhá s chybou MISSING_CARDHOLDER_NAME.

Společné vlastnosťi​

Všechny Secure Fields (SecurePanField, SecureExpiryField, SecureCvvField, SecureFullNameField) sdílejí tieto vlastnosťi a metody:

Vlastnosť / MetódaTypPopis
isFieldValidBooleanAktuálny stav validácie poľa (read-only).
onValidationChanged(Boolean) -> UnitCallback volaný pri zmene validačného stavu.
showLabelBooleanZobrazenie labelu nad poľom. Predvolené true. Nastavte false na skrytie labelu.
labelTextString?Vlastný text labelu. Ak je null, použije sa predvolený preložený label podľa session.translation.
setHint(hint)StringNastaví placeholder text.
setEnabled(enabled)BooleanPovolí/zakáže pole.
clear()—Vymaže obsah poľa a resetuje validáciu.

Labely vstupných polí​

Každé pole má label nad vstupom (SecurePanField, SecureExpiryField, SecureCvvField, SecureFullNameField).

  • Predvolený text labelu se bere z session.translation
  • Label možno skryť cez showLabel = false
  • Predvolený preklad možno prepísať cez labelText
SecurePanField(
state = panState,
modifier = Modifier.fillMaxWidth(),
update = {
showLabel = true
labelText = "Číslo platební karty"
}
)

SecureCardDataCollector​

SecureCardDataCollector prepája tri samostatné Secure Fields a sleduje ich celkový validačný stav. Je vyžadovaný na spracovanie platby.

import cz.comgate.sdk.compose.*

// Stav polí — raw kartové údaje zostávajú vnútri SDK
val panState = rememberSecurePanFieldState()
val expiryState = rememberSecureExpiryFieldState()
val cvvState = rememberSecureCvvFieldState()

// Kolektor propojující pole a sledující celkovou validaci
val collector = rememberSecureDataCollector(
panState = panState,
expiryState = expiryState,
cvvState = cvvState,
onValidationChanged = { isValid ->
// isValid je true, keď sú všetky tri polia validné
}
)

Odovzdávanie focusu medzi poľami​

rememberSecureDataCollector v predvolenom stave automaticky odovzdáva focus medzi poľami v poradí:

PAN -> Expirácia -> CVV

K presunu dôjde vo chvíli, keď je aktuálne pole kompletne vyplnené a validné.

val collector = rememberSecureDataCollector(
panState = panState,
expiryState = expiryState,
cvvState = cvvState,
autoAdvanceFocus = true // vychozi hodnota
)

Ak chcete focus riadiť sami, vypnite automatiku:

val collector = rememberSecureDataCollector(
panState = panState,
expiryState = expiryState,
cvvState = cvvState,
autoAdvanceFocus = false
)

Pri implementácii pomocou Android View môžete odovzdávanie focusu zapojiť ručne cez nextSecureField:

panField.nextSecureField = expiryField
expiryField.nextSecureField = cvvField
Vlastnosť / MetódaTypPopis
isValidBooleantrue ak sú všetky tri polia validné.
onValidationChanged(Boolean) -> UnitCallback volaný pri zmene validačného stavu ktoréhokoľvek poľa.

SecurePayButton​

SecurePayButton je predpripravené platobné tlačidlo, ktoré sa automaticky integruje so session a kolektorom:

  • Automaticky sa aktivuje/deaktivuje podľa validačného stavu kartových polí
  • Tlačidlo zostane deaktivované, kým nie je session úspešne inicializovaná
  • Po kliknutí zahájí spracovania platby prostredníctvom ComgateSecureSession
  • Počas spracovania zobrazuje shimmer sweep animáciu cez tlačidlo (animáciu možno vypnúť)
  • Vracia výsledok platby cez callback

Nastavenie tlačidla​

Composable SecurePayButton prijíma parametre session, kolektora, callbacku a providera platobných parametrov:

import cz.comgate.sdk.compose.*

SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result ->
// Spracovanie výsledku platby
},
paymentParamsProvider = {
PaymentParams(
email = "zakaznik@example.com",
price = 100,
curr = "CZK",
label = "Názov platby",
refId = "ref-123",
fullName = "Jan Novák",
country = "CZ", // voliteľné
expirationTime = "1h", // voliteľné
billingAddrCity = "Hradec Králové", // voliteľné
billingAddrStreet = "Jiráskova 115", // voliteľné
billingAddrPostalCode = "50304", // voliteľné
billingAddrCountry = "CZ" // voliteľné
)
},
modifier = Modifier.fillMaxWidth()
)

Parameter paymentParamsProvider je lambda, ktorá je zavolaná v okamihu kliknutia na tlačidlo. Vďaka tomu možno dynamicky čítať aktuálne hodnoty z UI (napr. sumu z textového poľa).

PaymentParams​

ParameterTypPovinnýPopis
emailStringÁnoE-mailová adresa platiteľa.
priceIntÁnoSuma platby v halieroch/centoch (napr. 10000 = 100,00 CZK).
currStringÁnoKód meny — ISO 4217 (napr. "CZK", "EUR"). Viď PaymentParams.supportedCurrencies pre úplný zoznam.
labelStringÁnoKrátky popis produktu (1–16 znakov).
refIdStringAnoVariabilní symbol alebo číslo objednávky (vaše interní ID).
fullNameStringPodmieneneMeno a priezvisko platiteľa. Ak je neprázdny, má prednosť pred hodnotou zo SecureFullNameField. Ak je prázdny, použije sa hodnota z pripojeného SecureFullNameField (vtedy povinného). Ak sú prázdne obidve, platba zlyhá s chybou MISSING_CARDHOLDER_NAME.
countryStringNieKód krajiny podľa ISO 3166-1 alpha-2 (napr. "CZ", "SK"). Predvolené: "CZ". Akákoľvek hodnota mimo zoznamu je pred odoslaním normalizovaná na "ALL". Hodnota sa odovzdáva tiež do platobného dialógu Google Pay. Viď PaymentParams.supportedCountries pre úplný zoznam.
accountString?NieIdentifikátor bankového účtu klienta v systéme Comgate.
nameString?NieIdentifikátor produktu (zobrazí sa v dennom CSV ako „Produkt").
preauthBoolean?NieOznačí platbu ako predautorizáciu — rezervuje prostriedky na karte bez okamžitého stiahnutia. true — predautorizácia, null — predvolené správanie. Nemožno kombinovať s initRecurring = true.
initRecurringBoolean?NieOznačí platbu ako prvú v sérii opakovaných platieb. true — iniciačná platba. Nemožno kombinovať s preauth = true.
expirationTimeString?NeDoba expirace platby (napr. "30m", "3h", "5d"). Rozsah: 30 minut — 7 dní.
dynamicExpirationBoolean?NieDynamická expirácia platby (true na zapnutie).
billingAddrCityString?NieFakturačná adresa — mesto.
billingAddrStreetString?NieFakturačná adresa — ulica.
billingAddrPostalCodeString?NieFakturačná adresa — PSČ.
billingAddrCountryString?NieFakturačná adresa — kód krajiny (ISO 3166-1 alpha-2).
deliveryString?NieSpôsob doručenia ("HOME_DELIVERY", "PICKUP", "ELECTRONIC_DELIVERY").
homeDeliveryCityString?NieDoručovacia adresa — mesto (len pri delivery = "HOME_DELIVERY").
homeDeliveryStreetString?NeDoručovací adresa — ulice (jen pri delivery = "HOME_DELIVERY").
homeDeliveryPostalCodeString?NeDoručovací adresa — PSČ (jen pri delivery = "HOME_DELIVERY").
homeDeliveryCountryString?NieDoručovacia adresa — kód krajiny (len pri delivery = "HOME_DELIVERY").
categoryString?NieKategória produktu ("PHYSICAL_GOODS_ONLY", "OTHER").
require3dsBoolean?NieIba v dev režime (devMode = true). Vynucuje typ 3DS priebehu na testovacom serveri. true — vynúti priebeh s challenge, false — vynúti frictionless priebeh (bez challenge), null — server rozhodne sám. V produkcii ignorované.
errorReasonErrorReason?NieIba v dev režime (devMode = true). Simuluje konkrétny dôvod zamietnutia platby.

Podporované meny a krajiny​

Podporované meny (PaymentParams.supportedCurrencies)​

PaymentParams.supportedCurrencies vracía zoznam ISO 4217 kódov mien prijateľných platebná bránou Comgate. Tento zoznam možno využiť napríklad na naplnenie výberu meny v UI.

BGN, CHF, CZK, DKK, EUR, GBP, HUF, NOK, PLN, RON, SEK, USD

Podporované krajiny (PaymentParams.supportedCountries)​

PaymentParams.supportedCountries vracía zoznam ISO 3166-1 alpha-2 kódov krajín prijateľných pre parameter country. Hodnota "ALL" reprezentuje žiadne obmedzenie na konkrétnu krajinu. Akákoľvek iná hodnota mimo tohto zoznamu je serverom normalizovaná na "ALL".

ALL, AT, BE, CY, CZ, DE, EE, EL, ES, FI, FR, GB, HR, HU, IE, IT, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, US

Príklad použitia pre naplnenie výberu meny a krajiny​

// Dostupné meny pre výber v UI
val currencies = PaymentParams.supportedCurrencies // ["BGN", "CHF", "CZK", ...]

// Dostupné krajiny pre výber v UI
val countries = PaymentParams.supportedCountries // ["ALL", "AT", "BE", "CY", "CZ", ...]

PaymentParams(
email = "zakaznik@example.com",
price = 10000,
curr = selectedCurrency, // hodnota z výberu
country = selectedCountry, // hodnota z výberu
label = "Objednávka",
refId = "order-123",
fullName = "Ján Novák"
)

Opakované platby a predautorizácia​

initRecurring​

Parameter initRecurring = true označí platbu ako prvú (iniciačnú) transakciu v sérii opakovaných platieb. Banka tým dostane signál, že v budúcnosti budú prebiehať ďalšie automatické platby (napr. predplatné, pravidelné poplatky).

PaymentParams(
email = "zakaznik@example.com",
price = 9900,
curr = "CZK",
label = "Předplatné — první platba",
refId = "sub-001",
fullName = "Jan Novák",
initRecurring = true // Tato platba zahájí sérii opakovaných plateb
)
Informácie

Parameter initRecurring nemožno kombinovať s preauth = true.

preauth​

Parameter preauth = true označí platbu ako predautorizáciu — banka dočasne rezervuje požadovanú sumu na karte platiteľa, ale prostriedky nie sú ihneď stiahnuté. K zachyteniu (stiahnutiu) dochádza až pri potvrdení transakcie na strane backendu.

Predautorizácia sa typicky využíva v situáciách, kde konečná výška platby nie je v čase autorizácie ešte jasná (napr. požičovne, hotely, tankovanie).

PaymentParams(
email = "zakaznik@example.com",
price = 50000,
curr = "CZK",
label = "Rezervace vozidla",
refId = "reservation-42",
fullName = "Jan Novák",
preauth = true // Rezervace prostředků bez okamžitého stržení
)
Informácie

Parameter preauth nemožno kombinovať s initRecurring = true.

Stylovaní tlačidla​

Voliteľný update blok umožňuje programovo štylizovať tlačidlo pri každej rekompozícii. Dostupné metódy sú popísané v sekcii Štylizácia komponentov.

import cz.comgate.sdk.compose.*

// Stav polí a kolektoru
val panState = rememberSecurePanFieldState()
val expiryState = rememberSecureExpiryFieldState()
val cvvState = rememberSecureCvvFieldState()
val collector = rememberSecureDataCollector(panState, expiryState, cvvState)

// Platobné tlačidlo
SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result -> handleResult(result) },
paymentParamsProvider = {
PaymentParams(
price = 10000, curr = "CZK",
label = "Objednávka", refId = "ref-1", fullName = "Jan Novák"
)
},
modifier = Modifier.fillMaxWidth(),
update = {
// Voliteľná programová štylizácia — viď sekcia Štylizácia
setText("Zaplatit")
setButtonBackgroundColor(Color.parseColor("#1E88E5"))
setButtonTextColor(Color.WHITE)
setButtonCornerRadius(12f * resources.displayMetrics.density)
setDisabledBackgroundColor(Color.parseColor("#CFD8DC"))
setDisabledTextColor(Color.parseColor("#78909C"))
setLoadingAnimationEnabled(true)
}
)

Vlastné tlačidlo a priame volanie processPayment​

Ak vám predpripravené SecurePayButton nevyhovuje (napr. chcete vlastný dizajn, animácie alebo zložitejšiu logiku), môžete platbu spustiť priamo volaním metódy session.processPayment() na inštancii ComgateSecureSession.

Tip

Metóda processPayment šifruje kartové údaje, odosiela ich na platobnú bránu a v prípade potreby automaticky vykoná 3D Secure autentizáciu. Citlivé údaje nikdy neopustia knižnicu v nechránenej podobe.

Signatúra metódy​

suspend fun processPayment(
activity: Activity,
collector: SecureCardDataCollector,
params: PaymentParams
): PaymentResult
ParameterTypPopis
activityActivityAktuálna aktivita — nutná na zobrazenie 3DS challenge UI.
collectorSecureCardDataCollectorKolektor prepájajúci Secure Fields (PAN, expirácia, CVV).
paramsPaymentParamsParametre platby (cena, mena, popis, refId, meno platiteľa a i.).

Príklad implementácie​

class PaymentActivity : AppCompatActivity() {

private lateinit var session: ComgateSecureSession

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Inicializace session
session = ComgateSecureSession(
checkoutId = "váš-checkout-id",
context = applicationContext,
threeDSConfig = ThreeDSConfig(),
lifecycleOwner = this,
onInitialized = { result ->
result.onFailure { e ->
Toast.makeText(this, "Chyba inicializace: ${e.message}", Toast.LENGTH_LONG).show()
}
}
)

setContent {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
CustomPaymentScreen(session)
}
}
}
}
}

@Composable
private fun CustomPaymentScreen(session: ComgateSecureSession) {
val activity = LocalContext.current as Activity
var isProcessing by remember { mutableStateOf(false) }
var isFormValid by remember { mutableStateOf(false) }

val panState = rememberSecurePanFieldState()
val expiryState = rememberSecureExpiryFieldState()
val cvvState = rememberSecureCvvFieldState()
val statusState = rememberPaymentStatusState()

val collector = rememberSecureDataCollector(
panState = panState,
expiryState = expiryState,
cvvState = cvvState,
onValidationChanged = { isValid ->
isFormValid = isValid
}
)

val scope = rememberCoroutineScope()

Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
SecurePanField(state = panState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(8.dp))
SecureExpiryField(state = expiryState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(8.dp))
SecureCvvField(state = cvvState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(16.dp))

// Vlastné tlačidlo — priame volanie processPayment
Button(
onClick = {
if (!isProcessing) {
isProcessing = true
scope.launch {
val result = session.processPayment(
activity = activity,
collector = collector,
params = PaymentParams(
email = "zakaznik@example.com",
price = 100,
curr = "CZK",
label = "Objednávka #123",
refId = "order-123",
fullName = "Jan Novák"
)
)
isProcessing = false
statusState.showStatus(result)

when (result) {
is PaymentResult.Paid -> { /* Platba úspěšná */ }
is PaymentResult.Authorized -> { /* Platba autorizovaná (predautorizácia) */ }
is PaymentResult.Pending -> { /* Platba se zpracovává */ }
is PaymentResult.Cancelled -> { /* Platba zrušená / zamietnutá */ }
is PaymentResult.Failed -> { /* Chyba knižnice */ }
}
}
}
},
enabled = isFormValid && !isProcessing,
modifier = Modifier.fillMaxWidth()
) {
Text(if (isProcessing) "Zpracování..." else "Zaplatit")
}

SecurePaymentStatusView(
state = statusState,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp)
)
}
}
Upozornenie

Pred volaním processPayment sa uistite, že:

  1. Session je úspešne inicializovaná (callback onInitialized vrátil Result.success).
  2. Kartové údaje sú validné (collector.isValid == true).

Ak tieto podmienky nie sú splnené, metóda okamžite vráti PaymentResult.Cancelled.

Spôsoby implementácie​

Knižnica podporuje implementáciu pomocou troch samostatných komponentov (SecurePanField, SecureExpiryField, SecureCvvField) prepojených cez SecureCardDataCollector.

Samostatné polia​

Každé pole je umiestnené nezávisle v Compose layoute. Tento prístup poskytuje plnú kontrolu nad rozložením a štylizáciou.

class PaymentActivity : AppCompatActivity() {

private lateinit var session: ComgateSecureSession

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

session = ComgateSecureSession(/* ... */)

setContent {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
PaymentScreen(session)
}
}
}
}
}

@Composable
private fun PaymentScreen(session: ComgateSecureSession) {
val panState = rememberSecurePanFieldState()
val expiryState = rememberSecureExpiryFieldState()
val cvvState = rememberSecureCvvFieldState()
val statusState = rememberPaymentStatusState()

val collector = rememberSecureDataCollector(panState, expiryState, cvvState)

Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
SecurePanField(state = panState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(8.dp))
SecureExpiryField(state = expiryState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(8.dp))
SecureCvvField(state = cvvState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(16.dp))

SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result ->
when (result) {
is PaymentResult.Paid -> statusState.showStatus(result)
is PaymentResult.Authorized -> statusState.showStatus(result)
is PaymentResult.Pending -> statusState.showStatus(result)
is PaymentResult.Cancelled -> statusState.showStatus(result)
is PaymentResult.Failed -> statusState.showStatus(result)
}
},
paymentParamsProvider = {
PaymentParams(
email = "zakaznik@example.com",
price = 100,
curr = "CZK",
label = "Testovací platba",
refId = "ref-123",
fullName = "Jan Novák",
country = "CZ", // voliteľné
expirationTime = "1h" // voliteľné
)
},
modifier = Modifier.fillMaxWidth()
)

SecurePaymentStatusView(
state = statusState,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp)
)
}
}

3D Secure​

Knižnica poskytuje kompletní podporu 3D Secure autentifikácie. Ak je 3DS nakonfigurováno, knižnica automaticky:

  1. Pripraví autentizačné parametre pri spracovaní platby
  2. Vyhodnotí odpoveď servera (frictionless / challenge)
  3. V prípade potreby zobrazí challenge obrazovku
  4. Vrátí výsledek autentifikácie prostredníctvom PaymentResult

Konfigurácia​

3DS sa konfiguruje prostredníctvom triedy ThreeDSConfig, ktorá sa odovzdáva do konštruktora ComgateSecureSession:

val threeDSConfig = ThreeDSConfig(
uiCustomization = threeDSUi, // Přizpůsobení vzhledu (volitelné)
challengeTimeoutMinutes = 5, // Timeout pro challenge (predvolené: 5)
defaultMessageVersion = "2.2.0", // Verze 3DS protokolu (predvolené: "2.2.0")
challengeWindowCornerRadiusDp = 16 // Zaoblení rohů challenge okna (volitelné)
)

val session = ComgateSecureSession(
checkoutId = "váš-checkout-id",
context = applicationContext,
threeDSConfig = threeDSConfig,
lifecycleOwner = this
)
Použitie vo Fragmente

Parameter lifecycleOwner riadi, kedy session automaticky uvoľní prostriedky. Vo vyššie uvedených príkladoch sa odovzdáva this (aktivita).

Ak session vytvárate vnútri Fragmentu, odovzdajte viewLifecycleOwner (dostupný od onViewCreated):

  • Activity: lifecycleOwner = this
  • Fragment: lifecycleOwner = viewLifecycleOwner (nie this — Fragment prežíva opätovné vytvorenie view a spôsobilo by memory leak)

Parametre ThreeDSConfig​

ParameterTypPredvolenéPopis
uiCustomizationThreeDSUiCustomization?nullPrispôsobenie vzhľadu challenge obrazovky. Ak je null, použijú sa predvolené štýly.
defaultMessageVersionString"2.2.0"Verzia 3DS protokolu.
challengeTimeoutMinutesInt5Maximálny čas čakania na dokončenie challenge v minútach (1–30).
challengeWindowCornerRadiusDpInt?nullZaoblenie rohov challenge okna v dp. Ak je null, použije sa predvolená hodnota z motívu.

Prispôsobenie vzhľadu challenge obrazovky​

Trieda ThreeDSUiCustomization umožňuje detailné prispôsobenie vzhľadu 3DS challenge obrazovky:

val threeDSUi = ThreeDSUiCustomization(
buttons = mapOf(
ThreeDSButtonType.SUBMIT to ThreeDSButtonStyle(
backgroundColor = "#4287f5",
cornerRadius = 48,
textColor = "#FFFFFF",
textFontSize = 16
),
ThreeDSButtonType.CONTINUE to ThreeDSButtonStyle(
backgroundColor = "#4287f5",
cornerRadius = 48,
textColor = "#FFFFFF",
textFontSize = 16
),
ThreeDSButtonType.RESEND to ThreeDSButtonStyle(
backgroundColor = "#F0F0F0",
cornerRadius = 48,
textColor = "#4287f5",
textFontSize = 16
)
),
labelStyle = ThreeDSLabelStyle(
headingTextColor = "#4287f5",
textColor = "#333333"
),
textBoxStyle = ThreeDSTextBoxStyle(
cornerRadius = 16,
borderColor = "#4287f5",
textColor = "#333333",
borderWidth = 4
),
toolbarStyle = ThreeDSToolbarStyle(
buttonText = "Zrušit",
headerText = "Ověření platby",
backgroundColor = "#F0F0F0",
textColor = "#333333"
)
)

ThreeDSButtonStyle​

Prispôsobenie tlačidiel na challenge obrazovke.

ParameterTypPopis
backgroundColorString?Farba pozadí ve formátu #RRGGBB alebo #AARRGGBB.
cornerRadiusInt?Zaoblenie rohov tlačidla v dp.
textColorString?Farba textu ve formátu #RRGGBB alebo #AARRGGBB.
textFontSizeInt?Veľkosť písma v sp (8–48).

Tlačidlá sa konfigurujú v mape podľa typu:

Typ tlačidlaPopis
ThreeDSButtonType.SUBMITTlačidlo na odoslanie (potvrdenie).
ThreeDSButtonType.CONTINUETlačidlo na pokračovanie.
ThreeDSButtonType.NEXTTlačidlo na ďalší krok.
ThreeDSButtonType.CANCELTlačidlo na zrušenie.
ThreeDSButtonType.RESENDTlačidlo na opätovné odoslanie kódu.

ThreeDSLabelStyle​

Prispôsobenie textových popiskov.

ParameterTypPopis
headingTextColorString?Farba nadpisu.
headingTextFontSizeInt?Veľkosť nadpisu v sp (8–48).
textColorString?Farba bežného textu.
textFontSizeInt?Veľkosť bežného textu v sp (8–48).

ThreeDSTextBoxStyle​

Prispôsobenie vstupných polí na challenge obrazovke.

ParameterTypPopis
borderWidthInt?Šírka orámovania v dp (0–10).
borderColorString?Farba orámovania.
cornerRadiusInt?Zaoblenie rohov v dp.
textColorString?Farba textu.
textFontSizeInt?Veľkosť textu v sp (8–48).

ThreeDSToolbarStyle​

Prispôsobenie toolbaru challenge obrazovky.

ParameterTypPopis
backgroundColorString?Farba pozadí toolbaru.
headerTextString?Text v hlavičke toolbaru.
buttonTextString?Text tlačidla v toolbaru (typicky „Zrušit").
textColorString?Farba textu.
textFontSizeInt?Veľkosť textu v sp (8–48).
Informácie

Farby sa zadávajú ako reťazce vo formáte #RRGGBB alebo #AARRGGBB. Neplatné formáty sú v runtime ignorované a použijú sa predvolené hodnoty.

Motívy challenge okna​

Knižnica obsahuje štyri preddefinované motívy na zobrazenie challenge obrazovky:

MotívPopis
ComgateSdkSvetlý dialóg (90 % šírky obrazovky, centrovaný) — predvolené
ComgateSdk.DarkTmavý dialóg
Theme.SecureFields.3DS.FullScreenSvetlý celoobrazovkový režim
Theme.SecureFields.3DS.FullScreen.DarkTmavý celoobrazovkový režim

Na prepnutie motívu stačí pridať do res/values/styles.xml vašej aplikácie prepis štýlu Theme.SecureFields.3DS.Challenge:

<!-- res/values/styles.xml -->
<style name="Theme.SecureFields.3DS.Challenge"
parent="Theme.SecureFields.3DS.FullScreen" />
Tip

Zaoblenie rohov dialógového okna možno prispôsobiť definovaním dimenzie securefields_3ds_dialog_corner_radius v resources vašej aplikácie:

<!-- res/values/dimens.xml -->
<dimen name="securefields_3ds_dialog_corner_radius">16dp</dimen>

Alternatívne možno zaoblenie nastaviť programovo cez parameter challengeWindowCornerRadiusDp v ThreeDSConfig.

Testovanie 3DS platieb​

Na uľahčenie vývoja a testovania ponúka knižnica v dev režime (devMode = true) možnosť simulovať rôzne priebehy 3DS autentifikácie bez nutnosti použiť skutočnú bankovú kartu.

Testovacie správanie sa riadi parametrom require3ds v PaymentParams:

Hodnota require3dsPriebeh platby
trueServer vráti challenge — zobrazí sa 3DS challenge obrazovka, používateľ musí zadať OTP alebo vykonať overenie.
falseServer vráti frictionless výsledok — platba prebehne bez zobrazenia challenge obrazovky.
null (predvolené)Server rozhodne sám; v produkci standardní chování.
Upozornenie

Parameter require3ds je funkčný výhradne v dev režime (devMode = true). V produkcii (devMode = false) je hodnota tohto parametra ignorovaná a platba prebehne štandardným spôsobom.

Simulácia 3DS challenge​

Nastavte require3ds = true. Knižnica zobrazí 3DS challenge obrazovku, kde používateľ vykoná overenie. Výsledok platby bude závisieť od akcie používateľa:

  • Dokončenie overenia → PaymentResult.Paid
  • Zrušenie challenge → PaymentResult.Failed(ComgateError.ThreeDSChallengeCancelled)
  • Vypršanie časového limitu → PaymentResult.Failed(ComgateError.ThreeDSChallengeTimeout)
SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result -> /* ... */ },
paymentParamsProvider = {
PaymentParams(
email = "zakaznik@example.com",
price = 100,
curr = "CZK",
label = "Testovací platba",
refId = "test-001",
fullName = "Jan Novák",
require3ds = true // Vynutí 3DS challenge průběh — iba devMode
)
},
modifier = Modifier.fillMaxWidth()
)

Simulácia frictionless priebehu​

Nastavte require3ds = false. Platba prebehne bez zobrazenia challenge obrazovky — autentifikácia je vyhodnotená serverom v pozadí. Výsledkom je PaymentResult.Paid, ak platba prebehne úspešne.

SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result -> /* ... */ },
paymentParamsProvider = {
PaymentParams(
email = "zakaznik@example.com",
price = 100,
curr = "CZK",
label = "Testovací platba",
refId = "test-001",
fullName = "Jan Novák",
require3ds = false // Frictionless průběh bez challenge — iba devMode
)
},
modifier = Modifier.fillMaxWidth()
)

Simulácia chybového dôvodu — ErrorReason​

V dev režime (devMode = true) možno pomocou parametra errorReason v PaymentParams simulovať konkrétny dôvod zamietnutia alebo zlyhania platby. Táto možnosť umožňuje testovať, ako aplikácia reaguje na rôzne chybové scenáre bez nutnosti skutočnej bankovej karty.

import cz.comgate.sdk.ErrorReason

SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result -> /* ... */ },
paymentParamsProvider = {
PaymentParams(
price = 100,
curr = "CZK",
label = "Testovací platba",
refId = "test-001",
fullName = "Jan Novák",
errorReason = ErrorReason.NO_FUNDS // Simulace nedostatku prostředků — iba devMode
)
},
modifier = Modifier.fillMaxWidth()
)
Upozornenie

Parameter errorReason je funkčný výhradne v dev režime (devMode = true). Hodnota (vrátane null) je vždy odovzdaná serveru, ak bežíte v dev móde. V produkcii je tento parameter úplne ignorovaný.

Dostupné hodnoty výčtu ErrorReason:

HodnotaPopis
CUSTOMER_CLICKZrušené platiteľom.
FRAUD_SUSPECTEDPodozrenie na podvod.
ESHOP_CANCELLEDZrušené obchodníkom.
PROVIDER_REPORTZrušené providerom.
PROVIDER_TIMEOUTVypršal časový limit poskytovateľa.
CUSTOMER_TIMEOUTVypršal časový limit platby.
ACS_TIMEOUTVypršal časový limit na overenie.
INVALID_CARDNO_EXPIRYNesprávne zadané číslo karty alebo dátum platnosti karty.
INVALID_CVCNesprávne zadaný CVC / CVV kód.
LIMIT_EXCEEDEDLimit karty bol prekročený.
NO_FUNDSNa účte nie je dostatočný zostatok.
REJECTED_BY_BANKPlatba bola zamietnutá bankou.
3DS_AUTH_FAILOverenie 3DS nebolo úspešné.
NOT_SPECIFIEDNešpecifikované.

Kompletný príklad​

Nasledujúci príklad ukazuje kompletnú implementáciu kartovej platby s 3D Secure od inicializácie po spracovanie výsledku:

class PaymentActivity : AppCompatActivity() {

private lateinit var session: ComgateSecureSession

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// 1. Konfigurácia 3DS
val threeDSConfig = ThreeDSConfig(
uiCustomization = ThreeDSUiCustomization(
toolbarStyle = ThreeDSToolbarStyle(
buttonText = "Zrušit",
headerText = "Ověření platby"
)
),
challengeTimeoutMinutes = 5
)

// 2. Vytvorenie session
session = ComgateSecureSession(
checkoutId = "váš-checkout-id",
context = applicationContext,
threeDSConfig = threeDSConfig,
lifecycleOwner = this,
onInitialized = { result ->
result.onSuccess {
// Session je pripravená
}.onFailure { e ->
Toast.makeText(this, "Chyba inicializace: ${e.message}", Toast.LENGTH_LONG).show()
}
}
)

// 3. Nastavenie Compose UI
setContent {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
PaymentScreen(session)
}
}
}
}
}

@Composable
private fun PaymentScreen(session: ComgateSecureSession) {
// 4. Stav polí — raw kartové údaje zostávajú vnútri SDK
val panState = rememberSecurePanFieldState()
val expiryState = rememberSecureExpiryFieldState()
val cvvState = rememberSecureCvvFieldState()
val statusState = rememberPaymentStatusState()
var cardInfo by remember { mutableStateOf("Vyplňte údaje karty") }

// Kolektor sleduje validáciu všetkých troch polí
val collector = rememberSecureDataCollector(
panState = panState,
expiryState = expiryState,
cvvState = cvvState,
onValidationChanged = { isValid ->
cardInfo = if (isValid) "✓ Karta končící na ${panState.last4}" else "Vyplňte údaje karty"
}
)

Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
.verticalScroll(rememberScrollState())
) {
Text(text = cardInfo, modifier = Modifier.padding(bottom = 8.dp))

// 5. Kartové polia
SecurePanField(state = panState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(8.dp))
SecureExpiryField(state = expiryState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(8.dp))
SecureCvvField(state = cvvState, modifier = Modifier.fillMaxWidth())
Spacer(modifier = Modifier.height(16.dp))

// 6. Platobné tlačidlo
SecurePayButton(
session = session,
collector = collector,
onPaymentResult = { result ->
when (result) {
is PaymentResult.Paid -> {
statusState.showStatus(result)
// Platba úspešná
}
is PaymentResult.Authorized -> {
statusState.showStatus(result)
// Platba autorizovaná — čaká na zachytenie
}
is PaymentResult.Pending -> {
statusState.showStatus(result)
// Platba sa spracováva
}
is PaymentResult.Cancelled -> {
statusState.showStatus(result)
}
is PaymentResult.Failed -> {
statusState.showStatus(result)
}
}
},
paymentParamsProvider = {
PaymentParams(
email = "zakaznik@example.com",
price = 100,
curr = "CZK",
label = "Objednávka #123",
refId = "order-123",
fullName = "Jan Novák",
country = "CZ", // voliteľné
expirationTime = "1h", // voliteľné
billingAddrCity = "Hradec Králové", // voliteľné
billingAddrStreet = "Jiráskova 115", // voliteľné
billingAddrPostalCode = "50304", // voliteľné
billingAddrCountry = "CZ" // voliteľné
)
},
modifier = Modifier.fillMaxWidth()
)

// Stavový banner
SecurePaymentStatusView(
state = statusState,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp)
)
}
}