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'
|
||||
|
||||
include ':FinTS4javaLib'
|
||||
include ':fints4javaLib'
|
Loading…
Reference in New Issue