Přeskočit na hlavní obsah

Výsledky platby

Výsledek platby je reprezentován výčtem PaymentResult. Asynchronní metody processPayment(...) a processApplePayPayment(...) vrací PaymentResult přímo, callback onResult v SecurePayButton a SecureApplePayButton je vždy volán na hlavním vlákně.

PaymentResult​

V praxi rozlišujte tyto typy výsledku:

Případ PaymentResultAsociované hodnotyPopis
.paid(transId:)StringPlatba byla dokončena a potvrzena.
.authorized(transId:)StringPlatba byla autorizována bankou (předautorizace).
.pending(transId:)StringPlatba se stále zpracovává (mezistav).
.cancelled(errorReason:transId:)String?, StringPlatba byla zrušena nebo zamítnuta serverem.
.failed(ComgateError)ComgateErrorChyba na straně knihovny během platebního procesu.

Platba je úspěšně dokončená.

case .paid(let transId):
// Platba dokončena
print("Paid: \(transId)")

Authorized​

Platba byla autorizována (předautorizována) bankou. Jde o finální stav. Zachycení (settlement) platby provede obchodník samostatně pomocí standardních endpointů /capturePreauth nebo /cancelPreauth.

case .authorized(let transId):
// Platba autorizována, čeká na zachycení
print("Authorized: \(transId)")

Pending​

Platba ještě není finální, backend ji stále zpracovává. Finálním stavem bude .paid, .authorized nebo .cancelled.

case .pending(let transId):
// Čekáme na finální stav
print("Pending: \(transId)")

Cancelled​

Platba byla zrušena nebo zamítnuta serverem. Obsahuje identifikátor transakce a volitelný důvod.

case .cancelled(let errorReason, let transId):
// Platba byla ukončena bez úhrady
print("Cancelled: \(errorReason ?? "-") (\(transId))")

Možné hodnoty errorReason​

errorReason je raw value výčtu ErrorReason (může být nil, pokud server hodnotu nedodá):

errorReasonVýznam
CUSTOMER_CLICKZrušeno plátcem.
FRAUD_SUSPECTEDPodezření na podvod.
ESHOP_CANCELLEDZrušeno obchodníkem.
PROVIDER_REPORTZrušeno providerem.
PROVIDER_TIMEOUTVypršel časový limit poskytovatele.
CUSTOMER_TIMEOUTVypršel časový limit platby.
ACS_TIMEOUTVypršel časový limit pro ověření.
INVALID_CARDNO_EXPIRYChybně zadané číslo karty nebo datum platnosti karty.
INVALID_CVCChybně zadaný CVC / CVV kód.
LIMIT_EXCEEDEDLimit karty byl překročen.
NO_FUNDSNa účtu není dostatečný zůstatek.
REJECTED_BY_BANKPlatba byla zamítnuta bankou.
3DS_AUTH_FAILOvěření platby nebylo úspěšné.
NOT_SPECIFIEDNespecifikováno.
Testování chybových scénářů

V dev režimu (devMode = true) můžete tyto hodnoty simulovat pomocí parametru errorReason v PaymentParams. Viz sekci Simulace chybového důvodu.

Failed​

Chyba na straně knihovny, která nastala během platebního procesu. Na rozdíl od .cancelled (kde server aktivně zamítl platbu) .failed značí, že k dokončení platby vůbec nedošlo — např. síťová chyba, neinicializovaná session apod.

Asociovanou hodnotou je objekt ComgateError s machine-readable kódem (code) a lidsky čitelnou zprávou (message).

case .failed(let error):
let errorCode = error.code // např. "PAYMENT_NETWORK_ERROR"
let errorMessage = error.message // např. "Network error during payment."
// Zobrazení chyby uživateli

ComgateError​

Všechny chyby jsou definovány jako case výčtu ComgateError. Každý case vystavuje:

  • code: String — strojově čitelný identifikátor chyby
  • message: String — lidsky čitelný popis v angličtině
Inicializace​
PřípadKódPopis
.deviceRootedDEVICE_ROOTEDZařízení je pravděpodobně jailbreaknuté nebo jinak pozměněné. Inicializace je zablokovaná za účelem ochrany karetních dat. V devMode se tato kontrola přeskočí.
.initNetworkErrorINIT_NETWORK_ERRORInicializace session selhala kvůli síťové chybě.
.initUnauthorizedINIT_UNAUTHORIZEDServer vrátil HTTP 401 při inicializaci — neplatná nebo expirovaná autorizace.
.initFailedINIT_FAILEDInicializace session selhala (jiný než síťový důvod).
.applicationNotAllowedAPPLICATION_NOT_ALLOWEDAplikace není povolena pro použití SDK (Bundle ID není na allow-listu).
Zpracování platby​
PřípadKódPopis
.sessionNotInitializedSESSION_NOT_INITIALIZEDSession nebyla inicializována. Zavolejte nejprve initialize().
.invalidCardDataINVALID_CARD_DATAKaretní data nejsou validní.
.missingCardholderNameMISSING_CARDHOLDER_NAMEJméno držitele karty nebylo poskytnuto.
.paymentFailedPAYMENT_FAILEDPlatba selhala (jiný než síťový důvod).
.paymentNetworkErrorPAYMENT_NETWORK_ERRORPlatební požadavek selhal kvůli síťové chybě.
.paymentCreateFailedPAYMENT_CREATE_FAILEDVytvoření platby selhalo.
.pollingTimeoutPOLLING_TIMEOUTKontrola stavu platby vypršela.
.pollingNetworkErrorPOLLING_NETWORK_ERRORKontrola stavu platby selhala kvůli síťové chybě.
.threeDSChallengeCancelledTHREE_DS_CHALLENGE_CANCELLED3D Secure challenge byla zrušena.
.threeDSChallengeTimeoutTHREE_DS_CHALLENGE_TIMEOUT3D Secure challenge vypršela časem.
.threeDSFailedTHREE_DS_FAILED3D Secure autentizace selhala.
Apple Pay​
PřípadKódPopis
.applePayNotConfiguredAPPLE_PAY_NOT_CONFIGUREDApple Pay není nakonfigurován.
.applePayCancelledAPPLE_PAY_CANCELLEDApple Pay byl zrušen uživatelem.
.applePayFailedAPPLE_PAY_FAILEDApple Pay platba selhala.
Validace polí​
PřípadKódPopis
.invalidPanINVALID_PANNeplatné číslo karty.
.invalidExpiryMonthINVALID_EXPIRY_MONTHNeplatný měsíc expirace.
.cardExpiredCARD_EXPIREDKarta je expirovaná.
.invalidCvvINVALID_CVVNeplatný CVV kód.
.conflictingPaymentOptionsCONFLICTING_PAYMENT_OPTIONSinitRecurring a preauth nemohou být oba true.
.invalidPriceINVALID_PRICEprice musí být kladné celé číslo v nejmenší jednotce měny.

SecurePaymentStatusView​

Komponenta SecurePaymentStatusView slouží k zobrazování stavových hlášek platby (úspěch, zpracování, chyba). Pracuje s objektem PaymentStatusState, který drží aktuální zobrazenou zprávu.

PaymentStatusState​

Vlastnost / MetodaTypPopis
visibleBooltrue pokud má být view zobrazené (read-only, @Published).
textStringAktuální text (read-only, @Published).
translationTranslationPřeklady použité pro automatické zprávy. Nastavte na session.translation.
show(result:)func show(result: PaymentResult)Automaticky vybere a zobrazí lokalizovanou zprávu pro daný výsledek.
showError(_:)func showError(_ message: String)Zobrazí vlastní chybovou zprávu.
hide()func hide()Skryje view (text zůstává).
clear()func clear()Skryje view a vyčistí text.

Zobrazení stavu z PaymentResult​

@StateObject private var statusState = PaymentStatusState()

statusState.translation = session.translation
statusState.show(result: paymentResult)

// V SwiftUI:
SecurePaymentStatusView(state: statusState)
PaymentResultChování
.paidZobrazí lokalizovanou zprávu z Translation.statusPaid se zeleným stylem (úspěch).
.authorizedZobrazí lokalizovanou zprávu z Translation.statusAuthorized se zeleným stylem (úspěch).
.pendingZobrazí lokalizovanou zprávu z Translation.statusPending s oranžovým stylem (zpracování).
.cancelledZobrazí errorReason s červeným stylem (chyba).
.failedZobrazí error.message s červeným stylem (chyba).

Skrytí view​

statusState.clear() // skryje view a vyčistí text
statusState.hide() // pouze skryje view, text zůstává

Stylizace​

Podrobnosti o stylizaci SecurePaymentStatusView prostřednictvím struktury PaymentStatusStyle naleznete v sekci Stylizace komponent.

Kompletní příklad zpracování výsledků​

struct PaymentResultHandler: View {
@ObservedObject var session: ComgateSecureSession
@StateObject private var statusState = PaymentStatusState()
@State private var resultText = ""
@State private var resultVisible = false

func handle(_ result: PaymentResult) {
statusState.translation = session.translation

switch result {
case .paid(let t):
statusState.show(result: result)
resultVisible = true
resultText = "Platba dokončena\nTransId: \(t)"
case .authorized(let t):
statusState.show(result: result)
resultVisible = true
resultText = "Platba autorizována\nTransId: \(t)"
case .pending(let t):
statusState.show(result: result)
resultVisible = true
resultText = "Platba se zpracovává\nTransId: \(t)"
case .cancelled:
statusState.show(result: result)
resultVisible = false
case .failed(let err):
statusState.show(result: result)
resultVisible = false
print("Failed: \(err.code) — \(err.message)")
}
}

var body: some View {
VStack {
// ... (karetní pole, tlačítko — viz sekce Karetní data)

SecurePaymentStatusView(state: statusState)

if resultVisible {
Text(resultText)
.padding(.top, 8)
}
}
}
}