Implemented DialoginitialisierungAnonym (to start an anonymous communication with bank)
This commit is contained in:
parent
46585d6fec
commit
f1e6ed1350
|
@ -0,0 +1,12 @@
|
||||||
|
package net.dankito.fints.messages
|
||||||
|
|
||||||
|
|
||||||
|
enum class Existenzstatus {
|
||||||
|
|
||||||
|
Mandatory,
|
||||||
|
|
||||||
|
Optional,
|
||||||
|
|
||||||
|
NotAllowed
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.dankito.fints.messages
|
||||||
|
|
||||||
|
|
||||||
|
abstract class Nachrichtenteil {
|
||||||
|
|
||||||
|
abstract fun format(): String
|
||||||
|
|
||||||
|
}
|
|
@ -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")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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()
|
|
@ -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<String>, 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(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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")
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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)
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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)
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte
|
||||||
|
|
||||||
|
|
||||||
|
enum class KundensystemStatusWerte(val code: String) {
|
||||||
|
|
||||||
|
NichtBenoetigt("0"),
|
||||||
|
|
||||||
|
Benoetigt("1")
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<DatenelementBase>, existenzstatus: Existenzstatus)
|
||||||
|
: DatenelementBase(existenzstatus) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val DataElementsSeparator = ":"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun format(): String {
|
||||||
|
return dataElements.joinToString(DataElementsSeparator) { it.format() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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) {
|
||||||
|
}
|
|
@ -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<Segment>) : Nachrichtenteil() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val SegmentSeparator = "'"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun format(): String {
|
||||||
|
return segments.joinToString(SegmentSeparator, postfix = SegmentSeparator) { it.format() }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
))
|
|
@ -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)
|
|
@ -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<DatenelementBase>, 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() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
|
@ -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) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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'"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
rootProject.name = 'fints4java'
|
rootProject.name = 'fints4java'
|
||||||
|
|
||||||
include ':FinTS4javaLib'
|
include ':fints4javaLib'
|
Loading…
Reference in New Issue