From 9798b3980702a65588d78a0a60eff0eb253cd3e0 Mon Sep 17 00:00:00 2001 From: dankl Date: Tue, 31 Dec 2019 17:27:17 +0100 Subject: [PATCH] Implemented parsing received transactions string as a whole as sometimes banks breaks MT940 data sets in the middle when sending transactions in multiple messages so that this data set cannot be parsed if received messages get parsed immediately --- .../kotlin/net/dankito/fints/FinTsClient.kt | 34 +++++++++++++------ .../dankito/fints/FinTsClientForCustomer.kt | 5 ++- .../dankito/fints/response/ResponseParser.kt | 6 +--- .../segments/ReceivedAccountTransactions.kt | 6 ++-- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt index 81f97b22..af23af50 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt @@ -18,6 +18,8 @@ import net.dankito.fints.response.client.FinTsClientResponse import net.dankito.fints.response.client.GetTanMediaListResponse import net.dankito.fints.response.client.GetTransactionsResponse import net.dankito.fints.response.segments.* +import net.dankito.fints.transactions.IAccountTransactionsParser +import net.dankito.fints.transactions.Mt940AccountTransactionsParser import net.dankito.fints.util.IBase64Service import net.dankito.utils.IThreadPool import net.dankito.utils.ThreadPool @@ -36,6 +38,7 @@ open class FinTsClient @JvmOverloads constructor( protected val webClient: IWebClient = OkHttpWebClient(), protected val messageBuilder: MessageBuilder = MessageBuilder(), protected val responseParser: ResponseParser = ResponseParser(), + protected val mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(), protected val threadPool: IThreadPool = ThreadPool(), protected val product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "0.1") // TODO: get version dynamically ) { @@ -261,7 +264,7 @@ open class FinTsClient @JvmOverloads constructor( // TODO: that should not work. Find out in which method transactions are retrieved after entering TAN // just retrieved all transactions -> check if retrieving that ones of last 90 days is possible without entering TAN if (customer.supportsRetrievingTransactionsOfLast90DaysWithoutTan == null && - response.successful && transactions.bookedTransactions.isNotEmpty() && parameter.fromDate == null) { + response.successful && transactions.bookedTransactionsString.isNotEmpty() && parameter.fromDate == null) { tryGetTransactionsOfLast90DaysWithoutTan(bank, customer) } @@ -277,22 +280,31 @@ open class FinTsClient @JvmOverloads constructor( } protected open fun getTransactionsFromResponse(response: Response, transactions: ReceivedAccountTransactions): Pair, List> { - val bookedTransactions = mutableListOf() - val unbookedTransactions = mutableListOf() + val bookedTransactionsString = StringBuilder() + val unbookedTransactionsString = StringBuilder() - bookedTransactions.addAll(transactions.bookedTransactions) - unbookedTransactions.addAll(transactions.unbookedTransactions) + getTransactionsFromResponse(response, transactions, bookedTransactionsString, unbookedTransactionsString) + + val bookedTransactions = mt940Parser.parseTransactions(bookedTransactionsString.toString()) + val unbookedTransactions = listOf() // TODO: implement parsing MT942 + + return Pair(bookedTransactions, unbookedTransactions) + } + + protected open fun getTransactionsFromResponse(response: Response, transactions: ReceivedAccountTransactions, + bookedTransactionsString: StringBuilder, unbookedTransactionsString: StringBuilder) { + + bookedTransactionsString.append(transactions.bookedTransactionsString) + + transactions.unbookedTransactionsString?.let { + unbookedTransactionsString.append(transactions.unbookedTransactionsString) + } response.followUpResponse?.let { followUpResponse -> followUpResponse.getFirstSegmentById(InstituteSegmentId.AccountTransactionsMt940)?.let { followUpTransactions -> - val followUpBookedAndUnbookedTransactions = getTransactionsFromResponse(followUpResponse, followUpTransactions) - - bookedTransactions.addAll(followUpBookedAndUnbookedTransactions.first) - unbookedTransactions.addAll(followUpBookedAndUnbookedTransactions.second) + getTransactionsFromResponse(followUpResponse, followUpTransactions, bookedTransactionsString, unbookedTransactionsString) } } - - return Pair(bookedTransactions, unbookedTransactions) } protected open fun getBalanceAfterDialogInit(bank: BankData, customer: CustomerData, diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt index 8abfb97f..324ca28e 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt @@ -7,6 +7,8 @@ import net.dankito.fints.response.ResponseParser import net.dankito.fints.response.client.AddAccountResponse import net.dankito.fints.response.client.FinTsClientResponse import net.dankito.fints.response.client.GetTransactionsResponse +import net.dankito.fints.transactions.IAccountTransactionsParser +import net.dankito.fints.transactions.Mt940AccountTransactionsParser import net.dankito.fints.util.IBase64Service import net.dankito.utils.IThreadPool import net.dankito.utils.ThreadPool @@ -22,11 +24,12 @@ open class FinTsClientForCustomer( webClient: IWebClient = OkHttpWebClient(), messageBuilder: MessageBuilder = MessageBuilder(), responseParser: ResponseParser = ResponseParser(), + mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(), threadPool: IThreadPool = ThreadPool(), product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "0.1") // TODO: get version dynamically ) { - protected val client = FinTsClient(callback, base64Service, webClient, messageBuilder, responseParser, threadPool, product) + protected val client = FinTsClient(callback, base64Service, webClient, messageBuilder, responseParser, mt940Parser, threadPool, product) open fun addAccountAsync(callback: (AddAccountResponse) -> Unit) { diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt index 07a1ac67..3eff405b 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -14,8 +14,6 @@ import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinsti import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil import net.dankito.fints.messages.segmente.id.MessageSegmentId import net.dankito.fints.response.segments.* -import net.dankito.fints.transactions.IAccountTransactionsParser -import net.dankito.fints.transactions.Mt940AccountTransactionsParser import net.dankito.fints.util.MessageUtils import org.slf4j.LoggerFactory import java.math.BigDecimal @@ -24,7 +22,6 @@ import java.util.regex.Pattern open class ResponseParser @JvmOverloads constructor( - protected val mt940Parser: IAccountTransactionsParser = Mt940AccountTransactionsParser(), protected val messageUtils: MessageUtils = MessageUtils() ) { @@ -504,10 +501,9 @@ open class ResponseParser @JvmOverloads constructor( protected open fun parseMt940AccountTransactions(segment: String, dataElementGroups: List): ReceivedAccountTransactions { val bookedTransactionsString = extractBinaryData(dataElementGroups[1]) - // TODO: implement parsing MT942 val unbookedTransactionsString = if (dataElementGroups.size > 2) extractBinaryData(dataElementGroups[2]) else null - return ReceivedAccountTransactions(mt940Parser.parseTransactions(bookedTransactionsString), listOf(), segment) + return ReceivedAccountTransactions(bookedTransactionsString, unbookedTransactionsString, segment) } diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/ReceivedAccountTransactions.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/ReceivedAccountTransactions.kt index ea8c8dd6..d42a8d86 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/ReceivedAccountTransactions.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/ReceivedAccountTransactions.kt @@ -1,11 +1,9 @@ package net.dankito.fints.response.segments -import net.dankito.fints.model.AccountTransaction - open class ReceivedAccountTransactions( - val bookedTransactions: List, - val unbookedTransactions: List, // TODO + val bookedTransactionsString: String, + val unbookedTransactionsString: String?, // TODO segmentString: String )