Added ZweiSchrittTanEinreichung. Authenticating with it works, but is not really configurable / usable.
This commit is contained in:
parent
b9733189e6
commit
9ac4af58ff
|
@ -2,6 +2,7 @@ package net.dankito.fints.messages
|
||||||
|
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.*
|
import net.dankito.fints.messages.datenelemente.implementierte.*
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion
|
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanProcess
|
||||||
import net.dankito.fints.messages.nachrichten.Nachricht
|
import net.dankito.fints.messages.nachrichten.Nachricht
|
||||||
import net.dankito.fints.messages.segmente.ISegmentNumberGenerator
|
import net.dankito.fints.messages.segmente.ISegmentNumberGenerator
|
||||||
import net.dankito.fints.messages.segmente.Segment
|
import net.dankito.fints.messages.segmente.Segment
|
||||||
|
@ -39,8 +40,12 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
productVersion: String
|
productVersion: String
|
||||||
): String {
|
): String {
|
||||||
|
|
||||||
return createDialogInitMessage(bankCountryCode, bankCode, KundenID.Anonymous, KundensystemID.Anonymous, KundensystemStatusWerte.NichtBenoetigt,
|
val customerId = KundenID.Anonymous
|
||||||
BPDVersion.VersionNotReceivedYet, UPDVersion.VersionNotReceivedYet, Dialogsprache.Default, productName, productVersion, false, false)
|
|
||||||
|
return createMessage(false, false, bankCountryCode, bankCode, customerId, listOf(
|
||||||
|
IdentifikationsSegment(generator.resetSegmentNumber(1), bankCountryCode, bankCode, customerId, KundensystemID.Anonymous, KundensystemStatusWerte.NichtBenoetigt),
|
||||||
|
Verarbeitungsvorbereitung(generator.getNextSegmentNumber(), BPDVersion.VersionNotReceivedYet, UPDVersion.VersionNotReceivedYet, Dialogsprache.Default, productName, productVersion)
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun createDialogInitMessage(
|
open fun createDialogInitMessage(
|
||||||
|
@ -53,14 +58,13 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
updVersion: Int,
|
updVersion: Int,
|
||||||
language: Dialogsprache,
|
language: Dialogsprache,
|
||||||
productName: String,
|
productName: String,
|
||||||
productVersion: String,
|
productVersion: String
|
||||||
signMessage: Boolean = true,
|
|
||||||
encryptMessage: Boolean = true
|
|
||||||
): String {
|
): String {
|
||||||
|
|
||||||
return createMessage(signMessage, encryptMessage, bankCountryCode, bankCode, customerId, listOf(
|
return createMessage(true, true, bankCountryCode, bankCode, customerId, listOf(
|
||||||
IdentifikationsSegment(generator.resetSegmentNumber(if (signMessage) 2 else 1), bankCountryCode, bankCode, customerId, customerSystemId, status),
|
IdentifikationsSegment(generator.resetSegmentNumber(2), bankCountryCode, bankCode, customerId, customerSystemId, status),
|
||||||
Verarbeitungsvorbereitung(generator.getNextSegmentNumber(), bpdVersion, updVersion, language, productName, productVersion)
|
Verarbeitungsvorbereitung(generator.getNextSegmentNumber(), bpdVersion, updVersion, language, productName, productVersion),
|
||||||
|
ZweiSchrittTanEinreichung(generator.getNextSegmentNumber(), TanProcess.TanProcess4, "HKIDN")
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,13 @@ open class BinaerDatenelement @JvmOverloads constructor(val data: ByteArray, exi
|
||||||
* Spezifikation vorzusehen.
|
* Spezifikation vorzusehen.
|
||||||
*/
|
*/
|
||||||
override fun format(): String {
|
override fun format(): String {
|
||||||
|
if (data.size > 0) {
|
||||||
return "@${data.size}@" + String(data)
|
return "@${data.size}@" + String(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
override fun validate() {
|
override fun validate() {
|
||||||
// binary data aren't checked, so they are always valid
|
// binary data aren't checked, so they are always valid
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ab FinTS 3.0 existieren beim RAH-Verfahren drei Schlüssel (DS-Schlüssel für Non-Repudiation,
|
||||||
|
* Signierschlüssel für Authentication und Chiffrierschlüssel für Verschlüsselung) und somit
|
||||||
|
* auch drei Sicherheitsfunktionen (Sicherheitsfunktion 1 bei Verwendung des DS-Schlüssels,
|
||||||
|
* Sicherheitsfunktion 2 bei Verwendung des Signierschlüssels und Sicherheitsfunktion 4 bei
|
||||||
|
* Verwendung des Chiffrierschlüssels) beim RAH-Verfahren.
|
||||||
|
*
|
||||||
|
* Die Sicherheitsfunktion hat ab FinTS 3.0 lediglich informatorischen Wert, da die eigentliche
|
||||||
|
* Steuerung über die Sicherheitsprofile und –Klassen erfolgt.
|
||||||
|
*
|
||||||
|
* Kodierte Information über die Sicherheitsfunktion, die auf die Nachricht angewendet wird.
|
||||||
|
*
|
||||||
|
* Codierung:
|
||||||
|
* - 1: Non-Repudiation of Origin (NRO)
|
||||||
|
* - 2: Message Origin Authentication (AUT)
|
||||||
|
* - 4: Encryption, Verschlüsselung und evtl. Komprimierung (ENC)
|
||||||
|
*/
|
||||||
|
enum class SicherheitsfunktionWhatIsThisShit(val code: String) {
|
||||||
|
|
||||||
|
NonRepudiationOfOrigin("1"),
|
||||||
|
|
||||||
|
MessageOriginAuthentication("2"),
|
||||||
|
|
||||||
|
Encryption("4")
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.basisformate.BinaerDatenelement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Er enthält im Falle des Zwei-Schritt-TAN-Verfahrens bei TAN-Prozess=1 den Hashwert über die
|
||||||
|
* Daten eines Kundenauftrags (z. B. „HKCCS“). Dieser wird z. B. im Rahmen des Geschäftsvorfalls
|
||||||
|
* HKTAN vom Kunden übermittelt und vom Kreditinstitut in der Antwortnachricht HITAN gespiegelt.
|
||||||
|
*
|
||||||
|
* Das vom Institut verwendete Auftrags-Hashwertverfahren wird in der BPD übermittelt. In der
|
||||||
|
* vorliegenden Version wird RIPEMD-160 verwendet.
|
||||||
|
*
|
||||||
|
* In die Berechnung des Auftrags-Hashwerts geht der Bereich vom ersten bit des Segmentkopfes
|
||||||
|
* bis zum letzten bit des Trennzeichens ein.
|
||||||
|
*
|
||||||
|
* RIPEMD-160
|
||||||
|
*
|
||||||
|
* Der Hash-Algorithmus RIPEMD-160 bildet Eingabe-Bitfolgen beliebiger Länge auf einen als
|
||||||
|
* Bytefolge dargestellten Hash-Wert von 20 Byte (160 Bit) Länge ab. Teil des Hash-Algorithmus
|
||||||
|
* ist das Padding von Eingabe-Bitfolgen auf ein Vielfaches von 64 Byte. Das Padding erfolgt
|
||||||
|
* auch dann, wenn die Eingabe-Bitfolge bereits eine Länge hat, die ein Vielfaches von 64 Byte ist.
|
||||||
|
* RIPEMD-160 verarbeitet die Eingabe-Bitfolgen in Blöcken von 64 Byte Länge.
|
||||||
|
*
|
||||||
|
* Als Initialisierungsvektor dient die binäre Zeichenfolge
|
||||||
|
* X’01 23 45 67 89 AB CD EF FE DC BA 98 76 54 32 10 F0 E1 D2 C3’.
|
||||||
|
*/
|
||||||
|
open class AuftragsHashwert(hash: ByteArray, existenzstatus: Existenzstatus)
|
||||||
|
: BinaerDatenelement(hash, existenzstatus, 256)
|
|
@ -0,0 +1,17 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enthält im Falle des Zwei-Schritt-TAN-Verfahrens die Referenz auf einen eingereichten Auftrag.
|
||||||
|
* Die Auftragsreferenz wird bei der späteren Einreichung der zugehörigen TANs (mittels HKTAN bei
|
||||||
|
* TAN-Prozess=2 bzw. 3) zur Referenzierung des Auftrags verwendet.
|
||||||
|
*
|
||||||
|
* Da die Auftragsreferenz immer eindeutig ist, sollten Kundenprodukte diese als zentrale
|
||||||
|
* Referenzierung verwenden und dem Kunden auch zusammen mit den Auftragsdaten präsentieren bzw.
|
||||||
|
* für die Problemverfolgung leicht zugänglich machen.
|
||||||
|
*/
|
||||||
|
open class Auftragsreferenz(reference: String, existenzstatus: Existenzstatus)
|
||||||
|
: AlphanumerischesDatenelement(reference, existenzstatus, 35)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symbolischer Name für ein TAN-Medium wie z. B. TAN-Generator oder Mobiltelefon. Diese Bezeichnung
|
||||||
|
* kann in Verwaltungs-Geschäftsvorfällen benutzt werden, wenn z. B. die Angabe der echten Handynummer
|
||||||
|
* aus Datenschutzgründen nicht möglich ist oder auch um die Benutzerfreundlichkeit zu erhöhen.
|
||||||
|
*/
|
||||||
|
open class BezeichnungDesTANMediums(identifier: String, existenzstatus: Existenzstatus)
|
||||||
|
: AlphanumerischesDatenelement(identifier, existenzstatus, 32)
|
|
@ -0,0 +1,16 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.basisformate.BinaerDatenelement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bei Verwendung von Zwei-Schritt-Verfahren mit unidirektionaler Kopplung (vgl. hierzu [HHD_UC])
|
||||||
|
* müssen zusätzlich zum Datenelement „Challenge“ die Daten für die Übertragung z. B. über eine
|
||||||
|
* optische Schnittstelle bereitgestellt werden. Die einzelnen Datenelemente der „Challenge HHD_UC“
|
||||||
|
* sind in [HHD_UC] beschrieben und werden hier im FinTS Data Dictionary nicht näher erläutert.
|
||||||
|
* Da HHD_UC einen anderen Basiszeichensatz verwendet (ISO 646) wird die HHD_UC-Struktur als binär
|
||||||
|
* definiert. Als maximale Länge kann ein Wert von 128 angenommen werden.
|
||||||
|
*/
|
||||||
|
open class ChallengeHHD_UC(challenge: ByteArray, existenzstatus: Existenzstatus)
|
||||||
|
: BinaerDatenelement(challenge, existenzstatus, 128)
|
|
@ -0,0 +1,27 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dieses Datenelement enthält im Falle des Zwei-Schritt-TAN-Verfahrens die Challenge zu einem
|
||||||
|
* eingereichten Auftrag. Aus der Challenge wird vom Kunden die eigentliche TAN ermittelt.
|
||||||
|
* Die Challenge wird unabhängig vom Prozessvariante 1 oder 2 in der Kreditinstitutsantwort im
|
||||||
|
* Segment HITAN übermittelt.
|
||||||
|
*
|
||||||
|
* Ist der BPD-Parameter „Challenge strukturiert“ mit „J“ belegt, so können im Text folgende
|
||||||
|
* Formatsteuerzeichen enthalten sein, die kundenseitig entsprechend zu interpretieren sind.
|
||||||
|
* Eine Kaskadierung von Steuerzeichen ist nicht erlaubt.
|
||||||
|
*
|
||||||
|
* <br> Zeilenumbruch
|
||||||
|
* <p> Neuer Absatz
|
||||||
|
* <b> ... </b> Fettdruck
|
||||||
|
* <i> ... </i> Kursivdruck
|
||||||
|
* <u> ... </u> Unterstreichen
|
||||||
|
* <ul> ... </ul> Beginn / Ende Aufzählung
|
||||||
|
* <ol> ... </ol> Beginn / Ende Nummerierte Liste
|
||||||
|
* <li> ... </li> Listenelement einer Aufzählung / Nummerierten Liste
|
||||||
|
*/
|
||||||
|
open class ChallengeVersion3(challenge: String, existenzstatus: Existenzstatus)
|
||||||
|
: AlphanumerischesDatenelement(challenge, existenzstatus, 2048)
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Beim Zwei-Schritt-Verfahren werden die notwendigen Prozess-Schritte mittels des Geschäftsvorfalls
|
||||||
|
* HKTAN durchgeführt. Dieser unterstützt flexibel vier unterschiedliche Ausprägungen für die beiden
|
||||||
|
* Prozessvarianten für Zwei-Schritt-Verfahren, wobei die TAN-Prozesse 3 und 4 nicht isoliert und nur
|
||||||
|
* in Verbindung mit TAN-Prozess=2 auftreten können. Der TAN-Prozess wird wie folgt kodiert:
|
||||||
|
*
|
||||||
|
* Codierung:
|
||||||
|
*
|
||||||
|
* Prozessvariante 1:
|
||||||
|
*
|
||||||
|
* TAN-Prozess=1:
|
||||||
|
* Im ersten Schritt wird der Auftrags-Hashwert über den Geschäftsvorfall HKTAN mitgeteilt, im
|
||||||
|
* zweiten Schritt erfolgt nach Ermittlung der TAN aus der zurückgemeldeten Challenge die
|
||||||
|
* Einreichung des eigentlichen Auftrags inklusive der TAN über das normale Auftragssegment.
|
||||||
|
* Abfolge der Segmente am Beispiel HKCCS:
|
||||||
|
* 1. Schritt: HKTAN <-> HITAN
|
||||||
|
* 2. Schritt: HKCCS <-> HIRMS zu HKCCS
|
||||||
|
*
|
||||||
|
* Prozessvariante 2:
|
||||||
|
* Im ersten Schritt wird der Auftrag komplett über das normale Auftragssegment eingereicht,
|
||||||
|
* jedoch ohne Übermittlung der TAN. Im zweiten Schritt erfolgt nach Ermittlung der TAN aus
|
||||||
|
* der zurückgemeldeten Challenge die Einreichung der TAN über den Geschäftsvorfall HKTAN.
|
||||||
|
* Abfolge der Segmente am Beispiel HKCCS:
|
||||||
|
* Schritt 1: HKCCS und HKTAN HITAN
|
||||||
|
* Schritt 2: HKTAN HITAN und HIRMS zu HICCS
|
||||||
|
*
|
||||||
|
* TAN-Prozess=2:
|
||||||
|
* kann nur im zweiten Schritt auftreten. Er dient zur Übermittlung der TAN mittels HKTAN,
|
||||||
|
* nachdem der Auftrag selbst zuvor bereits mit TAN-Prozess=3 oder 4 eingereicht wurde.
|
||||||
|
* Dieser Geschäftsvorfall wird mit HITAN, TAN-Prozess=2 beantwortet.
|
||||||
|
*
|
||||||
|
* TAN-Prozess=3:
|
||||||
|
* kann nur im ersten Schritt bei Mehrfach-TANs für die zweite und ggf. dritte TAN auftreten.
|
||||||
|
* Hierdurch wird die Einreichung eingeleitet, wenn zeitversetzte Einreichung von
|
||||||
|
* Mehrfach-TANs erlaubt ist.
|
||||||
|
*
|
||||||
|
* TAN-Prozess=4:
|
||||||
|
* kann nur im ersten Schritt auftreten. Hiermit wird das Zwei-Schritt-Verfahren nach
|
||||||
|
* Prozessvariante 2 für die erste TAN eingeleitet. HKTAN wird zusammen mit dem Auftragssegment
|
||||||
|
* übertragen und durch HITAN mit TAN-Prozess=4 beantwortet. TAN-Prozess=4 wird auch beim
|
||||||
|
* Geschäftsvorfall „Prüfen / Verbrennen von TANs“ eingesetzt.
|
||||||
|
*/
|
||||||
|
open class TANProzessDatenelement(process: TanProcess) : Code(process.code,
|
||||||
|
AllowedValues, Existenzstatus.Mandatory) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val AllowedValues = allCodes<TanProcess>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||||
|
|
||||||
|
|
||||||
|
enum class TanProcess(override val code: String) : ICodeEnum {
|
||||||
|
|
||||||
|
TanProcess1("1"),
|
||||||
|
|
||||||
|
TanProcess2("2"),
|
||||||
|
|
||||||
|
TanProcess3("3"),
|
||||||
|
|
||||||
|
TanProcess4("4"),
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package net.dankito.fints.messages.datenelementgruppen.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Datum
|
||||||
|
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Uhrzeit
|
||||||
|
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datum und Uhrzeit, bis zu welchem Zeitpunkt eine TAN auf Basis der gesendeten Challenge
|
||||||
|
* gültig ist. Nach Ablauf der Gültigkeitsdauer wird die entsprechende TAN entwertet.
|
||||||
|
*/
|
||||||
|
open class GueltigkeitsdatumUndUhrzeitFuerChallenge(date: Int, time: Int)
|
||||||
|
: Datenelementgruppe(listOf(
|
||||||
|
Datum(date, Existenzstatus.Mandatory),
|
||||||
|
Uhrzeit(time, Existenzstatus.Mandatory)
|
||||||
|
), Existenzstatus.Optional)
|
|
@ -0,0 +1,29 @@
|
||||||
|
package net.dankito.fints.messages.segmente.implementierte
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.NotAllowedDatenelement
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.*
|
||||||
|
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||||
|
import net.dankito.fints.messages.segmente.Segment
|
||||||
|
|
||||||
|
|
||||||
|
open class ZweiSchrittTanEinreichung(
|
||||||
|
segmentNumber: Int,
|
||||||
|
process: TanProcess,
|
||||||
|
jobReference: String,
|
||||||
|
challenge: String = "",
|
||||||
|
challgendHHD_UC: ByteArray = byteArrayOf(),
|
||||||
|
date: Int? = null,
|
||||||
|
time: Int? = null,
|
||||||
|
tanMediaIdentifier: String? = "N" // TODO: why 'N'?
|
||||||
|
|
||||||
|
) : Segment(listOf(
|
||||||
|
Segmentkopf("HKTAN", 6, segmentNumber),
|
||||||
|
TANProzessDatenelement(process),
|
||||||
|
// AuftragsHashwert(), // M: bei AuftragsHashwertverfahren<>0 und TAN-Prozess=1. N: sonst
|
||||||
|
Auftragsreferenz(jobReference, Existenzstatus.Mandatory), // M: bei TAN-Prozess=2, 3, 4. O: bei TAN-Prozess=1
|
||||||
|
ChallengeVersion3(challenge, Existenzstatus.Mandatory), // M: bei TAN-Prozess=1, 3, 4. O: bei TAN-Prozess=2
|
||||||
|
ChallengeHHD_UC(challgendHHD_UC, Existenzstatus.Optional),
|
||||||
|
NotAllowedDatenelement(), // GueltigkeitsdatumUndUhrzeitFuerChallenge // TODO: how to not write an element if it's optional and its paramters (date and time) are not set?
|
||||||
|
BezeichnungDesTANMediums(tanMediaIdentifier ?: "", Existenzstatus.Optional)// M: bei TAN-Prozess=1, 3, 4 und „Anzahl unterstützter aktiver TAN-Medien“ nicht vorhanden. O: sonst
|
||||||
|
), Existenzstatus.Mandatory)
|
|
@ -78,13 +78,14 @@ class MessageBuilderTest {
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(normalizeBinaryData(result)).isEqualTo(normalizeBinaryData(
|
assertThat(normalizeBinaryData(result)).isEqualTo(normalizeBinaryData(
|
||||||
"HNHBK:1:3+000000000363+300+0+1'" +
|
"HNHBK:1:3+000000000386+300+0+1'" +
|
||||||
"HNVSK:998:3+PIN:2+998+1+1::0+1:$Date:$Time+2:16:14:@8@ :5:1+280:$BankCode:$CustomerId:V:0:0+0+'" +
|
"HNVSK:998:3+PIN:2+998+1+1::0+1:$Date:$Time+2:16:14:@8@ :5:1+280:$BankCode:$CustomerId:V:0:0+0+'" +
|
||||||
"HNVSD:999:1+@198@" + "HNSHK:2:4+PIN:2+${SecurityFunction.code}+$ControlReference+1+1+1::0+1+1:$Date:$Time+1:999:1+6:10:16+280:$BankCode:$CustomerId:S:0:0'" +
|
"HNVSD:999:1+@221@" + "HNSHK:2:4+PIN:2+${SecurityFunction.code}+$ControlReference+1+1+1::0+1+1:$Date:$Time+1:999:1+6:10:16+280:$BankCode:$CustomerId:S:0:0'" +
|
||||||
"HKIDN:3:2+280:$BankCode+$CustomerId+0+1'" +
|
"HKIDN:3:2+280:$BankCode+$CustomerId+0+1'" +
|
||||||
"HKVVB:4:3+0+0+${Language.code}+$ProductName+$ProductVersion'" +
|
"HKVVB:4:3+0+0+${Language.code}+$ProductName+$ProductVersion'" +
|
||||||
"HNSHA:5:2+$ControlReference++$Pin''" +
|
"HKTAN:5:6+4+HKIDN++++N'" +
|
||||||
"HNHBS:6:1+1'"
|
"HNSHA:6:2+$ControlReference++$Pin''" +
|
||||||
|
"HNHBS:7:1+1'"
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue