From 61d8f2c342cf242cdeae573451f36bda90c532da Mon Sep 17 00:00:00 2001 From: dankito Date: Tue, 10 Sep 2024 02:37:02 +0200 Subject: [PATCH] Added preferredTanMethods and preferredTanMedium to JobContext --- .../net/codinux/banking/fints/FinTsClient.kt | 8 +++--- .../banking/fints/FinTsClientDeprecated.kt | 18 ++++++------ .../codinux/banking/fints/FinTsJobExecutor.kt | 28 +++++++++++-------- .../codinux/banking/fints/model/JobContext.kt | 2 ++ 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClient.kt b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClient.kt index 32d1b6ab..66517972 100644 --- a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClient.kt @@ -80,7 +80,7 @@ open class FinTsClient( } protected open suspend fun getAccountTransactions(param: GetAccountDataParameter, bank: BankData, account: AccountData): GetAccountTransactionsResponse { - val context = JobContext(JobContextType.GetTransactions, this.callback, config, bank, account) + val context = JobContext(JobContextType.GetTransactions, this.callback, config, bank, account, param.preferredTanMethods, param.preferredTanMedium) return config.jobExecutor.getTransactionsAsync(context, mapper.toGetAccountTransactionsParameter(param, bank, account)) } @@ -138,7 +138,7 @@ open class FinTsClient( accountToUse = selectedAccount } - val context = JobContext(JobContextType.TransferMoney, this.callback, config, bank, accountToUse) + val context = JobContext(JobContextType.TransferMoney, this.callback, config, bank, accountToUse, param.preferredTanMethods, param.preferredTanMedium) val response = config.jobExecutor.transferMoneyAsync(context, BankTransferData(param.recipientName, param.recipientAccountIdentifier, recipientBankIdentifier, param.amount, param.reference, param.instantPayment)) @@ -205,11 +205,11 @@ open class FinTsClient( // return GetAccountInfoResponse(it) } - val context = JobContext(JobContextType.GetAccountInfo, this.callback, config, bank) + val context = JobContext(JobContextType.GetAccountInfo, this.callback, config, bank, null, param.preferredTanMethods, param.preferredTanMedium) /* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */ - val newUserInfoResponse = config.jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, param.preferredTanMethods, param.preferredTanMedium) + val newUserInfoResponse = config.jobExecutor.retrieveBasicDataLikeUsersTanMethods(context) /* Second dialog, executed in retrieveBasicDataLikeUsersTanMethods() if required: some banks require that in order to initialize a dialog with strong customer authorization TAN media is required */ diff --git a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClientDeprecated.kt b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClientDeprecated.kt index bc77e8f5..e1883c12 100644 --- a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClientDeprecated.kt +++ b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsClientDeprecated.kt @@ -1,7 +1,5 @@ package net.codinux.banking.fints -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import kotlinx.datetime.* import net.codinux.banking.fints.callback.FinTsClientCallback import net.codinux.banking.fints.config.FinTsClientConfiguration @@ -39,13 +37,13 @@ open class FinTsClientDeprecated( } - open suspend fun addAccountAsync(parameter: AddAccountParameter): AddAccountResponse { - val bank = parameter.bank - val context = JobContext(JobContextType.AddAccount, this.callback, config, bank) + open suspend fun addAccountAsync(param: AddAccountParameter): AddAccountResponse { + val bank = param.bank + val context = JobContext(JobContextType.AddAccount, this.callback, config, bank, null, param.preferredTanMethods, param.preferredTanMedium) /* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */ - val newUserInfoResponse = config.jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, parameter.preferredTanMethods, parameter.preferredTanMedium) + val newUserInfoResponse = config.jobExecutor.retrieveBasicDataLikeUsersTanMethods(context) if (newUserInfoResponse.successful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong return AddAccountResponse(context, newUserInfoResponse) @@ -54,7 +52,7 @@ open class FinTsClientDeprecated( /* Second dialog, executed in retrieveBasicDataLikeUsersTanMethods() if required: some banks require that in order to initialize a dialog with strong customer authorization TAN media is required */ - return addAccountGetAccountsAndTransactions(context, parameter) + return addAccountGetAccountsAndTransactions(context, param) } protected open suspend fun addAccountGetAccountsAndTransactions(context: JobContext, parameter: AddAccountParameter): AddAccountResponse { @@ -120,11 +118,11 @@ open class FinTsClientDeprecated( return GetAccountTransactionsParameter(bank, account, account.supportsRetrievingBalance, ninetyDaysAgo, abortIfTanIsRequired = true) } - open suspend fun getAccountTransactionsAsync(parameter: GetAccountTransactionsParameter): GetAccountTransactionsResponse { + open suspend fun getAccountTransactionsAsync(param: GetAccountTransactionsParameter): GetAccountTransactionsResponse { - val context = JobContext(JobContextType.GetTransactions, this.callback, config, parameter.bank, parameter.account) + val context = JobContext(JobContextType.GetTransactions, this.callback, config, param.bank, param.account) - return config.jobExecutor.getTransactionsAsync(context, parameter) + return config.jobExecutor.getTransactionsAsync(context, param) } diff --git a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsJobExecutor.kt b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsJobExecutor.kt index 804c8b61..33ce4df2 100644 --- a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsJobExecutor.kt +++ b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/FinTsJobExecutor.kt @@ -20,6 +20,7 @@ import net.codinux.banking.fints.response.segments.* import net.codinux.banking.fints.tan.FlickerCodeDecoder import net.codinux.banking.fints.tan.TanImageDecoder import net.codinux.banking.fints.util.TanMethodSelector +import net.codinux.log.Log import kotlin.math.max import kotlin.time.Duration.Companion.seconds @@ -73,8 +74,7 @@ open class FinTsJobExecutor( * * Be aware this method resets BPD, UPD and selected TAN method! */ - open suspend fun retrieveBasicDataLikeUsersTanMethods(context: JobContext, preferredTanMethods: List? = null, preferredTanMedium: String? = null, - closeDialog: Boolean = false): BankResponse { + open suspend fun retrieveBasicDataLikeUsersTanMethods(context: JobContext): BankResponse { val bank = context.bank // just to ensure settings are in its initial state and that bank sends us bank parameter (BPD), @@ -90,7 +90,7 @@ open class FinTsJobExecutor( bank.resetSelectedTanMethod() // this is the only case where Einschritt-TAN-Verfahren is accepted: to get user's TAN methods - context.startNewDialog(closeDialog, versionOfSecurityProcedure = VersionDesSicherheitsverfahrens.Version_1) + context.startNewDialog(versionOfSecurityProcedure = VersionDesSicherheitsverfahrens.Version_1) val message = messageBuilder.createInitDialogMessage(context) @@ -103,12 +103,10 @@ open class FinTsJobExecutor( if (bank.tanMethodsAvailableForUser.isEmpty()) { // could not retrieve supported tan methods for user return getTanMethodsResponse } else { - getUsersTanMethod(context, preferredTanMethods) + getUsersTanMethod(context) - if (bank.isTanMethodSelected == false) { - return getTanMethodsResponse - } else if (bank.tanMedia.isEmpty() && isJobSupported(bank, CustomerSegmentId.TanMediaList)) { // tan media not retrieved yet - getTanMediaList(context, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien, preferredTanMedium) + if (bank.isTanMethodSelected && bank.tanMedia.isEmpty() && bank.tanMethodsAvailableForUser.any { it.nameOfTanMediumRequired } && isJobSupported(bank, CustomerSegmentId.TanMediaList)) { // tan media not retrieved yet + getTanMediaList(context, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien, context.preferredTanMedium) return getTanMethodsResponse // TODO: judge if bank requires selecting TAN media and if though evaluate getTanMediaListResponse } else { @@ -384,14 +382,22 @@ open class FinTsJobExecutor( mayRetrieveAutomaticallyIfUserEnteredDecoupledTan(context, tanChallenge, tanResponse) + var invocationCount = 0 // TODO: remove again + while (tanChallenge.isEnteringTanDone == false) { delay(500) + if (++invocationCount % 10 == 0) { + Log.info { "Waiting for TAN input invocation count: $invocationCount" } + } + val now = Instant.nowExt() if ((tanChallenge.tanExpirationTime != null && now > tanChallenge.tanExpirationTime) || // most TANs a valid 5 - 15 minutes. So terminate wait process after that time (tanChallenge.tanExpirationTime == null && now > tanChallenge.challengeCreationTimestamp.plusMinutes(15))) { if (tanChallenge.isEnteringTanDone == false) { +Log.info { "Terminating waiting for TAN input" } // TODO: remove again + tanChallenge.tanExpired() } @@ -624,7 +630,7 @@ open class FinTsJobExecutor( protected open suspend fun initDialogWithStrongCustomerAuthenticationAfterSuccessfulPreconditionChecks(context: JobContext): BankResponse { - context.startNewDialog(false) // don't know if it's ok for all invocations of this method to set closeDialog to false (was actually only set in getAccounts()) + context.startNewDialog() // don't know if it's ok for all invocations of this method to set closeDialog to false (was actually only set in getAccounts()) val message = messageBuilder.createInitDialogMessage(context) @@ -700,7 +706,7 @@ open class FinTsJobExecutor( return BankResponse(true, noTanMethodSelected = noTanMethodSelected, internalError = errorMessage) } - open suspend fun getUsersTanMethod(context: JobContext, preferredTanMethods: List? = null): Boolean { + open suspend fun getUsersTanMethod(context: JobContext): Boolean { val bank = context.bank if (bank.tanMethodsAvailableForUser.size == 1) { // user has only one TAN method -> set it and we're done @@ -708,7 +714,7 @@ open class FinTsJobExecutor( return true } else { - tanMethodSelector.findPreferredTanMethod(bank.tanMethodsAvailableForUser, preferredTanMethods)?.let { + tanMethodSelector.findPreferredTanMethod(bank.tanMethodsAvailableForUser, context.preferredTanMethods)?.let { bank.selectedTanMethod = it return true } diff --git a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/model/JobContext.kt b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/model/JobContext.kt index b3b67103..13d56923 100644 --- a/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/model/JobContext.kt +++ b/fints4k/src/commonMain/kotlin/net/codinux/banking/fints/model/JobContext.kt @@ -25,6 +25,8 @@ open class JobContext( * Only set if the current context is for a specific account (like get account's transactions). */ open val account: AccountData? = null, + open val preferredTanMethods: List? = null, + open val preferredTanMedium: String? = null, protected open val messageLogCollector: MessageLogCollector = MessageLogCollector(callback, config.options) ) : MessageBaseData(bank, config.options.product), IMessageLogAppender {