Account Linking
Good to know: account linking is helpful if you wish to use AIS (Account Information Service) or skip authentication steps when initiating payments via the in-app payments module.
Firstly, you will need to integrate kevin. API and fetch account linking state. Instructions on how to do it can be found here:

Basic flow

Customise linking flow by tweaking our configuration:
1
// initialize configuration with state fetched from the API
2
let configuration = KevinAccountLinkingSessionConfiguration.Builder(state: "state")
3
.setPreselectedCountry(.lithuania)
4
.setCountryFilter([.lithuania, .latvia, .estonia])
5
.setPreselectedBank("SOME_BANK_ID")
6
.setSkipBankSelection(false)
7
.build()
Copied!
Implement KevinAccountLinkingSessionDelegate protocol. Make sure you show returned UIViewController somewhere:
1
protocol KevinAccountLinkingSessionDelegate: AnyObject {
2
func onKevinAccountLinkingStarted(controller: UINavigationController)
3
func onKevinAccountLinkingCanceled(error: Error?)
4
func onKevinAccountLinkingSucceeded(authorizationCode: String, bank: ApiBank)
5
}
Copied!
Call KevinAccountLinkingSession and listen to delegate:
1
KevinAccountLinkingSession.shared.delegate = self
2
try KevinAccountLinkingSession.shared.initiateAccountLinking(
3
configuration: configuration
4
)
Copied!

SwiftUI

Library is built on UIKit, however it can be easily used within SwiftUI.
Firstly, create representable for kevin. UIViewController:
1
import SwiftUI
2
3
struct KevinViewControllerRepresentable: UIViewControllerRepresentable {
4
5
let controller: UIViewController
6
7
func makeUIViewController(context: Context) -> some UIViewController {
8
return controller
9
}
10
11
func updateUIViewController(
12
_ uiViewController: UIViewControllerType,
13
context: Context
14
) { }
15
}
Copied!
Define your view from which you will be showing representable:
1
import Kevin
2
import SwiftUI
3
4
struct SampleView: View {
5
6
@ObservedObject var viewModel: SampleViewModel
7
8
var body: some View {
9
VStack(spacing: 20) {
10
Spacer()
11
12
Button {
13
viewModel.invokeAccountLinkingSession()
14
} label: {
15
Text("Link Account")
16
}.buttonStyle(MainButtonStyle())
17
18
.sheet(isPresented: $viewModel.viewState.openKevin, content: {
19
if let controller = viewModel.kevinController {
20
KevinViewControllerRepresentable(controller: controller)
21
.presentation(canDismissSheet: false)
22
}
23
})
24
25
Spacer()
26
}
27
.padding(20)
28
}
29
}
Copied!
Define your ViewModel which will subscribe to KevinAccountLinkingSessionDelegate and invoke the SDK:
1
import Kevin
2
import UIKit
3
4
class SampleViewModel: ObservableObject, KevinAccountLinkingSessionDelegate {
5
6
@Published var viewState = SampleViewState()
7
8
var kevinController: UIViewController? = nil
9
10
private let apiClient = ApiClient()
11
12
func invokeAccountLinkingSession() {
13
apiClient.getAuthState().done { state in
14
do {
15
KevinAccountLinkingSession.shared.delegate = self
16
try KevinAccountLinkingSession.shared.initiateAccountLinking(
17
configuration: KevinAccountLinkingSessionConfiguration.Builder(
18
state: state.state
19
)
20
.setPreselectedCountry(.lithuania)
21
.build()
22
)
23
} catch {
24
// do something
25
}
26
}.catch { error in
27
// do something
28
}
29
}
30
31
32
//MARK: KevinAccountLinkingSessionDelegate
33
34
func onKevinAccountLinkingStarted(controller: UINavigationController) {
35
self.kevinController = controller
36
self.viewState = MainViewState(openKevin: true)
37
}
38
39
func onKevinAccountLinkingCanceled(error: Error?) {
40
// notify user if error has been returned
41
}
42
43
func onKevinAccountLinkingSucceeded(authorizationCode: String, bank: ApiBank) {
44
// notify user
45
}
46
}
Copied!

Customise session configuration

KevinAccountLinkingSessionConfiguration has multiple settings to tackle:
  • setPreselectedCountry - preselects country in our prebuilt UI
  • setDisableCountrySelection - uses only preselected country and does not allow to change it
  • setCountryFilter - allows only certain countries to be supported
  • setPreselectedBank - preselects bank in our prebuilt UI
  • setSkipBankSelection - skips bank and country selection and redirects user to the bank SCA immediately
Example:
1
KevinAccountLinkingSession.shared.initiateAccountLinking(
2
configuration: KevinAccountLinkingSessionConfiguration.Builder(
3
state: state
4
)
5
.setPreselectedCountry(.lithuania)
6
.setCountryFilter([.lithuania, .latvia, .estonia])
7
.setPreselectedBank("SOME_BANK_ID")
8
.build()
9
)
Copied!