From 1a0df93e0ceb4bad2139694dce3246e304f0cd14 Mon Sep 17 00:00:00 2001 From: dankito Date: Wed, 29 Apr 2020 13:45:03 +0200 Subject: [PATCH] Fixed that some banks encode SmsAbbuchungskontoErforderlich and as boolean values --- .../dankito/fints/response/ResponseParser.kt | 45 ++++++++++++++++++- .../fints/response/ResponseParserTest.kt | 24 ++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) 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 1b78a47b..a1fb2f1b 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -367,8 +367,8 @@ open class ResponseParser @JvmOverloads constructor( parseCodeEnum(procedureDataElements[11], TanZeitUndDialogbezug.values()), // for HITANS 4 and 5 here is another "TAN-Listennummer erforderlich" code element parseBoolean(procedureDataElements[12]), - parseCodeEnum(procedureDataElements[13], SmsAbbuchungskontoErforderlich.values()), - parseCodeEnum(procedureDataElements[14], AuftraggeberkontoErforderlich.values()), + tryToParseSmsAbbuchungskontoErforderlich(procedureDataElements[13]), + tryToParseAuftraggeberkontoErforderlich(procedureDataElements[14]), parseBoolean(procedureDataElements[15]), parseBoolean(procedureDataElements[16]), parseCodeEnum(procedureDataElements[17], Initialisierungsmodus.values()), @@ -386,6 +386,47 @@ open class ResponseParser @JvmOverloads constructor( return null } + protected open fun tryToParseSmsAbbuchungskontoErforderlich(smsAbbuchungskontoErforderlichString: String): SmsAbbuchungskontoErforderlich { + try { + return parseCodeEnum(smsAbbuchungskontoErforderlichString, SmsAbbuchungskontoErforderlich.values()) + } catch (e: Exception) { + log.error("Could not parse '$smsAbbuchungskontoErforderlichString' to SmsAbbuchungskontoErforderlich", e) + } + + // Bankhaus Neelmeyer and Oldenburgische Landesbank encode SmsAbbuchungskontoErforderlich with boolean values (with is wrong according to FinTS standard) + return tryToParseEnumAsBoolean(smsAbbuchungskontoErforderlichString, + SmsAbbuchungskontoErforderlich.SmsAbbuchungskontoMussAngegebenWerden, + SmsAbbuchungskontoErforderlich.SmsAbbuchungskontoDarfNichtAngegebenWerden) + } + + protected open fun tryToParseAuftraggeberkontoErforderlich(auftraggeberkontoErforderlichString: String): AuftraggeberkontoErforderlich { + try { + return parseCodeEnum(auftraggeberkontoErforderlichString, AuftraggeberkontoErforderlich.values()) + } catch (e: Exception) { + log.error("Could not parse '$auftraggeberkontoErforderlichString' to AuftraggeberkontoErforderlich", e) + } + + // Bankhaus Neelmeyer and Oldenburgische Landesbank encode AuftraggeberkontoErforderlich with boolean values (with is wrong according to FinTS standard) + return tryToParseEnumAsBoolean(auftraggeberkontoErforderlichString, + AuftraggeberkontoErforderlich.AuftraggeberkontoMussAngegebenWerdenWennImGeschaeftsvorfallEnthalten, + AuftraggeberkontoErforderlich.AuftraggeberkontoDarfNichtAngegebenWerden) + } + + protected open fun > tryToParseEnumAsBoolean(enumString: String, valueForTrue: T, valueForFalse: T): T { + try { + val bool = parseBoolean(enumString) + + return if (bool) { + valueForTrue + } + else { + valueForFalse + } + } catch (e: Exception) { } + + return valueForFalse + } + protected open fun parseTanResponse(segment: String, dataElementGroups: List): TanResponse { val binaryJobHashValue = if (dataElementGroups.size > 2) parseStringToNullIfEmpty(dataElementGroups[2]) else null 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 39b90e43..e5b5576f 100644 --- a/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt @@ -682,6 +682,30 @@ class ResponseParserTest : FinTsTestBase() { ?: run { Assert.fail("No segment of type TanInfo found in ${result.receivedSegments}") } } + @Test + fun parseTanInfo_SmsAbbuchungskontoErforderlichAnduftraggeberkontoErforderlichAreEncodedAsBoolean() { + + // when + val result = underTest.parse("HITANS:56:6:3+1+1+1+N:N:0:901:2:CR#1:::SMS-TAN:6:1:SMS-TAN:256:J:2:J:J:N:N:N:01:1:N:1:904:2:CR#5 - 1.4:HHDOPT1:1.4:chipTAN comfort:6:1:chipTAN comfort:2048:N:1:N:0:0:N:N:01:0:N:1:905:2:CR#6 - 1.4:HHD:1.4:chipTAN comfort manuell:6:1:chipTAN comfort manuell:2048:N:1:N:0:0:N:N:01:0:N:0:906:2:CR#8 - MS1.0:::BV AppTAN:6:1:BV AppTAN:2048:N:1:N:0:0:N:N:01:0:N:0:907:2:CR#7:::PhotoTAN:7:1:PhotoTAN:2048:N:1:N:N:N:N:J:01:1:N:0'") + + // then + assertSuccessfullyParsedSegment(result, InstituteSegmentId.TanInfo, 56, 6, 3) + + result.getFirstSegmentById(InstituteSegmentId.TanInfo)?.let { segment -> + assertThat(segment.maxCountJobs).isEqualTo(1) + assertThat(segment.minimumCountSignatures).isEqualTo(1) + assertThat(segment.securityClass).isEqualTo(1) + assertThat(segment.tanProcedureParameters.oneStepProcedureAllowed).isFalse() + assertThat(segment.tanProcedureParameters.moreThanOneTanDependentJobPerMessageAllowed).isFalse() + assertThat(segment.tanProcedureParameters.jobHashValue).isEqualTo("0") + + assertThat(segment.tanProcedureParameters.procedureParameters).hasSize(5) + assertThat(segment.tanProcedureParameters.procedureParameters).extracting("procedureName") + .containsExactlyInAnyOrder("SMS-TAN", "chipTAN comfort", "chipTAN comfort manuell", "BV AppTAN", "PhotoTAN") + } + ?: run { Assert.fail("No segment of type TanInfo found in ${result.receivedSegments}") } + } + @Test fun parseTanInfo7_NewAppBasedProcedure() {