From 8cf57d1c35f5a537718e2d3d4ea9444aa9681a7c Mon Sep 17 00:00:00 2001 From: dankl Date: Sat, 12 Oct 2019 23:51:12 +0200 Subject: [PATCH] Implemented parsing TAN info --- .../implementierte/tan/AllowedTanFormat.kt | 15 ++++ .../tan/AuftraggeberkontoErforderlich.kt | 19 ++++ .../BezeichnungDesTanMediumsErforderlich.kt | 18 ++++ .../tan/Initialisierungsmodus.kt | 23 +++++ .../tan/SmsAbbuchungskontoErforderlich.kt | 22 +++++ .../implementierte/tan/TanProcess.kt | 37 ++++++++ .../tan/TanZeitUndDialogbezug.kt | 26 ++++++ .../implementierte/tan/ZkaTanProcedure.kt | 14 +++ .../fints/response/InstituteSegmentId.kt | 2 + .../dankito/fints/response/ResponseParser.kt | 87 +++++++++++++++++++ .../fints/response/segments/TanInfo.kt | 12 +++ .../segments/TanProcedureParameters.kt | 29 +++++++ .../segments/TwoStepTanProcedureParameters.kt | 9 ++ .../fints/response/ResponseParserTest.kt | 42 +++++++-- 14 files changed, 349 insertions(+), 6 deletions(-) create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AllowedTanFormat.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AuftraggeberkontoErforderlich.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/BezeichnungDesTanMediumsErforderlich.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/Initialisierungsmodus.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/SmsAbbuchungskontoErforderlich.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanZeitUndDialogbezug.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/ZkaTanProcedure.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanInfo.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanProcedureParameters.kt create mode 100644 fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TwoStepTanProcedureParameters.kt diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AllowedTanFormat.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AllowedTanFormat.kt new file mode 100644 index 00000000..5b1eb7a8 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AllowedTanFormat.kt @@ -0,0 +1,15 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Angabe des erwarteten Formates der TAN im konkreten Zwei-Schritt-Verfahren. + */ +enum class AllowedTanFormat(override val code: String) : ICodeEnum { + + Numeric("1"), + + Alphanumeric("2") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AuftraggeberkontoErforderlich.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AuftraggeberkontoErforderlich.kt new file mode 100644 index 00000000..be64c414 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/AuftraggeberkontoErforderlich.kt @@ -0,0 +1,19 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Parameter, der angibt, ob eine Zahlungsverkehrskontoverbindung explizit angegeben werden muss, wenn diese + * im Geschäftsvorfall enthalten ist. + * + * Diese Funktion ermöglicht das Sicherstellen einer gültigen Kontoverbindung z. B. für die Abrechnung von + * SMS-Kosten bereits vor Erzeugen und Versenden einer (ggf. kostenpflichtigen!) TAN. + */ +enum class AuftraggeberkontoErforderlich(override val code: String) : ICodeEnum { + + AuftraggeberkontoDarfNichtAngegebenWerden("0"), + + AuftraggeberkontoMussAngegebenWerdenWennImGeschaeftsvorfallEnthalten("2") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/BezeichnungDesTanMediumsErforderlich.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/BezeichnungDesTanMediumsErforderlich.kt new file mode 100644 index 00000000..8d574ee3 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/BezeichnungDesTanMediumsErforderlich.kt @@ -0,0 +1,18 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Abhängig vom Kreditinstitut und der Anzahl unterstützter TAN-Medien ist die Angabe der Bezeichnung des TAN- + * Mediums erforderlich, damit der Kunde dem Institut mitteilen kann, welches der TAN-Medien er verwenden möchte. + */ +enum class BezeichnungDesTanMediumsErforderlich(override val code: String) : ICodeEnum { + + BezeichnungDesTanMediumsDarfNichtAngegebenWerden("0"), + + BezeichnungDesTanMediumsKannAngegebenWerden("1"), + + BezeichnungDesTanMediumsMussAngegebenWerden("2") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/Initialisierungsmodus.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/Initialisierungsmodus.kt new file mode 100644 index 00000000..3c9245aa --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/Initialisierungsmodus.kt @@ -0,0 +1,23 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Bezeichnet das Verfahren, welches bei Verwendung von PIN/TAN während der Dialoginitialisierung verwendet wird und + * bezieht sich dabei auf die in der Spezifikation des HandHeldDevice [HHD] bzw. den Belegungsrichtlinien [HHD-Belegung] + * definierten Schablonen 01 und 02. + * + * Die Schablonen werden in [HHD] zwar begrifflich auch als „Challengeklassen“ bezeichnet, sind jedoch Bestandteil des + * dort definierten „Start-Code“, der in Ausgaberichtung im FinTS Datenelement „Challenge“ übertragen wird und daher nicht + * zu verwechseln mit der „Challengeklasse“ im Sinne einer Geschäftsvorfallsklasse bei HKTAN in der Prozessvariante 1. + */ +enum class Initialisierungsmodus(override val code: String) : ICodeEnum { + + InitialisierungsverfahrenMitKlartextPinOhneTan("00"), + + VerwendungAnalogDerInHhdBeschriebenenSchablone01_VerschluesseltePinOhneTan("01"), + + VerwendungAnalogDerInHhdBeschriebenenSchablone02_ReserviertBeiFinTsDerzeitNichtVerwendet("02") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/SmsAbbuchungskontoErforderlich.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/SmsAbbuchungskontoErforderlich.kt new file mode 100644 index 00000000..45ef1dd8 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/SmsAbbuchungskontoErforderlich.kt @@ -0,0 +1,22 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Parameter, der angibt, ob eine Zahlungsverkehrskontoverbindung für die Abbuchung von SMS-Kosten angegeben werden + * kann oder muss. Die Belastung von SMS-Kosten durch das Institut wird unabhängig von dem Vorhandensein einer + * Kontoverbindung z. B. kundenindividuell geregelt. + * + * Das Element in der Version #2 ermöglicht eine detailliertere Steuerung der Belegung. Es wird z. B. in HKTAN + * ab Segmentversion #5 eingesetzt. + */ +enum class SmsAbbuchungskontoErforderlich(override val code: String) : ICodeEnum { + + SmsAbbuchungskontoDarfNichtAngegebenWerden("0"), + + SmsAbbuchungskontoKannAngegebenWerden("1"), + + SmsAbbuchungskontoMussAngegebenWerden("2") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanProcess.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanProcess.kt index 41fa9173..85a53c5e 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanProcess.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanProcess.kt @@ -3,14 +3,51 @@ package net.dankito.fints.messages.datenelemente.implementierte.tan import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum +/** + * Beim Zwei-Schritt-Verfahren werden die notwendigen Prozess-Schritte mittels des Geschäftsvorfalls HKTAN durchgeführt. + * Dieser unterstützt flexibel vier unterschiedliche Ausprägungen für die beiden Prozessvarianten für + * Zwei-Schritt-Verfahren, wobei die TAN-Prozesse 3 und 4 nicht isoliert und nur in Verbindung mit TAN-Prozess=2 auftreten können. + */ enum class TanProcess(override val code: String) : ICodeEnum { + /** + * Im ersten Schritt wird der Auftrags-Hashwert über den Geschäftsvorfall HKTAN mitgeteilt, im zweiten Schritt + * erfolgt nach Ermittlung der TAN aus der zurückgemeldeten Challenge die Einreichung des eigentlichen Auftrags + * inklusive der TAN über das normale Auftragssegment. Abfolge der Segmente am Beispiel HKCCS: + * 1. Schritt: HKTAN <-> HITAN + * 2. Schritt: HKCCS <-> HIRMS zu HKCCS + */ TanProcess1("1"), + /** + * Prozessvariante 2: + * + * Im ersten Schritt wird der Auftrag komplett über das normale Auftragssegment eingereicht, jedoch ohne + * Übermittlung der TAN. Im zweiten Schritt erfolgt nach Ermittlung der TAN aus der zurückgemeldeten Challenge die + * Einreichung der TAN über den Geschäftsvorfall HKTAN. + * Abfolge der Segmente am Beispiel HKCCS: + * Schritt 1: HKCCS und HKTAN <-> HITAN + * Schritt 2: HKTAN <-> HITAN und HIRMS zu HICCS + */ + + /** + * kann nur im zweiten Schritt auftreten. Er dient zur Übermittlung der TAN mittels HKTAN, nachdem der Auftrag + * selbst zuvor bereits mit TAN-Prozess=3 oder 4 eingereicht wurde. + * Dieser Geschäftsvorfall wird mit HITAN, TAN-Prozess=2 beantwortet. + */ TanProcess2("2"), + /** + * kann nur im ersten Schritt bei Mehrfach-TANs für die zweite und ggf. dritte TAN auftreten. Hierdurch wird die + * Einreichung eingeleitet, wenn zeitversetzte Einreichung von Mehrfach-TANs erlaubt ist. + */ TanProcess3("3"), + /** + * kann nur im ersten Schritt auftreten. Hiermit wird das Zwei-Schritt-Verfahren nach Prozessvariante 2 für die + * erste TAN eingeleitet. HKTAN wird zusammen mit dem Auftragssegment übertragen und durch HITAN mit TAN-Prozess=4 + * beantwortet. TAN-Prozess=4 wird auch beim Geschäftsvorfall „Prüfen / Verbrennen von TANs“ eingesetzt. + */ TanProcess4("4"), } \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanZeitUndDialogbezug.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanZeitUndDialogbezug.kt new file mode 100644 index 00000000..3087b202 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/TanZeitUndDialogbezug.kt @@ -0,0 +1,26 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Beschreibung der protokolltechnischen Möglichkeiten, die dem Kunden im Zusammenhang mit Mehrfach-TANs zur + * Verfügung stehen. Es wird festgelegt, ob die Eingabe der einzelnen TANs zu einem Auftrag durch die unterschiedlichen + * Benutzer synchron in einem Dialog erfolgen muss oder zeitversetzt in mehreren Dialogen erfolgen kann. + * Es wird auch festgelegt, ob ein Institut nur eines dieser Verfahren oder beide parallel anbietet. Voraussetzung ist, + * dass grundsätzlich die Verwendung von Mehrfach-TANs beim Zwei-Schritt-Verfahren erlaubt ist (vgl. Parameter + * „Mehrfach-TAN erlaubt“). Bei Prozessvariante 1 ist der Parameter immer mit „nicht zutreffend“ zu belegen, da hier + * generell keine zeitversetzte Verarbeitung möglich ist. Dieser Parameter erweitert den Parameter + * „TAN zeitversetzt / dialogübergreifend erlaubt“. + */ +enum class TanZeitUndDialogbezug(override val code: String) : ICodeEnum { + + TanNichtZeitversetztDialoguebergreifendErlaubt("1"), + + TanZeitversetztDialoguebergreifendErlaubt("2"), + + BothAllowed("3"), + + NotSupported("4") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/ZkaTanProcedure.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/ZkaTanProcedure.kt new file mode 100644 index 00000000..fc35318b --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/tan/ZkaTanProcedure.kt @@ -0,0 +1,14 @@ +package net.dankito.fints.messages.datenelemente.implementierte.tan + + +enum class ZkaTanProcedure { + + HHD, + + HHDUC, + + HHDOPT1, + + mobileTAN + +} \ No newline at end of file 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 111e1ef0..13047de8 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt @@ -15,6 +15,8 @@ enum class InstituteSegmentId(override val id: String) : ISegmentId { AccountInfo("HIUPD"), + TanInfo("HITANS"), + AccountTransactionsMt940("HIKAZ") } \ 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 633311aa..4e794b9e 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -4,8 +4,10 @@ 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.datenelemente.implementierte.signatur.Sicherheitsfunktion import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsverfahren import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens +import net.dankito.fints.messages.datenelemente.implementierte.tan.* import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil import net.dankito.fints.messages.segmente.id.MessageSegmentId @@ -78,6 +80,7 @@ open class ResponseParser @JvmOverloads constructor( InstituteSegmentId.UserParameters.id -> parseUserParameters(segment, dataElementGroups) InstituteSegmentId.AccountInfo.id -> parseAccountInfo(segment, dataElementGroups) + InstituteSegmentId.TanInfo.id -> parseTanInfo(segment, dataElementGroups) InstituteSegmentId.AccountTransactionsMt940.id -> parseMt940AccountTransactions(segment, dataElementGroups) @@ -165,6 +168,82 @@ open class ResponseParser @JvmOverloads constructor( } + protected open fun parseTanInfo(segment: String, dataElementGroups: List): TanInfo { + val maxCountJobs = parseInt(dataElementGroups[1]) + val minimumCountSignatures = parseInt(dataElementGroups[2]) + val securityClass = parseString(dataElementGroups[3]) + + return TanInfo(maxCountJobs, minimumCountSignatures, securityClass, + parseTwoStepTanProcedureParameters(dataElementGroups[4]), segment) + } + + protected open fun parseTwoStepTanProcedureParameters(tanProcedures: String): TwoStepTanProcedureParameters { + val dataElements = getDataElements(tanProcedures) + + val oneStepProcedureAllowed = parseBoolean(dataElements[0]) + val moreThanOneTanDependentJobPerMessageAllowed = parseBoolean(dataElements[1]) + val jobHashValue = dataElements[2] + + val proceduresDataElements = dataElements.subList(3, dataElements.size) + + return TwoStepTanProcedureParameters(oneStepProcedureAllowed, moreThanOneTanDependentJobPerMessageAllowed, + jobHashValue, mapToTanProcedureParameters(proceduresDataElements)) + } + + protected open fun mapToTanProcedureParameters(proceduresDataElements: List): List { + val parsedProceduresParameters = mutableListOf() + var remainingDataElements = proceduresDataElements + + while (remainingDataElements.size >= 20) { // parameters have at least 20 data elements, the last element is optional + val dataElementForNextProcedure = if (remainingDataElements.size >= 21) remainingDataElements.subList(0, 21) + else remainingDataElements.subList(0, 20) + + val procedureParameters = mapToSingleTanProcedureParameters(dataElementForNextProcedure) + parsedProceduresParameters.add(procedureParameters) + + if (procedureParameters.countSupportedActiveTanMedia != null) remainingDataElements = remainingDataElements.subList(21, remainingDataElements.size) + else remainingDataElements = remainingDataElements.subList(20, remainingDataElements.size) + } + + return parsedProceduresParameters + } + + protected open fun mapToSingleTanProcedureParameters(procedureDataElements: List): TanProcedureParameters { + + return TanProcedureParameters( + parseCodeEnum(procedureDataElements[0], Sicherheitsfunktion.values()), + parseCodeEnum(procedureDataElements[1], TanProcess.values()), + parseString(procedureDataElements[2]), + tryToParseZkaTanProcedure(procedureDataElements[3]), + parseStringToNullIfEmpty(procedureDataElements[4]), + parseString(procedureDataElements[5]), + parseInt(procedureDataElements[6]), + parseCodeEnum(procedureDataElements[7], AllowedTanFormat.values()), + parseString(procedureDataElements[8]), + parseInt(procedureDataElements[9]), + parseBoolean(procedureDataElements[10]), + parseCodeEnum(procedureDataElements[11], TanZeitUndDialogbezug.values()), + parseBoolean(procedureDataElements[12]), + parseCodeEnum(procedureDataElements[13], SmsAbbuchungskontoErforderlich.values()), + parseCodeEnum(procedureDataElements[14], AuftraggeberkontoErforderlich.values()), + parseBoolean(procedureDataElements[15]), + parseBoolean(procedureDataElements[16]), + parseCodeEnum(procedureDataElements[17], Initialisierungsmodus.values()), + parseCodeEnum(procedureDataElements[18], BezeichnungDesTanMediumsErforderlich.values()), + parseBoolean(procedureDataElements[19]), + if (procedureDataElements.size >= 20) parseNullableInt(procedureDataElements[20]) else null + ) + } + + protected open fun tryToParseZkaTanProcedure(mayZkaTanProcedure: String): ZkaTanProcedure? { + try { + return ZkaTanProcedure.valueOf(mayZkaTanProcedure) + } catch (ignored: Exception) { } + + return null + } + + protected open fun parseMt940AccountTransactions(segment: String, dataElementGroups: List): ReceivedAccountTransactions { val bookedTransactionsString = extractBinaryData(dataElementGroups[1]) @@ -323,6 +402,14 @@ open class ResponseParser @JvmOverloads constructor( return parseString(string).toInt() } + protected open fun parseNullableInt(mayInt: String): Int? { + try { + return parseInt(mayInt) + } catch (ignored: Exception) { } + + return null + } + protected open fun parseStringToNullIfEmpty(string: String): String? { val parsedString = parseString(string) diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanInfo.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanInfo.kt new file mode 100644 index 00000000..8b22a6b4 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanInfo.kt @@ -0,0 +1,12 @@ +package net.dankito.fints.response.segments + + +open class TanInfo( + val maxCountJobs: Int, + val minimumCountSignatures: Int, + val securityClass: String, // not used for PIN/TAN + val tanProcedureParameters: TwoStepTanProcedureParameters, + + segmentString: String +) + : ReceivedSegment(segmentString) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanProcedureParameters.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanProcedureParameters.kt new file mode 100644 index 00000000..5504f034 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TanProcedureParameters.kt @@ -0,0 +1,29 @@ +package net.dankito.fints.response.segments + +import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion +import net.dankito.fints.messages.datenelemente.implementierte.tan.* + + +open class TanProcedureParameters( + val securityFunction: Sicherheitsfunktion, + val tanProcess: TanProcess, + val technicalTanProcedureIdentification: String, + val zkaTanProcedure: ZkaTanProcedure?, + val versionZkaTanProcedure: String?, + val procedureName: String, + val maxTanInputLength: Int, + val allowedTanFormat: AllowedTanFormat, + val descriptionToShowToUser: String, + val maxReturnValueLength: Int, + val multipleTansAllowed: Boolean, + val timeAndDialogRelation: TanZeitUndDialogbezug, + val cancellationAllowed: Boolean, + val smsDebitAccountRequired: SmsAbbuchungskontoErforderlich, + val initiatorAccountRequired: AuftraggeberkontoErforderlich, + val challengeClassRequired: Boolean, + val signatureStructured: Boolean, + val initializingMode: Initialisierungsmodus, + val nameOfTanMediaRequired: BezeichnungDesTanMediumsErforderlich, + val hhdUcResponseRequired: Boolean, + val countSupportedActiveTanMedia: Int? +) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TwoStepTanProcedureParameters.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TwoStepTanProcedureParameters.kt new file mode 100644 index 00000000..fa63c189 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/TwoStepTanProcedureParameters.kt @@ -0,0 +1,9 @@ +package net.dankito.fints.response.segments + + +open class TwoStepTanProcedureParameters( + val oneStepProcedureAllowed: Boolean, + val moreThanOneTanDependentJobPerMessageAllowed: Boolean, + val jobHashValue: String, // not evaluated for PIN/TAN + val procedureParameters: List +) \ 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 3dc3fdd8..5069fe70 100644 --- a/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt @@ -211,19 +211,49 @@ class ResponseParserTest { } + @Test + fun parseTanInfo() { + + // when + val result = underTest.parse("HITANS:171:6:4+1+1+1+J:N:0:910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5:921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2:900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:0'") + + // then + assertSuccessfullyParsedSegment(result, InstituteSegmentId.TanInfo, 171, 6, 4) + + 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).isTrue() + assertThat(segment.tanProcedureParameters.moreThanOneTanDependentJobPerMessageAllowed).isFalse() + assertThat(segment.tanProcedureParameters.jobHashValue).isEqualTo("0") + + assertThat(segment.tanProcedureParameters.procedureParameters).hasSize(7) + assertThat(segment.tanProcedureParameters.procedureParameters).extracting("procedureName") + .containsExactlyInAnyOrder("chipTAN manuell", "chipTAN optisch", "chipTAN-USB", "chipTAN-QR", + "smsTAN", "pushTAN", "iTAN") + } + ?: run { Assert.fail("No segment of type TanInfo found in ${result.receivedSegments}") } + } + + private fun assertSuccessfullyParsedSegment(result: Response, segmentId: ISegmentId, segmentNumber: Int, segmentVersion: Int, referenceSegmentNumber: Int? = null) { assertThat(result.successful).isTrue() + assertThat(result.error).isNull() assertThat(result.receivedResponse).isNotNull() - assertThat(result.receivedSegments).hasSize(1) - val segment = result.receivedSegments.first() + val segment = result.getFirstSegmentById(segmentId) - assertThat(segment.segmentId).isEqualTo(segmentId.id) - assertThat(segment.segmentNumber).isEqualTo(segmentNumber) - assertThat(segment.segmentVersion).isEqualTo(segmentVersion) - assertThat(segment.referenceSegmentNumber).isEqualTo(referenceSegmentNumber) + assertThat(segment).isNotNull() + + segment?.let { + assertThat(segment.segmentId).isEqualTo(segmentId.id) + assertThat(segment.segmentNumber).isEqualTo(segmentNumber) + assertThat(segment.segmentVersion).isEqualTo(segmentVersion) + assertThat(segment.referenceSegmentNumber).isEqualTo(referenceSegmentNumber) + } } } \ No newline at end of file