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 8bfcb75c..c4ea7a9c 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt @@ -56,9 +56,9 @@ open class FinTsClient( protected val messageLogField = ArrayList() // TODO: make thread safe like with CopyOnWriteArrayList - // in either case remove sensitive data after response is parsed as otherwise some information like account holder name and accounts may is not set yet on CustomerData + // in either case remove sensitive data after response is parsed as otherwise some information like account holder name and accounts may is not set yet on BankData open val messageLogWithoutSensitiveData: List - get() = messageLogField.map { MessageLogEntry(removeSensitiveDataFromMessage(it.message, it.customer), it.time, it.customer) } + get() = messageLogField.map { MessageLogEntry(removeSensitiveDataFromMessage(it.message, it.bank), it.time, it.bank) } /** @@ -81,7 +81,7 @@ open class FinTsClient( * On success [bank] parameter is updated afterwards. */ open fun getAnonymousBankInfo(bank: BankData, callback: (FinTsClientResponse) -> Unit) { - val dialogContext = DialogContext(bank, CustomerData.Anonymous, product) + val dialogContext = DialogContext(bank, product) val message = messageBuilder.createAnonymousDialogInitMessage(dialogContext) @@ -109,21 +109,21 @@ open class FinTsClient( } - open fun getUsersTanProcedures(bank: BankData, customer: CustomerData, callback: (AddAccountResponse) -> Unit) { + open fun getUsersTanProcedures(bank: BankData, callback: (AddAccountResponse) -> Unit) { // just to ensure settings are in its initial state and that bank sends us bank parameter (BPD), // user parameter (UPD) and allowed tan procedures for user (therefore the resetSelectedTanProcedure()) bank.resetBpdVersion() - customer.resetUpdVersion() + bank.resetUpdVersion() /** * Sind dem Kundenprodukt die konkreten, für den Benutzer zugelassenen Sicherheitsverfahren nicht bekannt, so können * diese über eine Dialoginitialisierung mit Sicherheitsfunktion=999 angefordert werden. Die konkreten Verfahren * werden dann über den Rückmeldungscode=3920 zurückgemeldet. Im Rahmen dieses Prozesses darf keine UPD * zurückgeliefert werden und die Durchführung anderer Geschäftsvorfälle ist in einem solchen Dialog nicht erlaubt. */ - customer.resetSelectedTanProcedure() + bank.resetSelectedTanProcedure() // this is the only case where Einschritt-TAN-Verfahren is accepted: to get user's TAN procedures - val dialogContext = DialogContext(bank, customer, product, versionOfSecurityProcedure = VersionDesSicherheitsverfahrens.Version_1) + val dialogContext = DialogContext(bank, product, versionOfSecurityProcedure = VersionDesSicherheitsverfahrens.Version_1) val message = messageBuilder.createInitDialogMessage(dialogContext) @@ -139,15 +139,15 @@ open class FinTsClient( if (getUsersTanProceduresResponse.successful) { // TODO: really update data only on complete successfully response? as it may contain useful information anyway // TODO: extract method for this code part updateBankData(dialogContext.bank, getUsersTanProceduresResponse) - updateCustomerData(dialogContext.customer, dialogContext.bank, getUsersTanProceduresResponse) + updateCustomerData(dialogContext.bank, getUsersTanProceduresResponse) } // even though it is required by specification some banks don't support retrieving user's TAN procedure by setting TAN procedure to '999' if (bankDoesNotSupportRetrievingUsersTanProcedures(getUsersTanProceduresResponse)) { - getBankAndCustomerInfoForNewUserViaAnonymousDialog(dialogContext.bank, dialogContext.customer, callback) // TODO: should not be necessary anymore + getBankAndCustomerInfoForNewUserViaAnonymousDialog(dialogContext.bank, callback) // TODO: should not be necessary anymore } else { - callback(AddAccountResponse(getUsersTanProceduresResponse, dialogContext.bank, dialogContext.customer)) + callback(AddAccountResponse(getUsersTanProceduresResponse, dialogContext.bank)) } } @@ -158,44 +158,44 @@ open class FinTsClient( } // TODO: this is only a quick fix. Find a better and general solution - protected open fun getBankAndCustomerInfoForNewUserViaAnonymousDialog(bank: BankData, customer: CustomerData, callback: (AddAccountResponse) -> Unit) { + protected open fun getBankAndCustomerInfoForNewUserViaAnonymousDialog(bank: BankData, callback: (AddAccountResponse) -> Unit) { getAnonymousBankInfo(bank) { anonymousBankInfoResponse -> if (anonymousBankInfoResponse.isSuccessful == false) { - callback(AddAccountResponse(anonymousBankInfoResponse.toResponse(), bank, customer)) + callback(AddAccountResponse(anonymousBankInfoResponse.toResponse(), bank)) } - else if (bank.supportedTanProcedures.isEmpty()) { // should only be a theoretical error + else if (bank.tanProceduresSupportedByBank.isEmpty()) { // should only be a theoretical error callback(AddAccountResponse(Response(true, - errorMessage = "Die TAN Verfahren der Bank konnten nicht ermittelt werden"), bank, customer)) // TODO: translate + errorMessage = "Die TAN Verfahren der Bank konnten nicht ermittelt werden"), bank)) // TODO: translate } else { - customer.supportedTanProcedures = bank.supportedTanProcedures - getUsersTanProcedure(customer) + bank.tanProceduresAvailableForUser = bank.tanProceduresSupportedByBank + getUsersTanProcedure(bank) - val dialogContext = DialogContext(bank, customer, product) + val dialogContext = DialogContext(bank, product) initDialogAfterSuccessfulChecks(dialogContext) { initDialogResponse -> closeDialog(dialogContext) - callback(AddAccountResponse(initDialogResponse, bank, customer)) + callback(AddAccountResponse(initDialogResponse, bank)) } } } } - protected open fun getAccounts(bank: BankData, customer: CustomerData, callback: (AddAccountResponse) -> Unit) { + protected open fun getAccounts(bank: BankData, callback: (AddAccountResponse) -> Unit) { - val dialogContext = DialogContext(bank, customer, product) + val dialogContext = DialogContext(bank, product) initDialogAfterSuccessfulChecks(dialogContext) { response -> closeDialog(dialogContext) if (response.successful) { updateBankData(bank, response) - updateCustomerData(customer, bank, response) + updateCustomerData(bank, response) } - callback(AddAccountResponse(response, bank, customer)) + callback(AddAccountResponse(response, bank)) } } @@ -211,15 +211,15 @@ open class FinTsClient( * * If you change customer system id during a dialog your messages get rejected by bank institute. */ - protected open fun synchronizeCustomerSystemId(bank: BankData, customer: CustomerData, callback: (FinTsClientResponse) -> Unit) { + protected open fun synchronizeCustomerSystemId(bank: BankData, callback: (FinTsClientResponse) -> Unit) { - val dialogContext = DialogContext(bank, customer, product) + val dialogContext = DialogContext(bank, product) val message = messageBuilder.createSynchronizeCustomerSystemIdMessage(dialogContext) getAndHandleResponseForMessage(message, dialogContext) { response -> if (response.successful) { updateBankData(bank, response) - updateCustomerData(customer, bank, response) + updateCustomerData(bank, response) closeDialog(dialogContext) } @@ -229,15 +229,14 @@ open class FinTsClient( } - open fun addAccountAsync(bank: BankData, customer: CustomerData, - callback: (AddAccountResponse) -> Unit) { + open fun addAccountAsync(bank: BankData, callback: (AddAccountResponse) -> Unit) { val originalAreWeThatGentleToCloseDialogs = areWeThatGentleToCloseDialogs areWeThatGentleToCloseDialogs = false /* First dialog: Get user's basic data like BPD, customer system ID and her TAN procedures */ - getUsersTanProcedures(bank, customer) { newUserInfoResponse -> + getUsersTanProcedures(bank) { newUserInfoResponse -> if (newUserInfoResponse.isSuccessful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong callback(newUserInfoResponse) @@ -247,25 +246,25 @@ open class FinTsClient( // do not ask user for tan at this stage var didOverwriteUserUnselectedTanProcedure = false - if (customer.isTanProcedureSelected == false && customer.supportedTanProcedures.isNotEmpty()) { + if (bank.isTanProcedureSelected == false && bank.tanProceduresAvailableForUser.isNotEmpty()) { - if (customer.supportedTanProcedures.size == 1) { // user has only one TAN procedure -> set it and we're done - customer.selectedTanProcedure = customer.supportedTanProcedures.first() + if (bank.tanProceduresAvailableForUser.size == 1) { // user has only one TAN procedure -> set it and we're done + bank.selectedTanProcedure = bank.tanProceduresAvailableForUser.first() } else { didOverwriteUserUnselectedTanProcedure = true - customer.selectedTanProcedure = selectSuggestedTanProcedure(customer) ?: customer.supportedTanProcedures.first() + bank.selectedTanProcedure = selectSuggestedTanProcedure(bank) ?: bank.tanProceduresAvailableForUser.first() } } /* Second dialgo: some banks require that in order to initialize a dialog with strong customer authorization TAN media is required */ - getTanMediaList(bank, customer, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien) { + getTanMediaList(bank, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien) { /* Third dialog: Now we can initialize our first dialog with strong customer authorization. Use it to get UPD and customer's accounts */ - getAccounts(bank, customer) { getAccountsResponse -> + getAccounts(bank) { getAccountsResponse -> if (getAccountsResponse.isSuccessful == false) { callback(getAccountsResponse) @@ -274,48 +273,48 @@ open class FinTsClient( /* Fourth dialog: Try to retrieve account balances and transactions of last 90 days without TAN */ - addAccountGetAccountBalancesAndTransactions(customer, bank, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, + addAccountGetAccountBalancesAndTransactions(bank, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, originalAreWeThatGentleToCloseDialogs, callback) } } } } - protected open fun addAccountGetAccountBalancesAndTransactions(customer: CustomerData, bank: BankData, newUserInfoResponse: AddAccountResponse, + protected open fun addAccountGetAccountBalancesAndTransactions(bank: BankData, newUserInfoResponse: AddAccountResponse, didOverwriteUserUnselectedTanProcedure: Boolean, originalAreWeThatGentleToCloseDialogs: Boolean, callback: (AddAccountResponse) -> Unit) { val transactionsOfLast90DaysResponses = mutableListOf() val balances = mutableMapOf() - val accountSupportingRetrievingTransactions = customer.accounts.filter { it.supportsFeature(AccountFeature.RetrieveBalance) || it.supportsFeature(AccountFeature.RetrieveAccountTransactions) } + val accountSupportingRetrievingTransactions = bank.accounts.filter { it.supportsFeature(AccountFeature.RetrieveBalance) || it.supportsFeature(AccountFeature.RetrieveAccountTransactions) } val countAccountSupportingRetrievingTransactions = accountSupportingRetrievingTransactions.size var countRetrievedAccounts = 0 if (countAccountSupportingRetrievingTransactions == 0) { - addAccountAfterRetrievingTransactions(bank, customer, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, + addAccountAfterRetrievingTransactions(bank, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, originalAreWeThatGentleToCloseDialogs, transactionsOfLast90DaysResponses, balances, callback) } accountSupportingRetrievingTransactions.forEach { account -> - tryGetTransactionsOfLast90DaysWithoutTan(bank, customer, account) { response -> + tryGetTransactionsOfLast90DaysWithoutTan(bank, account) { response -> transactionsOfLast90DaysResponses.add(response) response.balance?.let { balances.put(account, it) } countRetrievedAccounts++ if (countRetrievedAccounts == countAccountSupportingRetrievingTransactions) { - addAccountAfterRetrievingTransactions(bank, customer, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, originalAreWeThatGentleToCloseDialogs, + addAccountAfterRetrievingTransactions(bank, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, originalAreWeThatGentleToCloseDialogs, transactionsOfLast90DaysResponses, balances, callback) } } } } - protected open fun addAccountAfterRetrievingTransactions(bank: BankData, customer: CustomerData, newUserInfoResponse: AddAccountResponse, + protected open fun addAccountAfterRetrievingTransactions(bank: BankData, newUserInfoResponse: AddAccountResponse, didOverwriteUserUnselectedTanProcedure: Boolean, originalAreWeThatGentleToCloseDialogs: Boolean, transactionsOfLast90DaysResponses: MutableList, balances: MutableMap, callback: (AddAccountResponse) -> Unit) { if (didOverwriteUserUnselectedTanProcedure) { - customer.resetSelectedTanProcedure() + bank.resetSelectedTanProcedure() } areWeThatGentleToCloseDialogs = originalAreWeThatGentleToCloseDialogs @@ -324,8 +323,9 @@ open class FinTsClient( val unbookedTransactions = transactionsOfLast90DaysResponses.flatMap { it.unbookedTransactions } val bookedTransactions = transactionsOfLast90DaysResponses.flatMap { it.bookedTransactions } - callback(AddAccountResponse(newUserInfoResponse.toResponse(), bank, customer, - supportsRetrievingTransactionsOfLast90DaysWithoutTan, bookedTransactions, unbookedTransactions, balances)) + // TODO: to evaluate if adding account has been successful also check if count accounts > 0 + callback(AddAccountResponse(newUserInfoResponse.toResponse(), bank, supportsRetrievingTransactionsOfLast90DaysWithoutTan, + bookedTransactions, unbookedTransactions, balances)) } @@ -335,20 +335,20 @@ open class FinTsClient( * * Check if bank supports this. */ - open fun tryGetTransactionsOfLast90DaysWithoutTan(bank: BankData, customer: CustomerData, account: AccountData, callback: (GetTransactionsResponse) -> Unit) { + open fun tryGetTransactionsOfLast90DaysWithoutTan(bank: BankData, account: AccountData, callback: (GetTransactionsResponse) -> Unit) { val now = Date() val ninetyDaysAgo = Date(now.millisSinceEpoch - NinetyDaysMillis) - getTransactionsAsync(GetTransactionsParameter(account.supportsFeature(AccountFeature.RetrieveBalance), ninetyDaysAgo, abortIfTanIsRequired = true), bank, customer, account) { response -> + getTransactionsAsync(GetTransactionsParameter(account.supportsFeature(AccountFeature.RetrieveBalance), ninetyDaysAgo, abortIfTanIsRequired = true), bank, account) { response -> callback(response) } } open fun getTransactionsAsync(parameter: GetTransactionsParameter, bank: BankData, - customer: CustomerData, account: AccountData, callback: (GetTransactionsResponse) -> Unit) { + account: AccountData, callback: (GetTransactionsResponse) -> Unit) { - val dialogContext = DialogContext(bank, customer, product) + val dialogContext = DialogContext(bank, product) initDialog(dialogContext) { initDialogResponse -> @@ -417,61 +417,60 @@ open class FinTsClient( } - open fun getTanMediaListAsync(bank: BankData, customer: CustomerData, - tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle, + open fun getTanMediaListAsync(bank: BankData, tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle, tanMediumClass: TanMediumKlasse = TanMediumKlasse.AlleMedien, callback: (GetTanMediaListResponse) -> Unit) { GlobalScope.launch { - getTanMediaList(bank, customer, tanMediaKind, tanMediumClass, callback) + getTanMediaList(bank, tanMediaKind, tanMediumClass, callback) } } - open fun getTanMediaList(bank: BankData, customer: CustomerData, tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle, + open fun getTanMediaList(bank: BankData, tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle, tanMediumClass: TanMediumKlasse = TanMediumKlasse.AlleMedien, callback: (GetTanMediaListResponse) -> Unit) { - sendMessageAndHandleResponse(bank, customer, true, CustomerSegmentId.TanMediaList, { dialogContext -> + sendMessageAndHandleResponse(bank, true, CustomerSegmentId.TanMediaList, { dialogContext -> messageBuilder.createGetTanMediaListMessage(dialogContext, tanMediaKind, tanMediumClass) }) { response -> - handleGetTanMediaListResponse(response, customer, callback) + handleGetTanMediaListResponse(response, bank, callback) } } - private fun handleGetTanMediaListResponse(response: Response, customer: CustomerData, callback: (GetTanMediaListResponse) -> Unit) { + private fun handleGetTanMediaListResponse(response: Response, bank: BankData, callback: (GetTanMediaListResponse) -> Unit) { // TAN media list (= TAN generator list) is only returned for users with chipTAN TAN procedures val tanMediaList = if (response.successful == false) null else response.getFirstSegmentById(InstituteSegmentId.TanMediaList) tanMediaList?.let { - customer.tanMedia = it.tanMedia + bank.tanMedia = it.tanMedia } callback(GetTanMediaListResponse(response, tanMediaList)) } - open fun changeTanMedium(newActiveTanMedium: TanGeneratorTanMedium, bank: BankData, customer: CustomerData, callback: (FinTsClientResponse) -> Unit) { + open fun changeTanMedium(newActiveTanMedium: TanGeneratorTanMedium, bank: BankData, callback: (FinTsClientResponse) -> Unit) { if (bank.changeTanMediumParameters?.enteringAtcAndTanRequired == true) { - this.callback.enterTanGeneratorAtc(customer, newActiveTanMedium) { enteredAtc -> + this.callback.enterTanGeneratorAtc(bank, newActiveTanMedium) { enteredAtc -> if (enteredAtc.hasAtcBeenEntered == false) { val message = "Bank requires to enter ATC and TAN in order to change TAN medium." // TODO: translate callback(FinTsClientResponse(Response(false, errorMessage = message))) } else { - sendChangeTanMediumMessage(bank, customer, newActiveTanMedium, enteredAtc, callback) + sendChangeTanMediumMessage(bank, newActiveTanMedium, enteredAtc, callback) } } } else { - sendChangeTanMediumMessage(bank, customer, newActiveTanMedium, null, callback) + sendChangeTanMediumMessage(bank, newActiveTanMedium, null, callback) } } - protected open fun sendChangeTanMediumMessage(bank: BankData, customer: CustomerData, newActiveTanMedium: TanGeneratorTanMedium, - enteredAtc: EnterTanGeneratorAtcResult?, callback: (FinTsClientResponse) -> Unit) { + protected open fun sendChangeTanMediumMessage(bank: BankData, newActiveTanMedium: TanGeneratorTanMedium, enteredAtc: EnterTanGeneratorAtcResult?, + callback: (FinTsClientResponse) -> Unit) { - sendMessageAndHandleResponse(bank, customer, false, null, { dialogContext -> + sendMessageAndHandleResponse(bank, false, null, { dialogContext -> messageBuilder.createChangeTanMediumMessage(newActiveTanMedium, dialogContext, enteredAtc?.tan, enteredAtc?.atc) }) { response -> callback(FinTsClientResponse(response)) @@ -479,10 +478,9 @@ open class FinTsClient( } - open fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData, - customer: CustomerData, account: AccountData, callback: (FinTsClientResponse) -> Unit) { + open fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData, account: AccountData, callback: (FinTsClientResponse) -> Unit) { - sendMessageAndHandleResponse(bank, customer, true, null, { dialogContext -> + sendMessageAndHandleResponse(bank, true, null, { dialogContext -> messageBuilder.createBankTransferMessage(bankTransferData, account, dialogContext) }) { response -> callback(FinTsClientResponse(response)) @@ -490,11 +488,10 @@ open class FinTsClient( } - protected open fun sendMessageAndHandleResponse(bank: BankData, customer: CustomerData, messageMayRequiresTan: Boolean = true, - segmentForNonStrongCustomerAuthenticationTwoStepTanProcess: CustomerSegmentId? = null, + protected open fun sendMessageAndHandleResponse(bank: BankData, messageMayRequiresTan: Boolean = true, segmentForNonStrongCustomerAuthenticationTwoStepTanProcess: CustomerSegmentId? = null, createMessage: (DialogContext) -> MessageBuilderResult, callback: (Response) -> Unit) { - val dialogContext = DialogContext(bank, customer, product) + val dialogContext = DialogContext(bank, product) if (segmentForNonStrongCustomerAuthenticationTwoStepTanProcess == null) { initDialog(dialogContext) { initDialogResponse -> @@ -527,13 +524,13 @@ open class FinTsClient( protected open fun initDialog(dialogContext: DialogContext, callback: (Response) -> Unit) { // we first need to retrieve supported tan procedures and jobs before we can do anything - ensureBasicBankDataRetrieved(dialogContext.bank, dialogContext.customer) { retrieveBasicBankDataResponse -> + ensureBasicBankDataRetrieved(dialogContext.bank) { retrieveBasicBankDataResponse -> if (retrieveBasicBankDataResponse.successful == false) { callback(retrieveBasicBankDataResponse) } else { // as in the next step we have to supply user's tan procedure, ensure user selected his or her - ensureTanProcedureIsSelected(dialogContext.bank, dialogContext.customer) { tanProcedureSelectedResponse -> + ensureTanProcedureIsSelected(dialogContext.bank) { tanProcedureSelectedResponse -> if (tanProcedureSelectedResponse.successful == false) { callback(tanProcedureSelectedResponse) } @@ -553,7 +550,7 @@ open class FinTsClient( if (response.successful) { updateBankData(dialogContext.bank, response) - updateCustomerData(dialogContext.customer, dialogContext.bank, response) + updateCustomerData(dialogContext.bank, response) } callback(response) @@ -568,7 +565,7 @@ open class FinTsClient( getAndHandleResponseForMessage(message, dialogContext) { response -> if (response.successful) { updateBankData(dialogContext.bank, response) - updateCustomerData(dialogContext.customer, dialogContext.bank, response) + updateCustomerData(dialogContext.bank, response) } callback(response) @@ -588,10 +585,10 @@ open class FinTsClient( } - protected open fun ensureBasicBankDataRetrieved(bank: BankData, customer: CustomerData, callback: (Response) -> Unit) { - if (bank.supportedTanProcedures.isEmpty() || bank.supportedJobs.isEmpty()) { - getUsersTanProcedures(bank, customer) { getBankInfoResponse -> - if (getBankInfoResponse.isSuccessful == false || bank.supportedTanProcedures.isEmpty() + protected open fun ensureBasicBankDataRetrieved(bank: BankData, callback: (Response) -> Unit) { + if (bank.tanProceduresSupportedByBank.isEmpty() || bank.supportedJobs.isEmpty()) { + getUsersTanProcedures(bank) { getBankInfoResponse -> + if (getBankInfoResponse.isSuccessful == false || bank.tanProceduresSupportedByBank.isEmpty() || bank.supportedJobs.isEmpty()) { callback(Response(false, errorMessage = @@ -607,48 +604,48 @@ open class FinTsClient( } } - protected open fun ensureTanProcedureIsSelected(bank: BankData, customer: CustomerData, callback: (Response) -> Unit) { - if (customer.isTanProcedureSelected == false) { - if (customer.supportedTanProcedures.isEmpty()) { - getUsersTanProcedures(bank, customer) { - if (customer.supportedTanProcedures.isEmpty()) { // could not retrieve supported tan procedures for user + protected open fun ensureTanProcedureIsSelected(bank: BankData, callback: (Response) -> Unit) { + if (bank.isTanProcedureSelected == false) { + if (bank.tanProceduresAvailableForUser.isEmpty()) { + getUsersTanProcedures(bank) { + if (bank.tanProceduresAvailableForUser.isEmpty()) { // could not retrieve supported tan procedures for user callback(Response(false, noTanProcedureSelected = true)) } else { - getUsersTanProcedure(customer) - callback(Response(customer.isTanProcedureSelected, noTanProcedureSelected = !!!customer.isTanProcedureSelected)) + getUsersTanProcedure(bank) + callback(Response(bank.isTanProcedureSelected, noTanProcedureSelected = !!!bank.isTanProcedureSelected)) } } } else { - getUsersTanProcedure(customer) - callback(Response(customer.isTanProcedureSelected, noTanProcedureSelected = !!!customer.isTanProcedureSelected)) + getUsersTanProcedure(bank) + callback(Response(bank.isTanProcedureSelected, noTanProcedureSelected = !!!bank.isTanProcedureSelected)) } } else { - callback(Response(customer.isTanProcedureSelected, noTanProcedureSelected = !!!customer.isTanProcedureSelected)) + callback(Response(bank.isTanProcedureSelected, noTanProcedureSelected = !!!bank.isTanProcedureSelected)) } } - protected open fun getUsersTanProcedure(customer: CustomerData) { - if (customer.supportedTanProcedures.size == 1) { // user has only one TAN procedure -> set it and we're done - customer.selectedTanProcedure = customer.supportedTanProcedures.first() + protected open fun getUsersTanProcedure(bank: BankData) { + if (bank.tanProceduresAvailableForUser.size == 1) { // user has only one TAN procedure -> set it and we're done + bank.selectedTanProcedure = bank.tanProceduresAvailableForUser.first() } else { // we know user's supported tan procedures, now ask user which one to select - callback.askUserForTanProcedure(customer.supportedTanProcedures, selectSuggestedTanProcedure(customer)) { selectedTanProcedure -> + callback.askUserForTanProcedure(bank.tanProceduresAvailableForUser, selectSuggestedTanProcedure(bank)) { selectedTanProcedure -> selectedTanProcedure?.let { - customer.selectedTanProcedure = selectedTanProcedure + bank.selectedTanProcedure = selectedTanProcedure } } } } - protected open fun selectSuggestedTanProcedure(customer: CustomerData): TanProcedure? { - return customer.supportedTanProcedures.firstOrNull { it.type != TanProcedureType.ChipTanUsb && it.type != TanProcedureType.SmsTan && it.type != TanProcedureType.ChipTanManuell } - ?: customer.supportedTanProcedures.firstOrNull { it.type != TanProcedureType.ChipTanUsb && it.type != TanProcedureType.SmsTan } - ?: customer.supportedTanProcedures.firstOrNull { it.type != TanProcedureType.ChipTanUsb } - ?: customer.supportedTanProcedures.firstOrNull() + protected open fun selectSuggestedTanProcedure(bank: BankData): TanProcedure? { + return bank.tanProceduresAvailableForUser.firstOrNull { it.type != TanProcedureType.ChipTanUsb && it.type != TanProcedureType.SmsTan && it.type != TanProcedureType.ChipTanManuell } + ?: bank.tanProceduresAvailableForUser.firstOrNull { it.type != TanProcedureType.ChipTanUsb && it.type != TanProcedureType.SmsTan } + ?: bank.tanProceduresAvailableForUser.firstOrNull { it.type != TanProcedureType.ChipTanUsb } + ?: bank.tanProceduresAvailableForUser.firstOrNull() } @@ -766,24 +763,24 @@ open class FinTsClient( log.debug { prettyPrintMessageWithPrefix } - messageLogField.add(MessageLogEntry(prettyPrintMessageWithPrefix, timeStamp, dialogContext.customer)) + messageLogField.add(MessageLogEntry(prettyPrintMessageWithPrefix, timeStamp, dialogContext.bank)) } protected fun prettyPrintHbciMessage(message: String): String { return message.replace("'", "'\r\n") } - protected open fun removeSensitiveDataFromMessage(message: String, customer: CustomerData): String { + protected open fun removeSensitiveDataFromMessage(message: String, bank: BankData): String { var prettyPrintMessageWithoutSensitiveData = message - .replace(customer.customerId, "") - .replace("+" + customer.pin, "+") + .replace(bank.customerId, "") + .replace("+" + bank.pin, "+") - if (customer.name.isNotBlank()) { + if (bank.customerName.isNotBlank()) { prettyPrintMessageWithoutSensitiveData = prettyPrintMessageWithoutSensitiveData - .replace(customer.name, "", true) + .replace(bank.customerName, "", true) } - customer.accounts.forEach { account -> + bank.accounts.forEach { account -> prettyPrintMessageWithoutSensitiveData = prettyPrintMessageWithoutSensitiveData .replace(account.accountIdentifier, "") @@ -836,19 +833,19 @@ open class FinTsClient( } protected open fun handleEnteringTanRequired(tanResponse: TanResponse, response: Response, dialogContext: DialogContext, callback: (Response) -> Unit) { - val customer = dialogContext.customer // TODO: copy required data to TanChallenge - val tanChallenge = createTanChallenge(tanResponse, customer) + val bank = dialogContext.bank // TODO: copy required data to TanChallenge + val tanChallenge = createTanChallenge(tanResponse, bank) - this.callback.enterTan(customer, tanChallenge) { enteredTanResult -> + this.callback.enterTan(bank, tanChallenge) { enteredTanResult -> handleEnterTanResult(enteredTanResult, tanResponse, response, dialogContext, callback) } } - protected open fun createTanChallenge(tanResponse: TanResponse, customer: CustomerData): TanChallenge { + protected open fun createTanChallenge(tanResponse: TanResponse, bank: BankData): TanChallenge { // TODO: is this true for all tan procedures? val messageToShowToUser = tanResponse.challenge ?: "" val challenge = tanResponse.challengeHHD_UC ?: "" - val tanProcedure = customer.selectedTanProcedure + val tanProcedure = bank.selectedTanProcedure return when (tanProcedure.type) { TanProcedureType.ChipTanFlickercode -> @@ -894,7 +891,7 @@ open class FinTsClient( protected open fun handleUserAsksToChangeTanProcedureAndResendLastMessage(changeTanProcedureTo: TanProcedure, dialogContext: DialogContext, callback: (Response) -> Unit) { - dialogContext.customer.selectedTanProcedure = changeTanProcedureTo + dialogContext.bank.selectedTanProcedure = changeTanProcedureTo val lastCreatedMessage = dialogContext.currentMessage @@ -914,7 +911,7 @@ open class FinTsClient( lastCreatedMessage?.let { closeDialog(dialogContext) } - changeTanMedium(changeTanMediumTo, dialogContext.bank, dialogContext.customer) { changeTanMediumResponse -> + changeTanMedium(changeTanMediumTo, dialogContext.bank) { changeTanMediumResponse -> changeTanMediumResultCallback?.invoke(changeTanMediumResponse) if (changeTanMediumResponse.isSuccessful == false || lastCreatedMessage == null) { @@ -930,7 +927,7 @@ open class FinTsClient( protected open fun resendMessageInNewDialog(lastCreatedMessage: MessageBuilderResult?, previousDialogContext: DialogContext, callback: (Response) -> Unit) { if (lastCreatedMessage != null) { // do not use previousDialogContext.currentMessage as this may is previous dialog's dialog close message - val newDialogContext = DialogContext(previousDialogContext.bank, previousDialogContext.customer, previousDialogContext.product, chunkedResponseHandler = previousDialogContext.chunkedResponseHandler) + val newDialogContext = DialogContext(previousDialogContext.bank, previousDialogContext.product, chunkedResponseHandler = previousDialogContext.chunkedResponseHandler) initDialog(newDialogContext) { initDialogResponse -> if (initDialogResponse.successful == false) { @@ -957,7 +954,7 @@ open class FinTsClient( protected open fun updateBankData(bank: BankData, response: Response) { response.getFirstSegmentById(InstituteSegmentId.BankParameters)?.let { bankParameters -> bank.bpdVersion = bankParameters.bpdVersion - bank.name = adjustBankName(bankParameters.bankName) + bank.bankName = adjustBankName(bankParameters.bankName) bank.bankCode = bankParameters.bankCode bank.countryCode = bankParameters.bankCountryCode bank.countMaxJobsPerMessage = bankParameters.countMaxJobsPerMessage @@ -972,7 +969,7 @@ open class FinTsClient( } response.getFirstSegmentById(InstituteSegmentId.TanInfo)?.let { tanInfo -> - bank.supportedTanProcedures = mapToTanProcedures(tanInfo) + bank.tanProceduresSupportedByBank = mapToTanProcedures(tanInfo) } response.getFirstSegmentById(InstituteSegmentId.CommunicationInfo)?.let { communicationInfo -> @@ -1000,19 +997,19 @@ open class FinTsClient( return bankName.replace("DB24-Filiale", "Deutsche Bank") // set a better name for Deutsche Bank's self title 'DB24-Filiale' } - protected open fun updateCustomerData(customer: CustomerData, bank: BankData, response: Response) { + protected open fun updateCustomerData(bank: BankData, response: Response) { response.getFirstSegmentById(InstituteSegmentId.BankParameters)?.let { bankParameters -> // TODO: ask user if there is more than one supported language? But it seems that almost all banks only support German. - if (customer.selectedLanguage == Dialogsprache.Default && bankParameters.supportedLanguages.isNotEmpty()) { - customer.selectedLanguage = bankParameters.supportedLanguages.first() + if (bank.selectedLanguage == Dialogsprache.Default && bankParameters.supportedLanguages.isNotEmpty()) { + bank.selectedLanguage = bankParameters.supportedLanguages.first() } } response.getFirstSegmentById(InstituteSegmentId.Synchronization)?.let { synchronization -> synchronization.customerSystemId?.let { - customer.customerSystemId = it + bank.customerSystemId = it - customer.customerSystemStatus = KundensystemStatusWerte.Benoetigt // TODO: didn't find out for sure yet, but i think i read somewhere, that this has to be set when customerSystemId is set + bank.customerSystemStatus = KundensystemStatusWerte.Benoetigt // TODO: didn't find out for sure yet, but i think i read somewhere, that this has to be set when customerSystemId is set } } @@ -1021,9 +1018,9 @@ open class FinTsClient( accountInfo.accountHolderName2?.let { accountHolderName += it // TODO: add a whitespace in between? } - customer.name = accountHolderName + bank.customerName = accountHolderName - findExistingAccount(customer, accountInfo)?.let { account -> + findExistingAccount(bank, accountInfo)?.let { account -> // TODO: update AccountData. But can this ever happen that an account changes? } ?: run { @@ -1032,7 +1029,7 @@ open class FinTsClient( accountInfo.accountType, accountInfo.currency, accountHolderName, accountInfo.productName, accountInfo.accountLimit, accountInfo.allowedJobNames) - customer.addAccount(newAccount) + bank.addAccount(newAccount) } // TODO: may also make use of other info @@ -1046,11 +1043,11 @@ open class FinTsClient( } response.getFirstSegmentById(InstituteSegmentId.UserParameters)?.let { userParameters -> - customer.updVersion = userParameters.updVersion + bank.updVersion = userParameters.updVersion - if (customer.name.isEmpty()) { + if (bank.customerName.isEmpty()) { userParameters.username?.let { - customer.name = it + bank.customerName = it } } @@ -1058,19 +1055,19 @@ open class FinTsClient( } response.getFirstSegmentById(InstituteSegmentId.CommunicationInfo)?.let { communicationInfo -> - if (customer.selectedLanguage != communicationInfo.defaultLanguage) { - customer.selectedLanguage = communicationInfo.defaultLanguage + if (bank.selectedLanguage != communicationInfo.defaultLanguage) { + bank.selectedLanguage = communicationInfo.defaultLanguage } } val supportedJobs = response.supportedJobs if (supportedJobs.isNotEmpty()) { // if allowedJobsForBank is empty than bank didn't send any allowed job - for (account in customer.accounts) { + for (account in bank.accounts) { setAllowedJobsForAccount(bank, account, supportedJobs) } } else if (bank.supportedJobs.isNotEmpty()) { - for (account in customer.accounts) { + for (account in bank.accounts) { if (account.allowedJobs.isEmpty()) { setAllowedJobsForAccount(bank, account, bank.supportedJobs) } @@ -1078,16 +1075,16 @@ open class FinTsClient( } if (response.supportedTanProceduresForUser.isNotEmpty()) { - customer.supportedTanProcedures = response.supportedTanProceduresForUser.mapNotNull { findTanProcedure(it, bank) } + bank.tanProceduresAvailableForUser = response.supportedTanProceduresForUser.mapNotNull { findTanProcedure(it, bank) } - if (customer.supportedTanProcedures.firstOrNull { it.securityFunction == customer.selectedTanProcedure.securityFunction } == null) { // supportedTanProcedures don't contain selectedTanProcedure anymore - customer.resetSelectedTanProcedure() + if (bank.tanProceduresAvailableForUser.firstOrNull { it.securityFunction == bank.selectedTanProcedure.securityFunction } == null) { // supportedTanProcedures don't contain selectedTanProcedure anymore + bank.resetSelectedTanProcedure() } } } protected open fun findTanProcedure(securityFunction: Sicherheitsfunktion, bank: BankData): TanProcedure? { - return bank.supportedTanProcedures.firstOrNull { it.securityFunction == securityFunction } + return bank.tanProceduresSupportedByBank.firstOrNull { it.securityFunction == securityFunction } } protected open fun setAllowedJobsForAccount(bank: BankData, account: AccountData, supportedJobs: List) { @@ -1214,8 +1211,8 @@ open class FinTsClient( return false } - protected open fun findExistingAccount(customer: CustomerData, accountInfo: AccountInfo): AccountData? { - customer.accounts.forEach { account -> + protected open fun findExistingAccount(bank: BankData, accountInfo: AccountInfo): AccountData? { + bank.accounts.forEach { account -> if (account.accountIdentifier == accountInfo.accountIdentifier && account.productName == accountInfo.productName && account.accountType == accountInfo.accountType) { 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 e8ec282c..978c7eaf 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientForCustomer.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientForCustomer.kt @@ -17,14 +17,13 @@ import net.dankito.banking.fints.webclient.KtorWebClient open class FinTsClientForCustomer( val bank: BankData, - val customer: CustomerData, callback: FinTsClientCallback, webClient: IWebClient = KtorWebClient(), base64Service: IBase64Service = PureKotlinBase64Service(), messageBuilder: MessageBuilder = MessageBuilder(), responseParser: ResponseParser = ResponseParser(), mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(), - product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically + product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically){} ) { protected val client = FinTsClient(callback, webClient, base64Service, messageBuilder, responseParser, mt940Parser, product) @@ -35,17 +34,17 @@ open class FinTsClientForCustomer( open fun addAccountAsync(callback: (AddAccountResponse) -> Unit) { - client.addAccountAsync(bank, customer, callback) + client.addAccountAsync(bank, callback) } open fun getTransactionsAsync(parameter: GetTransactionsParameter, account: AccountData, callback: (GetTransactionsResponse) -> Unit) { - client.getTransactionsAsync(parameter, bank, customer, account, callback) + client.getTransactionsAsync(parameter, bank, account, callback) } open fun doBankTransferAsync(bankTransferData: BankTransferData, account: AccountData, callback: (FinTsClientResponse) -> Unit) { - client.doBankTransferAsync(bankTransferData, bank, customer, account, callback) + client.doBankTransferAsync(bankTransferData, bank, account, callback) } } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/FinTsClientCallback.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/FinTsClientCallback.kt index 649facfb..64799c51 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/FinTsClientCallback.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/FinTsClientCallback.kt @@ -18,13 +18,13 @@ interface FinTsClientCallback { */ fun askUserForTanProcedure(supportedTanProcedures: List, suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit) - fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) + fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) /** * This method gets called for chipTan TAN generators when the bank asks the customer to synchronize her/his TAN generator. * * If you do not support entering TAN generator ATC, return [EnterTanGeneratorAtcResult.userDidNotEnterAtc] */ - fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) + fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/NoOpFinTsClientCallback.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/NoOpFinTsClientCallback.kt index 7e3b7624..ccd5f6df 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/NoOpFinTsClientCallback.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/NoOpFinTsClientCallback.kt @@ -12,11 +12,11 @@ open class NoOpFinTsClientCallback : FinTsClientCallback { callback(suggestedTanProcedure) } - override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { + override fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { callback(EnterTanResult.userDidNotEnterTan()) } - override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { + override fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { callback(EnterTanGeneratorAtcResult.userDidNotEnterAtc()) } diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/SimpleFinTsClientCallback.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/SimpleFinTsClientCallback.kt index 1e9625bd..76ec7537 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/SimpleFinTsClientCallback.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/callback/SimpleFinTsClientCallback.kt @@ -5,8 +5,8 @@ import net.dankito.banking.fints.model.* open class SimpleFinTsClientCallback( - protected val enterTan: ((customer: CustomerData, tanChallenge: TanChallenge) -> EnterTanResult)? = null, - protected val enterTanGeneratorAtc: ((customer: CustomerData, tanMedium: TanGeneratorTanMedium) -> EnterTanGeneratorAtcResult)? = null, + protected val enterTan: ((bank: BankData, tanChallenge: TanChallenge) -> EnterTanResult)? = null, + protected val enterTanGeneratorAtc: ((bank: BankData, tanMedium: TanGeneratorTanMedium) -> EnterTanGeneratorAtcResult)? = null, protected val askUserForTanProcedure: ((supportedTanProcedures: List, suggestedTanProcedure: TanProcedure?) -> TanProcedure?)? = null ) : FinTsClientCallback { @@ -16,12 +16,12 @@ open class SimpleFinTsClientCallback( callback(askUserForTanProcedure?.invoke(supportedTanProcedures, suggestedTanProcedure) ?: suggestedTanProcedure) } - override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { - callback(enterTan?.invoke(customer, tanChallenge) ?: EnterTanResult.userDidNotEnterTan()) + override fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { + callback(enterTan?.invoke(bank, tanChallenge) ?: EnterTanResult.userDidNotEnterTan()) } - override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { - callback(enterTanGeneratorAtc?.invoke(customer, tanMedium) ?: EnterTanGeneratorAtcResult.userDidNotEnterAtc()) + override fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { + callback(enterTanGeneratorAtc?.invoke(bank, tanMedium) ?: EnterTanGeneratorAtcResult.userDidNotEnterAtc()) } } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilder.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilder.kt index 2fee9d7c..88e1724d 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilder.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilder.kt @@ -117,11 +117,11 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg if (segmentIdForTwoStepTanProcess != null) { segments.add(createTwoStepTanSegment(segmentIdForTwoStepTanProcess, dialogContext)) } - else if (dialogContext.customer.isTanProcedureSelected) { + else if (dialogContext.bank.isTanProcedureSelected) { segments.add(createTwoStepTanSegment(CustomerSegmentId.Identification, dialogContext)) } - if (dialogContext.customer.customerSystemId == KundensystemID.Anonymous) { + if (dialogContext.bank.customerSystemId == KundensystemID.Anonymous) { segments.add(Synchronisierung(generator.getNextSegmentNumber(), Synchronisierungsmodus.NeueKundensystemIdZurueckmelden)) } @@ -229,7 +229,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg if (result.isJobVersionSupported) { val segments = listOf( TanGeneratorTanMediumAnOderUmmelden(result.getHighestAllowedVersion!!, generator.resetSegmentNumber(2), - dialogContext.bank, dialogContext.customer, newActiveTanMedium, tan, atc) + dialogContext.bank, newActiveTanMedium, tan, atc) ) return createSignedMessageBuilderResult(dialogContext, segments) @@ -261,7 +261,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg if (result.isJobVersionSupported && urn != null) { val segments = mutableListOf(SepaBankTransferBase(segmentId, generator.resetSegmentNumber(2), - urn, dialogContext.customer, account, dialogContext.bank.bic, data)) + urn, dialogContext.bank.customerName, account, dialogContext.bank.bic, data)) addTanSegmentIfRequired(segmentId, dialogContext, segments) @@ -395,7 +395,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg val signatureEnding = Signaturabschluss( generator.getNextSegmentNumber(), controlReference, - dialogContext.customer.pin, + dialogContext.bank.pin, tan ) @@ -469,10 +469,10 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg } protected open fun getTanMediaIdentifierIfRequired(dialogContext: DialogContext): String? { - val customer = dialogContext.customer + val bank = dialogContext.bank - if (customer.isTanProcedureSelected && customer.selectedTanProcedure.nameOfTanMediaRequired) { - return customer.tanMedia.firstOrNull { it.mediumName != null }?.mediumName + if (bank.isTanProcedureSelected && bank.selectedTanProcedure.nameOfTanMediaRequired) { + return bank.tanMedia.firstOrNull { it.mediumName != null }?.mediumName } return null diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/implementierte/tan/JobTanConfiguration.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/implementierte/tan/JobTanConfiguration.kt index 228b3e7a..0619ef39 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/implementierte/tan/JobTanConfiguration.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/implementierte/tan/JobTanConfiguration.kt @@ -6,6 +6,10 @@ open class JobTanConfiguration( val tanRequired: Boolean ) { + + internal constructor() : this("", false) // for object deserializers + + override fun toString(): String { return "$segmentId requires TAN? $tanRequired" } diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegment.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegment.kt index fb9a162c..1d6677bc 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegment.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegment.kt @@ -18,7 +18,7 @@ open class IdentifikationsSegment( ) : Segment(listOf( Segmentkopf(CustomerSegmentId.Identification, 2, segmentNumber), Kreditinstitutskennung(baseData.bank.countryCode, baseData.bank.bankCode), - KundenID(baseData.customer.customerId), - KundensystemID(baseData.customer.customerSystemId), - KundensystemStatus(baseData.customer.customerSystemStatus, Existenzstatus.Mandatory) + KundenID(baseData.bank.customerId), + KundensystemID(baseData.bank.customerSystemId), + KundensystemStatus(baseData.bank.customerSystemStatus, Existenzstatus.Mandatory) )) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanSignaturkopf.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanSignaturkopf.kt index 94295989..73d23e7a 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanSignaturkopf.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanSignaturkopf.kt @@ -14,7 +14,6 @@ open class PinTanSignaturkopf( ) : Signaturkopf( segmentNumber, baseData.bank, - baseData.customer, baseData.versionOfSecurityProcedure, securityControlReference, date, diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanVerschluesselungskopf.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanVerschluesselungskopf.kt index 3414de3a..61be91df 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanVerschluesselungskopf.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/PinTanVerschluesselungskopf.kt @@ -13,7 +13,6 @@ open class PinTanVerschluesselungskopf( ) : Verschluesselungskopf( baseData.bank, - baseData.customer, baseData.versionOfSecurityProcedure, date, time, diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Signaturkopf.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Signaturkopf.kt index 2422b987..a4b9ec89 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Signaturkopf.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Signaturkopf.kt @@ -6,7 +6,6 @@ import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.sig import net.dankito.banking.fints.messages.segmente.Segment import net.dankito.banking.fints.messages.segmente.id.MessageSegmentId import net.dankito.banking.fints.model.BankData -import net.dankito.banking.fints.model.CustomerData /** @@ -25,7 +24,6 @@ import net.dankito.banking.fints.model.CustomerData open class Signaturkopf( segmentNumber: Int, bank: BankData, - customer: CustomerData, versionOfSecurityProcedure: VersionDesSicherheitsverfahrens, securityControlReference: String, date: Int, @@ -41,15 +39,15 @@ open class Signaturkopf( Sicherheitsverfahren.PIN_TAN_Verfahren, versionOfSecurityProcedure ), // fints4k only supports Pin/Tan and PSD2 requires two step tan procedure; the only exception is the first dialog to get user's TAN procedures which allows to use one step tan procedure (as we don't know TAN procedures yet) - SicherheitsfunktionKodiert(customer.selectedTanProcedure.securityFunction), + SicherheitsfunktionKodiert(bank.selectedTanProcedure.securityFunction), Sicherheitskontrollreferenz(securityControlReference), // allowed: <>0 BereichDerSicherheitsapplikationKodiert(BereichDerSicherheitsapplikation.SignaturkopfUndHBCINutzdaten), // allowed: 1 ? RolleDesSicherheitslieferantenKodiert(), // allowed: 1 - SicherheitsidentifikationDetails(customer.customerSystemId), + SicherheitsidentifikationDetails(bank.customerSystemId), // "Bei softwarebasierten Verfahren wird die Sicherheitsreferenznummer auf Basis des DE Kundensystem-ID und des DE Benutzerkennung der DEG Schlüsselnamen verwaltet. Sicherheitsreferenznummer(1), // TODO: is this always 1? SicherheitsdatumUndUhrzeit(date, time), HashalgorithmusDatenelementgruppe(), SignaturalgorithmusDatenelementgruppe(algorithm, mode), - Schluesselname(bank.countryCode, bank.bankCode, customer.customerId, Schluesselart.Signierschluessel, keyNumber, keyVersion) + Schluesselname(bank.countryCode, bank.bankCode, bank.customerId, Schluesselart.Signierschluessel, keyNumber, keyVersion) )) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt index 0767eeb5..cd6624dd 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt @@ -14,8 +14,8 @@ open class Verarbeitungsvorbereitung( ) : Segment(listOf( Segmentkopf(CustomerSegmentId.ProcessingPreparation, 3, segmentNumber), BPDVersion(baseData.bank.bpdVersion, Existenzstatus.Mandatory), - UPDVersion(baseData.customer.updVersion, Existenzstatus.Mandatory), - DialogspracheDatenelement(baseData.customer.selectedLanguage, Existenzstatus.Mandatory), + UPDVersion(baseData.bank.updVersion, Existenzstatus.Mandatory), + DialogspracheDatenelement(baseData.bank.selectedLanguage, Existenzstatus.Mandatory), Produktbezeichnung(baseData.product.name, Existenzstatus.Mandatory), Produktversion(baseData.product.version, Existenzstatus.Mandatory) )) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verschluesselungskopf.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verschluesselungskopf.kt index 1f27e965..1e157079 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verschluesselungskopf.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/Verschluesselungskopf.kt @@ -14,7 +14,6 @@ import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.sig import net.dankito.banking.fints.messages.segmente.Segment import net.dankito.banking.fints.messages.segmente.id.MessageSegmentId import net.dankito.banking.fints.model.BankData -import net.dankito.banking.fints.model.CustomerData /** @@ -35,7 +34,6 @@ import net.dankito.banking.fints.model.CustomerData */ open class Verschluesselungskopf( bank: BankData, - customer: CustomerData, versionOfSecurityProcedure: VersionDesSicherheitsverfahrens, date: Int, time: Int, @@ -51,10 +49,10 @@ open class Verschluesselungskopf( Sicherheitsprofil(Sicherheitsverfahren.PIN_TAN_Verfahren, versionOfSecurityProcedure), // fints4k only supports Pin/Tan and PSD2 requires two step tan procedure; the only exception is the first dialog to get user's TAN procedures which allows to use one step tan procedure (as we don't know TAN procedures yet) SicherheitsfunktionKodiert(Sicherheitsfunktion.Klartext), RolleDesSicherheitslieferantenKodiert(), // allowed: 1, 4 - SicherheitsidentifikationDetails(customer.customerSystemId), + SicherheitsidentifikationDetails(bank.customerSystemId), SicherheitsdatumUndUhrzeit(date, time), VerschluesselungsalgorithmusDatenelementgruppe(mode, encryptionAlgorithm), - Schluesselname(bank.countryCode, bank.bankCode, customer.customerId, key, keyNumber, keyVersion), + Schluesselname(bank.countryCode, bank.bankCode, bank.customerId, key, keyNumber, keyVersion), KomprimierungsfunktionDatenelement(algorithm), NotAllowedDatenelement() // Certificate not applicapable for PIN/TAN )) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt index 733454b0..2a9d5068 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt @@ -3,14 +3,13 @@ package net.dankito.banking.fints.messages.segmente.implementierte.sepa import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId import net.dankito.banking.fints.model.AccountData import net.dankito.banking.fints.model.BankTransferData -import net.dankito.banking.fints.model.CustomerData open class SepaBankTransferBase( segmentId: CustomerSegmentId, segmentNumber: Int, sepaDescriptorUrn: String, - debitor: CustomerData, + debitorName: String, account: AccountData, debitorBic: String, data: BankTransferData, @@ -26,7 +25,7 @@ open class SepaBankTransferBase( debitorBic, mapOf( SepaMessageCreator.NumberOfTransactionsKey to "1", // TODO: may someday support more then one transaction per file - "DebitorName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(debitor.name), + "DebitorName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(debitorName), "DebitorIban" to account.iban!!, "DebitorBic" to debitorBic, "CreditorName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(data.creditorName), diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmelden.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmelden.kt index f5da3e89..6feb2fb4 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmelden.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmelden.kt @@ -16,7 +16,6 @@ import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.acc import net.dankito.banking.fints.messages.segmente.Segment import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId import net.dankito.banking.fints.model.BankData -import net.dankito.banking.fints.model.CustomerData import net.dankito.banking.fints.response.segments.ChangeTanMediaParameters @@ -41,7 +40,6 @@ open class TanGeneratorTanMediumAnOderUmmelden( segmentVersion: Int, segmentNumber: Int, bank: BankData, - customer: CustomerData, newActiveTanMedium: TanGeneratorTanMedium, /** * Has to be set if „Eingabe von ATC und TAN erforderlich“ (BPD)=“J“ @@ -55,7 +53,6 @@ open class TanGeneratorTanMediumAnOderUmmelden( * An optional field and only used in version 3 */ iccsn: String? = null, - parameters: ChangeTanMediaParameters = bank.changeTanMediumParameters!! ) : Segment(listOf( @@ -64,8 +61,8 @@ open class TanGeneratorTanMediumAnOderUmmelden( AlphanumerischesDatenelement(newActiveTanMedium.cardNumber, Existenzstatus.Mandatory), AlphanumerischesDatenelement(newActiveTanMedium.cardSequenceNumber, if (parameters.enteringCardSequenceNumberRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed), if (segmentVersion > 1) NumerischesDatenelement(newActiveTanMedium.cardType, 2, if (parameters.enteringCardTypeAllowed) Existenzstatus.Optional else Existenzstatus.NotAllowed) else DoNotPrintDatenelement(), - if (segmentVersion == 2) Kontoverbindung(customer.accounts.first()) else DoNotPrintDatenelement(), - if (segmentVersion >= 3 && parameters.accountInfoRequired) KontoverbindungInternational(customer.accounts.first(), bank) else DoNotPrintDatenelement(), + if (segmentVersion == 2) Kontoverbindung(bank.accounts.first()) else DoNotPrintDatenelement(), + if (segmentVersion >= 3 && parameters.accountInfoRequired) KontoverbindungInternational(bank.accounts.first(), bank) else DoNotPrintDatenelement(), if (segmentVersion >= 2) Datum(newActiveTanMedium.validFrom, Existenzstatus.Optional) else DoNotPrintDatenelement(), if (segmentVersion >= 2) Datum(newActiveTanMedium.validTo, Existenzstatus.Optional) else DoNotPrintDatenelement(), if (segmentVersion >= 3) AlphanumerischesDatenelement(iccsn, Existenzstatus.Optional, 19) else DoNotPrintDatenelement(), diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankData.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankData.kt index 504be877..936ba015 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankData.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankData.kt @@ -1,9 +1,9 @@ package net.dankito.banking.fints.model import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Laenderkennzeichen -import net.dankito.banking.fints.messages.datenelemente.implementierte.BPDVersion -import net.dankito.banking.fints.messages.datenelemente.implementierte.Dialogsprache -import net.dankito.banking.fints.messages.datenelemente.implementierte.HbciVersion +import net.dankito.banking.fints.messages.datenelemente.implementierte.* +import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion +import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedium import net.dankito.banking.fints.response.segments.ChangeTanMediaParameters import net.dankito.banking.fints.response.segments.JobParameters import net.dankito.banking.fints.response.segments.PinInfo @@ -11,12 +11,31 @@ import net.dankito.banking.fints.response.segments.PinInfo open class BankData( var bankCode: String, + var customerId: String, + var pin: String, var finTs3ServerAddress: String, var bic: String, - var name: String = "", + + var bankName: String = "", var countryCode: Int = Laenderkennzeichen.Germany, // TODO: currently there are only German banks. But change this if ever other countries get supported var bpdVersion: Int = BPDVersion.VersionNotReceivedYet, + var userId: String = customerId, + var customerName: String = "", + var updVersion: Int = UPDVersion.VersionNotReceivedYet, + + var tanProceduresSupportedByBank: List = listOf(), + var tanProceduresAvailableForUser: List = listOf(), + var selectedTanProcedure: TanProcedure = TanProcedureNotSelected, + var tanMedia: List = listOf(), + var changeTanMediumParameters: ChangeTanMediaParameters? = null, + var pinInfo: PinInfo? = null, + + var supportedLanguages: List = listOf(), + var selectedLanguage: Dialogsprache = Dialogsprache.Default, + var customerSystemId: String = KundensystemID.Anonymous, + var customerSystemStatus: KundensystemStatusWerte = KundensystemStatus.SynchronizingCustomerSystemId, + /** * Maximale Anzahl an Geschäftsvorfallsarten, die pro Nachricht zulässig ist. * Der Wert ‚0’ gibt an, dass keine Restriktionen bzgl. der Anzahl an Geschäftsvorfallsarten bestehen. @@ -24,32 +43,66 @@ open class BankData( var countMaxJobsPerMessage: Int = 0, var supportedHbciVersions: List = listOf(), - var supportedTanProcedures: List = listOf(), - var changeTanMediumParameters: ChangeTanMediaParameters? = null, - var pinInfo: PinInfo? = null, - var supportedLanguages: List = listOf(), var supportedJobs: List = listOf() ) { + companion object { + val SecurityFunctionNotSelected = Sicherheitsfunktion.Einschritt_Verfahren - internal constructor() : this("", "", "") // for object deserializers + val TanProcedureNotSelected = TanProcedure("NOT_SELECTED", SecurityFunctionNotSelected, TanProcedureType.EnterTan) + + // TODO: is the BIC really needed at anonymous dialog init? + fun anonymous(bankCode: String, finTs3ServerAddress: String, bic: String): BankData { + return BankData(bankCode, KundenID.Anonymous, "", finTs3ServerAddress, bic, customerSystemStatus = KundensystemStatusWerte.NichtBenoetigt) + } + } + + + internal constructor() : this("", "", "", "", "") // for object deserializers init { // for UniCredit / HypVereinsbank for online banking '70020270' has to be used as bank code - if (name.contains("unicredit", true)) { + if (bankName.contains("unicredit", true)) { bankCode = "70020270" } } + protected val _accounts = mutableListOf() + + open val accounts: List + get() = ArrayList(_accounts) + + + open val isTanProcedureSelected: Boolean + get() = selectedTanProcedure != TanProcedureNotSelected + + + open fun addAccount(account: AccountData) { + _accounts.add(account) + } + + open fun removeAccount(account: AccountData) { + _accounts.remove(account) + } + + open fun resetBpdVersion() { bpdVersion = BPDVersion.VersionNotReceivedYet } + open fun resetUpdVersion() { + updVersion = UPDVersion.VersionNotReceivedYet + } + + open fun resetSelectedTanProcedure() { + selectedTanProcedure = TanProcedureNotSelected + } + override fun toString(): String { - return "$name ($bankCode)" + return "$bankCode $customerId" } } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/CustomerData.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/CustomerData.kt deleted file mode 100644 index c26bb4d4..00000000 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/CustomerData.kt +++ /dev/null @@ -1,69 +0,0 @@ -package net.dankito.banking.fints.model - -import net.dankito.banking.fints.messages.datenelemente.implementierte.* -import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedium - - -open class CustomerData( - var customerId: String, - var pin: String, - var userId: String = customerId, - var name: String = "", - var updVersion: Int = UPDVersion.VersionNotReceivedYet, - var supportedTanProcedures: List = listOf(), - var selectedTanProcedure: TanProcedure = TanProcedureNotSelected, - var tanMedia: List = listOf(), - var selectedLanguage: Dialogsprache = Dialogsprache.Default, - var customerSystemId: String = KundensystemID.Anonymous, - var customerSystemStatus: KundensystemStatusWerte = KundensystemStatus.SynchronizingCustomerSystemId -) { - - companion object { - val SecurityFunctionNotSelected = Sicherheitsfunktion.Einschritt_Verfahren - - val TanProcedureNotSelected = TanProcedure("NOT_SELECTED", SecurityFunctionNotSelected, TanProcedureType.EnterTan) - - val Anonymous = CustomerData(KundenID.Anonymous, "", customerSystemStatus = KundensystemStatusWerte.NichtBenoetigt) - } - - - // for Java - constructor(customerId: String, pin: String) : this(customerId, pin, customerId) - - internal constructor() : this("", "") // for object deserializers - - - protected val accountsField = mutableListOf() - - open val accounts: List - get() = ArrayList(accountsField) - - - open val isTanProcedureSelected: Boolean - get() = selectedTanProcedure != TanProcedureNotSelected - - - open fun resetSelectedTanProcedure() { - selectedTanProcedure = TanProcedureNotSelected - } - - open fun resetUpdVersion() { - updVersion = UPDVersion.VersionNotReceivedYet - } - - - open fun addAccount(account: AccountData) { - accountsField.add(account) - } - - open fun removeAccount(account: AccountData) { - accountsField.remove(account) - } - - - override fun toString(): String { - return customerId - } - -} \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/DialogContext.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/DialogContext.kt index ae4617f5..ce468056 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/DialogContext.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/DialogContext.kt @@ -7,17 +7,16 @@ import net.dankito.banking.fints.response.Response open class DialogContext( bank: BankData, - customer: CustomerData, product: ProductData, var abortIfTanIsRequired: Boolean = false, var currentMessage: MessageBuilderResult? = null, var dialogId: String = InitialDialogId, var response: Response? = null, var didBankCloseDialog: Boolean = false, - versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.Version_2, // for PinTan almost always the case except for getting a user's TAN procedures - var previousMessageInDialog: MessageBuilderResult? = null, + versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.Version_2, + var previousMessageInDialog: MessageBuilderResult? = null, // for PinTan almost always the case except for getting a user's TAN procedures var chunkedResponseHandler: ((Response) -> Unit)? = null -) : MessageBaseData(bank, customer, product, versionOfSecurityProcedure) { +) : MessageBaseData(bank, product, versionOfSecurityProcedure) { companion object { const val InitialDialogId = "0" diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageBaseData.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageBaseData.kt index 10f00f38..c5181f05 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageBaseData.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageBaseData.kt @@ -5,7 +5,6 @@ import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur. open class MessageBaseData( val bank: BankData, - val customer: CustomerData, val product: ProductData, val versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.PinTanDefaultVersion ) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageLogEntry.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageLogEntry.kt index d13baa51..94a54fbc 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageLogEntry.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/MessageLogEntry.kt @@ -6,7 +6,7 @@ import net.dankito.utils.multiplatform.Date open class MessageLogEntry( val message: String, val time: Date, - val customer: CustomerData + val bank: BankData ) { override fun toString(): String { diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/client/AddAccountResponse.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/client/AddAccountResponse.kt index df73a0a2..cb8bbfa0 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/client/AddAccountResponse.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/client/AddAccountResponse.kt @@ -7,7 +7,6 @@ import net.dankito.banking.fints.response.Response open class AddAccountResponse( response: Response, val bank: BankData, - val customer: CustomerData, val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false, bookedTransactionsOfLast90Days: List = listOf(), unbookedTransactionsOfLast90Days: List = listOf(), diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/ChangeTanMediaParameters.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/ChangeTanMediaParameters.kt index 5a46677d..1272656e 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/ChangeTanMediaParameters.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/ChangeTanMediaParameters.kt @@ -10,4 +10,7 @@ open class ChangeTanMediaParameters( val accountInfoRequired: Boolean, val allowedCardTypes: List ) - : JobParameters(parameters) \ No newline at end of file + : JobParameters(parameters) { + + internal constructor() : this(JobParameters(), false, false, false, false, false, listOf()) // for object deserializers +} \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/PinInfo.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/PinInfo.kt index 9fbfc7aa..ce19489a 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/PinInfo.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/segments/PinInfo.kt @@ -12,4 +12,8 @@ open class PinInfo( val customerIdHint: String?, val jobTanConfiguration: List ) - : JobParameters(parameters) \ No newline at end of file + : JobParameters(parameters) { + + internal constructor() : this(JobParameters(), null, null, null, null, null, listOf()) // for object deserializers + +} \ No newline at end of file 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 778512d1..4a7a6b0d 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/FinTsTestBase.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/FinTsTestBase.kt @@ -30,15 +30,13 @@ abstract class FinTsTestBase { const val Bic = "ABCDDEMM123" - val Bank = BankData(BankCode, BankFinTsServerAddress, Bic, "", BankCountryCode) - val Language = Dialogsprache.German val SecurityFunction = Sicherheitsfunktion.PIN_TAN_910 const val ControlReference = "4477" - val Customer = CustomerData(CustomerId, Pin, selectedTanProcedure = TanProcedure("chipTAN-optisch", SecurityFunction, TanProcedureType.ChipTanFlickercode), selectedLanguage = Language) + val Bank = BankData(BankCode, CustomerId, Pin, BankFinTsServerAddress, Bic, "", BankCountryCode, selectedTanProcedure = TanProcedure("chipTAN-optisch", SecurityFunction, TanProcedureType.ChipTanFlickercode), selectedLanguage = Language) val Currency = "EUR" diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt index 534373fe..d7d8c38c 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt @@ -43,7 +43,7 @@ class MessageBuilderTest : FinTsTestBase() { fun createAnonymousDialogInitMessage() { // given - val dialogContext = DialogContext(Bank, CustomerData.Anonymous, Product) + val dialogContext = DialogContext(Bank, Product) // when val result = underTest.createAnonymousDialogInitMessage(dialogContext).createdMessage @@ -62,7 +62,7 @@ class MessageBuilderTest : FinTsTestBase() { // given val dialogId = createDialogId() - val dialogContext = DialogContext(Bank, Customer, Product, false, null, dialogId) + val dialogContext = DialogContext(Bank, Product, false, null, dialogId) // when val result = underTest.createAnonymousDialogEndMessage(dialogContext).createdMessage ?: "" @@ -80,7 +80,7 @@ class MessageBuilderTest : FinTsTestBase() { fun createDialogInitMessage() { // given - val dialogContext = DialogContext(Bank, Customer, Product) + val dialogContext = DialogContext(Bank, Product) // when val result = underTest.createSynchronizeCustomerSystemIdMessage(dialogContext).createdMessage ?: "" @@ -104,7 +104,7 @@ class MessageBuilderTest : FinTsTestBase() { // given val dialogId = createDialogId() - val dialogContext = DialogContext(Bank, Customer, Product, false, null, dialogId) + val dialogContext = DialogContext(Bank, Product, false, null, dialogId) // when val result = underTest.createDialogEndMessage(dialogContext).createdMessage ?: "" @@ -125,7 +125,7 @@ class MessageBuilderTest : FinTsTestBase() { fun createGetTransactionsMessage_JobIsNotAllowed() { // given - val dialogContext = DialogContext(Bank, Customer, Product) + val dialogContext = DialogContext(Bank, Product) // when val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(), Account, dialogContext) @@ -142,8 +142,8 @@ class MessageBuilderTest : FinTsTestBase() { val getTransactionsJobWithPreviousVersion = JobParameters("HKKAZ", 1, 1, null, "HKKAZ:72:4") Bank.supportedJobs = listOf(getTransactionsJob) val account = AccountData(CustomerId, null, BankCountryCode, BankCode, null, CustomerId, AccountType.Girokonto, "EUR", "", null, null, listOf(getTransactionsJob.jobName), listOf(getTransactionsJobWithPreviousVersion)) - Customer.addAccount(account) - val dialogContext = DialogContext(Bank, Customer, Product) + Bank.addAccount(account) + val dialogContext = DialogContext(Bank, Product) // when val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(), account, dialogContext) @@ -160,8 +160,8 @@ class MessageBuilderTest : FinTsTestBase() { val getTransactionsJob = JobParameters("HKKAZ", 1, 1, null, "HKKAZ:73:5") Bank.supportedJobs = listOf(getTransactionsJob) val account = AccountData(CustomerId, null, BankCountryCode, BankCode, null, CustomerId, AccountType.Girokonto, "EUR", "", null, null, listOf(getTransactionsJob.jobName), listOf(getTransactionsJob)) - Customer.addAccount(account) - val dialogContext = DialogContext(Bank, Customer, Product) + Bank.addAccount(account) + val dialogContext = DialogContext(Bank, Product) val fromDate = Date(2019, Month.August, 6) val toDate = Date(2019, Month.October, 21) @@ -191,8 +191,8 @@ class MessageBuilderTest : FinTsTestBase() { val getTransactionsJob = JobParameters("HKKAZ", 1, 1, null, "HKKAZ:73:5") Bank.supportedJobs = listOf(getTransactionsJob) val account = AccountData(CustomerId, null, BankCountryCode, BankCode, null, CustomerId, AccountType.Girokonto, "EUR", "", null, null, listOf(getTransactionsJob.jobName), listOf(getTransactionsJob)) - Customer.addAccount(account) - val dialogContext = DialogContext(Bank, Customer, Product) + Bank.addAccount(account) + val dialogContext = DialogContext(Bank, Product) val fromDate = Date(2019, Month.August, 6) val toDate = Date(2019, Month.October, 21) diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt index 5a70ad90..98981256 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt @@ -13,7 +13,7 @@ class IdentifikationsSegmentTest : FinTsTestBase() { fun format() { // given - val underTest = IdentifikationsSegment(2, MessageBaseData(Bank, Customer, Product)) + val underTest = IdentifikationsSegment(2, MessageBaseData(Bank, Product)) // when val result = underTest.format() diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/SignaturkopfTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/SignaturkopfTest.kt index dd92225e..f22a2e21 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/SignaturkopfTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/SignaturkopfTest.kt @@ -15,7 +15,7 @@ class SignaturkopfTest : FinTsTestBase() { // given val controlReference = "1902675680" - val underTest = PinTanSignaturkopf(2, MessageBaseData(Bank, Customer, Product), + val underTest = PinTanSignaturkopf(2, MessageBaseData(Bank, Product), controlReference, Date, Time) // when diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/VerschluesselungskopfTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/VerschluesselungskopfTest.kt index 8c8a099b..34c50219 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/VerschluesselungskopfTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/VerschluesselungskopfTest.kt @@ -14,7 +14,7 @@ class VerschluesselungskopfTest : FinTsTestBase() { // given - val underTest = PinTanVerschluesselungskopf(MessageBaseData(Bank, Customer, Product), Date, Time) + val underTest = PinTanVerschluesselungskopf(MessageBaseData(Bank, Product), Date, Time) // when val result = underTest.format() diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBaseTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBaseTest.kt index e2318f00..fbcea089 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBaseTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBaseTest.kt @@ -30,7 +30,7 @@ class SepaBankTransferBaseTest { // given val underTest = SepaBankTransferBase(CustomerSegmentId.SepaBankTransfer, segmentNumber, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03", - CustomerData("", "", "", debitorName), + debitorName, AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()), debitorBic, BankTransferData(creditorName, creditorIban, creditorBic, Money(amount, "EUR"), usage) @@ -52,7 +52,7 @@ class SepaBankTransferBaseTest { // given val underTest = SepaBankTransferBase(CustomerSegmentId.SepaBankTransfer, segmentNumber, "urn:iso:std:iso:20022:tech:xsd:pain.001.003.03", - CustomerData("", "", "", debitorName), + debitorName, AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()), debitorBic, BankTransferData(creditorName, creditorIban, creditorBic, Money(amount, "EUR"), usage) diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmeldenTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmeldenTest.kt index ae8c4d7d..1fe74a86 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmeldenTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/tan/TanGeneratorTanMediumAnOderUmmeldenTest.kt @@ -32,7 +32,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { init { - Customer.addAccount(Account) + Bank.addAccount(Account) } @@ -42,7 +42,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, false, false, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -59,7 +59,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, false, true, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -76,7 +76,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, true, false, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -93,7 +93,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, true, true, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(1, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -111,7 +111,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, false, false, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -128,7 +128,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, false, true, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -145,7 +145,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, true, false, false, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -162,7 +162,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, false, false, true, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when @@ -179,7 +179,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() { // given val parameters = ChangeTanMediaParameters(createEmptyJobParameters(), false, true, true, true, false, listOf()) - val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, Customer, NewActiveTanMedium, TAN, ATC, null, parameters) + val underTest = TanGeneratorTanMediumAnOderUmmelden(2, SegmentNumber, Bank, NewActiveTanMedium, TAN, ATC, null, parameters) // when diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt index 2bb80ee3..0511e571 100644 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt +++ b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt @@ -60,13 +60,13 @@ open class FinTsClientTestBase { callback(suggestedTanProcedure) // simply return suggestedTanProcedure as in most cases it's the best fitting one } - override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { + override fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { didAskUserToEnterTan = true callback(EnterTanResult.userDidNotEnterTan()) } - override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { + override fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { fail("Bank asks you to synchronize your TAN generator for card ${tanMedium.cardNumber} " + "(card sequence number ${tanMedium.cardSequenceNumber}). Please do this via your online banking portal or Banking UI.") } @@ -77,11 +77,10 @@ open class FinTsClientTestBase { private val underTest = FinTsClient(callback, KtorWebClient(), PureKotlinBase64Service()) - private val BankDataAnonymous = BankData("10070000","https://fints.deutsche-bank.de/", "DEUTDEBBXXX") + private val BankDataAnonymous = BankData.anonymous("10070000", "https://fints.deutsche-bank.de/", "DEUTDEBBXXX") private val bankInfo = InMemoryBankFinder().findBankByBankCode(BankCode).first() - private val Bank = BankData(bankInfo.bankCode, bankInfo.pinTanAddress ?: "", bankInfo.bic, bankInfo.name) - private val Customer = CustomerData(CustomerId, Password) + private val Bank = BankData(bankInfo.bankCode, CustomerId, Password, bankInfo.pinTanAddress ?: "", bankInfo.bic, bankInfo.name) @@ -94,10 +93,10 @@ open class FinTsClientTestBase { // then expect(result.isSuccessful).isTrue() expect(BankDataAnonymous.supportedHbciVersions).isNotEmpty() - expect(BankDataAnonymous.supportedTanProcedures).isNotEmpty() + expect(BankDataAnonymous.tanProceduresSupportedByBank).isNotEmpty() expect(BankDataAnonymous.supportedJobs).isNotEmpty() expect(BankDataAnonymous.supportedLanguages).isNotEmpty() - expect(BankDataAnonymous.name).isNotEmpty() + expect(BankDataAnonymous.bankName).isNotEmpty() } } @@ -111,7 +110,7 @@ open class FinTsClientTestBase { // when - underTest.addAccountAsync(Bank, Customer) { + underTest.addAccountAsync(Bank) { response.set(it) countDownLatch.countDown() } @@ -125,19 +124,19 @@ open class FinTsClientTestBase { expect(didAskUserForTanProcedure).isFalse() - expect(Bank.name).isNotEmpty() + expect(Bank.bankName).isNotEmpty() expect(Bank.supportedJobs).isNotEmpty() // supported jobs are now known - expect(Bank.supportedTanProcedures).isNotEmpty() // supported tan procedures are now known + expect(Bank.tanProceduresSupportedByBank).isNotEmpty() // supported tan procedures are now known expect(Bank.supportedHbciVersions).isNotEmpty() // supported HBIC versions are now known expect(Bank.supportedLanguages).isNotEmpty() // supported languages are now known - expect(Customer.name).isNotEmpty() - expect(Customer.supportedTanProcedures).isNotEmpty() - expect(Customer.selectedLanguage).notToBe(Dialogsprache.Default) // language is set now - expect(Customer.customerSystemId).notToBe(KundensystemStatus.SynchronizingCustomerSystemId.code) // customer system id is now set - expect(Customer.customerSystemStatus).toBe(KundensystemStatusWerte.Benoetigt) // customerSystemStatus is set now - expect(Customer.accounts).isNotEmpty() // accounts are now known - expect(Customer.accounts.first().allowedJobs).isNotEmpty() // allowed jobs are now known + expect(Bank.customerName).isNotEmpty() + expect(Bank.tanProceduresAvailableForUser).isNotEmpty() + expect(Bank.selectedLanguage).notToBe(Dialogsprache.Default) // language is set now + expect(Bank.customerSystemId).notToBe(KundensystemStatus.SynchronizingCustomerSystemId.code) // customer system id is now set + expect(Bank.customerSystemStatus).toBe(KundensystemStatusWerte.Benoetigt) // customerSystemStatus is set now + expect(Bank.accounts).isNotEmpty() // accounts are now known + expect(Bank.accounts.first().allowedJobs).isNotEmpty() // allowed jobs are now known } @@ -149,14 +148,14 @@ open class FinTsClientTestBase { val response = AtomicReference() val countDownLatch = CountDownLatch(1) - underTest.addAccountAsync(Bank, Customer) { // retrieve basic data, e.g. accounts - val account = Customer.accounts.firstOrNull { it.supportsFeature(AccountFeature.RetrieveAccountTransactions) } + underTest.addAccountAsync(Bank) { // retrieve basic data, e.g. accounts + val account = Bank.accounts.firstOrNull { it.supportsFeature(AccountFeature.RetrieveAccountTransactions) } expect(account).withRepresentation("We need at least one account that supports retrieving account transactions (${CustomerSegmentId.AccountTransactionsMt940.id})").notToBeNull() // when // some banks support retrieving account transactions of last 90 days without TAN - underTest.tryGetTransactionsOfLast90DaysWithoutTan(Bank, Customer, account!!) { + underTest.tryGetTransactionsOfLast90DaysWithoutTan(Bank, account!!) { response.set(it) countDownLatch.countDown() } @@ -185,11 +184,11 @@ open class FinTsClientTestBase { return } - expect(Customer.tanMedia).isEmpty() + expect(Bank.tanMedia).isEmpty() // when - underTest.getTanMediaList(Bank, Customer, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien) { result -> + underTest.getTanMediaList(Bank, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien) { result -> // then expect(result.isSuccessful).isTrue() @@ -198,7 +197,7 @@ open class FinTsClientTestBase { expect(result.tanMediaList!!.usageOption).toBe(TanEinsatzOption.KundeKannGenauEinMediumZuEinerZeitNutzen) // TODO: may adjust to your value expect(result.tanMediaList!!.tanMedia).isNotEmpty() - expect(Customer.tanMedia).isNotEmpty() + expect(Bank.tanMedia).isNotEmpty() } } @@ -208,7 +207,7 @@ open class FinTsClientTestBase { // when expect { - underTest.getTanMediaList(Bank, Customer, TanMedienArtVersion.Alle, TanMediumKlasse.BilateralVereinbart) { } + underTest.getTanMediaList(Bank, TanMedienArtVersion.Alle, TanMediumKlasse.BilateralVereinbart) { } }.toThrow() @@ -225,21 +224,21 @@ open class FinTsClientTestBase { val response = AtomicReference() val countDownLatch = CountDownLatch(1) - underTest.addAccountAsync(Bank, Customer) { // retrieve basic data, e.g. accounts + underTest.addAccountAsync(Bank) { // retrieve basic data, e.g. accounts // we need at least one account that supports cash transfer - val account = Customer.accounts.firstOrNull { it.supportsFeature(AccountFeature.TransferMoney) } + val account = Bank.accounts.firstOrNull { it.supportsFeature(AccountFeature.TransferMoney) } expect(account).withRepresentation("We need at least one account that supports cash transfer (${CustomerSegmentId.SepaBankTransfer.id})").notToBeNull() // IBAN should be set expect(account?.iban).withRepresentation("Account IBAN must be set").notToBeNull() // transfer 1 cent to yourself. Transferring money to oneself also doesn't require to enter a TAN according to PSD2 - val BankTransferData = BankTransferData(Customer.name, account?.iban!!, Bank.bic, Money(Amount("0,01"), "EUR"), + val BankTransferData = BankTransferData(Bank.customerName, account?.iban!!, Bank.bic, Money(Amount("0,01"), "EUR"), "${DateTimeFormatForUniqueBankTransferUsage.format(Date())} Test transaction ${UUID.random()}") // when - underTest.doBankTransferAsync(BankTransferData, Bank, Customer, account) { result -> + underTest.doBankTransferAsync(BankTransferData, Bank, account) { result -> response.set(result) countDownLatch.countDown() } diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt index 721dceec..de3b0487 100644 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt +++ b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt @@ -126,7 +126,7 @@ class BanksFinTsDetailsRetriever { private fun getAnonymousBankInfo(bank: BankData): Response { - val dialogContext = DialogContext(bank, CustomerData.Anonymous, product) + val dialogContext = DialogContext(bank, product) val requestBody = messageBuilder.createAnonymousDialogInitMessage(dialogContext) val anonymousBankInfoResponse = AtomicReference() @@ -145,7 +145,8 @@ class BanksFinTsDetailsRetriever { } private fun getAndSaveBankDetails(bankInfo: BankInfo, responsesFolder: File, csvPrinter: CSVPrinter) = runBlocking { - val bank = BankData(bankInfo.bankCode, bankInfo.pinTanAddress ?: "", bankInfo.bic, bankInfo.name) + val bank = BankData.anonymous(bankInfo.bankCode, bankInfo.pinTanAddress ?: "", bankInfo.bic) + bank.bankName = bankInfo.name val anonymousBankInfoResponse = getAnonymousBankInfo(bank) @@ -183,7 +184,7 @@ class BanksFinTsDetailsRetriever { csvPrinter.printRecord(bankInfo.bankCode, bankInfo.name, bankInfo.city, bank.bpdVersion, - bank.supportedTanProcedures.joinToString(", ") { it.securityFunction.code + ": " + it.displayName + " (" + it.type + ")" }, + bank.tanProceduresSupportedByBank.joinToString(", ") { it.securityFunction.code + ": " + it.displayName + " (" + it.type + ")" }, supportedTanProcedures.joinToString(", "), hhd13Supported, hhd14Supported, diff --git a/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt index 2069ef68..9f6a3ed5 100644 --- a/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt +++ b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt @@ -47,12 +47,10 @@ open class fints4kBankingClient( protected var didTryToGetAccountDataFromBank = false - protected val bank = BankData(customer.bankCode, customer.finTsServerAddress, customer.bic, customer.bankName) - - protected val fints4kCustomer = CustomerData(customer.customerId, customer.password) + protected val bank = BankData(customer.bankCode, customer.customerId, customer.password, customer.finTsServerAddress, customer.bic, customer.bankName) - protected open val client = FinTsClientForCustomer(bank, fints4kCustomer, createFinTsClientCallback(callback), webClient, base64Service) + protected open val client = FinTsClientForCustomer(bank, createFinTsClientCallback(callback), webClient, base64Service) override val messageLogWithoutSensitiveData: List @@ -67,7 +65,7 @@ open class fints4kBankingClient( protected open fun handleAddAccountResponse(response: net.dankito.banking.fints.response.client.AddAccountResponse, callback: (AddAccountResponse) -> Unit) { - mapper.mapCustomer(customer, fints4kCustomer, bank) + mapper.mapCustomer(customer, bank) val mappedResponse = mapper.mapResponse(customer, response) saveData() @@ -135,7 +133,7 @@ open class fints4kBankingClient( protected open fun findAccountForBankAccount(bankAccount: BankAccount, findAccountResult: (AccountData?, error: String?) -> Unit) { - val mappedAccount = mapper.findAccountForBankAccount(fints4kCustomer, bankAccount) + val mappedAccount = mapper.findAccountForBankAccount(bank, bankAccount) if (mappedAccount != null) { findAccountResult(mappedAccount, null) @@ -144,7 +142,7 @@ open class fints4kBankingClient( addAccountAsync { response -> didTryToGetAccountDataFromBank = !!! response.isSuccessful - findAccountResult(mapper.findAccountForBankAccount(fints4kCustomer, bankAccount), + findAccountResult(mapper.findAccountForBankAccount(bank, bankAccount), response.errorToShowToUser) } } @@ -155,12 +153,12 @@ open class fints4kBankingClient( override fun restoreData() { - val deserializedCustomer = serializer.deserializeObject(getFints4kClientDataFile(), CustomerData::class) + val deserializedBank = serializer.deserializeObject(getFints4kClientDataFile(), BankData::class) - deserializedCustomer?.let { - mapper.updateCustomer(fints4kCustomer, deserializedCustomer) + deserializedBank?.let { + mapper.updateCustomer(bank, deserializedBank) - mapper.mapCustomer(customer, fints4kCustomer, bank) // TODO: necessary? + mapper.mapCustomer(customer, bank) // TODO: necessary? } } @@ -168,9 +166,9 @@ open class fints4kBankingClient( try { val clientDataFile = getFints4kClientDataFile() - serializer.serializeObject(fints4kCustomer, clientDataFile) + serializer.serializeObject(bank, clientDataFile) } catch (e: Exception) { - log.error("Could not save customer data for $fints4kCustomer", e) + log.error("Could not save customer data for $bank", e) } } @@ -179,7 +177,7 @@ open class fints4kBankingClient( folder.mkdirs() - return File(folder, "${bank.bankCode}_${fints4kCustomer.customerId}_$fints4kClientDataFilename") + return File(folder, "${bank.bankCode}_${bank.customerId}_$fints4kClientDataFilename") } @@ -190,12 +188,12 @@ open class fints4kBankingClient( handleAskUserForTanProcedure(supportedTanProcedures, suggestedTanProcedure, callback) } - override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { - handleEnterTan(customer, tanChallenge, callback, clientCallback) + override fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { + handleEnterTan(bank, tanChallenge, callback, clientCallback) } - override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { - handleEnterTanGeneratorAtc(customer, tanMedium, callback, clientCallback) + override fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { + handleEnterTanGeneratorAtc(bank, tanMedium, callback, clientCallback) } } @@ -206,16 +204,16 @@ open class fints4kBankingClient( callback(suggestedTanProcedure) } - protected open fun handleEnterTan(customer: CustomerData, tanChallenge: TanChallenge, enterTanCallback: (EnterTanResult) -> Unit, clientCallback: BankingClientCallback) { - mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, customer) + protected open fun handleEnterTan(bank: BankData, tanChallenge: TanChallenge, enterTanCallback: (EnterTanResult) -> Unit, clientCallback: BankingClientCallback) { + mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, bank) clientCallback.enterTan(this@fints4kBankingClient.customer, mapper.mapTanChallenge(tanChallenge)) { result -> - enterTanCallback(mapper.mapEnterTanResult(result, customer)) + enterTanCallback(mapper.mapEnterTanResult(result, bank)) } } - protected open fun handleEnterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, enterAtcCallback: (EnterTanGeneratorAtcResult) -> Unit, clientCallback: BankingClientCallback) { - mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, customer) + protected open fun handleEnterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, enterAtcCallback: (EnterTanGeneratorAtcResult) -> Unit, clientCallback: BankingClientCallback) { + mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, bank) clientCallback.enterTanGeneratorAtc(mapper.mapTanMedium(tanMedium)) { result -> enterAtcCallback(mapper.mapEnterTanGeneratorAtcResult(result)) diff --git a/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt index 5f0a4040..f30c0f8d 100644 --- a/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt +++ b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt @@ -11,7 +11,6 @@ import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur. import net.dankito.banking.fints.model.AccountData import net.dankito.banking.fints.model.AccountFeature import net.dankito.banking.fints.model.BankData -import net.dankito.banking.fints.model.CustomerData import net.dankito.banking.fints.model.Money import net.dankito.banking.fints.response.client.FinTsClientResponse import net.dankito.banking.fints.response.segments.AccountType @@ -61,36 +60,36 @@ open class fints4kModelMapper { } - open fun mapCustomer(customer: Customer, customerData: CustomerData, bank: BankData) { + open fun mapCustomer(customer: Customer, bank: BankData) { customer.bankCode = bank.bankCode - customer.customerId = customerData.customerId - customer.password = customerData.pin + customer.customerId = bank.customerId + customer.password = bank.pin customer.finTsServerAddress = bank.finTs3ServerAddress - customer.bankName = bank.name + customer.bankName = bank.bankName customer.bic = bank.bic - customer.customerName = customerData.name - customer.userId = customerData.userId + customer.customerName = bank.customerName + customer.userId = bank.userId - customer.accounts = mapBankAccounts(customer, customerData.accounts) + customer.accounts = mapBankAccounts(customer, bank.accounts) - updateTanMediaAndProcedures(customer, customerData) + updateTanMediaAndProcedures(customer, bank) } // TODO: move to a fints4k internal mapper - open fun updateCustomer(customer: CustomerData, updatedCustomer: CustomerData) { - customer.pin = updatedCustomer.pin - customer.name = updatedCustomer.name + open fun updateCustomer(bank: BankData, updatedBank: BankData) { + bank.pin = updatedBank.pin + bank.customerName = updatedBank.customerName - customer.supportedTanProcedures = updatedCustomer.supportedTanProcedures - customer.selectedTanProcedure = updatedCustomer.selectedTanProcedure - customer.tanMedia = updatedCustomer.tanMedia + bank.tanProceduresAvailableForUser = updatedBank.tanProceduresAvailableForUser + bank.selectedTanProcedure = updatedBank.selectedTanProcedure + bank.tanMedia = updatedBank.tanMedia - customer.updVersion = updatedCustomer.updVersion - customer.selectedLanguage = updatedCustomer.selectedLanguage - customer.customerSystemId = updatedCustomer.customerSystemId - customer.customerSystemStatus = updatedCustomer.customerSystemStatus + bank.updVersion = updatedBank.updVersion + bank.selectedLanguage = updatedBank.selectedLanguage + bank.customerSystemId = updatedBank.customerSystemId + bank.customerSystemStatus = updatedBank.customerSystemStatus - updateBankAccounts(customer, updatedCustomer.accounts) + updateBankAccounts(bank, updatedBank.accounts) } @@ -140,25 +139,25 @@ open class fints4kModelMapper { } // TODO: move to a fints4k internal mapper - open fun updateBankAccounts(customer: CustomerData, updatedAccounts: List) { - val accounts = customer.accounts + open fun updateBankAccounts(bank: BankData, updatedAccounts: List) { + val accounts = bank.accounts updatedAccounts.forEach { updatedAccount -> val matchingExistingAccount = findMatchingBankAccount(accounts, updatedAccount) if (matchingExistingAccount == null) { - customer.addAccount(updatedAccount) + bank.addAccount(updatedAccount) } else { updateBankAccount(matchingExistingAccount, updatedAccount) } } - customer.accounts.forEach { account -> + bank.accounts.forEach { account -> val updatedAccount = findMatchingBankAccount(updatedAccounts, account) if (updatedAccount == null) { - customer.removeAccount(account) + bank.removeAccount(account) } } } @@ -171,8 +170,8 @@ open class fints4kModelMapper { } } - open fun findAccountForBankAccount(customer: CustomerData, bankAccount: BankAccount): AccountData? { - return customer.accounts.firstOrNull { bankAccount.identifier == it.accountIdentifier } + open fun findAccountForBankAccount(bank: BankData, bankAccount: BankAccount): AccountData? { + return bank.accounts.firstOrNull { bankAccount.identifier == it.accountIdentifier } } open fun findMatchingBankAccount(customer: Customer, accountData: AccountData): BankAccount? { @@ -231,17 +230,17 @@ open class fints4kModelMapper { } - open fun updateTanMediaAndProcedures(account: Customer, customer: CustomerData) { - account.supportedTanProcedures = mapTanProcedures(customer.supportedTanProcedures) + open fun updateTanMediaAndProcedures(account: Customer, bank: BankData) { + account.supportedTanProcedures = mapTanProcedures(bank.tanProceduresAvailableForUser) - if (customer.isTanProcedureSelected) { - account.selectedTanProcedure = findMappedTanProcedure(account, customer.selectedTanProcedure) + if (bank.isTanProcedureSelected) { + account.selectedTanProcedure = findMappedTanProcedure(account, bank.selectedTanProcedure) } else { account.selectedTanProcedure = null } - account.tanMedia = mapTanMediums(customer.tanMedia) + account.tanMedia = mapTanMediums(bank.tanMedia) } @@ -352,19 +351,19 @@ open class fints4kModelMapper { return if (tanMedium.status.name.contains("aktiv", true)) TanMediumStatus.Used else TanMediumStatus.Available } - open fun mapTanMedium(tanMedium: TanMedium, customer: CustomerData): net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedium { + open fun mapTanMedium(tanMedium: TanMedium, bank: BankData): net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedium { if (tanMedium is TanGeneratorTanMedium) { - return mapTanMedium(tanMedium, customer) + return mapTanMedium(tanMedium, bank) } val statusToHave = if (tanMedium.status == TanMediumStatus.Used) listOf(net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumStatus.Aktiv, net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumStatus.AktivFolgekarte) else listOf(net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumStatus.Verfuegbar, net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumStatus.VerfuegbarFolgekarte) - return customer.tanMedia.first { tanMedium.displayName == it.mediumClass.name && statusToHave.contains(it.status) } + return bank.tanMedia.first { tanMedium.displayName == it.mediumClass.name && statusToHave.contains(it.status) } } - open fun mapTanMedium(tanMedium: TanGeneratorTanMedium, customer: CustomerData): net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium { - return customer.tanMedia.mapNotNull { it as? net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium } + open fun mapTanMedium(tanMedium: TanGeneratorTanMedium, bank: BankData): net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium { + return bank.tanMedia.mapNotNull { it as? net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium } .first { it.cardNumber == tanMedium.cardNumber && (it.cardSequenceNumber == null || tanMedium.displayName.contains(it.cardSequenceNumber!!)) } } @@ -403,7 +402,7 @@ open class fints4kModelMapper { } } - open fun mapEnterTanResult(result: EnterTanResult, customer: CustomerData): net.dankito.banking.fints.model.EnterTanResult { + open fun mapEnterTanResult(result: EnterTanResult, bank: BankData): net.dankito.banking.fints.model.EnterTanResult { result.changeTanProcedureTo?.let { changeTanProcedureTo -> return net.dankito.banking.fints.model.EnterTanResult.userAsksToChangeTanProcedure(mapTanProcedure(changeTanProcedureTo)) } @@ -411,7 +410,7 @@ open class fints4kModelMapper { result.changeTanMediumTo?.let { changeTanMediumTo -> val callback: ((FinTsClientResponse) -> Unit)? = if (result.changeTanMediumResultCallback == null) null else { response -> result.changeTanMediumResultCallback?.invoke(mapResponse(response)) } - return net.dankito.banking.fints.model.EnterTanResult.userAsksToChangeTanMedium(mapTanMedium(changeTanMediumTo, customer), callback) + return net.dankito.banking.fints.model.EnterTanResult.userAsksToChangeTanMedium(mapTanMedium(changeTanMediumTo, bank), callback) } result.enteredTan?.let { enteredTan ->