Handling interrupts
Possible interrupts are either dialogs that you have to display to your users or redirects, i.e., links to web pages to which you have to send users to.
Check interrupts:
-
JavaScript
-
Kotlin
-
Rust
-
Swift
-
Lua
switch (response.constructor) {
case Result: ...; break
case Dialog: ...; break
case Redirect: ...; break
case RedirectHandle: ...; break
}
when (response) {
is Response.Dialog -> ...
is Response.Redirect -> ...
is Response.RedirectHandle -> ...
is Response.Result -> ...
}
match response {
OBResponse::Result(result, session, connection_data) => ...
OBResponse::Dialog(dialog) => ...
OBResponse::Redirect(redirect) => ...
OBResponse::RedirectHandle(handle) => ...
}
switch response {
case .result(let result, let session, let connectionData):
...
case .dialog(let contex, let message, let image, let input):
...
case .redirect(let url, let context):
...
case .redirectHandle(let handle, let context):
...
}
if response:isInstanceOf(Dialog) then
...
elseif response:isInstanceOf(Redirect) then
...
elseif response:isInstanceOf(RedirectHandle) then
...
elseif response:isInstanceOf(Result) then
...
end
Handle dialogs
Dialogs consist of an optional message and an optional image to display to the user as well as some input definition. Possible input types are:
- Confirmation
-
The user needs to confirm the dialog. This is typically used when waiting for a decoupled authentication, e.g., confirmation in the bank’s app.
- Selection
-
The user needs to choose from a list of options and confirm the choice.
- Field
-
A text input field in which the user has to enter some value.
Please confirm the transaction in your authenticator app.
Please use your TAN reader and enter the generated TAN.
The input details contain a context to continue with the process. Each service that might return interrupts also provides two ways for that, depending on the input type, e.g., for the accounts service:
Confirm dialog without input for the accounts service:
-
JavaScript
-
Kotlin
-
Rust
-
Swift
-
Lua
response = await client.confirmAccounts({ ticket, context })
response = client.confirmAccounts(ticket, context)
let response = client.confirm_accounts(ticket, context).await?;
let response = try await client
.confirmAccounts(ticket: ticket, context: context)
response = client:confirmAccounts({
ticket = ticket,
context = context,
})
Respond to any other dialog for the accounts service:
-
JavaScript
-
Kotlin
-
Rust
-
Swift
-
Lua
response = await client.respondAccounts({ ticket, context, response })
response = client.respondAccounts(ticket, context, response)
let response = client.respond_accounts({ticket, context, response}).await?;
let response = try await client.respondAccounts(
ticket: ticket,
context: context,
response: response
)
local response = client:respondAccounts({
ticket = accountsTicket,
context = context,
response = response,
})
The passed response is either the user’s choice from the list of options/actions or the user’s input. The result is, again, either another interrupt or the desired data.
This is an example for the Accounts service. See your client SDK for the respective methods for other services. |
Handle redirects
In case of a redirect, the user gets sent to a given URL. Desktop or mobile applications could either open it in a browser or inside an element like a WebView. Eventually, the user gets redirected to a URI that you provide. You may use it to redirect the user back to a web application or to jump back into the context of a desktop or mobile application.
The easiest and most efficient way to obtain a redirect URL is to provide your redirect URI before calling any service:
Set redirect URI:
-
JavaScript
-
Kotlin
-
Rust
-
Swift
-
Lua
await client.setRedirectUri('myapp://redirect?context=signup')
client.setRedirectUri(java.net.URI("myapp://redirect?context=signup"))
client.set_redirect_uri("myapp://redirect?context=signup")?;
client.setRedirectUri(redirectUri: "myapp://redirect?context=signup")
client:setRedirectUri("myapp://redirect?context=signup")
With a pre-set redirect URI services will provide redirect objects with the URL to send the user to and the context required to continue with the service.
If no redirect URI was set, the context will get returned along a handle that can be used to register a redirect URI and receive the redirect URL to use:
Register redirect URI:
-
JavaScript
-
Kotlin
-
Rust
-
Swift
-
Lua
let redirectUrl = await client.registerRedirectUri({
ticket,
handle,
redirectUri: 'myapp://redirect?context=signup'
})
client.registerRedirectUri(
ticket,
handle,
java.net.URI("myapp://redirect?context=signup"),
)
let redirect_url = client.register_redirect_uri(
ticket,
handle,
"myapp://redirect?context=signup",
).await?;
let redirectUrl = try await client.registerRedirect(
ticket: ticket,
handle: handle,
redirectUri: "myapp://redirect?context=signup"
)
local redirectUrl = client:registerRedirectUri({
ticket = accountsTicket,
handle = handle,
redirectUri = "myapp://redirect?context=signup",
})
When the redirect should be done, e.g., the URL that you provided got called or the user manually confirmed that he finished the process, you can continue with the redirect’s context as you would for a confirmation dialog:
Confirm redirect for the accounts service:
-
JavaScript
-
Kotlin
-
Rust
-
Swift
-
Lua
response = await client.confirmAccounts({
ticket,
context: redirect.context
})
client.confirmAccounts(
ticket,
context = redirect.context,
)
let response = client
.confirm_accounts(ticket, redirect.context)
.await?;
let response = try await client
.confirmAccounts(ticket: ticket, context: redirectContext)
response = client:confirmAccounts({
ticket = ticket,
context = redirect.context,
})
This is an example for the Accounts service. See your client SDK for the respective methods for other services. |
Polling
Confirmation dialogs are often used for decoupled steps where the user takes some action directly with the bank. The user confirms the completion with the dialog. As it is a bit clumsy and inconvenient to ask the user for explicit confirmation, you may poll the status. A confirmation that may be polled indicates a polling delay. When you confirm the dialog while the decoupled step is not completed, you get back a new confirmation dialog that you can continue with.
Make sure to poll only those confirmation dialogs that indicate a polling delay and to respect the value as a minimum before doing so. |
Make sure to stop polling at some point, as there are no guarantees that it will start failing if the step did not get completed. |
Confirmation dialogs may also be meant purely for polling, e.g., when waiting for a final status of an instant payment. In such cases, an explicit user confirmation does not really make sense. |
Polling is also possible for redirects for the case that you did not receive the signal, e.g. because the user or the system did not follow a deeplink into your app. When you confirm the redirect while it is not completed, you get back a confirmation dialog as well, indicating a redirect context and a polling delay. You can safely continue polling by confirming those dialogs.
Make sure to stop polling at some point, as there are no guarantees that it will start failing if the redirect did not get completed. |
Test cases
There is a demo connection available for development with identifier connection-96386142-60e5-4ca9-abcf-944efce5bc1e
.
It accepts a user identifier that determines the test case and no password. The following identifiers and responses are supported:
result
-
Immediate service result
confirmation
-
SCA confirmation dialog
selection
-
Account selection dialog
input
-
photoTAN-like dialog
redirect
-
Redirect
Confirming the redirect or confirmation dialog or responding to the selection or input dialog with any value leads to a service result.