The XignSys SDK offers non-blocking (i.e., asynchronous) and blocking (i.e., synchronous) calls of all flow functions of its major components. You can choose to write your own asynchronous flow handling or use the provided ones.
Be advised: DO NOT invoke synchronous function on the main thread. Most of these functions operate on network connections and wait for responses or use strong cryptographic functions that can take longer to complete especially on devices with weaker hardware.
The calls are built similar for all major components. In this documentation we will discuss the asynchronous and
synchronous calls using the XignCommon component and its function parseProcessInitializationData as an example.
The XignSys SDK offers asynchronous functions that can be safely called from the main thread without blocking the UI. It utilizes a 'publish/subscribe' model, meaning that events are published and can be consumed by specific subscribers.
Events are dispatched to all receivers in a FIFO matter. Once an event has been consumed, it's no longer sent to the remaining recipients. If no receiver consumes the event, it stays inside the queue and will be redelivered. Every callback function of the event receiver interface has a default implementation that skips incoming events. You can decide which event your receiver consumes and do not have to take care of events you're not interested in. Note, however, that unconsumed events remain in the delivery queue indefinitely and take up memory until consumed.
Beware: Events must be consumed, so they can be removed from the event queue. In order to consume an event, return
truefrom a receiver function as shown in the following sections.
Error events follow the same consumption cycle as success events. To handle error events, please see Error Handling.
To be able to receive results from asynchronous functions an event receiver must be subscribed. A Receiver, for
example a view controller, which must conform to the component's event receiver interface—in this example the
XignCommonEventReceiver—can subscribe an event receiver and receive events. Such a compatible receiver can
subscribe to the component as follows:
Swift
class YourEventReceiver: XignCommonEventReceiver {
func onAppearView() {
XignSdk.shared.xignCommon.subscribe(self)
}
// Other functions ...
}
Event receivers do not have to be unsubscribed, because the XignCommon component unsubscribes automatically if no hard
reference of the event receiver is held anymore. If you want to unsubscribe manually you can do it as follows:
Swift
class YourEventReceiver: XignCommonEventReceiver {
func onDisappearView() {
XignSdk.shared.xignCommon.unsubscribe(self)
}
// Other functions ...
}
After a receiver is subscribed by the component the flow functions can simply be invoked. All asynchronous flow
functions have an extra parameter requestCode. In case you want to identify your calls, you can explicitly set this
parameter. Otherwise, its default value is used.
Swift
// Handles the raw process initialization data e.g. received by scanning a QR-Code
func parseProcessInitializationData(rawProcessInitializationData: String) {
// Retrieve the XignCommon component that offers
// the desired asynchronous function to parse the data.
let xignCommon: XignCommon = XignSdk.shared.xignCommon
// Invoke the asynchronous function provided by the SDK
xignCommon.parseProcessInitializationData(
data: rawProcessInitializationData,
requestCode: 1337
)
}
The functions on which the events are delivered are similar in name to the called function. The name is derived as
follows: The origin name is prefixed with on and suffixed with Success for success and Error for error cases. For
example success results of parseProcessInitializationData are delivered on onParseProcessInitializationDataSuccess
while errors can be received with onParseProcessInitializationDataError.
For a more detailed view on errors and their handling, please see Error Handling.
Swift
class YourEventReceiver: XignCommonEventReceiver {
func onAppearView() {
XignSdk.shared.xignCommon.subscribe(self)
}
func onDisappearView() {
XignSdk.shared.xignCommon.unsubscribe(self)
}
func onParseProcessInitializationDataSuccess(
requestCode: RequestCode,
data: ProcessInitializationData
) -> Bool {
// Handle the received event
switch data {
case .personalization(let pid):
YourImplementation.startPersonalizationProcess(pid)
case .authentication(let aid):
YourImplementation.startAuthenticationProcess(aid)
case .transaction(let tid):
YourImplementation.startTransactionProcess(tid)
}
// Mark the event as consumed.
// Otherwise, this function will be invoked multiple times and
// the intended process most certainly messed up.
return true
}
func onParseProcessInitializationDataError(
requestCode: RequestCode,
errorCode: ParseProcessInitializationDataErrorCodes,
error: XignSdkError
) -> Bool {
// Handle the specific errors that can be thrown during this process step
switch errorCode {
case .parseProcessInitializationDataFailed,
.invalidSignature,
.identityManagerNotPersonalized,
.keyRemovedBySystem,
.unexpectedError:
YourImplementation.handleTheError()
}
// Mark the event as consumed.
// Otherwise, this function will be invoked multiple times and
// the intended process most certainly messed up.
return true
}
// Other functions ...
}
To be able to receive results from asynchronous functions an event receiver must be subscribed. The asynchronous calls
were modeled using the Android LiveData Jetpack
library. A LifecycleOwner, for example an AppCompatActivity, can subscribe an event receiver and receive events
beyond their life cycle. This means, in a case of a configuration change, the events will not be lost and instead will
be redelivered, when a receiver subscribes again. The receiver must conform to the component's event receiver interface,
in this example the XignCommonEventReceiver. Such a compatible receiver can subscribe to the component as follows:
Kotlin
class YourReceiverActivity : AppCompatActivity(), XignCommonEventReceiver {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
XignSdk.shared.xignCommon.subscribe(
owner = this,
observer = this
)
}
// Other functions ...
}
Event receivers do not have to be unsubscribed, because the LiveData framework handles this task. However, they can be unsubscribed if desired.
Kotlin
class YourReceiverActivity : AppCompatActivity(), XignCommonEventReceiver {
override fun onDestroy() {
super.onDestroy()
XignSdk.shared.xignCommon.unsubscribe(owner = this)
}
// Other functions ...
}
The above example will unsubscribe all event receivers of a LifecycleOwner. Currently, it is only possible to
unsubscribe all event receivers of a LifecycleOwner.
After a receiver is subscribed by the component the flow functions can simply be invoked. All asynchronous flow
functions have an extra parameter requestCode. In case you want to identify your calls, you can explicitly set this
parameter. Otherwise, its default value is used.
Kotlin
fun parseProcessInitializationData(rawProcessInitializationData: String) {
// Retrieve the XignCommon component that offers
// the desired asynchronous function to parse the data.
val xignCommon: XignCommon = XignSdk.shared.xignCommon
// Invoke the asynchronous function provided by the SDK
xignCommon.parseProcessInitializationData(
data = rawProcessInitializationData,
requestCode = 1337
)
}
The functions on which the events are delivered are similar in name to the called function. The name is derived as
follows: The origin name is prefixed with on and suffixed with Success for success and Error for error cases. For
example success results of parseProcessInitializationData are delivered on onParseProcessInitializationDataSuccess
while errors can be received with onParseProcessInitializationDataError.
For a more detailed view on errors and their handling, please see Error Handling.
Kotlin
class YourReceiverActivity : AppCompatActivity(), XignCommonEventReceiver {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
XignSdk.shared.xignCommon.subscribe(
owner = this,
observer = this
)
}
override fun onDestroy() {
super.onDestroy()
XignSdk.shared.xignCommon.unsubscribe(owner = this)
}
override fun onParseProcessInitializationDataSuccess(
requestCode: RequestCode,
data: ProcessInitializationData
): Boolean {
// Handle the received event
when (data) {
is PersonalizationInitializationData ->
YourImplementation.startPersonalizationProcess(data)
is AuthenticationInitializationData ->
YourImplementation.startAuthenticationProcess(data)
is TransactionInitializationData ->
YourImplementation.startTransactionProcess(data)
}
// Mark the event as consumed.
// Otherwise, this function will be invoked multiple times and
// the intended process most certainly messed up.
return true
}
override fun onParseProcessInitializationDataError(
requestCode: RequestCode,
errorCode: ParseProcessInitializationDataErrorCodes,
error: XignSdkException
): Boolean {
// Handle the specific errors that can be thrown during this process step.
when (errorCode) {
ParseProcessInitializationDataErrorCodes.PARSE_PROCESS_INITIALIZATION_DATA_FAILED,
ParseProcessInitializationDataErrorCodes.INVALID_SIGNATURE,
ParseProcessInitializationDataErrorCodes.IDENTITY_MANAGER_NOT_PERSONALIZED,
ParseProcessInitializationDataErrorCodes.KEY_REMOVED_BY_SYSTEM,
ParseProcessInitializationDataErrorCodes.UNEXPECTED_ERROR -> {
YourImplementation.handleTheException()
}
}
// Mark the event as consumed.
// Otherwise, this function will be invoked multiple times and
// the intended process most certainly messed up.
return true
}
// Other functions ...
}
The synchronous flow functions block the current thread until a result can be returned or an error is thrown. For the
error handling, please see Error Handling. Every major components has functions suffixed with
Synchronous. If you want to implement your own threading you can choose these. Be advised, for the time being, these
functions are not thread safe. Executing the same function from multiple threads at the same time, can lead to
unexpected behavior.