diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersion.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersion.kt index d6b1def3..80cea848 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersion.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersion.kt @@ -1,16 +1,16 @@ package net.dankito.fints.messages.datenelemente.implementierte -enum class HbciVersion(val versionNumber: Int) { +enum class HbciVersion(val versionNumber: Int, override val code: String) : ICodeEnum { - Hbci_2_0_1(201), + Hbci_2_0_1(201, "201"), - Hbci_2_1_0(210), + Hbci_2_1_0(210, "210"), - Hbci_2_2_0(220), + Hbci_2_2_0(220, "220"), - FinTs_3_0_0(300), + FinTs_3_0_0(300, "300"), - FinTs_4_0_0(400) + FinTs_4_0_0(400, "400") } \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Kreditinstitutskennung.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Kreditinstitutskennung.kt index 6f728cf0..5849c233 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Kreditinstitutskennung.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Kreditinstitutskennung.kt @@ -7,8 +7,8 @@ import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe open class Kreditinstitutskennung @JvmOverloads constructor( - bankCountryCode: Int, - bankCode: String, + val bankCountryCode: Int, + val bankCode: String, existenzstatus: Existenzstatus = Existenzstatus.Mandatory ) : Datenelementgruppe(listOf( diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt index 1a16a4f5..1c2d23f3 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt @@ -5,6 +5,8 @@ import net.dankito.fints.messages.segmente.id.ISegmentId enum class InstituteSegmentId(override val id: String) : ISegmentId { - Synchronization("HISYN") + Synchronization("HISYN"), + + BankParameters("HIBPA") } \ No newline at end of file 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 e5c7aa1e..f06cd4b1 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -1,7 +1,12 @@ package net.dankito.fints.response import net.dankito.fints.messages.Separators +import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache +import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum +import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung import net.dankito.fints.messages.segmente.id.MessageSegmentId +import net.dankito.fints.response.segments.BankParameters import net.dankito.fints.response.segments.ReceivedMessageHeader import net.dankito.fints.response.segments.ReceivedSegment import net.dankito.fints.response.segments.ReceivedSynchronization @@ -54,6 +59,7 @@ open class ResponseParser { return when (segmentId) { MessageSegmentId.MessageHeader.id -> parseMessageHeaderSegment(segment, dataElementGroups) InstituteSegmentId.Synchronization.id -> parseSynchronization(segment, dataElementGroups) + InstituteSegmentId.BankParameters.id -> parseBankParameters(segment, dataElementGroups) else -> null } } @@ -78,4 +84,50 @@ open class ResponseParser { securityReferenceNumberForSigningKey, securityReferenceNumberForDigitalSignature) } + protected open fun parseBankParameters(segment: String, dataElementGroups: List): BankParameters { + val bpdVersion = dataElementGroups[1].toInt() + val bankDetails = parseBankDetails(dataElementGroups[2]) + val bankName = dataElementGroups[3] + + val countMaxJobsPerMessage = dataElementGroups[4].toInt() + val supportedLanguages = parseLanguages(dataElementGroups[5]) + val supportedHbciVersions = parseHbciVersions(dataElementGroups[6]) + + val maxMessageSize = if (dataElementGroups.size > 7) dataElementGroups[7].toInt() else null + val minTimeout = if (dataElementGroups.size > 8) dataElementGroups[8].toInt() else null + val maxTimeout = if (dataElementGroups.size > 9) dataElementGroups[9].toInt() else null + + return BankParameters(bpdVersion, bankDetails.bankCountryCode, bankDetails.bankCode, bankName, + countMaxJobsPerMessage, supportedLanguages, supportedHbciVersions, maxMessageSize, minTimeout, maxTimeout, segment) + } + + + protected open fun parseBankDetails(dataElementsGroup: String): Kreditinstitutskennung { + val detailsStrings = getDataElements(dataElementsGroup) + + return Kreditinstitutskennung(detailsStrings[0].toInt(), detailsStrings[1]) + } + + protected open fun parseLanguages(dataElementsGroup: String): List { + val languageStrings = getDataElements(dataElementsGroup) + + return parseFromCode(languageStrings, Dialogsprache.values()) + } + + protected open fun parseHbciVersions(dataElementsGroup: String): List { + val versionStrings = getDataElements(dataElementsGroup) + + return parseFromCode(versionStrings, HbciVersion.values()) + } + + protected open fun parseFromCode(codeValues: List, allValues: Array): List { + // mapNotNull: don't crash if new, at time of implementation unknown values get introduced / returned by bank + return codeValues.mapNotNull { code -> allValues.first { it.code == code } } + } + + + protected open fun getDataElements(dataElementGroup: String): List { + return dataElementGroup.split(Separators.DataElementsSeparator) + } + } \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/BankParameters.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/BankParameters.kt new file mode 100644 index 00000000..6227aebe --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/BankParameters.kt @@ -0,0 +1,52 @@ +package net.dankito.fints.response.segments + +import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache +import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion + + +open class BankParameters( + val bpdVersion: Int, + + val bankCountryCode: Int, + + val bankCode: String, + + val bankName: String, + + /** + * Maximale Anzahl an Geschäftsvorfallsarten, die pro Nachricht zulässig ist. + * Der Wert ‚0’ gibt an, dass keine Restriktionen bzgl. der Anzahl an Geschäftsvorfallsarten bestehen. + */ + val countMaxJobsPerMessage: Int, + + val supportedLanguages: List, + + val supportedHbciVersions: List, + + /** + * Obergrenze in Kilobyte (=1024 Byte) für die Nachrichtengröße. Dies kann kreditinstitutsindividuell + * je nach technischen Restriktionen bzgl. der Verarbeitung umfangreicher Kundennachrichten vorgegeben werden. + * + * Der Wert ‚0’ gibt an, dass keine Restriktionen bzgl. der Nachrichtengröße bestehen. + * + * Eingehende Nachrichten, die dekomprimiert und entschlüsselt diese Grenze überschreiten, können dann + * abgelehnt werden. + */ + val maxMessageSize: Int?, + + /** + * Zeitraum, nach dem frühestens eine weitere Life-Indikator-Nachricht gesendet werden darf. + * Die Angabe erfolgt in Sekunden. Liegt keine Begrenzung vor, kann der Wert ‚0’ angegeben werden. + */ + val minTimeout: Int?, + + /** + * Zeitraum, nach dem das Kreditinstitut einen Dialog voraussichtlich beenden wird, sofern keine + * weiteren Kundennachrichten gesendet wurden. Die Angabe erfolgt in Sekunden. Liegt keine + * Begrenzung vor, kann der Wert ‚0’ angegeben werden. + */ + val maxTimeout: Int?, + + segmentString: String + +) : ReceivedSegment(segmentString) \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt index c9b0c094..93b7e018 100644 --- a/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt @@ -1,10 +1,14 @@ package net.dankito.fints.response +import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache +import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion import net.dankito.fints.messages.segmente.id.ISegmentId import net.dankito.fints.messages.segmente.id.MessageSegmentId +import net.dankito.fints.response.segments.BankParameters import net.dankito.fints.response.segments.ReceivedMessageHeader import net.dankito.fints.response.segments.ReceivedSynchronization import org.assertj.core.api.Assertions.assertThat +import org.junit.Assert import org.junit.Test @@ -31,6 +35,7 @@ class ResponseParserTest { assertThat(header.messageNumber).isEqualTo(2) } + @Test fun parseSynchronization() { @@ -40,9 +45,37 @@ class ResponseParserTest { // then assertSuccessfullyParsedSegment(result, InstituteSegmentId.Synchronization, 173, 4, 6) - val segment = result.receivedSegments.first() as ReceivedSynchronization + result.getFirstSegmentById(InstituteSegmentId.Synchronization)?.let { segment -> + assertThat(segment.customerSystemId).isEqualTo("WL/2/Trhmm0BAAAjIADlyFkXrAQA") + } + ?: run { Assert.fail("No segment of type ReceivedSynchronization found in ${result.receivedSegments}") } + } - assertThat(segment.customerSystemId).isEqualTo("WL/2/Trhmm0BAAAjIADlyFkXrAQA") + + @Test + fun parseBankParameters() { + + // when + val result = underTest.parse("HIBPA:5:3:3+34+280:10070000+Deutsche Bank+0+1+300+0'") + + // then + assertSuccessfullyParsedSegment(result, InstituteSegmentId.BankParameters, 5, 3, 3) + + result.getFirstSegmentById(InstituteSegmentId.BankParameters)?.let { segment -> + assertThat(segment.bpdVersion).isEqualTo(34) + assertThat(segment.bankCountryCode).isEqualTo(280) + assertThat(segment.bankCode).isEqualTo("10070000") + assertThat(segment.bankName).isEqualTo("Deutsche Bank") + + assertThat(segment.countMaxJobsPerMessage).isEqualTo(0) + assertThat(segment.supportedLanguages).containsExactly(Dialogsprache.German) + assertThat(segment.supportedHbciVersions).containsExactly(HbciVersion.FinTs_3_0_0) + + assertThat(segment.maxMessageSize).isEqualTo(0) + assertThat(segment.minTimeout).isNull() + assertThat(segment.maxTimeout).isNull() + } + ?: run { Assert.fail("No segment of type BankParameters found in ${result.receivedSegments}") } }