Payment Initiation
Good to know: payment initiation is responsible for bank and card payment support.
Firstly, you will need to integrate kevin. API and fetch payment ID. Instructions on how to do it can be found here:

Basic flow

Customise payment flow by tweaking our configuration:
1
// initialize configuration with paymentId fetched from the API
2
let configuration = KevinPaymentSessionConfiguration.Builder(paymentId: paymentId)
3
.setPaymentType(.bank)
4
.setPreselectedCountry(.lithuania)
5
.setCountryFilter([.lithuania, .latvia, .estonia])
6
.setDisableCountrySelection(false)
7
.setPreselectedBank("SOME_BANK_ID")
8
.setSkipBankSelection(false)
9
.setSkipAuthentication(false)
10
.build()
Copied!
Implement KevinPaymentSessionDelegate protocol. Make sure you show returned UIViewController somewhere:
1
protocol KevinPaymentSessionDelegate: AnyObject {
2
func onKevinPaymentInitiationStarted(controller: UINavigationController)
3
func onKevinPaymentCanceled(error: Error?)
4
func onKevinPaymentSucceeded(paymentId: String)
5
}
Copied!
Call KevinPaymentSession and listen to delegate:
1
KevinPaymentSession.shared.delegate = self
2
try KevinPaymentSession.shared.initiatePayment(
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.invokeBankPaymentInitiationSession()
14
} label: {
15
Text("Make Bank Payment")
16
}.buttonStyle(MainButtonStyle())
17
18
Button {
19
viewModel.invokeCardPaymentInitiationSession()
20
} label: {
21
Text("Make Card Payment")
22
}.buttonStyle(MainButtonStyle())
23
24
25
.sheet(isPresented: $viewModel.viewState.openKevin, content: {
26
if let controller = viewModel.kevinController {
27
KevinViewControllerRepresentable(controller: controller)
28
.presentation(canDismissSheet: false)
29
}
30
})
31
32
Spacer()
33
}
34
.padding(20)
35
}
36
}
Copied!
Define your ViewModel which will subscribe to KevinPaymentSessionDelegate and invoke the SDK:
1
import UIKit
2
import Kevin
3
4
class SampleViewModel: ObservableObject, KevinPaymentSessionDelegate {
5
6
@Published var viewState = SampleViewState()
7
8
var kevinController: UIViewController? = nil
9
10
private let apiClient = ApiClient()
11
12
func invokeBankPaymentInitiationSession() {
13
apiClient.initializeBankPayment().done { state in
14
do {
15
KevinPaymentSession.shared.delegate = self
16
try KevinPaymentSession.shared.initiatePayment(
17
configuration: KevinPaymentSessionConfiguration.Builder(
18
paymentId: state.id
19
)
20
.setPreselectedCountry(.lithuania)
21
.setSkipBankSelection(false)
22
.build()
23
)
24
} catch {
25
// do something
26
}
27
}.catch { error in
28
// do something
29
}
30
}
31
32
func invokeCardPaymentInitiationSession() {
33
apiClient.initializeCardPayment().done { state in
34
do {
35
KevinPaymentSession.shared.delegate = self
36
try KevinPaymentSession.shared.initiatePayment(
37
configuration: KevinPaymentSessionConfiguration.Builder(
38
paymentId: state.id
39
)
40
.setPaymentType(.card)
41
.build()
42
)
43
} catch {
44
// do something
45
}
46
}.catch { error in
47
// do something
48
}
49
}
50
51
//MARK: KevinPaymentSessionDelegate
52
53
func onKevinPaymentInitiationStarted(controller: UINavigationController) {
54
self.kevinController = controller
55
self.viewState = MainViewState(openKevin: true)
56
}
57
58
func onKevinPaymentCanceled(error: Error?) {
59
// notify user if error has been returned
60
}
61
62
func onKevinPaymentSucceeded(paymentId: String) {
63
// notify user
64
}
65
}
66
Copied!

Customise session configuration

KevinPaymentSessionConfiguration has multiple settings to tackle:
  • setPaymentType - sets payment to be BANK or CARD. The payment needs to be initialised with the corresponding type. See reference here.
  • setPreselectedCountry - preselects country in our prebuilt UI
  • setDisableCountrySelection - uses only preselected country and does not allow to change it
  • setCountryFilter - allow 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
  • setSkipAuthentication - allows users to skip the SCA bank step and proceed directly to the payment confirmation. Bank payment needs to be initialised with an account access token. See reference here.
Example:
1
KevinPaymentSession.shared.initiatePayment(
2
configuration: KevinPaymentSessionConfiguration.Builder(
3
paymentId: state.id
4
)
5
.setPreselectedCountry(.lithuania)
6
.setCountryFilter([.lithuania, .latvia, .estonia])
7
.setPreselectedBank("SOME_BANK_ID")
8
.build()
9
)
Copied!