Implemented reusing FinTsClient and therefore don't have to fetch basic data before all operations
This commit is contained in:
parent
fbfcbb1d2c
commit
1b3ec8f7c1
|
@ -1,7 +1,7 @@
|
||||||
package net.dankito.banking.fints.rest.service
|
package net.dankito.banking.fints.rest.service
|
||||||
|
|
||||||
import net.dankito.banking.bankfinder.InMemoryBankFinder
|
import net.dankito.banking.bankfinder.InMemoryBankFinder
|
||||||
import net.dankito.banking.fints.FinTsClient
|
import net.dankito.banking.fints.FinTsClientForCustomer
|
||||||
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
||||||
import net.dankito.banking.fints.model.*
|
import net.dankito.banking.fints.model.*
|
||||||
import net.dankito.banking.fints.response.BankResponse
|
import net.dankito.banking.fints.response.BankResponse
|
||||||
|
@ -9,10 +9,10 @@ import net.dankito.banking.fints.response.client.AddAccountResponse
|
||||||
import net.dankito.banking.fints.response.client.GetTransactionsResponse
|
import net.dankito.banking.fints.response.client.GetTransactionsResponse
|
||||||
import net.dankito.banking.fints.rest.model.BankAccessData
|
import net.dankito.banking.fints.rest.model.BankAccessData
|
||||||
import net.dankito.banking.fints.rest.model.EnterTanContext
|
import net.dankito.banking.fints.rest.model.EnterTanContext
|
||||||
import net.dankito.banking.fints.rest.model.EnteringTanRequested
|
|
||||||
import net.dankito.banking.fints.rest.model.dto.request.AccountRequestDto
|
import net.dankito.banking.fints.rest.model.dto.request.AccountRequestDto
|
||||||
import net.dankito.banking.fints.rest.model.dto.request.GetAccountsTransactionsRequestDto
|
import net.dankito.banking.fints.rest.model.dto.request.GetAccountsTransactionsRequestDto
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import javax.enterprise.context.ApplicationScoped
|
import javax.enterprise.context.ApplicationScoped
|
||||||
|
@ -23,6 +23,8 @@ class fints4kService {
|
||||||
|
|
||||||
protected val bankFinder = InMemoryBankFinder()
|
protected val bankFinder = InMemoryBankFinder()
|
||||||
|
|
||||||
|
protected val clientCache = ConcurrentHashMap<String, FinTsClientForCustomer>()
|
||||||
|
|
||||||
protected val tanRequests = mutableMapOf<String, EnterTanContext>()
|
protected val tanRequests = mutableMapOf<String, EnterTanContext>()
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ class fints4kService {
|
||||||
|
|
||||||
// TODO: as in most cases we really just want the account data, so just retrieve these without balances and transactions
|
// TODO: as in most cases we really just want the account data, so just retrieve these without balances and transactions
|
||||||
protected fun getAccountData(bank: BankData): AddAccountResponse {
|
protected fun getAccountData(bank: BankData): AddAccountResponse {
|
||||||
return getAsyncResponse { client, responseRetrieved ->
|
return getAsyncResponse(bank) { client, responseRetrieved ->
|
||||||
client.addAccountAsync(AddAccountParameter(bank)) { response ->
|
client.addAccountAsync(AddAccountParameter(bank)) { response ->
|
||||||
responseRetrieved(response)
|
responseRetrieved(response)
|
||||||
}
|
}
|
||||||
|
@ -53,38 +55,34 @@ class fints4kService {
|
||||||
return listOf(GetTransactionsResponse(BankResponse(false, errorMessage = errorMessage)))
|
return listOf(GetTransactionsResponse(BankResponse(false, errorMessage = errorMessage)))
|
||||||
}
|
}
|
||||||
|
|
||||||
val accountData = getAccountData(bank)
|
|
||||||
|
|
||||||
return dto.accounts.map { accountDto ->
|
return dto.accounts.map { accountDto ->
|
||||||
val account = findAccount(accountData, accountDto)
|
val account = findAccount(dto.credentials, accountDto)
|
||||||
|
|
||||||
return@map if (account != null) {
|
return@map if (account != null) {
|
||||||
val parameter = GetTransactionsParameter(account, dto.alsoRetrieveBalance, dto.fromDate, dto.toDate, abortIfTanIsRequired = dto.abortIfTanIsRequired)
|
val parameter = GetTransactionsParameter(account, dto.alsoRetrieveBalance, dto.fromDate, dto.toDate, abortIfTanIsRequired = dto.abortIfTanIsRequired)
|
||||||
getAccountTransactions(bank, parameter)
|
getAccountTransactions(bank, parameter)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GetTransactionsResponse(BankResponse(false, errorMessage = "Account with identifier '${accountDto.identifier}' not found. Available accounts: ${accountData.bank.accounts.map { it.accountIdentifier }.joinToString(", ")}"))
|
GetTransactionsResponse(BankResponse(false, errorMessage = "Account with identifier '${accountDto.identifier}' not found. Available accounts: " +
|
||||||
|
"${getCachedClient(dto.credentials)?.bank?.accounts?.map { it.accountIdentifier }?.joinToString(", ")}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAccountTransactions(bank: BankData, parameter: GetTransactionsParameter): GetTransactionsResponse {
|
fun getAccountTransactions(bank: BankData, parameter: GetTransactionsParameter): GetTransactionsResponse {
|
||||||
return getAsyncResponse { client, responseRetrieved ->
|
return getAsyncResponse(bank) { client, responseRetrieved ->
|
||||||
client.getTransactionsAsync(parameter, bank) { response ->
|
client.getTransactionsAsync(parameter) { response ->
|
||||||
responseRetrieved(response)
|
responseRetrieved(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected fun <T> getAsyncResponse(executeRequest: (FinTsClient, ((T) -> Unit)) -> Unit): T {
|
protected fun <T> getAsyncResponse(bank: BankData, executeRequest: (FinTsClientForCustomer, ((T) -> Unit)) -> Unit): T {
|
||||||
val result = AtomicReference<T>()
|
val result = AtomicReference<T>()
|
||||||
val countDownLatch = CountDownLatch(1)
|
val countDownLatch = CountDownLatch(1)
|
||||||
|
|
||||||
// val client = FinTsClient(SimpleFinTsClientCallback { supportedTanMethods: List<TanMethod>, suggestedTanMethod: TanMethod? ->
|
val client = getClient(bank, result, countDownLatch)
|
||||||
val client = FinTsClient(SimpleFinTsClientCallback({ bank, tanChallenge -> handleEnterTan(bank, tanChallenge, countDownLatch, result) }) { supportedTanMethods, suggestedTanMethod ->
|
|
||||||
suggestedTanMethod
|
|
||||||
})
|
|
||||||
|
|
||||||
executeRequest(client) { response ->
|
executeRequest(client) { response ->
|
||||||
result.set(response)
|
result.set(response)
|
||||||
|
@ -96,6 +94,23 @@ class fints4kService {
|
||||||
return result.get()
|
return result.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T> getClient(bank: BankData, result: AtomicReference<T>, countDownLatch: CountDownLatch): FinTsClientForCustomer {
|
||||||
|
val cacheKey = getCacheKey(bank.bankCode, bank.customerId)
|
||||||
|
|
||||||
|
clientCache[cacheKey]?.let {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
// val client = FinTsClient(SimpleFinTsClientCallback { supportedTanMethods: List<TanMethod>, suggestedTanMethod: TanMethod? ->
|
||||||
|
val client = FinTsClientForCustomer(bank, SimpleFinTsClientCallback({ bank, tanChallenge -> handleEnterTan(bank, tanChallenge, countDownLatch, result) }) { supportedTanMethods, suggestedTanMethod ->
|
||||||
|
suggestedTanMethod
|
||||||
|
})
|
||||||
|
|
||||||
|
clientCache[cacheKey] = client
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
protected fun <T> handleEnterTan(bank: BankData, tanChallenge: TanChallenge, originatingRequestLatch: CountDownLatch, originatingRequestResult: AtomicReference<T>): EnterTanResult {
|
protected fun <T> handleEnterTan(bank: BankData, tanChallenge: TanChallenge, originatingRequestLatch: CountDownLatch, originatingRequestResult: AtomicReference<T>): EnterTanResult {
|
||||||
val enterTanResult = AtomicReference<EnterTanResult>()
|
val enterTanResult = AtomicReference<EnterTanResult>()
|
||||||
val enterTanLatch = CountDownLatch(1)
|
val enterTanLatch = CountDownLatch(1)
|
||||||
|
@ -131,8 +146,19 @@ class fints4kService {
|
||||||
return Pair(bank, null)
|
return Pair(bank, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun findAccount(allAccounts: AddAccountResponse, accountDto: AccountRequestDto): AccountData? {
|
protected fun findAccount(credentials: BankAccessData, accountDto: AccountRequestDto): AccountData? {
|
||||||
return allAccounts.bank.accounts.firstOrNull { it.accountIdentifier == accountDto.identifier }
|
return getCachedClient(credentials)?.bank?.accounts?.firstOrNull { it.accountIdentifier == accountDto.identifier }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getCachedClient(credentials: BankAccessData): FinTsClientForCustomer? {
|
||||||
|
val cacheKey = getCacheKey(credentials.bankCode, credentials.loginName)
|
||||||
|
|
||||||
|
return clientCache[cacheKey]
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCacheKey(bankCode: String, loginName: String): String {
|
||||||
|
return bankCode + "_" + loginName
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue