Implemented parsing TAN info
This commit is contained in:
parent
e9469e131a
commit
8cf57d1c35
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -3,14 +3,51 @@ package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
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 {
|
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"),
|
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"),
|
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"),
|
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"),
|
TanProcess4("4"),
|
||||||
|
|
||||||
}
|
}
|
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
|
||||||
|
enum class ZkaTanProcedure {
|
||||||
|
|
||||||
|
HHD,
|
||||||
|
|
||||||
|
HHDUC,
|
||||||
|
|
||||||
|
HHDOPT1,
|
||||||
|
|
||||||
|
mobileTAN
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ enum class InstituteSegmentId(override val id: String) : ISegmentId {
|
||||||
|
|
||||||
AccountInfo("HIUPD"),
|
AccountInfo("HIUPD"),
|
||||||
|
|
||||||
|
TanInfo("HITANS"),
|
||||||
|
|
||||||
AccountTransactionsMt940("HIKAZ")
|
AccountTransactionsMt940("HIKAZ")
|
||||||
|
|
||||||
}
|
}
|
|
@ -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.Dialogsprache
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
|
import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
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.Sicherheitsverfahren
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
|
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.Kreditinstitutskennung
|
||||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil
|
import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil
|
||||||
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
||||||
|
@ -78,6 +80,7 @@ open class ResponseParser @JvmOverloads constructor(
|
||||||
|
|
||||||
InstituteSegmentId.UserParameters.id -> parseUserParameters(segment, dataElementGroups)
|
InstituteSegmentId.UserParameters.id -> parseUserParameters(segment, dataElementGroups)
|
||||||
InstituteSegmentId.AccountInfo.id -> parseAccountInfo(segment, dataElementGroups)
|
InstituteSegmentId.AccountInfo.id -> parseAccountInfo(segment, dataElementGroups)
|
||||||
|
InstituteSegmentId.TanInfo.id -> parseTanInfo(segment, dataElementGroups)
|
||||||
|
|
||||||
InstituteSegmentId.AccountTransactionsMt940.id -> parseMt940AccountTransactions(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<String>): 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<String>): List<TanProcedureParameters> {
|
||||||
|
val parsedProceduresParameters = mutableListOf<TanProcedureParameters>()
|
||||||
|
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<String>): 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<String>): ReceivedAccountTransactions {
|
protected open fun parseMt940AccountTransactions(segment: String, dataElementGroups: List<String>): ReceivedAccountTransactions {
|
||||||
val bookedTransactionsString = extractBinaryData(dataElementGroups[1])
|
val bookedTransactionsString = extractBinaryData(dataElementGroups[1])
|
||||||
|
|
||||||
|
@ -323,6 +402,14 @@ open class ResponseParser @JvmOverloads constructor(
|
||||||
return parseString(string).toInt()
|
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? {
|
protected open fun parseStringToNullIfEmpty(string: String): String? {
|
||||||
val parsedString = parseString(string)
|
val parsedString = parseString(string)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -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?
|
||||||
|
)
|
|
@ -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<TanProcedureParameters>
|
||||||
|
)
|
|
@ -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<TanInfo>(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,
|
private fun assertSuccessfullyParsedSegment(result: Response, segmentId: ISegmentId, segmentNumber: Int,
|
||||||
segmentVersion: Int, referenceSegmentNumber: Int? = null) {
|
segmentVersion: Int, referenceSegmentNumber: Int? = null) {
|
||||||
|
|
||||||
assertThat(result.successful).isTrue()
|
assertThat(result.successful).isTrue()
|
||||||
|
assertThat(result.error).isNull()
|
||||||
assertThat(result.receivedResponse).isNotNull()
|
assertThat(result.receivedResponse).isNotNull()
|
||||||
assertThat(result.receivedSegments).hasSize(1)
|
|
||||||
|
|
||||||
val segment = result.receivedSegments.first()
|
val segment = result.getFirstSegmentById<ReceivedSegment>(segmentId)
|
||||||
|
|
||||||
assertThat(segment.segmentId).isEqualTo(segmentId.id)
|
assertThat(segment).isNotNull()
|
||||||
assertThat(segment.segmentNumber).isEqualTo(segmentNumber)
|
|
||||||
assertThat(segment.segmentVersion).isEqualTo(segmentVersion)
|
segment?.let {
|
||||||
assertThat(segment.referenceSegmentNumber).isEqualTo(referenceSegmentNumber)
|
assertThat(segment.segmentId).isEqualTo(segmentId.id)
|
||||||
|
assertThat(segment.segmentNumber).isEqualTo(segmentNumber)
|
||||||
|
assertThat(segment.segmentVersion).isEqualTo(segmentVersion)
|
||||||
|
assertThat(segment.referenceSegmentNumber).isEqualTo(referenceSegmentNumber)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue