Údaje karty
Kartové platby prebiehajú prostredníctvom zabezpečených vstupných komponentov — Secure Fields. Tieto komponenty zabezpečujú bezpečné zadávanie, validáciu a ochranu údajov karty. 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 deteguje kartovú sieť (Visa, Mastercard)
- Formátuje číslo karty s medzerami podľa kartovej siete (napr.
4111 1111 1111 1111) - Obmedzuje dĺžku vstupu podľa detegovanej kartovej siete
- Validuje číslo karty pomocou Luhnovho algoritmu
- Sprístupňuje vlastnosť
last4— posledné 4 číslice karty (bezpečné na zobrazenie v UI)
import SwiftUI
import ComgateSDK
@StateObject private var panState = SecurePanFieldState()
var body: some View {
SecurePanField(state: panState)
}
SecureExpiryField
Pole na zadanie dátumu exspirácie karty.
- Prijíma iba číslice
- Automaticky formátuje vstup v tvare MM/RR
- Validuje mesiac (1–12) a kontroluje, či karta nie je po platnosti
@StateObject private var expiryState = SecureExpiryFieldState()
SecureExpiryField(state: expiryState)
SecureCvvField
Pole na zadanie bezpečnostného kódu karty (CVV/CVC).
- Prijíma iba číslice
- Dĺžka je 3 číslice
- Validuje minimálnu požadovanú dĺžku
@StateObject private var cvvState = SecureCvvFieldState()
SecureCvvField(state: cvvState)
SecureFullNameField
Pole na zadanie mena a priezviska platiteľa.
- Prijíma textový vstup (vrátane medzier)
- Je platné pri neprázdnej hodnote
- Po pripojení k
ComgateSecureSessionsa jeho hodnota automaticky použije akofullName
@StateObject private var fullNameState = SecureFullNameFieldState()
SecureFullNameField(state: fullNameState)
.onAppear { fullNameState.attachTo(session) }
.onDisappear { fullNameState.detachFrom(session) }
PaymentParams.fullName má vždy prednosť pred hodnotou z 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 je prázdne oboje, platba zlyhá s chybou MISSING_CARDHOLDER_NAME.
Spoločné vlastnosti
Všetky stavy Secure Fields (SecurePanFieldState, SecureExpiryFieldState, SecureCvvFieldState, SecureFullNameFieldState) zdieľajú tieto vlastnosti a metódy:
| Vlastnosť / Metóda | Typ | Popis |
|---|---|---|
isValid | Bool | Aktuálny stav validácie poľa (read-only, @Published). |
errorText | String? | Aktuálna chybová správa — lokalizovaná podľa translation. |
translation | Translation | Preklady použité pre placeholder a chybové správy. Nastavte na session.translation pre zhodu so session. |
onFieldError | ((String?) -> Void)? | Callback volaný pri zmene chybového stavu. |
clear() | — | Vymaže obsah poľa a resetuje validáciu. |
requestFocus() | @discardableResult Bool | Programovo zaostrí pole. |
Označenia vstupných polí
Každé pole má označenie nad vstupom. Predvolený text označenia sa berie z translation. Pre vlastné označenie nastavte zodpovedajúci kľúč v Translation:
panState.translation = Translation(panLabel: "Číslo platobnej karty")
SecureCardDataCollector
SecureCardDataCollector prepája tri samostatné Secure Fields a sleduje ich celkový validačný stav. Je vyžadovaný na spracovanie platby. Vytvorte ho raz pomocou factory funkcie secureCardDataCollector(pan:expiry:cvv:) a uchovajte v @StateObject ObservableObject obale, aby prežil rerendery view:
@MainActor
final class CollectorHolder: ObservableObject {
let collector: SecureCardDataCollector
init(pan: SecurePanFieldState, expiry: SecureExpiryFieldState, cvv: SecureCvvFieldState) {
self.collector = secureCardDataCollector(pan: pan, expiry: expiry, cvv: cvv)
}
}
struct PaymentForm: View {
@StateObject private var panState: SecurePanFieldState
@StateObject private var expiryState: SecureExpiryFieldState
@StateObject private var cvvState: SecureCvvFieldState
@StateObject private var holder: CollectorHolder
init() {
let pan = SecurePanFieldState()
let expiry = SecureExpiryFieldState()
let cvv = SecureCvvFieldState()
_panState = StateObject(wrappedValue: pan)
_expiryState = StateObject(wrappedValue: expiry)
_cvvState = StateObject(wrappedValue: cvv)
_holder = StateObject(wrappedValue: CollectorHolder(pan: pan, expiry: expiry, cvv: cvv))
}
private var collector: SecureCardDataCollector { holder.collector }
}
Nepoužívajte var collector: SecureCardDataCollector { secureCardDataCollector(...) } ako computed property — vytváral by nový collector pri každom renderi, čím by sa stratil focus advance aj validačný stav.
| Vlastnosť / Metóda | Typ | Popis |
|---|---|---|
isValid | Bool | true ak sú všetky tri polia platné. |
autoAdvanceFocus | Bool | Zapne/vypne automatický presun fokusu medzi poľami (PAN → Exspirácia → CVV). Predvolene: true. |
onValidationChanged | ((Bool) -> Void)? | Callback volaný pri zmene validačného stavu ktoréhokoľvek poľa. |
Posun fokusu medzi poľami
Kolektor v predvolenom stave automaticky presúva fokus medzi poľami v poradí:
PAN → Exspirácia → CVV
K presunu dôjde vo chvíli, keď je aktuálne pole kompletne vyplnené a platné. Ak chcete fokus riadiť sami, vypnite automatiku:
let collector = secureCardDataCollector(pan: panState, expiry: expiryState, cvv: cvvState)
collector.autoAdvanceFocus = false
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 polí karty
- Tlačidlo zostane deaktivované, kým nie je session úspešne inicializovaná (
session.state == .ready) - Po kliknutí spustí spracovanie platby prostredn íctvom
ComgateSecureSession - Počas spracovania zobrazuje shimmer animáciu (možno vypnúť v
PayButtonStyle) - Vracia výsledok platby cez
onResultcallback
Nastavenie tlačidla
SecurePayButton(
session: session,
collector: collector,
paymentParams: {
try! PaymentParams(
email: "zakaznik@example.com",
price: 100,
curr: "EUR",
country: "SK",
label: "Názov platby",
refId: "ref-123",
fullName: "Ján Novák",
billingAddrCity: "Bratislava",
billingAddrStreet: "Hlavná 10",
billingAddrPostalCode: "81101",
billingAddrCountry: "SK"
)
},
onResult: { result in
// Spracovanie výsledku platby
}
)
Parameter paymentParams je closure, 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
| Parameter | Typ | Povinný | Popis |
|---|---|---|---|
email | String | Áno | E-mailová adresa platiteľa. |
price | Int | Áno | Suma platby v centoch (napr. 10000 = 100,00 EUR). Musí byť kladné celé číslo. |
curr | String | Áno | Kód meny — ISO 4217 (napr. "EUR", "CZK"). Pozri PaymentParams.supportedCurrencies pre úplný zoznam. |
label | String | Áno | Krátky popis produktu (1–16 znakov). |
refId | String | Áno | Variabilný symbol alebo číslo objednávky (vaše interné ID). |
fullName | String | Podmienečne | Meno a priezvisko platiteľa. Ak je neprázdny, má prednosť pred hodnotou z SecureFullNameField. |
country | String | Nie | Kód krajiny podľa ISO 3166-1 alpha-2 (napr. "SK", "CZ"). Predvolene: "CZ". |
account | String? | Nie | Identifikátor bankového účtu klienta v systéme Comgate. |
name | String? | Nie | Identifikátor produktu (zobrazí sa v dennom CSV ako „Produkt"). |
preauth | Bool? | Nie | Označí platbu ako predautorizáciu. Nemožno kombinovať s initRecurring = true. |
initRecurring | Bool? | Nie | Označí platbu ako prvú v sérii opakovaných platieb. Nemožno kombinovať s preauth = true. |
billingAddrCity | String? | Nie | Fakturačná adresa — mesto. |
billingAddrStreet | String? | Nie | Fakturačná adresa — ulica. |
billingAddrPostalCode | String? | Nie | Fakturačná adresa — PSČ. |
billingAddrCountry | String? | Nie | Fakturačná adresa — kód krajiny (ISO 3166-1 alpha-2). |
delivery | String? | Nie | Spôsob doručenia ("HOME_DELIVERY", "PICKUP", "ELECTRONIC_DELIVERY"). |
homeDeliveryCity | String? | Nie | Doručovacia adresa — mesto (iba pri delivery = "HOME_DELIVERY"). |
homeDeliveryStreet | String? | Nie | Doručovacia adresa — ulica (iba pri delivery = "HOME_DELIVERY"). |
homeDeliveryPostalCode | String? | Nie | Doručovacia adresa — PSČ (iba pri delivery = "HOME_DELIVERY"). |
homeDeliveryCountry | String? | Nie | Doručovacia adresa — kód krajiny (iba pri delivery = "HOME_DELIVERY"). |
category | String? | Nie | Kategória produktu ("PHYSICAL_GOODS_ONLY", "OTHER"). |
require3ds | Bool? | Nie | Iba v dev režime (devMode = true). Vynucuje typ 3DS priebehu. V produkcii ignorované. |
errorReason | ErrorReason? | Nie | Iba v dev režime. Simuluje konkrétny dôvod zamietnutia. V produkcii ignorované. Pozri ErrorReason. |
Konštruktor PaymentParams vyhodí ComgateError.invalidPrice, ak nie je price kladné celé číslo, alebo ComgateError.conflictingPaymentOptions pri kombinácii initRecurring = true a preauth = true.
Podporované meny a krajiny
Podporované meny (PaymentParams.supportedCurrencies)
PaymentParams.supportedCurrencies vracia zoznam ISO 4217 kódov mien prijímaných platobnou bránou Comgate.
BGN, CHF, CZK, DKK, EUR, GBP, HUF, NOK, PLN, RON, SEK, USD
Podporované krajiny (PaymentParams.supportedCountries)
PaymentParams.supportedCountries vracia zoznam ISO 3166-1 alpha-2 kódov krajín prijímaných pre parameter country. Hodnota "ALL" predstavuje žiadne obmedzenie na konkrétnu krajinu.
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 naplnenia výberu meny a krajiny
let currencies = PaymentParams.supportedCurrencies
let countries = PaymentParams.supportedCountries
let params = try PaymentParams(
email: "zakaznik@example.com",
price: 10000,
curr: selectedCurrency,
country: selectedCountry,
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).
let params = try PaymentParams(
email: "zakaznik@example.com",
price: 9900,
curr: "EUR",
label: "Predplatné",
refId: "sub-001",
fullName: "Ján Novák",
initRecurring: true
)
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é.
let params = try PaymentParams(
email: "zakaznik@example.com",
price: 50000,
curr: "EUR",
label: "Rezervácia",
refId: "reservation-42",
fullName: "Ján Novák",
preauth: true
)
Parameter preauth nemožno kombinovať s initRecurring = true.
Vlastné tlačidlo a priame volanie processPayment
Ak vám predpripravené SecurePayButton nevyhovuje, môžete platbu spustiť priamo volaním metódy session.processPayment().
Metóda processPayment šifruje údaje karty, odosiela ich na platobnú bránu a v prípade potreby automaticky vykoná 3D Secure autentifikáciu. Citlivé údaje nikdy neopustia knižnicu v nechránenej podobe.
Signatúra metódy
public func processPayment(
collector: SecureCardDataCollector,
params: PaymentParams,
presenter: UIViewController? = nil
) async -> PaymentResult
| Parameter | Typ | Popis |
|---|---|---|
collector | SecureCardDataCollector | Kolektor prepájajúci Secure Fields (PAN, exspirácia, CVV). |
params | PaymentParams | Parametre platby. |
presenter | UIViewController? | Voliteľný presenter pre 3DS challenge UI. Ak nil, knižnica použije aktuálny top view controller. |
Príklad implementácie
struct CustomPaymentScreen: View {
@ObservedObject var session: ComgateSecureSession
@StateObject private var panState: SecurePanFieldState
@StateObject private var expiryState: SecureExpiryFieldState
@StateObject private var cvvState: SecureCvvFieldState
@StateObject private var holder: CollectorHolder
@State private var isProcessing = false
@State private var resultText = ""
init(session: ComgateSecureSession) {
self._session = ObservedObject(wrappedValue: session)
let pan = SecurePanFieldState()
let expiry = SecureExpiryFieldState()
let cvv = SecureCvvFieldState()
_panState = StateObject(wrappedValue: pan)
_expiryState = StateObject(wrappedValue: expiry)
_cvvState = StateObject(wrappedValue: cvv)
_holder = StateObject(wrappedValue: CollectorHolder(pan: pan, expiry: expiry, cvv: cvv))
}
private var collector: SecureCardDataCollector { holder.collector }
var body: some View {
VStack(spacing: 12) {
SecurePanField(state: panState)
SecureExpiryField(state: expiryState)
SecureCvvField(state: cvvState)
Button(isProcessing ? "Spracovávam…" : "Zaplatiť") {
Task {
isProcessing = true
let params = try! PaymentParams(
email: "zakaznik@example.com",
price: 100,
curr: "EUR",
country: "SK",
label: "Objednávka #123",
refId: "order-123",
fullName: "Ján Novák"
)
let result = await session.processPayment(collector: collector, params: params)
isProcessing = false
switch result {
case .paid(let t): resultText = "Zaplatené (\(t))"
case .authorized(let t): resultText = "Autorizované (\(t))"
case .pending(let t): resultText = "Čaká (\(t))"
case .cancelled(let reason, _): resultText = "Zrušené: \(reason ?? "-")"
case .failed(let err): resultText = "Chyba: \(err.message)"
}
}
}
.disabled(!collector.isValid || isProcessing || session.state != .ready)
Text(resultText)
}
.padding()
}
}
Pred volaním processPayment sa uistite, že:
- Session je úspešne inicializovaná (
session.state == .ready). - Údaje karty sú platné (
collector.isValid == true).
Ak tieto podmienky nie sú splnené, metóda okamžite vráti .failed(.sessionNotInitialized) alebo .failed(.invalidCardData).
3D Secure
Knižnica poskytuje kompletnú podporu 3D Secure autentifikácie. Ak je 3DS nakonfigurované, knižnica automaticky:
- Pripraví autentifikačné parametre pri spracovaní platby
- Vyhodnotí odpoveď servera (frictionless / challenge)
- V prípade potreby zobrazí challenge obrazovku
- Vráti výsledok autentifikácie prostredníctvom
PaymentResult
Konfigurácia
3DS sa konfiguruje prostredníctvom štruktúry ThreeDSConfig, ktorá sa odovzdáva do konštruktora ComgateSecureSession:
let threeDSConfig = ThreeDSConfig(
uiCustomization: threeDSUi,
defaultMessageVersion: "2.2.0",
challengeTimeoutMinutes: 5,
challengeWindowCornerRadiusDp: 16
)
let session = ComgateSecureSession(
checkoutId: "váš-checkout-id",
threeDSConfig: threeDSConfig
)
Parametre ThreeDSConfig
| Parameter | Typ | Predvolene | Popis |
|---|---|---|---|
uiCustomization | ThreeDSUiCustomization? | nil | Prispôsobenie vzhľadu challenge obrazovky. Ak je nil, použijú sa predvolené štýly. |
defaultMessageVersion | String | "2.2.0" | Verzia 3DS protokolu. Podporované hodnoty: pozri ThreeDSConfig.supportedMessageVersions. |
challengeTimeoutMinutes | Int | 5 | Maximálny čas čakania na dokončenie challenge v minútach (1–30). |
challengeWindowCornerRadiusDp | Int? | nil | Zaoblenie rohov challenge okna (0–64). Ak je nil, použije sa predvolená hodnota. |
Prispôsobenie vzhľadu challenge obrazovky
Štruktúra ThreeDSUiCustomization umožňuje detailné prispôsobenie vzhľadu 3DS challenge obrazovky:
let threeDSUi = ThreeDSUiCustomization(
buttons: [
.submit: ThreeDSButtonStyle(
backgroundColor: "#4287F5",
textColor: "#FFFFFF",
textFontSize: 16,
cornerRadius: 48
),
.continue: ThreeDSButtonStyle(
backgroundColor: "#4287F5",
textColor: "#FFFFFF",
textFontSize: 16,
cornerRadius: 48
),
.resend: ThreeDSButtonStyle(
backgroundColor: "#F0F0F0",
textColor: "#4287F5",
textFontSize: 16,
cornerRadius: 48
)
],
labelStyle: ThreeDSLabelStyle(
headingTextColor: "#4287F5",
textColor: "#333333"
),
textBoxStyle: ThreeDSTextBoxStyle(
borderColor: "#4287F5",
borderWidth: 4,
cornerRadius: 16,
textColor: "#333333"
),
toolbarStyle: ThreeDSToolbarStyle(
headerText: "Overenie platby",
buttonText: "Zrušiť",
backgroundColor: "#F0F0F0",
textColor: "#333333"
)
)
ThreeDSButtonStyle
Prispôsobenie tlačidiel na challenge obrazovke.
| Parameter | Typ | Popis |
|---|---|---|
backgroundColor | String? | Farba pozadia vo formáte #RRGGBB alebo #AARRGGBB. Predvolene "#4287F5". |
textColor | String? | Farba textu. Predvolene "#FFFFFF". |
textFontSize | Int? | Veľkosť písma (8–48). |
cornerRadius | Int? | Zaoblenie rohov tlačidla (0–64). |
Tlačidlá sa konfigurujú v dictionary kľúčovanom typom:
| Typ tlačidla | Popis |
|---|---|
.submit | Tlačidlo na odoslanie (potvrdenie). |
.continue | Tlačidlo na pokračovanie. |
.next | Tlačidlo na ďalší krok. |
.cancel | Tlačidlo na zrušenie. |
.resend | Tlačidlo na opätovné odoslanie kódu. |
ThreeDSLabelStyle
Prispôsobenie textových popiskov.
| Parameter | Typ | Popis |
|---|---|---|
headingTextColor | String? | Farba nadpisu. |
headingTextFontSize | Int? | Veľkosť nadpisu (8–48). |
textColor | String? | Farba bežného textu. |
textFontSize | Int? | Veľkosť bežného textu (8–48). |
ThreeDSTextBoxStyle
Prispôsobenie vstupných polí na challenge obrazovke.
| Parameter | Typ | Popis |
|---|---|---|
borderColor | String? | Farba ohraničenia. |
borderWidth | Int? | Šírka ohraničenia (0–16). |
cornerRadius | Int? | Zaoblenie rohov (0–64). |
textColor | String? | Farba textu. |
textFontSize | Int? | Veľkosť textu (8–48). |
ThreeDSToolbarStyle
Prispôsobenie toolbaru challenge obrazovky.
| Parameter | Typ | Popis |
|---|---|---|
headerText | String? | Text v hlavičke toolbaru. |
buttonText | String? | Text tlačidla v toolbare (typicky „Zrušiť"). |
backgroundColor | String? | Farba pozadia toolbaru. |
textColor | String? | Farba textu. |
textFontSize | Int? | Veľkosť textu (8–48). |
Farby sa zadávajú ako reťazce vo formáte #RRGGBB alebo #AARRGGBB. Neplatné formáty spôsobia runtime chybu validácie ThreeDSConfigurationError.invalidHexColor.
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 require3ds | Priebeh platby |
|---|---|
true | Server vráti challenge — zobrazí sa 3DS challenge obrazovka, používateľ musí zadať OTP alebo vykonať overenie. |
false | Server vráti frictionless výsledok — platba prebehne bez zobrazenia challenge obrazovky. |
nil (predvolene) | Server rozhodne sám; v produkcii štandardné správanie. |
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. Výsledok platby závisí od akcie používateľa:
- Dokončenie overenia →
.paid(transId:) - Zrušenie challenge →
.failed(.threeDSChallengeCancelled) - Vypršanie časového limitu →
.failed(.threeDSChallengeTimeout)
let params = try PaymentParams(
email: "zakaznik@example.com",
price: 100,
curr: "EUR",
label: "Testovacia platba",
refId: "test-001",
fullName: "Ján Novák",
require3ds: true
)
Simulácia frictionless priebehu
Nastavte require3ds = false. Platba prebehne bez zobrazenia challenge obrazovky.
let params = try PaymentParams(
email: "zakaznik@example.com",
price: 100,
curr: "EUR",
label: "Testovacia platba",
refId: "test-001",
fullName: "Ján Novák",
require3ds: false
)
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.
let params = try PaymentParams(
email: "zakaznik@example.com",
price: 100,
curr: "EUR",
label: "Testovacia platba",
refId: "test-001",
fullName: "Ján Novák",
errorReason: .noFunds
)
Parameter errorReason je funkčný výhradne v dev režime (devMode = true). V produkcii je tento parameter úplne ignorovaný.
Dostupné hodnoty výčtu ErrorReason:
| Hodnota | Raw value | Popis |
|---|---|---|
.customerClick | CUSTOMER_CLICK | Zrušené platiteľom. |
.fraudSuspected | FRAUD_SUSPECTED | Podozrenie na podvod. |
.eshopCancelled | ESHOP_CANCELLED | Zrušené obchodníkom. |
.providerReport | PROVIDER_REPORT | Zrušené poskytovateľom. |
.providerTimeout | PROVIDER_TIMEOUT | Vypršal časový limit poskytovateľa. |
.customerTimeout | CUSTOMER_TIMEOUT | Vypršal časový limit platby. |
.acsTimeout | ACS_TIMEOUT | Vypršal časový limit overenia. |
.invalidCardnoExpiry | INVALID_CARDNO_EXPIRY | Chybne zadané číslo karty alebo dátum platnosti karty. |
.invalidCvc | INVALID_CVC | Chybne zadaný CVC / CVV kód. |
.limitExceeded | LIMIT_EXCEEDED | Limit karty bol prekročený. |
.noFunds | NO_FUNDS | Na účte nie je dostatočný zostatok. |
.rejectedByBank | REJECTED_BY_BANK | Platba bola zamietnutá bankou. |
.threeDSAuthFail | 3DS_AUTH_FAIL | Overenie 3DS nebolo úspešné. |
.notSpecified | NOT_SPECIFIED | Nešpecifikované. |
Kompletný príklad
Nasledujúci príklad ukazuje kompletnú implementáciu kartovej platby s 3D Secure od inicializácie po spracovanie výsledku:
import SwiftUI
import ComgateSDK
@main
struct CardPaymentApp: App {
@StateObject private var session = ComgateSecureSession(
checkoutId: "váš-checkout-id",
threeDSConfig: ThreeDSConfig(
uiCustomization: ThreeDSUiCustomization(
toolbarStyle: ThreeDSToolbarStyle(
headerText: "Overenie platby",
buttonText: "Zrušiť"
)
),
challengeTimeoutMinutes: 5
)
)
var body: some Scene {
WindowGroup {
PaymentScreen(session: session)
.task {
if case .notInitialized = session.state {
try? await session.initialize()
}
}
}
}
}
struct PaymentScreen: View {
@ObservedObject var session: ComgateSecureSession
@StateObject private var panState: SecurePanFieldState
@StateObject private var expiryState: SecureExpiryFieldState
@StateObject private var cvvState: SecureCvvFieldState
@StateObject private var nameState: SecureFullNameFieldState
@StateObject private var statusState = PaymentStatusState()
@StateObject private var holder: CollectorHolder
@State private var cardInfo = "Vyplňte údaje karty"
init(session: ComgateSecureSession) {
self._session = ObservedObject(wrappedValue: session)
let pan = SecurePanFieldState()
let expiry = SecureExpiryFieldState()
let cvv = SecureCvvFieldState()
let name = SecureFullNameFieldState()
_panState = StateObject(wrappedValue: pan)
_expiryState = StateObject(wrappedValue: expiry)
_cvvState = StateObject(wrappedValue: cvv)
_nameState = StateObject(wrappedValue: name)
_holder = StateObject(wrappedValue: CollectorHolder(pan: pan, expiry: expiry, cvv: cvv))
}
private var collector: SecureCardDataCollector { holder.collector }
var body: some View {
ScrollView {
VStack(spacing: 12) {
Text(cardInfo)
SecureFullNameField(state: nameState)
SecurePanField(state: panState)
SecureExpiryField(state: expiryState)
SecureCvvField(state: cvvState)
SecurePayButton(
session: session,
collector: collector,
paymentParams: {
try! PaymentParams(
email: "zakaznik@example.com",
price: 100,
curr: "EUR",
country: "SK",
label: "Objednávka #123",
refId: "order-123",
fullName: "Ján Novák",
billingAddrCity: "Bratislava",
billingAddrStreet: "Hlavná 10",
billingAddrPostalCode: "81101",
billingAddrCountry: "SK"
)
},
onResult: { result in
statusState.translation = session.translation
statusState.show(result: result)
}
)
SecurePaymentStatusView(state: statusState)
}
.padding()
}
.onChange(of: panState.isValid) { isValid in
cardInfo = isValid ? "✓ Karta končiaca na \(panState.last4)" : "Vyplňte údaje karty"
}
.onAppear {
panState.translation = session.translation
expiryState.translation = session.translation
cvvState.translation = session.translation
nameState.translation = session.translation
nameState.attachTo(session)
}
.onDisappear { nameState.detachFrom(session) }
.secureLoadingOverlay(session: session)
}
}