Skip to main content

Transaction

A Transaction is a message sent to user's app when he is logged in to Security Service. To handle situations when app is not running or in background a push notification is sent to inform the user.

The app can be in one of four states when you receive a Transaction:

There are mainly two types of transactions:

  • Wire Transfer (without authentication confirmation)
  • Wire Transfer - free text (with and without authentication confirmation)

One more type of transaction is Send Message which is mainly used to display some message in the application and it does not require any pin confirmation. Below is the diagram to understand the Transaction event categorization:

A user will receive transactions only if he is logged into the application. Furthermore, a user can receive transaction requests irrespective of the screen they are on. The Transaction flow involves a specific set of events.

Note that the server side is expected to select a localization of the texts sent to the app based on the language information that was provided in the StartEvent.

Transaction event flow-diagram

The following diagram shows the event flow in detail.

Transaction Sequence Diagram

For a better understanding of this decisive flow, here is a diagram that additionally shows the interaction of the various screens in our demo application:

As an app developer you can trigger a transaction by following the instructions.

iOS/Swift

Here are two code snippets for Swift:

Transaction (Swift)
func receive(_ event: KsEvent,
withCompletionHandler completionBlock:
((KsEvent?) -> Void)? = nil) {
if event is KSMTriggerBannerEvent{
if let bannerEvent = event as? KSMTriggerBannerEvent{
switch (bannerEvent.bannerType) {
case .displayMessage:
// Handle display message
case .transaction:
//Handle transaction.
default:
break
}
}
}
}

After receiving TriggerBannerEvent UI will trigger 

Trigger-Events-As-Per Transaction Event received (Swift)
if KSMTriggerBannerEvent.bannerType == .transaction{
masterControllerAdapter.sendEvent2MasterController(
KSMStartTransactionEvent(), withCompletionHandler: nil)
}else {
masterControllerAdapter.sendEvent2MasterController(
KSMStartDisplayMessageEvent(), withCompletionHandler: nil)
}

Android/Kotlin

Below is the code sample to handle transaction events in Kotlin:

Handling Transaction Events (Kotlin)
override fun onEventReceived(eventFrameworkEvent: EventFrameworkEvent) {
when (eventFrameworkEvent) {
is TriggerBannerEvent -> {
when (eventFrameworkEvent.bannerType) {
BannerType.TRANSACTION -> {
mcWrapper?.triggerStartTransactionEvent()
}
BannerType.DISPLAY_MESSAGE -> {
mcWrapper?.triggerStartDisplayMessageEvent()
}
}
}
is TransactionPinRequiredRequestEvent -> {
TransactionPinActivity.startTransactionPinActivity(
this,
eventFrameworkEvent.timerInformation
)
}
is DisplayConfirmationRequestEvent -> {
launchMain {
showHideProgressBar(false)
if (this@BaseActivity is TransactionPinActivity) {
finish()
}
DisplayConfirmationMessageActivity.startDisplayConfirmationMessageActivity(
this@BaseActivity,
eventFrameworkEvent.transactionInformation,
eventFrameworkEvent.timerValue
)
}
}
is DisplayConfirmationResultEvent -> {

}
is DisplayMessageEvent -> {
launchMain {
showHideProgressBar(false)
DisplayBannerMessageActivity.startDisplayMessageActivity(
this@BaseActivity,
eventFrameworkEvent.messageInformation
)
}

}
is TransactionEndEvent -> {

launchMain {
showHideProgressBar(false)
if (this@BaseActivity is TransactionPinActivity || this@BaseActivity is
DisplayConfirmationMessageActivity) {
finish()
}
}
when (eventFrameworkEvent.status) {
StatusType.OK -> Utils.showToast(this, getString(R.string.transaction_success))
StatusType.USER_CANCEL -> Utils.showToast(this, getString(
R.string.transaction_cancelled))
StatusType.USER_CONFIRMATION_TIMEOUT -> {
Utils.showToast(this, getString(R.string.transaction_cancelled_timeout))
}
else -> {
Utils.showToast(this, getString(R.string.some_error_occurred_in_transaction))
}
}

}
is ProvidePinResultEvent -> {

if (eventFrameworkEvent.status == StatusType.OK) {
transactionPinHandlerCallback.onProvidePinSuccess()
return

}
if (eventFrameworkEvent.status == StatusType.USER_CANCEL) {
transactionPinHandlerCallback.onProvidePinCancel()
return
}

if (eventFrameworkEvent.status == StatusType.NOT_REACHABLE) {
launchMain {
Utils.showAlertDialog(
context = baseActivity,
text = baseActivity.getString(
R.string.ks_ast_001_activation_useridactivationcodeview_alert_text_connectionnotestablished),
clickListener = null,
title = baseActivity.getString(R.string.label_error)
)
}
return
}

if (eventFrameworkEvent.status == StatusType.USER_CONFIRMATION_TIMEOUT) {
launchMain {
Utils.showAlertDialog(
context = baseActivity,
text = baseActivity.getString(R.string.msg_transaction_timeout),
clickListener = DialogInterface.OnClickListener { _, _ ->
transactionPinHandlerCallback.finishActivity() },
title = baseActivity.getString(
R.string.ks_sc_ast_tms_008a_verification_failed_title)
)
}
return
}

val retryCounter = eventFrameworkEvent.retryCounter
val errorMessage: String
if (retryCounter > 0) {
errorMessage = String.format(
baseActivity.resources.getQuantityString(
R.plurals.ks_wrong_pin_error_message,
retryCounter
), retryCounter
)
} else {
errorMessage =
baseActivity.getString(
R.string.ks_ast_015_login_view_alert_text_appdisabled)
}
launchMain {
Utils.showAlertDialog(
context = baseActivity,
text = errorMessage,
clickListener = DialogInterface.OnClickListener { _, _ ->
if (retryCounter <= 0) {
transactionPinHandlerCallback.restart()
}
},
title = baseActivity.getString(
R.string.ks_sc_ast_tms_008a_verification_failed_title)
)
}

}
}
}