Created FinTsServerAddressFinder with BankListCreator to easily retrieve a FinTS server address to a bank code

This commit is contained in:
dankito 2022-02-21 01:07:00 +01:00
parent 73a98eea67
commit 3ed9e10c22
13 changed files with 1776 additions and 26 deletions

View File

@ -47,7 +47,7 @@ class FirstFragment : Fragment() {
}
// TODO: set your credentials here
presenter.retrieveAccountData("", "", "", "") { response ->
presenter.retrieveAccountData("", "", "") { response ->
response.customerAccount?.let { customer ->
accountTransactionsAdapter.items = customer.accounts.flatMap { it.bookedTransactions }
}

View File

@ -34,9 +34,9 @@ open class Presenter {
open fun retrieveAccountData(bankCode: String, customerId: String, pin: String, finTs3ServerAddress: String, retrievedResult: (GetAccountDataResponse) -> Unit) {
open fun retrieveAccountData(bankCode: String, loginName: String, password: String, retrievedResult: (GetAccountDataResponse) -> Unit) {
GlobalScope.launch(Dispatchers.IO) {
val response = fintsClient.getAccountData(GetAccountDataParameter(bankCode, customerId, pin, finTs3ServerAddress))
val response = fintsClient.getAccountData(GetAccountDataParameter(bankCode, loginName, password))
log.info("Retrieved response from ${response.customerAccount?.bankName} for ${response.customerAccount?.customerName}")
withContext(Dispatchers.Main) {

View File

@ -27,7 +27,7 @@ class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent<
// due to CORS your bank's servers can not be requested directly from browser -> set a CORS proxy url in main.kt
// TODO: set your credentials here
GlobalScope.launch {
props.presenter.retrieveAccountData("", "", "", "") { response ->
props.presenter.retrieveAccountData("", "", "") { response ->
response.customerAccount?.let { customer ->
val balance = customer.accounts.sumOf { it.balance?.amount?.string?.replace(',', '.')?.toDoubleOrNull() ?: 0.0 } // i know, double is not an appropriate data type for amounts

View File

@ -32,9 +32,9 @@ open class Presenter {
}
open fun retrieveAccountData(bankCode: String, customerId: String, pin: String, finTs3ServerAddress: String, retrievedResult: (GetAccountDataResponse) -> Unit) {
open fun retrieveAccountData(bankCode: String, loginName: String, password: String, retrievedResult: (GetAccountDataResponse) -> Unit) {
GlobalScope.launch(Dispatchers.Unconfined) {
val response = fintsClient.getAccountData(GetAccountDataParameter(bankCode, customerId, pin, finTs3ServerAddress))
val response = fintsClient.getAccountData(GetAccountDataParameter(bankCode, loginName, password))
log.info("Retrieved response from ${response.customerAccount?.bankName} for ${response.customerAccount?.customerName}")

View File

@ -51,7 +51,7 @@ struct ContentView: View {
private func retrieveTransactions() {
// TODO: set your credentials here
self.presenter.getAccountData("", "", "", "", self.handleGetAccountDataResponse)
self.presenter.getAccountData("", "", "", self.handleGetAccountDataResponse)
}
private func handleGetAccountDataResponse(_ response: GetAccountDataResponse) {

View File

@ -11,7 +11,7 @@ open class CustomerAccount(
override var bankCode: String,
override var loginName: String,
override var password: String,
override var finTsServerAddress: String,
open var finTsServerAddress: String,
open var bankName: String,
open var bic: String,
@ -25,7 +25,7 @@ open class CustomerAccount(
open var selectedTanMethod: TanMethod? = null,
open var tanMedia: List<TanMedium> = listOf(),
open var selectedTanMedium: TanMedium? = null,
) : CustomerCredentials(bankCode, loginName, password, finTsServerAddress) {
) : CustomerCredentials(bankCode, loginName, password) {
override fun toString(): String {

View File

@ -4,10 +4,9 @@ package net.dankito.banking.client.model
open class CustomerCredentials(
open val bankCode: String,
open val loginName: String,
open val password: String,
open val finTsServerAddress: String // TODO: get rid of this
open val password: String
) {
internal constructor() : this("", "", "", "") // for object deserializers
internal constructor() : this("", "", "") // for object deserializers
}

View File

@ -10,10 +10,9 @@ open class FinTsClientParameter(
bankCode: String,
loginName: String,
password: String,
finTsServerAddress: String, // TODO: get rid of this
open val preferredTanMethods: List<TanMethodType>? = null,
open val preferredTanMedium: String? = null, // the ID of the medium
open val abortIfTanIsRequired: Boolean = false,
open val finTsModel: BankData? = null
) : CustomerCredentials(bankCode, loginName, password, finTsServerAddress)
) : CustomerCredentials(bankCode, loginName, password)

View File

@ -10,7 +10,6 @@ open class GetAccountDataParameter(
bankCode: String,
loginName: String,
password: String,
finTsServerAddress: String, // TODO: get rid of this
/**
* Optionally specify for which bank account to retrieve the account data.
* If not set the data for all bank accounts of this account will be retrieved.
@ -25,7 +24,7 @@ open class GetAccountDataParameter(
preferredTanMedium: String? = null,
abortIfTanIsRequired: Boolean = false,
finTsModel: BankData? = null
) : FinTsClientParameter(bankCode, loginName, password, finTsServerAddress, preferredTanMethods, preferredTanMedium, abortIfTanIsRequired, finTsModel) {
) : FinTsClientParameter(bankCode, loginName, password, preferredTanMethods, preferredTanMedium, abortIfTanIsRequired, finTsModel) {
open val retrieveOnlyAccountInfo: Boolean
get() = retrieveBalance == false && retrieveTransactions == RetrieveTransactions.No

View File

@ -3,6 +3,8 @@ package net.dankito.banking.client.model.response
enum class ErrorCode {
BankDoesNotSupportFinTs3,
InternalError,
BankReturnedError,

View File

@ -12,6 +12,7 @@ import net.dankito.banking.fints.response.client.FinTsClientResponse
import net.dankito.banking.fints.response.client.GetAccountInfoResponse
import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse
import net.dankito.banking.fints.response.segments.AccountType
import net.dankito.banking.fints.util.FinTsServerAddressFinder
import net.dankito.banking.fints.webclient.IWebClient
import net.dankito.utils.multiplatform.extensions.minusDays
import net.dankito.utils.multiplatform.extensions.todayAtEuropeBerlin
@ -21,6 +22,7 @@ import kotlin.jvm.JvmOverloads
open class FinTsClient @JvmOverloads constructor(
open var callback: FinTsClientCallback,
protected open val jobExecutor: FinTsJobExecutor = FinTsJobExecutor(),
protected open val finTsServerAddressFinder: FinTsServerAddressFinder = FinTsServerAddressFinder(),
protected open val product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically
) {
@ -29,16 +31,19 @@ open class FinTsClient @JvmOverloads constructor(
}
constructor(callback: FinTsClientCallback) : this(callback, FinTsJobExecutor()) // Swift does not support default parameter values -> create constructor overloads
constructor(callback: FinTsClientCallback, webClient: IWebClient) : this(callback, FinTsJobExecutor(RequestExecutor(webClient = webClient)))
constructor(callback: FinTsClientCallback, webClient: IWebClient) : this(callback, FinTsJobExecutor(RequestExecutor(webClient = webClient))) // Swift does not support default parameter values -> create constructor overloads
protected open val mapper = FinTsModelMapper()
open suspend fun getAccountData(param: GetAccountDataParameter): GetAccountDataResponse {
val bank = BankData(param.bankCode, param.loginName, param.password, param.finTsServerAddress, "")
val finTsServerAddress = finTsServerAddressFinder.findFinTsServerAddress(param.bankCode)
if (finTsServerAddress.isNullOrBlank()) {
return GetAccountDataResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not FinTS 3.0 or we don't know its FinTS server address", null, listOf())
}
val bank = BankData(param.bankCode, param.loginName, param.password, finTsServerAddress, "")
val accounts = param.accounts
if (accounts.isNullOrEmpty() || param.retrieveOnlyAccountInfo) { // then first retrieve customer's bank accounts

View File

@ -10,22 +10,22 @@ import net.dankito.utils.multiplatform.extensions.*
import platform.posix.exit
fun main(args: Array<String>) {
if (args.size < 4) {
println("Bitte geben Sie Ihre Bankzugangsdaten ein in der Reihenfolge: <Bankleitzahl> <Login name> <Password> <FinTS Serveradresse der Bank>\r\n" +
"Z. B.: ./fints4k.kexe 10050000 \"Mein Loginname\" GeheimesPasswort \"https://banking-be3.s-fints-pt-be.de/fints30\"")
if (args.size < 3) {
println("Bitte geben Sie Ihre Bankzugangsdaten ein in der Reihenfolge: <Bankleitzahl> <Login name> <Password>\r\n" +
"Z. B.: ./fints4k.kexe 10050000 \"Mein Loginname\" GeheimesPasswort")
exit(0)
}
Application().retrieveAccountData(args[0], args[1], args[2], args[3])
Application().retrieveAccountData(args[0], args[1], args[2])
}
class Application {
fun retrieveAccountData(bankCode: String, customerId: String, pin: String, finTs3ServerAddress: String) {
fun retrieveAccountData(bankCode: String, loginName: String, password: String) {
runBlocking {
val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) })
val response = client.getAccountData(GetAccountDataParameter(bankCode, customerId, pin, finTs3ServerAddress))
val response = client.getAccountData(GetAccountDataParameter(bankCode, loginName, password))
if (response.error != null) {
println("An error occurred: ${response.error}${response.errorMessage?.let { " $it" }}")