Implemented passing Customer to fints4kBankingClient, so that fints4kBankingClient doesn't have a different Customer instance as BankingPresenter

This commit is contained in:
dankito 2020-09-01 13:49:18 +02:00
parent ec65600153
commit 2b8c9316d0
10 changed files with 65 additions and 74 deletions

View File

@ -1,5 +1,6 @@
package net.dankito.banking.fints.model 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.BPDVersion
import net.dankito.banking.fints.messages.datenelemente.implementierte.Dialogsprache 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.HbciVersion
@ -10,11 +11,11 @@ import net.dankito.banking.fints.response.segments.PinInfo
open class BankData( open class BankData(
var bankCode: String, var bankCode: String,
var countryCode: Int,
var finTs3ServerAddress: String, var finTs3ServerAddress: String,
var bic: String, var bic: String,
var bpdVersion: Int = BPDVersion.VersionNotReceivedYet,
var name: String = "", var name: 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,
/** /**
* Maximale Anzahl an Geschäftsvorfallsarten, die pro Nachricht zulässig ist. * Maximale Anzahl an Geschäftsvorfallsarten, die pro Nachricht zulässig ist.
@ -31,7 +32,15 @@ open class BankData(
) { ) {
internal constructor() : this("", 0, "", "") // for object deserializers 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)) {
bankCode = "70020270"
}
}
open fun resetBpdVersion() { open fun resetBpdVersion() {

View File

@ -22,8 +22,6 @@ abstract class FinTsTestBase {
const val BankFinTsServerAddress = "banking.supi-dupi-bank.de/fints30" const val BankFinTsServerAddress = "banking.supi-dupi-bank.de/fints30"
val Bank = BankData(BankCode, BankCountryCode, "", "")
const val CustomerId = "0987654321" const val CustomerId = "0987654321"
const val Pin = "12345" const val Pin = "12345"
@ -32,6 +30,8 @@ abstract class FinTsTestBase {
const val Bic = "ABCDDEMM123" const val Bic = "ABCDDEMM123"
val Bank = BankData(BankCode, BankFinTsServerAddress, Bic, "", BankCountryCode)
val Language = Dialogsprache.German val Language = Dialogsprache.German
val SecurityFunction = Sicherheitsfunktion.PIN_TAN_910 val SecurityFunction = Sicherheitsfunktion.PIN_TAN_910

View File

@ -1,16 +1,14 @@
package net.dankito.banking.ui package net.dankito.banking.ui
import net.dankito.utils.multiplatform.File import net.dankito.utils.multiplatform.File
import net.dankito.banking.bankfinder.BankInfo import net.dankito.banking.ui.model.Customer
import net.dankito.banking.util.IAsyncRunner import net.dankito.banking.util.IAsyncRunner
interface IBankingClientCreator { interface IBankingClientCreator {
fun createClient( fun createClient(
bankInfo: BankInfo, // TODO: create own value object to get rid off fints4k dependency customer: Customer,
customerId: String,
pin: String,
dataFolder: File, dataFolder: File,
asyncRunner: IAsyncRunner, asyncRunner: IAsyncRunner,
callback: BankingClientCallback callback: BankingClientCallback

View File

@ -118,10 +118,7 @@ open class BankingPresenter(
val deserializedAccounts = persister.readPersistedAccounts() val deserializedAccounts = persister.readPersistedAccounts()
deserializedAccounts.forEach { customer -> deserializedAccounts.forEach { customer ->
val bankInfo = BankInfo(customer.bankName, customer.bankCode, customer.bic, "", "", "", customer.finTsServerAddress, "FinTS V3.0", null) val newClient = bankingClientCreator.createClient(customer, dataFolder, asyncRunner, callback)
val newClient = bankingClientCreator.createClient(bankInfo, customer.customerId, customer.password,
dataFolder, asyncRunner, callback)
try { try {
newClient.restoreData() newClient.restoreData()
@ -148,8 +145,9 @@ open class BankingPresenter(
// TODO: move BankInfo out of fints4k // TODO: move BankInfo out of fints4k
open fun addAccountAsync(bankInfo: BankInfo, customerId: String, pin: String, callback: (AddAccountResponse) -> Unit) { open fun addAccountAsync(bankInfo: BankInfo, customerId: String, pin: String, callback: (AddAccountResponse) -> Unit) {
val customer = Customer(bankInfo.bankCode, customerId, pin, bankInfo.pinTanAddress ?: "", bankInfo.name, bankInfo.bic, "")
val newClient = bankingClientCreator.createClient(bankInfo, customerId, pin, dataFolder, asyncRunner, this.callback) val newClient = bankingClientCreator.createClient(customer, dataFolder, asyncRunner, this.callback)
val startDate = Date() val startDate = Date()

View File

@ -14,12 +14,10 @@ import net.dankito.banking.fints.FinTsClientForCustomer
import net.dankito.banking.fints.callback.FinTsClientCallback import net.dankito.banking.fints.callback.FinTsClientCallback
import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.dankito.banking.fints.model.* import net.dankito.banking.fints.model.*
import net.dankito.banking.mapper.BankDataMapper
import net.dankito.banking.fints.util.IBase64Service import net.dankito.banking.fints.util.IBase64Service
import net.dankito.banking.fints.util.PureKotlinBase64Service import net.dankito.banking.fints.util.PureKotlinBase64Service
import net.dankito.banking.fints.webclient.IWebClient import net.dankito.banking.fints.webclient.IWebClient
import net.dankito.banking.fints.webclient.KtorWebClient import net.dankito.banking.fints.webclient.KtorWebClient
import net.dankito.banking.bankfinder.BankInfo
import net.dankito.banking.extensions.toMoney import net.dankito.banking.extensions.toMoney
import net.dankito.banking.fints.response.client.FinTsClientResponse import net.dankito.banking.fints.response.client.FinTsClientResponse
import net.dankito.banking.util.ISerializer import net.dankito.banking.util.ISerializer
@ -28,9 +26,7 @@ import net.dankito.utils.multiplatform.log.LoggerFactory
open class fints4kBankingClient( open class fints4kBankingClient(
bankInfo: BankInfo, protected val customer: Customer,
customerId: String,
pin: String,
protected val dataFolder: File, protected val dataFolder: File,
protected val serializer: ISerializer, protected val serializer: ISerializer,
webClient: IWebClient = KtorWebClient(), webClient: IWebClient = KtorWebClient(),
@ -48,16 +44,12 @@ open class fints4kBankingClient(
protected val mapper = net.dankito.banking.mapper.fints4kModelMapper() protected val mapper = net.dankito.banking.mapper.fints4kModelMapper()
protected val bankDataMapper = BankDataMapper()
protected var didTryToGetAccountDataFromBank = false protected var didTryToGetAccountDataFromBank = false
protected val bank = bankDataMapper.mapFromBankInfo(bankInfo) protected val bank = BankData(customer.bankCode, customer.finTsServerAddress, customer.bic, customer.bankName)
protected val fints4kCustomer = CustomerData(customerId, pin) protected val fints4kCustomer = CustomerData(customer.customerId, customer.password)
protected var customer: Customer = mapper.mapCustomer(fints4kCustomer, bank) // temporary save temp customer, we update with data from server response like BankAccounts later
protected open val client = FinTsClientForCustomer(bank, fints4kCustomer, createFinTsClientCallback(callback), webClient, base64Service) protected open val client = FinTsClientForCustomer(bank, fints4kCustomer, createFinTsClientCallback(callback), webClient, base64Service)
@ -75,7 +67,7 @@ open class fints4kBankingClient(
protected open fun handleAddAccountResponse(response: net.dankito.banking.fints.response.client.AddAccountResponse, protected open fun handleAddAccountResponse(response: net.dankito.banking.fints.response.client.AddAccountResponse,
callback: (AddAccountResponse) -> Unit) { callback: (AddAccountResponse) -> Unit) {
this.customer = mapper.mapCustomer(fints4kCustomer, bank) mapper.mapCustomer(customer, fints4kCustomer, bank)
val mappedResponse = mapper.mapResponse(customer, response) val mappedResponse = mapper.mapResponse(customer, response)
saveData() saveData()
@ -168,7 +160,7 @@ open class fints4kBankingClient(
deserializedCustomer?.let { deserializedCustomer?.let {
mapper.updateCustomer(fints4kCustomer, deserializedCustomer) mapper.updateCustomer(fints4kCustomer, deserializedCustomer)
customer = mapper.mapCustomer(fints4kCustomer, bank) mapper.mapCustomer(customer, fints4kCustomer, bank) // TODO: necessary?
} }
} }

View File

@ -3,9 +3,9 @@ package net.dankito.banking
import net.dankito.banking.ui.BankingClientCallback import net.dankito.banking.ui.BankingClientCallback
import net.dankito.banking.ui.IBankingClient import net.dankito.banking.ui.IBankingClient
import net.dankito.banking.ui.IBankingClientCreator import net.dankito.banking.ui.IBankingClientCreator
import net.dankito.banking.bankfinder.BankInfo
import net.dankito.banking.fints.webclient.IWebClient import net.dankito.banking.fints.webclient.IWebClient
import net.dankito.banking.fints.webclient.KtorWebClient import net.dankito.banking.fints.webclient.KtorWebClient
import net.dankito.banking.ui.model.Customer
import net.dankito.banking.util.IAsyncRunner import net.dankito.banking.util.IAsyncRunner
import net.dankito.banking.util.ISerializer import net.dankito.banking.util.ISerializer
import net.dankito.utils.multiplatform.File import net.dankito.utils.multiplatform.File
@ -17,15 +17,13 @@ open class fints4kBankingClientCreator(
) : IBankingClientCreator { ) : IBankingClientCreator {
override fun createClient( override fun createClient(
bankInfo: BankInfo, customer: Customer,
customerId: String,
pin: String,
dataFolder: File, dataFolder: File,
asyncRunner: IAsyncRunner, asyncRunner: IAsyncRunner,
callback: BankingClientCallback callback: BankingClientCallback
): IBankingClient { ): IBankingClient {
return fints4kBankingClient(bankInfo, customerId, pin, dataFolder, serializer, webClient, callback = callback) return fints4kBankingClient(customer, dataFolder, serializer, webClient, callback = callback)
} }
} }

View File

@ -1,6 +1,5 @@
package net.dankito.banking.mapper package net.dankito.banking.mapper
import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Laenderkennzeichen
import net.dankito.banking.fints.model.BankData import net.dankito.banking.fints.model.BankData
import net.dankito.banking.bankfinder.BankInfo import net.dankito.banking.bankfinder.BankInfo
@ -9,21 +8,11 @@ open class BankDataMapper {
open fun mapFromBankInfo(bankInfo: BankInfo): BankData { open fun mapFromBankInfo(bankInfo: BankInfo): BankData {
return BankData( return BankData(
getBankCodeForOnlineBanking(bankInfo), bankInfo.bankCode,
Laenderkennzeichen.Germany, // TODO: currently there are only German banks. But change this if ever other countries get supported
bankInfo.pinTanAddress ?: "", bankInfo.pinTanAddress ?: "",
name = bankInfo.name, bankInfo.bic,
bic = bankInfo.bic bankInfo.name
) )
} }
protected open fun getBankCodeForOnlineBanking(bankInfo: BankInfo): String {
// for UniCredit / HypVereinsbank for online banking '70020270' has to be used as bank code
if (bankInfo.name.contains("unicredit", true)) {
return "70020270"
}
return bankInfo.bankCode
}
} }

View File

@ -61,15 +61,19 @@ open class fints4kModelMapper {
} }
open fun mapCustomer(customer: CustomerData, bank: BankData): Customer { open fun mapCustomer(customer: Customer, customerData: CustomerData, bank: BankData) {
val mappedCustomer = Customer(bank.bankCode, customer.customerId, customer.pin, customer.bankCode = bank.bankCode
bank.finTs3ServerAddress, bank.name, bank.bic, customer.name, customer.userId) customer.customerId = customerData.customerId
customer.password = customerData.pin
customer.finTsServerAddress = bank.finTs3ServerAddress
customer.bankName = bank.name
customer.bic = bank.bic
customer.customerName = customerData.name
customer.userId = customerData.userId
mappedCustomer.accounts = mapBankAccounts(mappedCustomer, customer.accounts) customer.accounts = mapBankAccounts(customer, customerData.accounts)
updateTanMediaAndProcedures(mappedCustomer, customer) updateTanMediaAndProcedures(customer, customerData)
return mappedCustomer
} }
// TODO: move to a fints4k internal mapper // TODO: move to a fints4k internal mapper
@ -92,7 +96,9 @@ open class fints4kModelMapper {
open fun mapBankAccounts(customer: Customer, accountData: List<AccountData>): List<BankAccount> { open fun mapBankAccounts(customer: Customer, accountData: List<AccountData>): List<BankAccount> {
return accountData.mapIndexed { index, account -> return accountData.mapIndexed { index, account ->
val mappedAccount = mapBankAccount(customer, account) val mappedAccount = customer.accounts.firstOrNull { it.identifier == account.accountIdentifier } ?: BankAccount(customer, account.productName, account.accountIdentifier)
mapBankAccount(mappedAccount, account)
mappedAccount.displayIndex = index mappedAccount.displayIndex = index
@ -100,13 +106,22 @@ open class fints4kModelMapper {
} }
} }
open fun mapBankAccount(customer: Customer, accountData: AccountData): BankAccount { open fun mapBankAccount(account: BankAccount, accountData: AccountData) {
return BankAccount(customer, accountData.accountIdentifier, accountData.accountHolderName, accountData.iban, account.identifier = accountData.accountIdentifier
accountData.subAccountAttribute, accountData.customerId, BigDecimal.Zero, accountData.currency ?: "EUR", account.accountHolderName = accountData.accountHolderName
mapBankAccountType(accountData.accountType), accountData.productName, accountData.accountLimit, account.iban = accountData.iban
null, accountData.supportsFeature(AccountFeature.RetrieveAccountTransactions), account.subAccountNumber = accountData.subAccountAttribute
accountData.supportsFeature(AccountFeature.RetrieveBalance), accountData.supportsFeature(AccountFeature.TransferMoney), account.customerId = accountData.customerId
accountData.supportsFeature(AccountFeature.InstantPayment))
account.currency = accountData.currency ?: "EUR"
account.type = mapBankAccountType(accountData.accountType)
account.productName = accountData.productName
account.accountLimit = accountData.accountLimit
account.supportsRetrievingBalance = accountData.supportsFeature(AccountFeature.RetrieveBalance)
account.supportsRetrievingAccountTransactions = accountData.supportsFeature(AccountFeature.RetrieveAccountTransactions)
account.supportsTransferringMoney = accountData.supportsFeature(AccountFeature.TransferMoney)
account.supportsInstantPaymentMoneyTransfer = accountData.supportsFeature(AccountFeature.InstantPayment)
} }
open fun mapBankAccountType(type: AccountType?): BankAccountType { open fun mapBankAccountType(type: AccountType?): BankAccountType {

View File

@ -12,7 +12,6 @@ import net.dankito.banking.ui.model.responses.BankingClientResponse
import net.dankito.banking.ui.model.responses.GetTransactionsResponse import net.dankito.banking.ui.model.responses.GetTransactionsResponse
import net.dankito.banking.util.AccountTransactionMapper import net.dankito.banking.util.AccountTransactionMapper
import net.dankito.banking.util.hbci4jModelMapper import net.dankito.banking.util.hbci4jModelMapper
import net.dankito.banking.bankfinder.BankInfo
import net.dankito.banking.util.* import net.dankito.banking.util.*
import net.dankito.utils.ThreadPool import net.dankito.utils.ThreadPool
import net.dankito.utils.multiplatform.* import net.dankito.utils.multiplatform.*
@ -33,9 +32,7 @@ import java.util.*
open class hbci4jBankingClient( open class hbci4jBankingClient(
bankInfo: BankInfo, protected val customer: Customer,
customerId: String,
pin: String,
protected val dataFolder: File, protected val dataFolder: File,
protected val asyncRunner: IAsyncRunner = ThreadPoolAsyncRunner(ThreadPool()), protected val asyncRunner: IAsyncRunner = ThreadPoolAsyncRunner(ThreadPool()),
protected val callback: BankingClientCallback protected val callback: BankingClientCallback
@ -51,10 +48,7 @@ open class hbci4jBankingClient(
} }
protected val credentials = AccountCredentials(bankInfo.bankCode, customerId, pin) protected val credentials = AccountCredentials(customer.bankCode, customer.customerId, customer.password)
protected var customer = Customer(bankInfo.bankCode, customerId, pin,
bankInfo.pinTanAddress ?: "", bankInfo.name, bankInfo.bic, "")
protected val mapper = hbci4jModelMapper() protected val mapper = hbci4jModelMapper()

View File

@ -3,7 +3,7 @@ package net.dankito.banking
import net.dankito.banking.ui.BankingClientCallback import net.dankito.banking.ui.BankingClientCallback
import net.dankito.banking.ui.IBankingClient import net.dankito.banking.ui.IBankingClient
import net.dankito.banking.ui.IBankingClientCreator import net.dankito.banking.ui.IBankingClientCreator
import net.dankito.banking.bankfinder.BankInfo import net.dankito.banking.ui.model.Customer
import net.dankito.banking.util.IAsyncRunner import net.dankito.banking.util.IAsyncRunner
import net.dankito.utils.multiplatform.File import net.dankito.utils.multiplatform.File
@ -11,15 +11,13 @@ import net.dankito.utils.multiplatform.File
open class hbci4jBankingClientCreator : IBankingClientCreator { open class hbci4jBankingClientCreator : IBankingClientCreator {
override fun createClient( override fun createClient(
bankInfo: BankInfo, customer: Customer,
customerId: String,
pin: String,
dataFolder: File, dataFolder: File,
asyncRunner: IAsyncRunner, asyncRunner: IAsyncRunner,
callback: BankingClientCallback callback: BankingClientCallback
): IBankingClient { ): IBankingClient {
return hbci4jBankingClient(bankInfo, customerId, pin, dataFolder, asyncRunner, callback) return hbci4jBankingClient(customer, dataFolder, asyncRunner, callback)
} }
} }