diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt index 2a6b1fbe..927aef16 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt @@ -7,6 +7,7 @@ import net.dankito.banking.client.model.response.ErrorCode import net.dankito.banking.client.model.response.GetAccountDataResponse import net.dankito.banking.client.model.response.TransferMoneyResponse import net.dankito.banking.fints.callback.FinTsClientCallback +import net.dankito.banking.fints.config.FinTsClientConfiguration import net.dankito.banking.fints.mapper.FinTsModelMapper import net.dankito.banking.fints.model.* import net.dankito.banking.fints.response.client.FinTsClientResponse @@ -14,16 +15,11 @@ import net.dankito.banking.fints.response.client.GetAccountInfoResponse import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse import net.dankito.banking.fints.response.segments.AccountType import net.dankito.banking.fints.util.BicFinder -import net.dankito.banking.fints.util.FinTsServerAddressFinder -import net.dankito.banking.fints.webclient.IWebClient -import kotlin.jvm.JvmOverloads -open class FinTsClient @JvmOverloads constructor( - open var callback: FinTsClientCallback, - protected open val jobExecutor: FinTsJobExecutor = FinTsJobExecutor(), - protected open val finTsServerAddressFinder: FinTsServerAddressFinder = FinTsServerAddressFinder(), - protected open val product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically +open class FinTsClient( + protected open val config: FinTsClientConfiguration, + open var callback: FinTsClientCallback ) { companion object { // TODO: use the English names @@ -31,7 +27,7 @@ open class FinTsClient @JvmOverloads constructor( } - constructor(callback: FinTsClientCallback, webClient: IWebClient) : this(callback, FinTsJobExecutor(RequestExecutor(webClient = webClient))) // Swift does not support default parameter values -> create constructor overloads + constructor(callback: FinTsClientCallback) : this(FinTsClientConfiguration(), callback) protected open val mapper = FinTsModelMapper() @@ -44,7 +40,7 @@ open class FinTsClient @JvmOverloads constructor( } open suspend fun getAccountDataAsync(param: GetAccountDataParameter): GetAccountDataResponse { - val finTsServerAddress = finTsServerAddressFinder.findFinTsServerAddress(param.bankCode) + val finTsServerAddress = config.finTsServerAddressFinder.findFinTsServerAddress(param.bankCode) if (finTsServerAddress.isNullOrBlank()) { return GetAccountDataResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not support FinTS 3.0 or we don't know its FinTS server address", null, listOf()) } @@ -88,9 +84,9 @@ open class FinTsClient @JvmOverloads constructor( } protected open suspend fun getAccountData(param: GetAccountDataParameter, bank: BankData, account: AccountData): GetAccountTransactionsResponse { - val context = JobContext(JobContextType.GetTransactions, this.callback, product, bank, account) + val context = JobContext(JobContextType.GetTransactions, this.callback, config, bank, account) - return jobExecutor.getTransactionsAsync(context, mapper.toGetAccountTransactionsParameter(param, bank, account)) + return config.jobExecutor.getTransactionsAsync(context, mapper.toGetAccountTransactionsParameter(param, bank, account)) } @@ -100,7 +96,7 @@ open class FinTsClient @JvmOverloads constructor( } open suspend fun transferMoneyAsync(param: TransferMoneyParameter): TransferMoneyResponse { - val finTsServerAddress = finTsServerAddressFinder.findFinTsServerAddress(param.bankCode) + val finTsServerAddress = config.finTsServerAddressFinder.findFinTsServerAddress(param.bankCode) if (finTsServerAddress.isNullOrBlank()) { return TransferMoneyResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not FinTS 3.0 or we don't know its FinTS server address", listOf(), null) } @@ -146,9 +142,9 @@ open class FinTsClient @JvmOverloads constructor( accountToUse = selectedAccount } - val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, accountToUse) + val context = JobContext(JobContextType.TransferMoney, this.callback, config, bank, accountToUse) - val response = jobExecutor.transferMoneyAsync(context, BankTransferData(param.recipientName, param.recipientAccountIdentifier, recipientBankIdentifier, + val response = config.jobExecutor.transferMoneyAsync(context, BankTransferData(param.recipientName, param.recipientAccountIdentifier, recipientBankIdentifier, param.amount, param.reference, param.instantPayment)) return TransferMoneyResponse(mapper.mapErrorCode(response), mapper.mapErrorMessages(response), mapper.mergeMessageLog(previousJobResponse, response), bank) @@ -173,11 +169,11 @@ open class FinTsClient @JvmOverloads constructor( // return GetAccountInfoResponse(it) } - val context = JobContext(JobContextType.GetAccountInfo, this.callback, product, bank) + val context = JobContext(JobContextType.GetAccountInfo, this.callback, config, bank) /* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */ - val newUserInfoResponse = jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, param.preferredTanMethods, param.preferredTanMedium) + val newUserInfoResponse = config.jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, param.preferredTanMethods, param.preferredTanMedium) if (newUserInfoResponse.successful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong return GetAccountInfoResponse(context, newUserInfoResponse) @@ -186,7 +182,7 @@ open class FinTsClient @JvmOverloads constructor( /* 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 */ - val getAccountsResponse = jobExecutor.getAccounts(context) + val getAccountsResponse = config.jobExecutor.getAccounts(context) return GetAccountInfoResponse(context, getAccountsResponse) } diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt index 9c1aeb2c..60228c3c 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.datetime.* import net.dankito.banking.fints.callback.FinTsClientCallback +import net.dankito.banking.fints.config.FinTsClientConfiguration import net.dankito.banking.fints.extensions.minusDays import net.dankito.banking.fints.extensions.todayAtEuropeBerlin import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.* @@ -18,14 +19,11 @@ import net.dankito.banking.fints.webclient.IWebClient * [addAccountAsync] gets user's TAN methods, user's TAN media, user's bank accounts and may even current balance and account transactions of last 90 days. */ open class FinTsClientDeprecated( - open var callback: FinTsClientCallback, - protected open val jobExecutor: FinTsJobExecutor = FinTsJobExecutor(), - protected open val product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically + protected val config: FinTsClientConfiguration, + open var callback: FinTsClientCallback ) { - constructor(callback: FinTsClientCallback) : this(callback, FinTsJobExecutor()) // Swift does not support default parameter values -> create constructor overloads - - constructor(callback: FinTsClientCallback, webClient: IWebClient) : this(callback, FinTsJobExecutor(RequestExecutor(webClient = webClient))) + constructor(callback: FinTsClientCallback) : this(FinTsClientConfiguration(), callback) /** @@ -48,20 +46,20 @@ open class FinTsClientDeprecated( * On success [bank] parameter is updated afterwards. */ open suspend fun getAnonymousBankInfo(bank: BankData): FinTsClientResponse { - val context = JobContext(JobContextType.AnonymousBankInfo, this.callback, product, bank) + val context = JobContext(JobContextType.AnonymousBankInfo, this.callback, config, bank) - val response = jobExecutor.getAnonymousBankInfo(context) + val response = config.jobExecutor.getAnonymousBankInfo(context) return FinTsClientResponse(context, response) } open suspend fun addAccountAsync(parameter: AddAccountParameter): AddAccountResponse { val bank = parameter.bank - val context = JobContext(JobContextType.AddAccount, this.callback, product, bank) + val context = JobContext(JobContextType.AddAccount, this.callback, config, bank) /* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */ - val newUserInfoResponse = jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, parameter.preferredTanMethods, parameter.preferredTanMedium) + val newUserInfoResponse = config.jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, parameter.preferredTanMethods, parameter.preferredTanMedium) if (newUserInfoResponse.successful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong return AddAccountResponse(context, newUserInfoResponse) @@ -77,7 +75,7 @@ open class FinTsClientDeprecated( /* Third dialog: Now we can initialize our first dialog with strong customer authorization. Use it to get UPD and customer's accounts */ - val getAccountsResponse = jobExecutor.getAccounts(context) + val getAccountsResponse = config.jobExecutor.getAccounts(context) if (getAccountsResponse.successful == false) { return AddAccountResponse(context, getAccountsResponse) @@ -138,33 +136,33 @@ open class FinTsClientDeprecated( open suspend fun getAccountTransactionsAsync(parameter: GetAccountTransactionsParameter): GetAccountTransactionsResponse { - val context = JobContext(JobContextType.GetTransactions, this.callback, product, parameter.bank, parameter.account) + val context = JobContext(JobContextType.GetTransactions, this.callback, config, parameter.bank, parameter.account) - return jobExecutor.getTransactionsAsync(context, parameter) + return config.jobExecutor.getTransactionsAsync(context, parameter) } open suspend fun getTanMediaList(bank: BankData, tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle, tanMediumClass: TanMediumKlasse = TanMediumKlasse.AlleMedien): GetTanMediaListResponse { - val context = JobContext(JobContextType.GetTanMedia, this.callback, product, bank) + val context = JobContext(JobContextType.GetTanMedia, this.callback, config, bank) - return jobExecutor.getTanMediaList(context, tanMediaKind, tanMediumClass) + return config.jobExecutor.getTanMediaList(context, tanMediaKind, tanMediumClass) } open suspend fun changeTanMedium(newActiveTanMedium: TanGeneratorTanMedium, bank: BankData): FinTsClientResponse { - val context = JobContext(JobContextType.ChangeTanMedium, this.callback, product, bank) + val context = JobContext(JobContextType.ChangeTanMedium, this.callback, config, bank) - val response = jobExecutor.changeTanMedium(context, newActiveTanMedium) + val response = config.jobExecutor.changeTanMedium(context, newActiveTanMedium) return FinTsClientResponse(context, response) } open suspend fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData, account: AccountData): FinTsClientResponse { - val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, account) + val context = JobContext(JobContextType.TransferMoney, this.callback, config, bank, account) - return jobExecutor.transferMoneyAsync(context, bankTransferData) + return config.jobExecutor.transferMoneyAsync(context, bankTransferData) } } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientForCustomer.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientForCustomer.kt index 09e78ee2..e0d62302 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientForCustomer.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientForCustomer.kt @@ -1,35 +1,23 @@ package net.dankito.banking.fints import net.dankito.banking.fints.callback.FinTsClientCallback -import net.dankito.banking.fints.messages.MessageBuilder +import net.dankito.banking.fints.config.FinTsClientConfiguration import net.dankito.banking.fints.model.* -import net.dankito.banking.fints.model.mapper.ModelMapper import net.dankito.banking.fints.response.client.AddAccountResponse import net.dankito.banking.fints.response.client.FinTsClientResponse import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse -import net.dankito.banking.fints.util.IBase64Service -import net.dankito.banking.fints.util.PureKotlinBase64Service -import net.dankito.banking.fints.util.TanMethodSelector -import net.dankito.banking.fints.webclient.IWebClient -import net.dankito.banking.fints.webclient.KtorWebClient open class FinTsClientForCustomer( val bank: BankData, - callback: FinTsClientCallback, - requestExecutor: RequestExecutor = RequestExecutor(), - messageBuilder: MessageBuilder = MessageBuilder(), - modelMapper: ModelMapper = ModelMapper(messageBuilder), - protected open val tanMethodSelector: TanMethodSelector = TanMethodSelector(), - product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically) + config: FinTsClientConfiguration, + callback: FinTsClientCallback ) { - constructor(bank: BankData, callback: FinTsClientCallback, webClient: IWebClient = KtorWebClient(), base64Service: IBase64Service = PureKotlinBase64Service(), - product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0")) // TODO: get version dynamically) - : this(bank, callback, RequestExecutor(MessageBuilder(), webClient, base64Service), product = product) + constructor(bank: BankData, callback: FinTsClientCallback) : this(bank, FinTsClientConfiguration(), callback) - protected val client = FinTsClientDeprecated(callback, FinTsJobExecutor(requestExecutor, messageBuilder, modelMapper, tanMethodSelector), product) + protected val client = FinTsClientDeprecated(config, callback) open val messageLogWithoutSensitiveData: List = mutableListOf() diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/config/FinTsClientConfiguration.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/config/FinTsClientConfiguration.kt new file mode 100644 index 00000000..d2bb0b5a --- /dev/null +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/config/FinTsClientConfiguration.kt @@ -0,0 +1,26 @@ +package net.dankito.banking.fints.config + +import net.dankito.banking.fints.FinTsJobExecutor +import net.dankito.banking.fints.RequestExecutor +import net.dankito.banking.fints.log.MessageLogCollector +import net.dankito.banking.fints.messages.MessageBuilder +import net.dankito.banking.fints.model.mapper.ModelMapper +import net.dankito.banking.fints.util.FinTsServerAddressFinder +import net.dankito.banking.fints.util.IBase64Service +import net.dankito.banking.fints.util.PureKotlinBase64Service +import net.dankito.banking.fints.util.TanMethodSelector +import net.dankito.banking.fints.webclient.IWebClient +import net.dankito.banking.fints.webclient.KtorWebClient + +class FinTsClientConfiguration( + var options: FinTsClientOptions = FinTsClientOptions(), + messageBuilder: MessageBuilder = MessageBuilder(), + webClient: IWebClient = KtorWebClient(), + base64Service: IBase64Service = PureKotlinBase64Service(), + requestExecutor: RequestExecutor = RequestExecutor(messageBuilder, webClient, base64Service), + modelMapper: ModelMapper = ModelMapper(messageBuilder), + tanMethodSelector: TanMethodSelector = TanMethodSelector(), + var jobExecutor: FinTsJobExecutor = FinTsJobExecutor(requestExecutor, messageBuilder, modelMapper, tanMethodSelector), + var finTsServerAddressFinder: FinTsServerAddressFinder = FinTsServerAddressFinder(), + var messageLogCollector: MessageLogCollector = MessageLogCollector() +) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/config/FinTsClientOptions.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/config/FinTsClientOptions.kt new file mode 100644 index 00000000..57d6dfc7 --- /dev/null +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/config/FinTsClientOptions.kt @@ -0,0 +1,12 @@ +package net.dankito.banking.fints.config + +import net.dankito.banking.fints.model.ProductData + +data class FinTsClientOptions( + val version: String = "1.0.0", // TODO: get version dynamically + val productName: String = "15E53C26816138699C7B6A3E8" +) { + + val product: ProductData by lazy { ProductData(productName, version) } + +} \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/JobContext.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/JobContext.kt index 3073d9f9..ace69564 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/JobContext.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/JobContext.kt @@ -2,6 +2,7 @@ package net.dankito.banking.fints.model import kotlinx.atomicfu.atomic import net.dankito.banking.fints.callback.FinTsClientCallback +import net.dankito.banking.fints.config.FinTsClientConfiguration import net.dankito.banking.fints.log.IMessageLogAppender import net.dankito.banking.fints.log.MessageContext import net.dankito.banking.fints.log.MessageLogCollector @@ -17,14 +18,13 @@ import kotlin.reflect.KClass open class JobContext( open val type: JobContextType, open val callback: FinTsClientCallback, - product: ProductData, + open val config: FinTsClientConfiguration, bank: BankData, /** * Only set if the current context is for a specific account (like get account's transactions). */ - open val account: AccountData? = null, - protected open val messageLogCollector: MessageLogCollector = MessageLogCollector() -) : MessageBaseData(bank, product), IMessageLogAppender { + open val account: AccountData? = null +) : MessageBaseData(bank, config.options.product), IMessageLogAppender { companion object { private val JobCount = atomic(0) // this variable is accessed from multiple threads, so make it thread safe @@ -38,7 +38,7 @@ open class JobContext( open val responseParser: ResponseParser = ResponseParser(logAppender = this) open val messageLogWithoutSensitiveData: List - get() = messageLogCollector.messageLogWithoutSensitiveData + get() = config.messageLogCollector.messageLogWithoutSensitiveData open var dialog: DialogContext = DialogContext() // create null value so that variable is not null @@ -72,11 +72,11 @@ open class JobContext( open fun addMessageLog(type: MessageLogEntryType, message: String) { - messageLogCollector.addMessageLog(type, message, createMessageContext()) + config.messageLogCollector.addMessageLog(type, message, createMessageContext()) } override fun logError(loggingClass: KClass<*>, message: String, e: Exception?) { - messageLogCollector.logError(loggingClass, message, createMessageContext(), e) + config.messageLogCollector.logError(loggingClass, message, createMessageContext(), e) } protected open fun createMessageContext(): MessageContext { diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/FinTsTestBase.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/FinTsTestBase.kt index c00fb4c7..2fb6b8f1 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/FinTsTestBase.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/FinTsTestBase.kt @@ -2,6 +2,7 @@ package net.dankito.banking.fints import kotlinx.datetime.LocalDate import net.dankito.banking.fints.callback.SimpleFinTsClientCallback +import net.dankito.banking.fints.config.FinTsClientConfiguration import net.dankito.banking.fints.extensions.randomWithSeed import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Datum import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Laenderkennzeichen @@ -55,6 +56,8 @@ abstract class FinTsTestBase { const val Time = 182752 + val ClientConfig = FinTsClientConfiguration() + init { Bank.changeTanMediumParameters = ChangeTanMediaParameters(JobParameters("", 1, 1, 1, ":0:0"), false, false, false, false, false, listOf()) @@ -72,7 +75,7 @@ abstract class FinTsTestBase { protected open fun createContext(bank: BankData = Bank, dialogId: String = DialogContext.InitialDialogId): JobContext { - val context = JobContext(JobContextType.AnonymousBankInfo, SimpleFinTsClientCallback(), Product, bank) + val context = JobContext(JobContextType.AnonymousBankInfo, SimpleFinTsClientCallback(), ClientConfig, bank) context.startNewDialog(dialogId = dialogId) return context