diff --git a/FinTS4javaLib/build.gradle b/fints4javaLib/build.gradle similarity index 100% rename from FinTS4javaLib/build.gradle rename to fints4javaLib/build.gradle diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/Existenzstatus.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/Existenzstatus.kt new file mode 100644 index 00000000..1c2d8a82 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/Existenzstatus.kt @@ -0,0 +1,12 @@ +package net.dankito.fints.messages + + +enum class Existenzstatus { + + Mandatory, + + Optional, + + NotAllowed + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/HbciCharset.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/HbciCharset.kt new file mode 100644 index 00000000..b8574351 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/HbciCharset.kt @@ -0,0 +1,27 @@ +package net.dankito.fints.messages + + +/** + * Der HBCI-Basiszeichensatz baut auf dem international normierten Zeichensatz ISO 8859 auf. + * Im DE „Unterstützte Sprachen“ in die Bankparameterdaten (s. Kap. D.2) stellt das Kreditinstitut + * das jeweiligen Codeset des ISO 8859 ein. Ferner wird in die BPD das sprachen-spezifische Subset + * des ISO 8859 eingestellt. Codeset und Subset definieren gemeinsam den FinTS-Basiszeichensatz. + * Dieser gilt grundsätzlich für sämtliche nicht-binären Datenelemente. Sofern hiervon aufgrund + * von Verarbeitungsrestriktionen abgewichen wird, ist dies bei der jeweiligen Formatbeschreibung + * vermerkt. Für transparente Daten gilt der jeweilige Zeichensatz des Fremdformats. + * + * Kreditinstitutsseitig ist jeweils der vollständige erlaubte Zeichensatz zu unterstützen. + * FinTS-Syntaxzeichen (s. Kap. H.1.1) bleiben von den Zeichensatzvorgaben unberührt (d. h. + * sind stets erforderlich und mit fester Codierung vorgegeben). + * + * Wird ein Auftrag an ein Kreditinstitut übermittelt, der hinsichtlich Zeichensatz und Codierung + * nicht den Richtlinien entspricht, so ist dieser abzuweisen. Eine kreditinstitutsseitige Korrektur + * der Auftragsdaten erfolgt nicht. + */ +class HbciCharset { + + companion object { + val DefaultCharset = Charsets.ISO_8859_1 + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/Nachrichtenteil.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/Nachrichtenteil.kt new file mode 100644 index 00000000..9d39881e --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/Nachrichtenteil.kt @@ -0,0 +1,8 @@ +package net.dankito.fints.messages + + +abstract class Nachrichtenteil { + + abstract fun format(): String + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/Datenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/Datenelement.kt new file mode 100644 index 00000000..f94fd0f2 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/Datenelement.kt @@ -0,0 +1,18 @@ +package net.dankito.fints.messages.datenelemente + +import net.dankito.fints.messages.Existenzstatus + + +abstract class Datenelement(existenzstatus: Existenzstatus): DatenelementBase(existenzstatus) { + + + @Throws(IllegalArgumentException::class) + abstract fun validate() + + + @Throws(IllegalArgumentException::class) + protected fun throwValidationException(message: String) { + throw IllegalArgumentException("Daten von ${javaClass.simpleName} sind ungültig: $message") + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/DatenelementBase.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/DatenelementBase.kt new file mode 100644 index 00000000..dbacb6cb --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/DatenelementBase.kt @@ -0,0 +1,7 @@ +package net.dankito.fints.messages.datenelemente + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.Nachrichtenteil + + +abstract class DatenelementBase(val existenzstatus: Existenzstatus) : Nachrichtenteil() \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/abgeleiteteformate/Code.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/abgeleiteteformate/Code.kt new file mode 100644 index 00000000..447717d0 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/abgeleiteteformate/Code.kt @@ -0,0 +1,23 @@ +package net.dankito.fints.messages.datenelemente.abgeleiteteformate + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement + + +/** + * Es sind nur die jeweils aufgeführten Werte zulässig. + */ +abstract class Code(code: String, val allowedValues: List, existenzstatus: Existenzstatus) + : AlphanumerischesDatenelement(code, existenzstatus) { + + override fun validate() { + super.validate() + + if (allowedValues.contains(text) == false) { + throwValidationException("'$text' ist kein Wert aus der Liste der zulässigen Werte: " + + allowedValues.joinToString(", ") + ) + } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/abgeleiteteformate/Identifikation.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/abgeleiteteformate/Identifikation.kt new file mode 100644 index 00000000..186196f8 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/abgeleiteteformate/Identifikation.kt @@ -0,0 +1,13 @@ +package net.dankito.fints.messages.datenelemente.abgeleiteteformate + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement + + +/** + * Dient der eindeutigen Kennzeichnung von Objekten (z. B. Benutzerkennung, Kontonummer). + * + * Maximal 30 Zeichen + */ +abstract class Identifikation(identifikation: String, existenzstatus: Existenzstatus) + : AlphanumerischesDatenelement(identifikation, existenzstatus, 30) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/AlphanumerischesDatenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/AlphanumerischesDatenelement.kt new file mode 100644 index 00000000..d8a0c62f --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/AlphanumerischesDatenelement.kt @@ -0,0 +1,30 @@ +package net.dankito.fints.messages.datenelemente.basisformate + +import net.dankito.fints.messages.Existenzstatus + + +/** + * Es gilt der FinTS-Basiszeichensatz ohne die Zeichen CR und LF. + */ +abstract class AlphanumerischesDatenelement @JvmOverloads constructor( + alphanumericValue: String, existenzstatus: Existenzstatus, val maxLength: Int? = null +) : TextDatenelement(alphanumericValue, existenzstatus) { + + + override fun validate() { + super.validate() + + if (text.contains("\r") || text.contains("\n")) { + throwValidationException("Alphanumerischer Wert '$text' darf kein Carriage Return (\r) oder " + + "Line Feed (\n) enthalten.") + } + + maxLength?.let { + if (text.length > maxLength) { + throwValidationException("Wert '$text' darf maximal $maxLength Zeichen lang sein, " + + "hat aber ${text.length} Zeichen.") + } + } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/NumerischesDatenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/NumerischesDatenelement.kt new file mode 100644 index 00000000..c8d4c592 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/NumerischesDatenelement.kt @@ -0,0 +1,27 @@ +package net.dankito.fints.messages.datenelemente.basisformate + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.Datenelement + + +/** + * Zulässig sind lediglich die Ziffern ‘0’ bis ‘9’. Führende Nullen sind nicht zugelassen. + */ +abstract class NumerischesDatenelement(val value: Int, val numberOfDigits: Int, existenzstatus: Existenzstatus) + : Datenelement(existenzstatus) { + + + override fun format(): String { + return value.toString() + } + + + override fun validate() { + val maxValue = Math.pow(10.0, numberOfDigits.toDouble()) - 1 + + if (value < 0 || value > maxValue) { + throwValidationException("Wert '$value' muss im Wertebereich von 0 - $maxValue liegen.") + } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/TextDatenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/TextDatenelement.kt new file mode 100644 index 00000000..9bf19332 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/TextDatenelement.kt @@ -0,0 +1,36 @@ +package net.dankito.fints.messages.datenelemente.basisformate + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.HbciCharset +import net.dankito.fints.messages.datenelemente.Datenelement + + +/** + * Es gilt der vollständige FinTS-Basiszeichensatz. + */ +abstract class TextDatenelement(val text: String, existenzstatus: Existenzstatus) : Datenelement(existenzstatus) { + + + override fun format(): String { + return text + } + + + override fun validate() { + try { + if (HbciCharset.DefaultCharset.newEncoder().canEncode(text) == false) { + throwInvalidCharacterException() + } + } catch (e: Exception) { + throwInvalidCharacterException() + } + } + + protected open fun throwInvalidCharacterException() { + throwValidationException( + "Wert '$text' enthält Zeichen die gemäß des Zeichensatzes " + + "${HbciCharset.DefaultCharset.displayName()} nicht erlaubt sind." + ) + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/ZiffernDatenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/ZiffernDatenelement.kt new file mode 100644 index 00000000..91549566 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/basisformate/ZiffernDatenelement.kt @@ -0,0 +1,17 @@ +package net.dankito.fints.messages.datenelemente.basisformate + +import net.dankito.fints.messages.Existenzstatus + + +/** + * Zulässig sind die Ziffern ‘0’ bis ‘9’. Führende Nullen sind zugelassen. + */ +abstract class ZiffernDatenelement(value: Int, numberOfDigits: Int, existenzstatus: Existenzstatus) + : NumerischesDatenelement(value, numberOfDigits, existenzstatus) { + + + override fun format(): String { + return String.format("%0${numberOfDigits}d", value) + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BPDVersion.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BPDVersion.kt new file mode 100644 index 00000000..382d2404 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BPDVersion.kt @@ -0,0 +1,24 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Es handelt sich um eine kreditinstitutsseitig vergebene Versionsnummer der + * Bankparameterdaten (BPD), die den jeweiligen Stand der instituts-spezifischen + * Unterstützung des Systems kennzeichnet (bei jeder für das Kundensystem relevanten + * Änderung des Kreditinstitutssystems werden neue BPD mit einer neuen BPD-Versionsnummer + * kreditinstitutsseitig bereitgestellt). + * + * Diese BPD-Versionsnummer ist unabhängig von der Version des BPD-Nachrichtenformats, + * die im Nachrichtenkopf eingestellt ist und lediglich das syntaktische Format der + * Nachricht, nicht jedoch deren Inhalt kennzeichnet. + */ +class BPDVersion(version: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(version, 3, existenzstatus) { + + companion object { + const val VersionNotReceivedYet = 0 + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Bezugssegment.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Bezugssegment.kt new file mode 100644 index 00000000..f07ead67 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Bezugssegment.kt @@ -0,0 +1,29 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Sofern sich ein Kreditinstitutssegment auf ein bestimmtes Kundensegment bezieht + * (z. B. Antwortrückmeldung auf einen Kundenauftrag) hat das Kreditinstitut die + * Segmentnummer des Segments der Kundennachricht einzustellen, auf das sich das + * aktuelle Segment bezieht (s. DE „Segmentnummer“). In Zusammenhang mit den Angaben + * zur Bezugsnachricht aus dem Nachrichtenkopf ist hierdurch eine eindeutige Referenz + * auf das Segment einer Kundennachricht möglich. + * + * Falls die Angabe eines Bezugssegments erforderlich ist, ist dieses bei der + * Formatbeschreibung eines Kreditinstitutsegments angegeben. + */ +abstract class Bezugssegment(segmentNumber: Int, existenzstatus: Existenzstatus) + : NumerischesDatenelement(segmentNumber, 3, existenzstatus) { + + override fun validate() { + super.validate() + + if (value < 1) { + throwValidationException("Bezug Segmentnummer '$value' muss größer oder gleich 1 sein.") + } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BezugssegmentInKreditinstitutsnachricht.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BezugssegmentInKreditinstitutsnachricht.kt new file mode 100644 index 00000000..39d37481 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BezugssegmentInKreditinstitutsnachricht.kt @@ -0,0 +1,6 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus + + +open class BezugssegmentInKreditinstitutsnachricht(segmentNumber: Int) : Bezugssegment(segmentNumber, Existenzstatus.Optional) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BezugssegmentInKundennachricht.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BezugssegmentInKundennachricht.kt new file mode 100644 index 00000000..f2f440ed --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BezugssegmentInKundennachricht.kt @@ -0,0 +1,6 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus + + +open class BezugssegmentInKundennachricht(segmentNumber: Int) : Bezugssegment(segmentNumber, Existenzstatus.NotAllowed) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/DialogId.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/DialogId.kt new file mode 100644 index 00000000..c89a6eb6 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/DialogId.kt @@ -0,0 +1,7 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation + + +class DialogId(dialogId: String) : Identifikation(dialogId, Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Dialogsprache.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Dialogsprache.kt new file mode 100644 index 00000000..b614f44c --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Dialogsprache.kt @@ -0,0 +1,14 @@ +package net.dankito.fints.messages.datenelemente.implementierte + + +enum class Dialogsprache(val code: String) { + + Default("0"), + + German("1"), + + English("2"), + + French("3") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/DialogspracheDatenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/DialogspracheDatenelement.kt new file mode 100644 index 00000000..43be138a --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/DialogspracheDatenelement.kt @@ -0,0 +1,35 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code + + +/** + * Über dieses DE spezifiziert der Kunde die Sprache, in der er im laufenden Dialog + * mit dem Kreditinstitut kommunizieren möchte. Rückmeldungen und Kreditinstitutsmeldungen + * werden (soweit kreditinstitutsseitig unterstützt) in der zuvor spezifizierten Sprache + * an den Kunden übermittelt. Damit verbunden wird ein zugehöriger FinTS-Basiszeichensatz + * (s. Kap. B.1), der sich durch einen ISO 8859-Codeset und einen ISO 8859-Subset definiert, + * ausgewählt. Die Definition des Subsets ist den Anlagen (Kap. I.3) zu entnehmen. Der + * Codeset soll ermöglichen, zu einem späteren Zeitpunkt evtl. auch nicht-lateinische + * Zeichensätze zuzulassen. + * + * Codierung: + * - 0: Standard + * - 1: Deutsch, Code ‚de’ (German), Subset Deutsch, Codeset 1 (Latin 1) + * - 2: Englisch, Code ‚en’ (English), Subset Englisch, Codeset 1 (Latin 1) + * - 3: Französisch, Code ‚fr’ (French), Subset Französisch, Codeset 1 (Latin 1) + */ +class DialogspracheDatenelement(language: Dialogsprache, existenzstatus: Existenzstatus) + : Code(language.code, AllowedValues, existenzstatus) { + + companion object { + val AllowedValues = listOf( + Dialogsprache.Default.code, + Dialogsprache.German.code, + Dialogsprache.English.code, + Dialogsprache.French.code + ) + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/FinTsKundensystemStatus.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/FinTsKundensystemStatus.kt new file mode 100644 index 00000000..dcccd6eb --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/FinTsKundensystemStatus.kt @@ -0,0 +1,6 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus + + +open class FinTsKundensystemStatus : KundensystemStatus(KundensystemStatusWerte.NichtBenoetigt, Existenzstatus.Mandatory) \ No newline at end of file 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 new file mode 100644 index 00000000..d6b1def3 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersion.kt @@ -0,0 +1,16 @@ +package net.dankito.fints.messages.datenelemente.implementierte + + +enum class HbciVersion(val versionNumber: Int) { + + Hbci_2_0_1(201), + + Hbci_2_1_0(210), + + Hbci_2_2_0(220), + + FinTs_3_0_0(300), + + FinTs_4_0_0(400) + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersionDatenelement.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersionDatenelement.kt new file mode 100644 index 00000000..13ac6fdd --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/HbciVersionDatenelement.kt @@ -0,0 +1,34 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Version der HBCI-/FinTS-Schnittstellenspezifikation, die der jeweiligen Realisierung zugrunde liegt. + * + * HBCI- bzw. FinTS-Versionen, die vor Version 2.0.1 veröffentlicht wurden, werden + * kreditinstitutsseitig nicht unterstützt. + * + * Ein geregelter Dialog ist nur zwischen Systemen möglich, die mit derselben HBCI-/FinTS-Version + * arbeiten. Stimmt die vom Kunden übermittelte HBCI-/FinTS-Version nicht mit einer der vom + * Kreditinstitut in den BPD mitgeteilten unterstützten HBCI-/FinTS-Versionen überein, so muss der + * Dialog vom Kreditinstitut beendet werden. Innerhalb eines Dialoges dürfen nicht Nachrichten + * unterschiedlicher HBCI-/FinTS-Versionen gesendet werden. + * + * Segment- und HBCI-/FinTS-Versionen werden unabhängig voneinander geführt. Innerhalb eines HBCI-/ + * FinTS-Dialoges dürfen nur Versionen administrativer Segmente gesendet werden, die der angegebenen + * HBCI-/FinTS-Version entsprechen. Im Rahmen einer HBCI-/FinTS-Version wird eine Liste der zugehörigen + * Segmentversionen veröffentlicht (s. [Messages], Anlagen). Weiterhin werden in dieser Liste auch die + * zusätzlich noch unterstützten Segmentversionen genannt. + * + * Der Zeitpunkt der Unterstützung einer neuen HBCI-/FinTS-Version kann zwischen den Kreditinstituten variieren. + * + * Zulässige Werte: + * + * - Version 2.0.1: 201 (Spezifikationsstatus: obsolet) + * - Version 2.1: 210 (Spezifikationsstatus: obsolet) + * - Version 2.2: 220 (Spezifikationsstatus: obsolet) + * - Version 3.0: 300 + */ +class HbciVersionDatenelement(version: HbciVersion) : NumerischesDatenelement(version.versionNumber, 3, Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Kreditinstitutscode.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Kreditinstitutscode.kt new file mode 100644 index 00000000..0ccb4a0b --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Kreditinstitutscode.kt @@ -0,0 +1,14 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement + + +/** + * Landesspezifische Kennung, die das Kreditinstitut eindeutig identifiziert. In Deutschland + * wird die Bankleitzahl eingestellt. Bei Kreditinstituten, die in Ländern ohne + * Institutskennungssystem beheimatet sind, kann die Belegung entfallen. + * Zu weiteren Informationen siehe Kap. E.5. + */ +open class Kreditinstitutscode(bankCode: String, existenzstatus: Existenzstatus) + : AlphanumerischesDatenelement(bankCode, existenzstatus, 30) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundenID.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundenID.kt new file mode 100644 index 00000000..8e9952c3 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundenID.kt @@ -0,0 +1,19 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation + + +/** + * Institutsweit eindeutige Identifikation des Kunden. Die Vergabe obliegt dem Kreditinstitut. + * Die Kunden-ID kann beliebige Informationen enthalten. Es steht dem Kreditinstitut frei, ob + * es jedem Kunden genau eine Kunden-ID zuordnet oder dem Kunden in Abhängigkeit vom Benutzer + * jeweils eine unterschiedliche Kunden-ID zuordnet. + */ +open class KundenID(customerId: String) : Identifikation(customerId, Existenzstatus.Mandatory) { + + companion object { + const val Anonymous = "9999999999" + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemID.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemID.kt new file mode 100644 index 00000000..abe8d415 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemID.kt @@ -0,0 +1,26 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation + + +/** + * Eindeutige Kennzeichnung des Kundensystems, die in Kombination mit der Signatur-ID die + * Validität (Eindeutigkeit) der Signatur sichert. + * + * Die Kundensystem-ID ist nicht eindeutig für das Endgerät (PC), sondern für die Anwendung + * auf einem Endgerät, d. h., wenn der Kunde auf einem Endgerät mit mehreren Homebanking- + * Anwendungen arbeitet, muss für jede Anwendung eine eigene Kundensystem-ID geführt werden. + * + * Die Kundensystem-ID ist beim HBCI RAH- / RDH- sowie dem PIN/TAN-Verfahren erforderlich. + * Bei der Verwendung von RAH-/RDH-Chipkarten ab Sicherheitsprofil-Version 3 wird anstatt + * der Kundensystem-ID die CID der gesteckten Karte verwendet. Beim HBCI DDV-Verfahren und + * bei TAN-Verfahren ist dieses DE mit dem Wert 0 zu belegen. + */ +open class KundensystemID(customerSystemId: String) : Identifikation(customerSystemId, Existenzstatus.Mandatory) { + + companion object { + const val Anonymous = "0" + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemStatus.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemStatus.kt new file mode 100644 index 00000000..8de5950b --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemStatus.kt @@ -0,0 +1,28 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code + + +/** + * Information darüber, ob die Kundensystem-ID erforderlich ist: + * + * Codierung: + * + * 0: Kundensystem-ID wird nicht benötigt (HBCI DDV-Verfahren und chipkartenbasierte Verfahren ab Sicherheitsprofil-Version 3) + * + * 1: Kundensystem-ID wird benötigt (sonstige HBCI RAH- / RDH- und PIN/TAN-Verfahren) + */ +open class KundensystemStatus(status: KundensystemStatusWerte, existenzstatus: Existenzstatus) + : Code(status.code, AllowedValues, existenzstatus) { + + companion object { + val AllowedValues = listOf( + KundensystemStatusWerte.NichtBenoetigt.code, + KundensystemStatusWerte.Benoetigt.code + ) + + val Anonymous = KundensystemStatusWerte.NichtBenoetigt + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemStatusWerte.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemStatusWerte.kt new file mode 100644 index 00000000..a6cb3460 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/KundensystemStatusWerte.kt @@ -0,0 +1,10 @@ +package net.dankito.fints.messages.datenelemente.implementierte + + +enum class KundensystemStatusWerte(val code: String) { + + NichtBenoetigt("0"), + + Benoetigt("1") + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Laenderkennzeichen.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Laenderkennzeichen.kt new file mode 100644 index 00000000..74d20ee0 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Laenderkennzeichen.kt @@ -0,0 +1,22 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.ZiffernDatenelement + + +/** + * Kennzeichen gemäß ISO 3166-1 (numerischer Code). + * + * (Siehe z.B. PDF Messages_Geschaeftsvorfaelle Kapitel E.4 (S. 813) oder https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes .) + */ +open class Laenderkennzeichen(countryCode: Int, existenzstatus: Existenzstatus) + : ZiffernDatenelement(countryCode, 3, existenzstatus) { + + companion object { + /** + * Für Deutschland wird der Code 280 verwendet da dieser im Kreditgewerbe gebräuchlicher als der neue Code 276 ist. + */ + const val Germany = 280 + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Nachrichtengroesse.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Nachrichtengroesse.kt new file mode 100644 index 00000000..64484a24 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Nachrichtengroesse.kt @@ -0,0 +1,12 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.ZiffernDatenelement + + +/** + * Größe der Nachricht (nach Verschlüsselung und Komprimierung) in Byte. + * Das DE ist mit führenden Nullen auf die vorgegebene feste Länge aufzufüllen. + * Dies ist erforderlich, damit die Nachrichtenlänge nicht mit der Länge des DE variiert. + */ +class Nachrichtengroesse(messageSize: Int) : ZiffernDatenelement(messageSize, 12, Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Nachrichtennummer.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Nachrichtennummer.kt new file mode 100644 index 00000000..f5338149 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Nachrichtennummer.kt @@ -0,0 +1,26 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Information zur Referenzierung von Nachrichten innerhalb eines Dialoges. In + * Zusammenhang mit der Dialog-ID und der Kundensystem-ID können Nachrichten + * über die Nachrichtennummer auch dialogübergreifend eindeutig referenziert werden. + * Eine Doppeleinreichungskontrolle ist mit Hilfe der Nachrichtennummer nicht möglich. + * + * Mit Hilfe der Nachrichtennummer nummerieren sowohl das Kundensystem als auch das + * Kreditinstitutssystem seine Nachrichten unabhängig voneinander innerhalb eines Dialoges + * in Einerschritten streng monoton aufsteigend. Die Nummerierung beginnt sowohl beim Kunden- + * als auch beim Kreditinstitutssystem mit der Dialoginitialisierungsnachricht bei '1'. + * Nachrichten, deren Nummerierung nicht streng monoton aufsteigend erfolgt ist, werden + * institutsseitig bzw. kundenseitig abgelehnt. + */ +class Nachrichtennummer(number: Int) : NumerischesDatenelement(number, 4, Existenzstatus.Mandatory) { + + companion object { + const val FirstMessageNumber = 1 + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Produktbezeichnung.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Produktbezeichnung.kt new file mode 100644 index 00000000..4b347eef --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Produktbezeichnung.kt @@ -0,0 +1,19 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement + + +/** + * Name des Kundenproduktes, mit dem kundenseitig die Nachrichten erzeugt wurden. + * Diese Angabe dient dem Kreditinstitut, um Kundenprodukthersteller gezielt unterstützen zu können. + * + * Die Produktbezeichnung ist verpflichtend mit aussagekräftigen Informationen über das verwendete + * Kundenprodukt, nicht eine ggf. verwendete interne FinTS-/HBCI-Bibliothek, zu füllen, um + * Support-Anfragen leichter beantworten zu können. + * + * Kundenprodukte, die nach dem durch die Deutsche Kreditwirtschaft festgelegten Verfahren registriert + * sind, müssen in dieses DE die vergebene Produktregistrierungsnummer einstellen. + */ +class Produktbezeichnung(name: String, existenzstatus: Existenzstatus) + : AlphanumerischesDatenelement(name, existenzstatus, 25) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Produktversion.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Produktversion.kt new file mode 100644 index 00000000..43443a44 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Produktversion.kt @@ -0,0 +1,15 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement + + +/** + * Version des Kundenproduktes, mit dem kundenseitig die Nachrichten erzeugt wurden. + * + * Die Produktversion ist verpflichtend mit aussagekräftigen Informationen über das verwendete + * Kundenprodukt, nicht eine ggf. verwendete interne FinTS-/HBCI-Bibliothek, zu füllen, um + * Support-Anfragen leichter beantworten zu können. + */ +class Produktversion(version: String, existenzstatus: Existenzstatus) + : AlphanumerischesDatenelement(version, existenzstatus, 5) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentkennung.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentkennung.kt new file mode 100644 index 00000000..42ba6b3d --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentkennung.kt @@ -0,0 +1,11 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement + + +/** + * Segmentspezifische Kennung, die jedem Segment bzw. Auftrag zugeordnet ist (z. B. "HKCCS" + * für "SEPA Einzelüberweisung"). Die Angabe hat in Großschreibung zu erfolgen. + */ +open class Segmentkennung(identifier: String): AlphanumerischesDatenelement(identifier, Existenzstatus.Mandatory, 6) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentnummer.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentnummer.kt new file mode 100644 index 00000000..042e3765 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentnummer.kt @@ -0,0 +1,22 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Information zur eindeutigen Identifizierung eines Segments innerhalb einer Nachricht. + * Die Segmente einer Nachricht werden in Einerschritten streng monoton aufsteigend nummeriert. + * Die Nummerierung beginnt mit 1 im ersten Segment der Nachricht (Nachrichtenkopf). + */ +open class Segmentnummer(number: Int) : NumerischesDatenelement(number, 3, Existenzstatus.Mandatory) { + + override fun validate() { + super.validate() + + if (value < 1) { + throwValidationException("Segmentnummer '$value' muss größer oder gleich 1 sein.") + } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentversion.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentversion.kt new file mode 100644 index 00000000..d7810db3 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/Segmentversion.kt @@ -0,0 +1,25 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Versionsnummer zur Dokumentation von Änderungen eines Segmentformats. + * Die Segmentversion von administrativen Segmenten (die Segmentart ‘Administration’ bzw. ‘Geschäftsvorfall’ + * ist bei jeder Segmentbeschreibung angegeben) wird bei jeder Änderung des Segmentformats inkrementiert. + * + * Bei Geschäftsvorfallssegmenten wird die Segmentversion auf logischer Ebene verwaltet, d. h. sie ist für das + * Auftrags-, das Antwort- und das Parametersegment des Geschäftsvorfalls stets identisch und wird inkrementiert, + * wenn sich das Format von mindestens einem der drei Segmente ändert. + * + * Dieses Verfahren gilt bei Standardsegmenten einheitlich für alle Kreditinstitute. Bei verbandsindividuellen + * Segmenten obliegt die Versionssteuerung dem jeweiligen Verband. Der Zeitpunkt der Unterstützung einer neuen + * Segmentversion kann jedoch zwischen den Verbänden variieren. + * + * Die für die jeweilige HBCI-Version gültige Segmentversion ist bei der jeweiligen Segmentbeschreibung vermerkt. + * + * Falls der Kunde ein Segment mit einer veralteten Versionsnummer einreicht, sollte ihm in einer entsprechenden + * Warnung rückgemeldet werden, dass sein Kundenprodukt aktualisiert werden sollte. + */ +open class Segmentversion(version: Int) : NumerischesDatenelement(version, 3, Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/UPDVersion.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/UPDVersion.kt new file mode 100644 index 00000000..7ad469b3 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelemente/implementierte/UPDVersion.kt @@ -0,0 +1,17 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement + + +/** + * Versionsnummer der Userparameterdaten (UPD). Bei jeder kreditinstitutsseitigen Änderung + * wird die Version inkrementiert. (S. auch DE BPD-Version). + */ +class UPDVersion(version: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(version, 3, existenzstatus) { + + companion object { + const val VersionNotReceivedYet = 0 + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/Datenelementgruppe.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/Datenelementgruppe.kt new file mode 100644 index 00000000..3911aaa7 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/Datenelementgruppe.kt @@ -0,0 +1,19 @@ +package net.dankito.fints.messages.datenelementgruppen + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.DatenelementBase + + +abstract class Datenelementgruppe(val dataElements: List, existenzstatus: Existenzstatus) + : DatenelementBase(existenzstatus) { + + companion object { + const val DataElementsSeparator = ":" + } + + + override fun format(): String { + return dataElements.joinToString(DataElementsSeparator) { it.format() } + } + +} \ 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 new file mode 100644 index 00000000..cec45918 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Kreditinstitutskennung.kt @@ -0,0 +1,13 @@ +package net.dankito.fints.messages.datenelementgruppen.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.implementierte.Kreditinstitutscode +import net.dankito.fints.messages.datenelemente.implementierte.Laenderkennzeichen +import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe + + +open class Kreditinstitutskennung(bankCountryCode: Int, bankCode: String) + : Datenelementgruppe(listOf( + Laenderkennzeichen(bankCountryCode, Existenzstatus.Mandatory), + Kreditinstitutscode(bankCode, Existenzstatus.Mandatory) + ), Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Segmentkopf.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Segmentkopf.kt new file mode 100644 index 00000000..deeacf45 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/datenelementgruppen/implementierte/Segmentkopf.kt @@ -0,0 +1,21 @@ +package net.dankito.fints.messages.datenelementgruppen.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.implementierte.Segmentkennung +import net.dankito.fints.messages.datenelemente.implementierte.Segmentnummer +import net.dankito.fints.messages.datenelemente.implementierte.Segmentversion +import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe + + +open class Segmentkopf @JvmOverloads constructor( + identifier: String, + segmentNumber: Int, + segmentVersion: Int, + bezugssegment: Int? = null + +) : Datenelementgruppe(listOf( + Segmentkennung(identifier), + Segmentnummer(segmentNumber), + Segmentversion(segmentVersion) // TODO: how to conditionally add Bezugsegment? +), Existenzstatus.Mandatory) { +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/Nachricht.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/Nachricht.kt new file mode 100644 index 00000000..303d643d --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/Nachricht.kt @@ -0,0 +1,19 @@ +package net.dankito.fints.messages.nachrichten + +import net.dankito.fints.messages.Nachrichtenteil +import net.dankito.fints.messages.segmente.Segment + + +open class Nachricht(val segments: List) : Nachrichtenteil() { + + companion object { + const val SegmentSeparator = "'" + } + + + override fun format(): String { + return segments.joinToString(SegmentSeparator, postfix = SegmentSeparator) { it.format() } + } + + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/implementierte/Dialoginitialisierung.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/implementierte/Dialoginitialisierung.kt new file mode 100644 index 00000000..5eb85142 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/implementierte/Dialoginitialisierung.kt @@ -0,0 +1,29 @@ +package net.dankito.fints.messages.nachrichten.implementierte + +import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache +import net.dankito.fints.messages.datenelemente.implementierte.Nachrichtennummer.Companion.FirstMessageNumber +import net.dankito.fints.messages.nachrichten.Nachricht +import net.dankito.fints.messages.segmente.implementierte.IdentifikationsSegment +import net.dankito.fints.messages.segmente.implementierte.Nachrichtenabschluss +import net.dankito.fints.messages.segmente.implementierte.Nachrichtenkopf +import net.dankito.fints.messages.segmente.implementierte.Verarbeitungsvorbereitung + + +open class Dialoginitialisierung( + messageSize: Int, // TODO: how to get / calculate size? (give each Segment, Dataelement, ... a size value?) + bankCountryCode: Int, + bankCode: String, + customerId: String, + customerSystemId: String, + bpdVersion: Int, + updVersion: Int, + language: Dialogsprache, + productName: String, + productVersion: String +) + : Nachricht(listOf( + Nachrichtenkopf(1, messageSize, "0", FirstMessageNumber), + IdentifikationsSegment(2, bankCountryCode, bankCode, customerId, customerSystemId), + Verarbeitungsvorbereitung(3, bpdVersion, updVersion, language, productName, productVersion), + Nachrichtenabschluss(4, FirstMessageNumber) +)) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/implementierte/DialoginitialisierungAnonym.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/implementierte/DialoginitialisierungAnonym.kt new file mode 100644 index 00000000..835f7458 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/nachrichten/implementierte/DialoginitialisierungAnonym.kt @@ -0,0 +1,20 @@ +package net.dankito.fints.messages.nachrichten.implementierte + +import net.dankito.fints.messages.datenelemente.implementierte.* + + +/** + * Um Kunden die Möglichkeit zu geben, sich anonym anzumelden, um sich bspw. über die + * angebotenen Geschäftsvorfälle fremder Kreditinstitute (von denen sie keine BPD besitzen) + * zu informieren bzw. nicht-signierungspflichtige Aufträge bei fremden Kreditinstituten + * einreichen zu können, kann sich der Kunde anonym (als Gast) anmelden. + * + * Bei anonymen Dialogen werden Nachrichten weder signiert, noch können sie verschlüsselt und komprimiert werden. + */ +open class DialoginitialisierungAnonym( + bankCountryCode: Int, + bankCode: String, + productName: String, + productVersion: String +) : Dialoginitialisierung(125, bankCountryCode, bankCode, KundenID.Anonymous, KundensystemID.Anonymous, + BPDVersion.VersionNotReceivedYet, UPDVersion.VersionNotReceivedYet, Dialogsprache.Default, productName, productVersion) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/Segment.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/Segment.kt new file mode 100644 index 00000000..07a8c577 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/Segment.kt @@ -0,0 +1,20 @@ +package net.dankito.fints.messages.segmente + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.DatenelementBase + + +abstract class Segment(val dataElementsAndGroups: List, existenzstatus: Existenzstatus) + : DatenelementBase(existenzstatus) { + + companion object { + const val DataElementGroupsSeparator = "+" + } + + + override fun format(): String { + // TODO: really use DatenelementGruppenSeparator for all elements or use for Datenelement Datenelementgruppe.DatenelementSeparator ? + return dataElementsAndGroups.joinToString(DataElementGroupsSeparator) { it.format() } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/IdentifikationsSegment.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/IdentifikationsSegment.kt new file mode 100644 index 00000000..34a09a51 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/IdentifikationsSegment.kt @@ -0,0 +1,25 @@ +package net.dankito.fints.messages.segmente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.implementierte.FinTsKundensystemStatus +import net.dankito.fints.messages.datenelemente.implementierte.KundenID +import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID +import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung +import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf +import net.dankito.fints.messages.segmente.Segment + + +open class IdentifikationsSegment( + segmentNumber: Int, + bankCountryCode: Int, + bankCode: String, + customerId: String, + customerSystemId: String + +) : Segment(listOf( + Segmentkopf("HKIDN", segmentNumber, 2), + Kreditinstitutskennung(bankCountryCode, bankCode), + KundenID(customerId), + KundensystemID(customerSystemId), + FinTsKundensystemStatus() +), Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Nachrichtenabschluss.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Nachrichtenabschluss.kt new file mode 100644 index 00000000..3bc0273c --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Nachrichtenabschluss.kt @@ -0,0 +1,18 @@ +package net.dankito.fints.messages.segmente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.implementierte.Nachrichtennummer +import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf +import net.dankito.fints.messages.segmente.Segment + + +/** + * Dieses Segment beendet alle Kunden- und Kreditinstitutsnachrichten. + */ +class Nachrichtenabschluss( + segmentNumber: Int, + messageNumber: Int +) : Segment(listOf( + Segmentkopf("HNHBS", segmentNumber, 1), + Nachrichtennummer(messageNumber) +), Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Nachrichtenkopf.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Nachrichtenkopf.kt new file mode 100644 index 00000000..56b6525d --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Nachrichtenkopf.kt @@ -0,0 +1,21 @@ +package net.dankito.fints.messages.segmente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.implementierte.* +import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf +import net.dankito.fints.messages.segmente.Segment + + +open class Nachrichtenkopf( + segmentNumber: Int, + messageSize: Int, + dialogId: String, + messageNumber: Int + +) : Segment(listOf( + Segmentkopf("HNHBK", segmentNumber, 3), + Nachrichtengroesse(messageSize), + HbciVersionDatenelement(HbciVersion.FinTs_3_0_0), + DialogId(dialogId), + Nachrichtennummer(messageNumber) +), Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt new file mode 100644 index 00000000..6ea4f7b2 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/segmente/implementierte/Verarbeitungsvorbereitung.kt @@ -0,0 +1,23 @@ +package net.dankito.fints.messages.segmente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import net.dankito.fints.messages.datenelemente.implementierte.* +import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf +import net.dankito.fints.messages.segmente.Segment + + +class Verarbeitungsvorbereitung( + segmentNumber: Int, + bpdVersion: Int, + updVersion: Int, + language: Dialogsprache, + productName: String, + productVersion: String +) : Segment(listOf( + Segmentkopf("HKVVB", segmentNumber, 3), + BPDVersion(bpdVersion, Existenzstatus.Mandatory), + UPDVersion(updVersion, Existenzstatus.Mandatory), + DialogspracheDatenelement(language, Existenzstatus.Mandatory), + Produktbezeichnung(productName, Existenzstatus.Mandatory), + Produktversion(productVersion, Existenzstatus.Mandatory) +), Existenzstatus.Mandatory) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/util/IBase64Service.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/util/IBase64Service.kt new file mode 100644 index 00000000..93d2f3ba --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/util/IBase64Service.kt @@ -0,0 +1,26 @@ +package net.dankito.fints.util + +import java.nio.charset.Charset + + +interface IBase64Service { + + companion object { + val DefaultCharset = Charsets.UTF_8 + } + + + fun encode(text: String): String { + return encode(text, DefaultCharset) + } + + fun encode(text: String, charset: Charset): String + + + fun decode(base64: String): String { + return decode(base64, DefaultCharset) + } + + fun decode(base64: String, charset: Charset): String + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/basisformate/TextDatenelementTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/basisformate/TextDatenelementTest.kt new file mode 100644 index 00000000..4bbad140 --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/basisformate/TextDatenelementTest.kt @@ -0,0 +1,66 @@ +package net.dankito.fints.messages.datenelemente.basisformate + +import net.dankito.fints.messages.Existenzstatus +import org.junit.Test + + +class TextDatenelementTest { + + @Test + fun validate_ValidCharacters() { + + // given + val underTest = createTextDatenelement("àéôçñøäöüß¿") + + // when + underTest.validate() + + // then + // no exception + } + + @Test(expected = IllegalArgumentException::class) + fun validate_GreekCharacter_Invalid() { + + // given + val underTest = createTextDatenelement("α") + + // when + underTest.validate() + + // then + // exception gets thrown + } + + @Test(expected = IllegalArgumentException::class) + fun validate_CyrillicCharacter_Invalid() { + + // given + val underTest = createTextDatenelement("Я") + + // when + underTest.validate() + + // then + // exception gets thrown + } + + @Test(expected = IllegalArgumentException::class) + fun validate_EuroSymbol_Invalid() { + + // given + val underTest = createTextDatenelement("€") // is only allowed by ISO-8859-15, not by ISO-8859-1 + + // when + underTest.validate() + + // then + // exception gets thrown + } + + + private fun createTextDatenelement(text: String): TextDatenelement { + return object : TextDatenelement(text, Existenzstatus.Mandatory) { } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/basisformate/ZiffernDatenelementTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/basisformate/ZiffernDatenelementTest.kt new file mode 100644 index 00000000..b160f446 --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/basisformate/ZiffernDatenelementTest.kt @@ -0,0 +1,81 @@ +package net.dankito.fints.messages.datenelemente.basisformate + +import net.dankito.fints.messages.Existenzstatus +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + + +class ZiffernDatenelementTest { + + @Test + fun format() { + + // given + val underTest = createZiffernDatenelement(1, 6) + + // when + val result = underTest.format() + + // then + assertThat(result).isEqualTo("000001") + } + + + @Test + fun validate_0_Valid() { + + // given + val underTest = createZiffernDatenelement(0, 3) + + // when + underTest.validate() + + // then + // no exception + } + + @Test + fun validate_999_Valid() { + + // given + val underTest = createZiffernDatenelement(999, 3) + + // when + underTest.validate() + + // then + // no exception + } + + @Test(expected = IllegalArgumentException::class) + fun validate_Minus1_Invalid() { + + // given + val underTest = createZiffernDatenelement(-1, 3) + + // when + underTest.validate() + + // then + // exception gets thrown + } + + @Test(expected = IllegalArgumentException::class) + fun validate_1000_Invalid() { + + // given + val underTest = createZiffernDatenelement(1000, 3) + + // when + underTest.validate() + + // then + // exception gets thrown + } + + + private fun createZiffernDatenelement(value: Int, numberOfDigits: Int): ZiffernDatenelement { + return object : ZiffernDatenelement(value, numberOfDigits, Existenzstatus.Mandatory) { } + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BPDVersionTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BPDVersionTest.kt new file mode 100644 index 00000000..469d7e6d --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/implementierte/BPDVersionTest.kt @@ -0,0 +1,76 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + + +class BPDVersionTest { + + @Test + fun format() { + + // given + val underTest = BPDVersion(3, Existenzstatus.Mandatory) + + // when + val result = underTest.format() + + // then + assertThat(result).isEqualTo("3") + } + + + @Test + fun validate_0_Valid() { + + // given + val underTest = BPDVersion(0, Existenzstatus.Mandatory) + + // when + underTest.validate() + + // then + // no exception + } + + @Test + fun validate_999_Valid() { + + // given + val underTest = BPDVersion(999, Existenzstatus.Mandatory) + + // when + underTest.validate() + + // then + // no exception + } + + @Test(expected = IllegalArgumentException::class) + fun validate_TooLow() { + + // given + val underTest = BPDVersion(-1, Existenzstatus.Mandatory) + + // when + underTest.validate() + + // then + // exception gets thrown + } + + @Test(expected = IllegalArgumentException::class) + fun validate_TooHigh() { + + // given + val underTest = BPDVersion(1000, Existenzstatus.Mandatory) + + // when + underTest.validate() + + // then + // exception gets thrown + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/implementierte/ProduktbezeichnungTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/implementierte/ProduktbezeichnungTest.kt new file mode 100644 index 00000000..3704549c --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/datenelemente/implementierte/ProduktbezeichnungTest.kt @@ -0,0 +1,35 @@ +package net.dankito.fints.messages.datenelemente.implementierte + +import net.dankito.fints.messages.Existenzstatus +import org.junit.Test + + +class ProduktbezeichnungTest { + + @Test + fun validate_MaxLength() { + + // given + val underTest = Produktbezeichnung("1234567890123456789012345", Existenzstatus.Mandatory) + + // when + underTest.validate() + + // then + // no exception + } + + @Test(expected = IllegalArgumentException::class) + fun validate_MaxLengthExceeded() { + + // given + val underTest = Produktbezeichnung("12345678901234567890123456", Existenzstatus.Mandatory) + + // when + underTest.validate() + + // then + // exception gets thrown + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/nachrichten/implementierte/DialoginitialisierungAnonymTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/nachrichten/implementierte/DialoginitialisierungAnonymTest.kt new file mode 100644 index 00000000..c9645fa3 --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/nachrichten/implementierte/DialoginitialisierungAnonymTest.kt @@ -0,0 +1,28 @@ +package net.dankito.fints.messages.nachrichten.implementierte + +import net.dankito.fints.messages.datenelemente.implementierte.Laenderkennzeichen +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + + +class DialoginitialisierungAnonymTest { + + @Test + fun format() { + + // given + val underTest = DialoginitialisierungAnonym(Laenderkennzeichen.Germany, "12345678", "36792786FA12F235F04647689", "3") + + // when + val result = underTest.format() + + // then + assertThat(result).isEqualTo( + "HNHBK:1:3+000000000125+300+0+1'" + + "HKIDN:2:2+280:12345678+9999999999+0+0'" + + "HKVVB:3:3+0+0+0+36792786FA12F235F04647689+3'" + + "HNHBS:4:1+1'" + ) + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt new file mode 100644 index 00000000..c6a0e21f --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/messages/segmente/implementierte/IdentifikationsSegmentTest.kt @@ -0,0 +1,25 @@ +package net.dankito.fints.messages.segmente.implementierte + +import net.dankito.fints.messages.datenelemente.implementierte.KundenID +import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID +import net.dankito.fints.messages.datenelemente.implementierte.Laenderkennzeichen +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + + +class IdentifikationsSegmentTest { + + @Test + fun format() { + + // given + val underTest = IdentifikationsSegment(2, Laenderkennzeichen.Germany, "12345678", KundenID.Anonymous, KundensystemID.Anonymous) + + // when + val result = underTest.format() + + // then + assertThat(result).isEqualTo("HKIDN:2:2+280:12345678+9999999999+0+0") + } + +} \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/util/Java8Base64Service.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/util/Java8Base64Service.kt new file mode 100644 index 00000000..8962820f --- /dev/null +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/util/Java8Base64Service.kt @@ -0,0 +1,21 @@ +package net.dankito.fints.util + +import java.nio.charset.Charset +import java.util.* + + +// TODO: use version from JavaFxUtils +class Java8Base64Service : IBase64Service { + + + override fun encode(text: String, charset: Charset): String { + return Base64.getEncoder().encodeToString(text.toByteArray(charset)) + } + + override fun decode(base64: String, charset: Charset): String { + val decodedBytes = Base64.getDecoder().decode(base64) + + return String(decodedBytes, charset) + } + +} diff --git a/FinTS4javaLib/src/test/resources/logback-test.xml b/fints4javaLib/src/test/resources/logback-test.xml similarity index 100% rename from FinTS4javaLib/src/test/resources/logback-test.xml rename to fints4javaLib/src/test/resources/logback-test.xml diff --git a/settings.gradle b/settings.gradle index 48924466..cd9dc977 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'fints4java' -include ':FinTS4javaLib' \ No newline at end of file +include ':fints4javaLib' \ No newline at end of file