Compare commits

...

3 Commits

4 changed files with 48 additions and 15 deletions

View File

@ -21,7 +21,7 @@ open class TanChallenge(
* As [availableTanMethods] also contains selected TanMethod, we didn't want to duplicate this object. Use * As [availableTanMethods] also contains selected TanMethod, we didn't want to duplicate this object. Use
* [selectedTanMethod] to get selected TanMethod or iterate over [availableTanMethods] and filter selected one by this id. * [selectedTanMethod] to get selected TanMethod or iterate over [availableTanMethods] and filter selected one by this id.
*/ */
open val selectedTanMethodId: String, open val selectedTanMethodIdentifier: String,
/** /**
* When adding an account, frontend has no UserAccount object in BankingClientCallback to know which TanMethods are * When adding an account, frontend has no UserAccount object in BankingClientCallback to know which TanMethods are
* available for user. * available for user.
@ -38,7 +38,7 @@ open class TanChallenge(
* As [availableTanMedia] also contains selected TanMedium, we didn't want to duplicate this object. Use * As [availableTanMedia] also contains selected TanMedium, we didn't want to duplicate this object. Use
* [selectedTanMedium] to get selected TanMedium or iterate over [availableTanMedia] and filter selected one by this medium name. * [selectedTanMedium] to get selected TanMedium or iterate over [availableTanMedia] and filter selected one by this medium name.
*/ */
open val selectedTanMediumName: String? = null, open val selectedTanMediumIdentifier: String? = null,
open val availableTanMedia: List<TanMedium> = emptyList(), open val availableTanMedia: List<TanMedium> = emptyList(),
open val tanImage: TanImage? = null, open val tanImage: TanImage? = null,
@ -56,11 +56,11 @@ open class TanChallenge(
@get:JsonIgnore @get:JsonIgnore
open val selectedTanMethod: TanMethod open val selectedTanMethod: TanMethod
get() = availableTanMethods.first { it.identifier == selectedTanMethodId } get() = availableTanMethods.first { it.identifier == selectedTanMethodIdentifier }
@get:JsonIgnore @get:JsonIgnore
open val selectedTanMedium: TanMedium? open val selectedTanMedium: TanMedium?
get() = availableTanMedia.firstOrNull { it.mediumName == selectedTanMediumName } get() = availableTanMedia.firstOrNull { it.mediumName == selectedTanMediumIdentifier }
/** /**

View File

@ -292,11 +292,11 @@ open class FinTs4kMapper {
val action = mapActionRequiringTan(challenge.forAction) val action = mapActionRequiringTan(challenge.forAction)
val tanMethods = challenge.bank.tanMethodsAvailableForUser.map { mapTanMethod(it) } val tanMethods = challenge.bank.tanMethodsAvailableForUser.map { mapTanMethod(it) }
val selectedTanMethodId = challenge.tanMethod.securityFunction.code val selectedTanMethodIdentifier = challenge.tanMethod.securityFunction.code
val tanMedia = challenge.bank.tanMedia.map { mapTanMedium(it) } val tanMedia = challenge.bank.tanMedia.map { mapTanMedium(it) }
// TanMedium has not natural id in FinTS model so we have to create our own one // TanMedium has not natural id in FinTS model so we have to create our own one
val selectedTanMediumName = challenge.bank.selectedTanMedium?.let { selected -> tanMedia.firstOrNull { it == selected } }?.identifier val selectedTanMediumIdentifier = challenge.bank.selectedTanMedium?.let { selected -> tanMedia.firstOrNull { it == selected } }?.identifier
val bank = mapToBankViewInfo(challenge.bank) val bank = mapToBankViewInfo(challenge.bank)
val account = challenge.account?.let { mapToBankAccountViewInfo(it) } val account = challenge.account?.let { mapToBankAccountViewInfo(it) }
@ -304,7 +304,7 @@ open class FinTs4kMapper {
val tanImage = if (challenge is ImageTanChallenge) mapTanImage(challenge.image) else null val tanImage = if (challenge is ImageTanChallenge) mapTanImage(challenge.image) else null
val flickerCode = if (challenge is FlickerCodeTanChallenge) mapFlickerCode(challenge.flickerCode) else null val flickerCode = if (challenge is FlickerCodeTanChallenge) mapFlickerCode(challenge.flickerCode) else null
return object : TanChallenge(type, action, challenge.messageToShowToUser, selectedTanMethodId, tanMethods, selectedTanMediumName, tanMedia, tanImage, flickerCode, bank, account, challenge.tanExpirationTime, challenge.challengeCreationTimestamp) { return object : TanChallenge(type, action, challenge.messageToShowToUser, selectedTanMethodIdentifier, tanMethods, selectedTanMediumIdentifier, tanMedia, tanImage, flickerCode, bank, account, challenge.tanExpirationTime, challenge.challengeCreationTimestamp) {
override fun addTanExpiredCallback(callback: () -> Unit) { override fun addTanExpiredCallback(callback: () -> Unit) {
challenge.addTanExpiredCallback(callback) challenge.addTanExpiredCallback(callback)
} }

View File

@ -82,7 +82,10 @@ class ShowUsage {
This fetches the booked account transactions of the last 90 days. In most cases no TAN is required for this. This fetches the booked account transactions of the last 90 days. In most cases no TAN is required for this.
You can also specify options e.g. which transactions should be retrieved:
#### GetAccountData parameter
You can also specify options e.g. which transactions you would like to retrieve:
```kotlin ```kotlin
val options = GetAccountDataOptions( val options = GetAccountDataOptions(
@ -95,20 +98,40 @@ val options = GetAccountDataOptions(
val response = client.getAccountData(options) val response = client.getAccountData(options)
``` ```
Retrieving transactions older than 90 days requires a TAN, so add TAN handling in Client Callback: #### TAN handling
Retrieving transactions older than 90 days or sometimes even log in requires a TAN, so add TAN handling in Client Callback:
```kotlin ```kotlin
val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback -> val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback ->
val tan: String? = null // if a TAN is required, add a UI or ... val tan: String? = null // if a TAN is required, read TAN from command line, add a UI, ...
callback.invoke(EnterTanResult(tan)) // ... set a break point here, get TAN e.g. from your TAN app, set tan variable in debugger view and resume debugger callback.invoke(EnterTanResult(tan)) // ... set a break point here, get TAN e.g. from your TAN app, set tan variable in debugger view and resume debugger
}) })
``` ```
E.g. TAN handling on the command line:
```kotlin
println("Enter password for $bankCode:")
val password = readln() // as an alternative for hard coding password; of course can also be done for bankCode and login name
val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback ->
println("A TAN is required for ${tanChallenge.forAction}. Selected TAN method is '${tanChallenge.selectedTanMethod.displayName}'. Messsage of your credit institute:")
println(tanChallenge.messageToShowToUser)
println("Get TAN from your TAN app etc., enter it and press Enter (or press Enter without an input to abort process):")
val tan: String? = readlnOrNull().takeUnless { it.isNullOrBlank() } // map empty input to null to abort process
callback.invoke(EnterTanResult(tan))
})
```
#### Error handling
Add some error handling by checking `response.error`: Add some error handling by checking `response.error`:
```kotlin ```kotlin
response.error?.let{ error -> response.error?.let{ error ->
println("Could not fetch account data: ${error.internalError ?: error.errorMessagesFromBank.joinToString()}") println("Could not fetch account data: ${error.type} ${error.internalError ?: error.errorMessagesFromBank.joinToString()}")
} }
``` ```

View File

@ -42,9 +42,16 @@ class ShowUsage {
} }
fun getAccountDataFullExample() { fun getAccountDataFullExample() {
println("Enter password for $bankCode:")
val password = readln() // as an alternative for hard coding password; of course can also be done for bankCode and login name
val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback -> val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback ->
val tan: String? = null // if a TAN is required, add a UI or ... println("A TAN is required for ${tanChallenge.forAction}. Selected TAN method is '${tanChallenge.selectedTanMethod.displayName}'. Messsage of your credit institute:")
callback.invoke(EnterTanResult(tan)) // ... set a break point here, get TAN e.g. from your TAN app, set tan variable in debugger view and resume debugger println(tanChallenge.messageToShowToUser)
println("Get TAN from your TAN app etc., enter it and press Enter (or press Enter without an input to abort process):")
val tan: String? = readlnOrNull().takeUnless { it.isNullOrBlank() } // map empty input to null to abort process
callback.invoke(EnterTanResult(tan))
}) })
val options = GetAccountDataOptions( val options = GetAccountDataOptions(
@ -57,7 +64,7 @@ class ShowUsage {
val response = client.getAccountData(options) val response = client.getAccountData(options)
response.error?.let{ error -> response.error?.let{ error ->
println("Could not fetch account data: ${error.internalError ?: error.errorMessagesFromBank.joinToString()}") println("Could not fetch account data: ${error.type} ${error.internalError ?: error.errorMessagesFromBank.joinToString()}")
} }
printReceivedData(response) printReceivedData(response)
@ -65,7 +72,10 @@ class ShowUsage {
fun updateAccountTransactions() { fun updateAccountTransactions() {
val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback()) val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback ->
val tan: String? = readlnOrNull() // if a TAN is required, read TAN from command line, add a UI, ...
callback.invoke(EnterTanResult(tan)) // ... set a break point here, get TAN e.g. from your TAN app, set tan variable in debugger view and resume debugger
})
// simulate account transactions we retrieved last time // simulate account transactions we retrieved last time
val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date