Collecting now message on JobContext (makes FinTsClient, FinTsJobExecutor and RequestExecutor state free); moved therefore Mt940AccountTransactionsParser to JobContext

This commit is contained in:
dankito 2021-11-12 22:31:07 +01:00
parent b57847b4f2
commit 471fd0caf4
15 changed files with 104 additions and 96 deletions

View File

@ -27,10 +27,6 @@ open class FinTsClient @JvmOverloads constructor(
} }
open val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = jobExecutor.messageLogWithoutSensitiveData
/** /**
* Retrieves information about bank (e.g. supported HBCI versions, FinTS server address, * Retrieves information about bank (e.g. supported HBCI versions, FinTS server address,
* supported jobs, ...). * supported jobs, ...).
@ -51,8 +47,10 @@ open class FinTsClient @JvmOverloads constructor(
* On success [bank] parameter is updated afterwards. * On success [bank] parameter is updated afterwards.
*/ */
open fun getAnonymousBankInfo(bank: BankData, callback: (FinTsClientResponse) -> Unit) { open fun getAnonymousBankInfo(bank: BankData, callback: (FinTsClientResponse) -> Unit) {
jobExecutor.getAnonymousBankInfo(JobContext(JobContextType.AnonymousBankInfo, this.callback, product, bank)) { response -> val context = JobContext(JobContextType.AnonymousBankInfo, this.callback, product, bank)
callback(FinTsClientResponse(response))
jobExecutor.getAnonymousBankInfo(context) { response ->
callback(FinTsClientResponse(context, response))
} }
} }
@ -66,7 +64,7 @@ open class FinTsClient @JvmOverloads constructor(
jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, parameter.preferredTanMethods, parameter.preferredTanMedium) { newUserInfoResponse -> jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, parameter.preferredTanMethods, parameter.preferredTanMedium) { newUserInfoResponse ->
if (newUserInfoResponse.successful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong if (newUserInfoResponse.successful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong
callback(AddAccountResponse(newUserInfoResponse, bank)) callback(AddAccountResponse(context, newUserInfoResponse, bank))
return@retrieveBasicDataLikeUsersTanMethods return@retrieveBasicDataLikeUsersTanMethods
} }
@ -84,7 +82,7 @@ open class FinTsClient @JvmOverloads constructor(
jobExecutor.getAccounts(context) { getAccountsResponse -> jobExecutor.getAccounts(context) { getAccountsResponse ->
if (getAccountsResponse.successful == false) { if (getAccountsResponse.successful == false) {
callback(AddAccountResponse(getAccountsResponse, context.bank)) callback(AddAccountResponse(context, getAccountsResponse, context.bank))
return@getAccounts return@getAccounts
} }
@ -119,7 +117,7 @@ open class FinTsClient @JvmOverloads constructor(
tryGetTransactionsOfLast90DaysWithoutTan(bank, account) { response -> tryGetTransactionsOfLast90DaysWithoutTan(bank, account) { response ->
retrievedAccountData.put(account, response.retrievedData.first()) retrievedAccountData.put(account, response.retrievedData.first())
if (response.internalError != null) { if (response.internalError != null) { // TODO: errors from response get lost! User then only sees "null" as error message
//getAccountsResponse.errorMessage = response.errorMessage //getAccountsResponse.errorMessage = response.errorMessage
} }
@ -135,7 +133,7 @@ open class FinTsClient @JvmOverloads constructor(
retrievedAccountData: Map<AccountData, RetrievedAccountData>, retrievedAccountData: Map<AccountData, RetrievedAccountData>,
callback: (AddAccountResponse) -> Unit) { callback: (AddAccountResponse) -> Unit) {
callback(AddAccountResponse(getAccountsResponse, context.bank, retrievedAccountData.values.toList())) callback(AddAccountResponse(context, getAccountsResponse, context.bank, retrievedAccountData.values.toList()))
} }
@ -175,7 +173,7 @@ open class FinTsClient @JvmOverloads constructor(
val context = JobContext(JobContextType.ChangeTanMedium, this.callback, product, bank) val context = JobContext(JobContextType.ChangeTanMedium, this.callback, product, bank)
jobExecutor.changeTanMedium(context, newActiveTanMedium) { response -> jobExecutor.changeTanMedium(context, newActiveTanMedium) { response ->
callback(FinTsClientResponse(response)) callback(FinTsClientResponse(context, response))
} }
} }

View File

@ -21,7 +21,6 @@ open class FinTsClientForCustomer(
callback: FinTsClientCallback, callback: FinTsClientCallback,
requestExecutor: RequestExecutor = RequestExecutor(), requestExecutor: RequestExecutor = RequestExecutor(),
messageBuilder: MessageBuilder = MessageBuilder(), messageBuilder: MessageBuilder = MessageBuilder(),
mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(),
modelMapper: ModelMapper = ModelMapper(messageBuilder), modelMapper: ModelMapper = ModelMapper(messageBuilder),
protected open val tanMethodSelector: TanMethodSelector = TanMethodSelector(), protected open val tanMethodSelector: TanMethodSelector = TanMethodSelector(),
product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically) product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically)
@ -29,14 +28,13 @@ open class FinTsClientForCustomer(
constructor(bank: BankData, callback: FinTsClientCallback, webClient: IWebClient = KtorWebClient(), base64Service: IBase64Service = PureKotlinBase64Service(), constructor(bank: BankData, callback: FinTsClientCallback, webClient: IWebClient = KtorWebClient(), base64Service: IBase64Service = PureKotlinBase64Service(),
product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0")) // TODO: get version dynamically) product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0")) // TODO: get version dynamically)
: this(bank, callback, RequestExecutor(MessageBuilder(), webClient, base64Service)) : this(bank, callback, RequestExecutor(MessageBuilder(), webClient, base64Service), product = product)
protected val client = FinTsClient(callback, FinTsJobExecutor(requestExecutor, messageBuilder, mt940Parser, modelMapper, tanMethodSelector), product) protected val client = FinTsClient(callback, FinTsJobExecutor(requestExecutor, messageBuilder, modelMapper, tanMethodSelector), product)
open val messageLogWithoutSensitiveData: List<MessageLogEntry> open val messageLogWithoutSensitiveData: List<MessageLogEntry> = mutableListOf()
get() = client.messageLogWithoutSensitiveData
open fun setCallback(callback: FinTsClientCallback) { open fun setCallback(callback: FinTsClientCallback) {
client.callback = callback client.callback = callback

View File

@ -33,7 +33,6 @@ import net.dankito.utils.multiplatform.ObjectReference
open class FinTsJobExecutor( open class FinTsJobExecutor(
protected open val requestExecutor: RequestExecutor = RequestExecutor(), protected open val requestExecutor: RequestExecutor = RequestExecutor(),
protected open val messageBuilder: MessageBuilder = MessageBuilder(), protected open val messageBuilder: MessageBuilder = MessageBuilder(),
protected open val mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(),
protected open val modelMapper: ModelMapper = ModelMapper(messageBuilder), protected open val modelMapper: ModelMapper = ModelMapper(messageBuilder),
protected open val tanMethodSelector: TanMethodSelector = TanMethodSelector() protected open val tanMethodSelector: TanMethodSelector = TanMethodSelector()
) { ) {
@ -43,15 +42,6 @@ open class FinTsJobExecutor(
} }
open val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = requestExecutor.messageLogWithoutSensitiveData
init {
mt940Parser.logAppender = requestExecutor.messageLogAppender // TODO: find a better solution to append messages to MessageLog
}
open fun getAnonymousBankInfo(context: JobContext, callback: (BankResponse) -> Unit) { open fun getAnonymousBankInfo(context: JobContext, callback: (BankResponse) -> Unit) {
context.startNewDialog() context.startNewDialog()
@ -197,7 +187,7 @@ open class FinTsJobExecutor(
initDialogWithStrongCustomerAuthentication(context) { initDialogResponse -> initDialogWithStrongCustomerAuthentication(context) { initDialogResponse ->
if (initDialogResponse.successful == false) { if (initDialogResponse.successful == false) {
callback(GetTransactionsResponse(initDialogResponse, RetrievedAccountData.unsuccessfulList(parameter.account))) callback(GetTransactionsResponse(context, initDialogResponse, RetrievedAccountData.unsuccessfulList(parameter.account)))
} }
else { else {
// we now retrieved the fresh account information from FinTS server, use that one // we now retrieved the fresh account information from FinTS server, use that one
@ -205,7 +195,7 @@ open class FinTsJobExecutor(
mayGetBalance(context, parameter) { balanceResponse -> mayGetBalance(context, parameter) { balanceResponse ->
if (dialogContext.didBankCloseDialog) { if (dialogContext.didBankCloseDialog) {
callback(GetTransactionsResponse(balanceResponse ?: initDialogResponse, RetrievedAccountData.unsuccessfulList(parameter.account))) callback(GetTransactionsResponse(context, balanceResponse ?: initDialogResponse, RetrievedAccountData.unsuccessfulList(parameter.account)))
} }
else { else {
getTransactionsAfterInitAndGetBalance(context, parameter, balanceResponse, callback) getTransactionsAfterInitAndGetBalance(context, parameter, balanceResponse, callback)
@ -235,7 +225,7 @@ open class FinTsJobExecutor(
context.dialog.chunkedResponseHandler = { response -> context.dialog.chunkedResponseHandler = { response ->
response.getFirstSegmentById<ReceivedAccountTransactions>(InstituteSegmentId.AccountTransactionsMt940)?.let { transactionsSegment -> response.getFirstSegmentById<ReceivedAccountTransactions>(InstituteSegmentId.AccountTransactionsMt940)?.let { transactionsSegment ->
val (chunkTransaction, remainder) = mt940Parser.parseTransactionsChunk(remainingMt940String + transactionsSegment.bookedTransactionsString, val (chunkTransaction, remainder) = context.mt940Parser.parseTransactionsChunk(remainingMt940String + transactionsSegment.bookedTransactionsString,
context.bank, parameter.account) context.bank, parameter.account)
bookedTransactions.addAll(chunkTransaction) bookedTransactions.addAll(chunkTransaction)
@ -261,7 +251,7 @@ open class FinTsJobExecutor(
val retrievedData = RetrievedAccountData(parameter.account, successful, balance, bookedTransactions, unbookedTransactions, fromDate, parameter.toDate ?: Date.today, response.internalError) val retrievedData = RetrievedAccountData(parameter.account, successful, balance, bookedTransactions, unbookedTransactions, fromDate, parameter.toDate ?: Date.today, response.internalError)
callback( callback(
GetTransactionsResponse(response, listOf(retrievedData), GetTransactionsResponse(context, response, listOf(retrievedData),
if (parameter.maxCountEntries != null) parameter.isSettingMaxCountEntriesAllowedByBank else null if (parameter.maxCountEntries != null) parameter.isSettingMaxCountEntriesAllowedByBank else null
) )
) )
@ -302,7 +292,7 @@ open class FinTsJobExecutor(
closeDialog(context) closeDialog(context)
} }
callback(FinTsClientResponse(response)) callback(FinTsClientResponse(context, response))
} }
} }
@ -318,11 +308,13 @@ open class FinTsJobExecutor(
sendMessageAndHandleResponse(context, CustomerSegmentId.TanMediaList, false, { sendMessageAndHandleResponse(context, CustomerSegmentId.TanMediaList, false, {
messageBuilder.createGetTanMediaListMessage(context, tanMediaKind, tanMediumClass) messageBuilder.createGetTanMediaListMessage(context, tanMediaKind, tanMediumClass)
}) { response -> }) { response ->
handleGetTanMediaListResponse(response, context.bank, preferredTanMedium, callback) handleGetTanMediaListResponse(context, response, preferredTanMedium, callback)
} }
} }
protected open fun handleGetTanMediaListResponse(response: BankResponse, bank: BankData, preferredTanMedium: String? = null, callback: (GetTanMediaListResponse) -> Unit) { protected open fun handleGetTanMediaListResponse(context: JobContext, response: BankResponse, preferredTanMedium: String? = null, callback: (GetTanMediaListResponse) -> Unit) {
val bank = context.bank
// TAN media list (= TAN generator list) is only returned for users with chipTAN TAN methods // TAN media list (= TAN generator list) is only returned for users with chipTAN TAN methods
val tanMediaList = if (response.successful == false) null val tanMediaList = if (response.successful == false) null
else response.getFirstSegmentById<TanMediaList>(InstituteSegmentId.TanMediaList) else response.getFirstSegmentById<TanMediaList>(InstituteSegmentId.TanMediaList)
@ -335,7 +327,7 @@ open class FinTsJobExecutor(
?: bank.tanMedia.firstOrNull { it.mediumName != null } ?: bank.tanMedia.firstOrNull { it.mediumName != null }
} }
callback(GetTanMediaListResponse(response, tanMediaList)) callback(GetTanMediaListResponse(context, response, tanMediaList))
} }
@ -373,7 +365,7 @@ open class FinTsJobExecutor(
val updatedAccount = getUpdatedAccount(context, context.account!!) val updatedAccount = getUpdatedAccount(context, context.account!!)
messageBuilder.createBankTransferMessage(context, bankTransferData, updatedAccount) messageBuilder.createBankTransferMessage(context, bankTransferData, updatedAccount)
}) { response -> }) { response ->
callback(FinTsClientResponse(response)) callback(FinTsClientResponse(context, response))
} }
} }
@ -499,7 +491,7 @@ open class FinTsJobExecutor(
changeTanMedium(context, changeTanMediumTo) { changeTanMediumResponse -> changeTanMedium(context, changeTanMediumTo) { changeTanMediumResponse ->
changeTanMediumResultCallback?.invoke(FinTsClientResponse(changeTanMediumResponse)) changeTanMediumResultCallback?.invoke(FinTsClientResponse(context, changeTanMediumResponse))
if (changeTanMediumResponse.successful == false || lastCreatedMessage == null) { if (changeTanMediumResponse.successful == false || lastCreatedMessage == null) {
callback(changeTanMediumResponse) callback(changeTanMediumResponse)

View File

@ -1,7 +1,5 @@
package net.dankito.banking.fints package net.dankito.banking.fints
import net.dankito.banking.fints.log.IMessageLogAppender
import net.dankito.banking.fints.log.MessageLogCollector
import net.dankito.banking.fints.messages.MessageBuilder import net.dankito.banking.fints.messages.MessageBuilder
import net.dankito.banking.fints.messages.MessageBuilderResult import net.dankito.banking.fints.messages.MessageBuilderResult
import net.dankito.banking.fints.model.* import net.dankito.banking.fints.model.*
@ -14,7 +12,6 @@ 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.fints.webclient.WebClientResponse import net.dankito.banking.fints.webclient.WebClientResponse
import net.dankito.utils.multiplatform.getAllExceptionMessagesJoined import net.dankito.utils.multiplatform.getAllExceptionMessagesJoined
import net.dankito.utils.multiplatform.log.Logger
import net.dankito.utils.multiplatform.log.LoggerFactory import net.dankito.utils.multiplatform.log.LoggerFactory
@ -22,8 +19,7 @@ open class RequestExecutor(
protected open val messageBuilder: MessageBuilder = MessageBuilder(), protected open val messageBuilder: MessageBuilder = MessageBuilder(),
protected open val webClient: IWebClient = KtorWebClient(), protected open val webClient: IWebClient = KtorWebClient(),
protected open val base64Service: IBase64Service = PureKotlinBase64Service(), protected open val base64Service: IBase64Service = PureKotlinBase64Service(),
protected open val responseParser: ResponseParser = ResponseParser(), protected open val responseParser: ResponseParser = ResponseParser()
protected open val messageLogCollector: MessageLogCollector = MessageLogCollector()
) { ) {
companion object { companion object {
@ -31,18 +27,6 @@ open class RequestExecutor(
} }
open val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = messageLogCollector.messageLogWithoutSensitiveData
internal open val messageLogAppender: IMessageLogAppender = object : IMessageLogAppender {
override fun logError(message: String, e: Exception?, logger: Logger?, bank: BankData?) {
messageLogCollector.logError(message, e, logger, bank)
}
}
open fun getAndHandleResponseForMessage(message: MessageBuilderResult, context: JobContext, open fun getAndHandleResponseForMessage(message: MessageBuilderResult, context: JobContext,
tanRequiredCallback: (TanResponse, BankResponse, callback: (BankResponse) -> Unit) -> Unit, callback: (BankResponse) -> Unit) { tanRequiredCallback: (TanResponse, BankResponse, callback: (BankResponse) -> Unit) -> Unit, callback: (BankResponse) -> Unit) {
if (message.createdMessage == null) { if (message.createdMessage == null) {
@ -190,11 +174,11 @@ open class RequestExecutor(
protected open fun addMessageLog(context: JobContext, type: MessageLogEntryType, message: String) { protected open fun addMessageLog(context: JobContext, type: MessageLogEntryType, message: String) {
messageLogCollector.addMessageLog(message, type, context.bank) context.addMessageLog(type, message)
} }
protected open fun logError(context: JobContext, message: String, e: Exception?) { protected open fun logError(context: JobContext, message: String, e: Exception?) {
messageLogAppender.logError(message, e, log, context.bank) context.logError(RequestExecutor::class, message, e)
} }
} }

View File

@ -1,11 +1,10 @@
package net.dankito.banking.fints.log package net.dankito.banking.fints.log
import net.dankito.banking.fints.model.BankData import kotlin.reflect.KClass
import net.dankito.utils.multiplatform.log.Logger
interface IMessageLogAppender { interface IMessageLogAppender {
fun logError(message: String, e: Exception? = null, logger: Logger? = null, bank: BankData? = null) fun logError(loggingClass: KClass<*>, message: String, e: Exception? = null)
} }

View File

@ -8,6 +8,7 @@ import net.dankito.utils.multiplatform.log.LoggerFactory
import net.dankito.utils.multiplatform.Date import net.dankito.utils.multiplatform.Date
import net.dankito.utils.multiplatform.StackTraceHelper import net.dankito.utils.multiplatform.StackTraceHelper
import net.dankito.utils.multiplatform.getInnerException import net.dankito.utils.multiplatform.getInnerException
import kotlin.reflect.KClass
open class MessageLogCollector { open class MessageLogCollector {
@ -32,7 +33,7 @@ open class MessageLogCollector {
protected open val stackTraceHelper = StackTraceHelper() protected open val stackTraceHelper = StackTraceHelper()
open fun addMessageLog(message: String, type: MessageLogEntryType, bank: BankData) { open fun addMessageLog(bank: BankData, type: MessageLogEntryType, message: String) {
val timeStamp = Date() val timeStamp = Date()
val prettyPrintMessage = prettyPrintHbciMessage(message) val prettyPrintMessage = prettyPrintHbciMessage(message)
@ -46,13 +47,11 @@ open class MessageLogCollector {
} }
open fun logError(message: String, e: Exception? = null, logger: Logger? = null, bank: BankData?) { open fun logError(loggingClass: KClass<*>, bank: BankData, message: String, e: Exception? = null) {
val loggerToUse = logger ?: log
if (e != null) { if (e != null) {
loggerToUse.error(e) { message } getLogger(loggingClass).error(e) { message }
} else { } else {
loggerToUse.error(message) getLogger(loggingClass).error(message)
} }
val errorStackTrace = if (e != null) "\r\n" + getStackTrace(e) else "" val errorStackTrace = if (e != null) "\r\n" + getStackTrace(e) else ""
@ -114,4 +113,8 @@ open class MessageLogCollector {
return stackTraceHelper.getStackTrace(innerException, MaxCountStackTraceElements) return stackTraceHelper.getStackTrace(innerException, MaxCountStackTraceElements)
} }
protected open fun getLogger(loggingClass: KClass<*>): Logger {
return LoggerFactory.getLogger(loggingClass)
}
} }

View File

@ -1,8 +1,14 @@
package net.dankito.banking.fints.model package net.dankito.banking.fints.model
import net.dankito.banking.fints.callback.FinTsClientCallback import net.dankito.banking.fints.callback.FinTsClientCallback
import net.dankito.banking.fints.log.IMessageLogAppender
import net.dankito.banking.fints.log.MessageLogCollector
import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
import net.dankito.banking.fints.response.BankResponse import net.dankito.banking.fints.response.BankResponse
import net.dankito.banking.fints.transactions.IAccountTransactionsParser
import net.dankito.banking.fints.transactions.Mt940AccountTransactionsParser
import net.dankito.banking.fints.transactions.mt940.Mt940Parser
import kotlin.reflect.KClass
open class JobContext( open class JobContext(
@ -13,12 +19,18 @@ open class JobContext(
/** /**
* Only set if the current context is for a specific account (like get account's transactions). * Only set if the current context is for a specific account (like get account's transactions).
*/ */
open val account: AccountData? = null open val account: AccountData? = null,
) : MessageBaseData(bank, product) { protected open val messageLogCollector: MessageLogCollector = MessageLogCollector()
) : MessageBaseData(bank, product), IMessageLogAppender {
protected open val _dialogs = mutableListOf<DialogContext>() protected open val _dialogs = mutableListOf<DialogContext>()
open val mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(Mt940Parser(this), this)
open val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = messageLogCollector.messageLogWithoutSensitiveData
open var dialog: DialogContext = DialogContext() // create null value so that variable is not null open var dialog: DialogContext = DialogContext() // create null value so that variable is not null
protected set protected set
@ -27,7 +39,7 @@ open class JobContext(
get() = ArrayList(_dialogs) // create a copy get() = ArrayList(_dialogs) // create a copy
fun startNewDialog(closeDialog: Boolean = true, dialogId: String = DialogContext.InitialDialogId, open fun startNewDialog(closeDialog: Boolean = true, dialogId: String = DialogContext.InitialDialogId,
versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.Version_2, versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.Version_2,
chunkedResponseHandler: ((BankResponse) -> Unit)? = null) : DialogContext { chunkedResponseHandler: ((BankResponse) -> Unit)? = null) : DialogContext {
val newDialogContext = DialogContext(closeDialog, dialogId = dialogId, chunkedResponseHandler = chunkedResponseHandler) val newDialogContext = DialogContext(closeDialog, dialogId = dialogId, chunkedResponseHandler = chunkedResponseHandler)
@ -41,4 +53,13 @@ open class JobContext(
return newDialogContext return newDialogContext
} }
open fun addMessageLog(type: MessageLogEntryType, message: String) {
messageLogCollector.addMessageLog(bank, type, message)
}
override fun logError(loggingClass: KClass<*>, message: String, e: Exception?) {
messageLogCollector.logError(loggingClass, bank, message, e)
}
} }

View File

@ -1022,7 +1022,7 @@ open class ResponseParser(
protected open fun logError(message: String, e: Exception?) { protected open fun logError(message: String, e: Exception?) {
logAppender?.let { logAppender -> logAppender?.let { logAppender ->
logAppender.logError(message, e, log) logAppender.logError(ResponseParser::class, message, e)
} }
?: run { ?: run {
log.error(e) { message } log.error(e) { message }

View File

@ -5,10 +5,11 @@ import net.dankito.banking.fints.response.BankResponse
open class AddAccountResponse( open class AddAccountResponse(
context: JobContext,
response: BankResponse, response: BankResponse,
open val bank: BankData, open val bank: BankData,
retrievedData: List<RetrievedAccountData> = listOf() retrievedData: List<RetrievedAccountData> = listOf()
) : GetTransactionsResponse(response, retrievedData) { ) : GetTransactionsResponse(context, response, retrievedData) {
override val successful: Boolean override val successful: Boolean
get() = super.successful && bank.accounts.isNotEmpty() get() = super.successful && bank.accounts.isNotEmpty()

View File

@ -1,5 +1,7 @@
package net.dankito.banking.fints.response.client package net.dankito.banking.fints.response.client
import net.dankito.banking.fints.model.JobContext
import net.dankito.banking.fints.model.MessageLogEntry
import net.dankito.banking.fints.response.BankResponse import net.dankito.banking.fints.response.BankResponse
import net.dankito.banking.fints.response.segments.TanResponse import net.dankito.banking.fints.response.segments.TanResponse
@ -13,6 +15,8 @@ open class FinTsClientResponse(
open val isStrongAuthenticationRequired: Boolean, open val isStrongAuthenticationRequired: Boolean,
open val tanRequired: TanResponse? = null, open val tanRequired: TanResponse? = null,
open val messageLogWithoutSensitiveData: List<MessageLogEntry>,
/** /**
* A fints4k internal error like an error occurred during web request or response parsing. * A fints4k internal error like an error occurred during web request or response parsing.
*/ */
@ -34,9 +38,9 @@ open class FinTsClientResponse(
) { ) {
constructor(response: BankResponse) : this(response.successful, response.noTanMethodSelected, constructor(context: JobContext, response: BankResponse) : this(response.successful, response.noTanMethodSelected,
response.isStrongAuthenticationRequired, response.tanResponse, response.internalError, response.isStrongAuthenticationRequired, response.tanResponse, context.messageLogWithoutSensitiveData,
response.errorsToShowToUser, response.wrongCredentialsEntered, response.internalError, response.errorsToShowToUser, response.wrongCredentialsEntered,
response.tanRequiredButUserDidNotEnterOne, response.tanRequiredButWeWereToldToAbortIfSo, response.tanRequiredButUserDidNotEnterOne, response.tanRequiredButWeWereToldToAbortIfSo,
response.messageThatCouldNotBeCreated?.isJobAllowed ?: true, response.messageThatCouldNotBeCreated?.isJobAllowed ?: true,
response.messageThatCouldNotBeCreated?.isJobVersionSupported ?: true, response.messageThatCouldNotBeCreated?.isJobVersionSupported ?: true,

View File

@ -1,11 +1,13 @@
package net.dankito.banking.fints.response.client package net.dankito.banking.fints.response.client
import net.dankito.banking.fints.model.JobContext
import net.dankito.banking.fints.response.BankResponse import net.dankito.banking.fints.response.BankResponse
import net.dankito.banking.fints.response.segments.TanMediaList import net.dankito.banking.fints.response.segments.TanMediaList
open class GetTanMediaListResponse( open class GetTanMediaListResponse(
context: JobContext,
response: BankResponse, response: BankResponse,
val tanMediaList: TanMediaList? val tanMediaList: TanMediaList?
) )
: FinTsClientResponse(response) : FinTsClientResponse(context, response)

View File

@ -1,17 +1,19 @@
package net.dankito.banking.fints.response.client package net.dankito.banking.fints.response.client
import net.dankito.banking.fints.model.JobContext
import net.dankito.banking.fints.model.RetrievedAccountData import net.dankito.banking.fints.model.RetrievedAccountData
import net.dankito.banking.fints.response.BankResponse import net.dankito.banking.fints.response.BankResponse
open class GetTransactionsResponse( open class GetTransactionsResponse(
context: JobContext,
response: BankResponse, response: BankResponse,
open val retrievedData: List<RetrievedAccountData> = listOf(), open val retrievedData: List<RetrievedAccountData> = listOf(),
/** /**
* This value is only set if [GetTransactionsParameter.maxCountEntries] was set to tell caller if maxCountEntries parameter has been evaluated or not * This value is only set if [GetTransactionsParameter.maxCountEntries] was set to tell caller if maxCountEntries parameter has been evaluated or not
*/ */
open var isSettingMaxCountEntriesAllowedByBank: Boolean? = null open var isSettingMaxCountEntriesAllowedByBank: Boolean? = null
) : FinTsClientResponse(response) { ) : FinTsClientResponse(context, response) {
override val successful: Boolean override val successful: Boolean
get() = super.successful get() = super.successful

View File

@ -9,7 +9,7 @@ import net.dankito.banking.fints.transactions.mt940.model.Balance
import net.dankito.banking.fints.transactions.mt940.model.Transaction import net.dankito.banking.fints.transactions.mt940.model.Transaction
import net.dankito.banking.fints.transactions.mt940.model.StatementLine import net.dankito.banking.fints.transactions.mt940.model.StatementLine
import net.dankito.utils.multiplatform.log.LoggerFactory import net.dankito.utils.multiplatform.log.LoggerFactory
import net.dankito.utils.multiplatform.log.Logger import kotlin.reflect.KClass
open class Mt940AccountTransactionsParser( open class Mt940AccountTransactionsParser(
@ -121,8 +121,8 @@ open class Mt940AccountTransactionsParser(
mt940Parser.logAppender = logAppender?.let { logAppender -> mt940Parser.logAppender = logAppender?.let { logAppender ->
object : IMessageLogAppender { object : IMessageLogAppender {
override fun logError(message: String, e: Exception?, logger: Logger?, bank: BankData?) { override fun logError(loggingClass: KClass<*>, message: String, e: Exception?) {
logAppender.logError(message, e, logger, bank ?: bankDataOfCall) logAppender.logError(loggingClass, message, e)
} }
} }
@ -131,7 +131,7 @@ open class Mt940AccountTransactionsParser(
protected open fun logError(message: String, e: Exception?, bank: BankData) { protected open fun logError(message: String, e: Exception?, bank: BankData) {
logAppender?.let { logAppender -> logAppender?.let { logAppender ->
logAppender.logError(message, e, log, bank) logAppender.logError(Mt940AccountTransactionsParser::class, message, e)
} }
?: run { ?: run {
log.error(e) { message } log.error(e) { message }

View File

@ -23,7 +23,9 @@ usertouser messages.
Character is not permitted as the first character of the line. Character is not permitted as the first character of the line.
None of lines include only Space. None of lines include only Space.
*/ */
open class Mt940Parser : IMt940Parser { open class Mt940Parser(
override var logAppender: IMessageLogAppender? = null
) : IMt940Parser {
companion object { companion object {
val AccountStatementsSeparatorRegex = Regex("^\\s*-\\s*\$", RegexOption.MULTILINE) // a line only with '-' and may other white space characters val AccountStatementsSeparatorRegex = Regex("^\\s*-\\s*\$", RegexOption.MULTILINE) // a line only with '-' and may other white space characters
@ -78,9 +80,6 @@ open class Mt940Parser : IMt940Parser {
} }
override var logAppender: IMessageLogAppender? = null
/** /**
* Parses a whole MT 940 statements string, that is one that ends with a "-" line. * Parses a whole MT 940 statements string, that is one that ends with a "-" line.
*/ */
@ -496,7 +495,7 @@ open class Mt940Parser : IMt940Parser {
protected open fun logError(message: String, e: Exception?) { protected open fun logError(message: String, e: Exception?) {
logAppender?.let { logAppender -> logAppender?.let { logAppender ->
logAppender.logError(message, e, log) logAppender.logError(Mt940Parser::class, message, e)
} }
?: run { ?: run {
log.error(e) { message } log.error(e) { message }

View File

@ -53,17 +53,11 @@ open class fints4kBankingClient(
protected open val client = FinTsClientForCustomer(fintsBank, createFinTsClientCallback(callback), webClient, base64Service) protected open val client = FinTsClientForCustomer(fintsBank, createFinTsClientCallback(callback), webClient, base64Service)
protected open val _messageLogWithoutSensitiveData: MutableList<MessageLogEntry> = mutableListOf()
override val messageLogWithoutSensitiveData: List<MessageLogEntry> override val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = client.messageLogWithoutSensitiveData.map { MessageLogEntry(it.message, map(it.type), it.time, bank) } get() = ArrayList(_messageLogWithoutSensitiveData)
protected open fun map(type: MessageLogEntryType): net.dankito.banking.ui.model.MessageLogEntryType {
return when (type) {
MessageLogEntryType.Sent -> net.dankito.banking.ui.model.MessageLogEntryType.Sent
MessageLogEntryType.Received -> net.dankito.banking.ui.model.MessageLogEntryType.Received
MessageLogEntryType.Error -> net.dankito.banking.ui.model.MessageLogEntryType.Error
}
}
override fun addAccountAsync(callback: (AddAccountResponse) -> Unit) { override fun addAccountAsync(callback: (AddAccountResponse) -> Unit) {
@ -84,7 +78,7 @@ open class fints4kBankingClient(
val mappedResponse = mapper.mapResponse(bank, response) val mappedResponse = mapper.mapResponse(bank, response)
saveData() saveData(response)
callback(mappedResponse) callback(mappedResponse)
} }
@ -124,7 +118,7 @@ open class fints4kBankingClient(
callback: (GetTransactionsResponse) -> Unit) { callback: (GetTransactionsResponse) -> Unit) {
val mappedResponse = mapper.mapResponse(account, response) val mappedResponse = mapper.mapResponse(account, response)
saveData() saveData(response)
callback(mappedResponse) callback(mappedResponse)
} }
@ -156,7 +150,7 @@ open class fints4kBankingClient(
} }
protected open fun handleBankTransferResponse(callback: (BankingClientResponse) -> Unit, response: FinTsClientResponse) { protected open fun handleBankTransferResponse(callback: (BankingClientResponse) -> Unit, response: FinTsClientResponse) {
saveData() saveData(response)
callback(mapper.mapResponse(response)) callback(mapper.mapResponse(response))
} }
@ -218,8 +212,11 @@ open class fints4kBankingClient(
return null return null
} }
protected open fun saveData() { protected open fun saveData(response: FinTsClientResponse) {
try { try {
_messageLogWithoutSensitiveData.addAll(response.messageLogWithoutSensitiveData
.map { MessageLogEntry(it.message, map(it.type), it.time, bank) })
// TODO: fix that real (child) class get serialized and re-enable again // TODO: fix that real (child) class get serialized and re-enable again
// val clientDataFile = getFints4kClientDataFile(fintsBank.bankCode, fintsBank.customerId) // val clientDataFile = getFints4kClientDataFile(fintsBank.bankCode, fintsBank.customerId)
// //
@ -229,6 +226,14 @@ open class fints4kBankingClient(
} }
} }
protected open fun map(type: MessageLogEntryType): net.dankito.banking.ui.model.MessageLogEntryType {
return when (type) {
MessageLogEntryType.Sent -> net.dankito.banking.ui.model.MessageLogEntryType.Sent
MessageLogEntryType.Received -> net.dankito.banking.ui.model.MessageLogEntryType.Received
MessageLogEntryType.Error -> net.dankito.banking.ui.model.MessageLogEntryType.Error
}
}
protected open fun getFints4kClientDataFile(bank: TypedBankData): File { protected open fun getFints4kClientDataFile(bank: TypedBankData): File {
return getFints4kClientDataFile(bank.bankCode, bank.userName) return getFints4kClientDataFile(bank.bankCode, bank.userName)
} }