Implemented reading user's tan media list
This commit is contained in:
parent
677f360855
commit
553b55e090
|
@ -6,12 +6,15 @@ import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID
|
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
||||||
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.TanMedienArtVersion
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasseVersion
|
||||||
import net.dankito.fints.model.*
|
import net.dankito.fints.model.*
|
||||||
import net.dankito.fints.response.InstituteSegmentId
|
import net.dankito.fints.response.InstituteSegmentId
|
||||||
import net.dankito.fints.response.Response
|
import net.dankito.fints.response.Response
|
||||||
import net.dankito.fints.response.ResponseParser
|
import net.dankito.fints.response.ResponseParser
|
||||||
import net.dankito.fints.response.client.AddAccountResponse
|
import net.dankito.fints.response.client.AddAccountResponse
|
||||||
import net.dankito.fints.response.client.FinTsClientResponse
|
import net.dankito.fints.response.client.FinTsClientResponse
|
||||||
|
import net.dankito.fints.response.client.GetTanMediaListResponse
|
||||||
import net.dankito.fints.response.client.GetTransactionsResponse
|
import net.dankito.fints.response.client.GetTransactionsResponse
|
||||||
import net.dankito.fints.response.segments.*
|
import net.dankito.fints.response.segments.*
|
||||||
import net.dankito.fints.util.IBase64Service
|
import net.dankito.fints.util.IBase64Service
|
||||||
|
@ -300,6 +303,42 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open fun getTanMediaListAsync(bank: BankData, customer: CustomerData,
|
||||||
|
tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle,
|
||||||
|
tanMediumClass: TanMediumKlasseVersion = TanMediumKlasseVersion.AlleMedien,
|
||||||
|
callback: (GetTanMediaListResponse) -> Unit) {
|
||||||
|
|
||||||
|
threadPool.runAsync {
|
||||||
|
callback(getTanMediaList(bank, customer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getTanMediaList(bank: BankData, customer: CustomerData, tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle,
|
||||||
|
tanMediumClass: TanMediumKlasseVersion = TanMediumKlasseVersion.AlleMedien): GetTanMediaListResponse {
|
||||||
|
|
||||||
|
val dialogData = DialogData()
|
||||||
|
|
||||||
|
val initDialogResponse = initDialog(bank, customer, dialogData)
|
||||||
|
|
||||||
|
if (initDialogResponse.successful == false) {
|
||||||
|
return GetTanMediaListResponse(initDialogResponse, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dialogData.increaseMessageNumber()
|
||||||
|
|
||||||
|
val message = messageBuilder.createGetTanMediaListMessage(bank, customer, dialogData, tanMediaKind, tanMediumClass)
|
||||||
|
|
||||||
|
val response = getAndHandleResponseForMessageThatMayRequiresTan(message, bank, customer, dialogData)
|
||||||
|
|
||||||
|
closeDialog(bank, customer, dialogData)
|
||||||
|
|
||||||
|
val tanMediaList = response.getFirstSegmentById<TanMediaList>(InstituteSegmentId.TanMediaList)
|
||||||
|
|
||||||
|
return GetTanMediaListResponse(response, tanMediaList)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData,
|
open fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData,
|
||||||
customer: CustomerData, callback: (FinTsClientResponse) -> Unit) {
|
customer: CustomerData, callback: (FinTsClientResponse) -> Unit) {
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package net.dankito.fints.messages
|
||||||
import net.dankito.fints.extensions.containsAny
|
import net.dankito.fints.extensions.containsAny
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.Aufsetzpunkt
|
import net.dankito.fints.messages.datenelemente.implementierte.Aufsetzpunkt
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.Synchronisierungsmodus
|
import net.dankito.fints.messages.datenelemente.implementierte.Synchronisierungsmodus
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasseVersion
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanProcess
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanProcess
|
||||||
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
|
||||||
|
@ -11,6 +13,7 @@ import net.dankito.fints.messages.segmente.Synchronisierung
|
||||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||||
import net.dankito.fints.messages.segmente.implementierte.*
|
import net.dankito.fints.messages.segmente.implementierte.*
|
||||||
import net.dankito.fints.messages.segmente.implementierte.sepa.SepaEinzelueberweisung
|
import net.dankito.fints.messages.segmente.implementierte.sepa.SepaEinzelueberweisung
|
||||||
|
import net.dankito.fints.messages.segmente.implementierte.tan.TanGeneratorListeAnzeigen
|
||||||
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version5
|
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version5
|
||||||
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version6
|
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version6
|
||||||
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version7
|
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version7
|
||||||
|
@ -136,6 +139,24 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open fun createGetTanMediaListMessage(bank: BankData, customer: CustomerData, dialogData: DialogData,
|
||||||
|
tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle,
|
||||||
|
tanMediumClass: TanMediumKlasseVersion = TanMediumKlasseVersion.AlleMedien): MessageBuilderResult {
|
||||||
|
|
||||||
|
val result = getSupportedVersionsOfJob(CustomerSegmentId.TanMediaList, customer, listOf(2, 3, 4, 5))
|
||||||
|
|
||||||
|
if (result.isJobVersionSupported) {
|
||||||
|
val segments = listOf(
|
||||||
|
TanGeneratorListeAnzeigen(result.getHighestAllowedVersion!!,
|
||||||
|
generator.resetSegmentNumber(2), tanMediaKind, tanMediumClass)
|
||||||
|
)
|
||||||
|
|
||||||
|
return createMessageBuilderResult(bank, customer, dialogData, segments)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
open fun createSendEnteredTanMessage(enteredTan: String, tanResponse: TanResponse, bank: BankData, customer: CustomerData, dialogData: DialogData): String {
|
open fun createSendEnteredTanMessage(enteredTan: String, tanResponse: TanResponse, bank: BankData, customer: CustomerData, dialogData: DialogData): String {
|
||||||
|
|
||||||
val tanProcess = if (tanResponse.tanProcess == TanProcess.TanProcess1) TanProcess.TanProcess1 else TanProcess.TanProcess2
|
val tanProcess = if (tanResponse.tanProcess == TanProcess.TanProcess1) TanProcess.TanProcess1 else TanProcess.TanProcess2
|
||||||
|
|
|
@ -22,4 +22,7 @@ open class MessageBuilderResult(
|
||||||
return allowedVersions.contains(version)
|
return allowedVersions.contains(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open val getHighestAllowedVersion: Int?
|
||||||
|
get() = allowedVersions.max()
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Es werden die Möglichkeiten festgelegt, die ein Kunde hat, wenn er für
|
||||||
|
* PIN/TAN parallel mehrere TAN-Medien zur Verfügung hat.
|
||||||
|
*/
|
||||||
|
enum class TanEinsatzOption(override val code: String) : ICodeEnum {
|
||||||
|
|
||||||
|
KundeKannAlleAktivenMedienParallelNutzen("0"),
|
||||||
|
|
||||||
|
KundeKannGenauEinMediumZuEinerZeitNutzen("1"),
|
||||||
|
|
||||||
|
KundeKannEinMobiltelefonUndEinenTanGeneratorParallelNutzen("2")
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class TanGeneratorTanMedium(
|
||||||
|
mediumClass: TanMediumKlasseVersion,
|
||||||
|
status: TanMediumStatus,
|
||||||
|
val cardNumber: String,
|
||||||
|
val followUpCardNumber: String?,
|
||||||
|
val cardType: String?,
|
||||||
|
val validFrom: Date?,
|
||||||
|
val validTo: Date?,
|
||||||
|
val mediaName: String?
|
||||||
|
) : TanMedium(mediumClass, status) {
|
||||||
|
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
if (!super.equals(other)) return false
|
||||||
|
|
||||||
|
other as TanGeneratorTanMedium
|
||||||
|
|
||||||
|
if (cardNumber != other.cardNumber) return false
|
||||||
|
if (followUpCardNumber != other.followUpCardNumber) return false
|
||||||
|
if (cardType != other.cardType) return false
|
||||||
|
if (validFrom != other.validFrom) return false
|
||||||
|
if (validTo != other.validTo) return false
|
||||||
|
if (mediaName != other.mediaName) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + cardNumber.hashCode()
|
||||||
|
result = 31 * result + followUpCardNumber.hashCode()
|
||||||
|
result = 31 * result + (cardType?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (validFrom?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (validTo?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (mediaName?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return super.toString() + " $mediaName $cardNumber (follow up: ${followUpCardNumber ?: "-"})"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dient der Klassifizierung der gesamten dem Kunden zugeordneten TAN-Medien. Bei
|
||||||
|
* Geschäftsvorfällen zum Management des TAN-Generators kann aus diesen nach folgender
|
||||||
|
* Codierung selektiert werden.
|
||||||
|
*/
|
||||||
|
enum class TanMedienArtVersion(override val code: String) : ICodeEnum {
|
||||||
|
|
||||||
|
Alle("0"),
|
||||||
|
|
||||||
|
Aktiv("1"),
|
||||||
|
|
||||||
|
Verfuegbar("2")
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informationen zu Art und Parametrisierung von TAN-Medien. Als TAN-Medien werden sowohl
|
||||||
|
* TAN-Listen als auch DK-TAN-Generatoren / Karten oder Mobiltelefone sowie bilateral
|
||||||
|
* vereinbarte Medien bezeichnet.
|
||||||
|
*
|
||||||
|
* Wird das Datenelement „TAN-Medium-Klasse“ mit „B“ (bilateral vereinbart) belegt, so muss im Element „Sicherheitsfunktion, kodiert“ die entsprechende Sicherheitsfunktion in der DEG „Verfahrensparameter Zwei-Schritt-Verfahren“ referenziert werden.
|
||||||
|
*/
|
||||||
|
open class TanMedium(
|
||||||
|
val mediumClass: TanMediumKlasseVersion,
|
||||||
|
val status: TanMediumStatus
|
||||||
|
) {
|
||||||
|
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as TanMedium
|
||||||
|
|
||||||
|
if (mediumClass != other.mediumClass) return false
|
||||||
|
if (status != other.status) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = mediumClass.hashCode()
|
||||||
|
result = 31 * result + status.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "$mediumClass $status"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dient der Klassifizierung der möglichen TAN-Medien. Bei Geschäftsvorfällen zum
|
||||||
|
* Management der TAN-Medien kann aus diesen nach folgender Codierung selektiert werden.
|
||||||
|
*/
|
||||||
|
enum class TanMediumKlasseVersion(override val code: String, val supportedHkTabVersions: List<Int>) : ICodeEnum {
|
||||||
|
|
||||||
|
AlleMedien("A", listOf(4, 5)),
|
||||||
|
|
||||||
|
Liste("L", listOf(1, 2, 3, 4, 5)),
|
||||||
|
|
||||||
|
TanGenerator("G", listOf(1, 2, 3, 4, 5)),
|
||||||
|
|
||||||
|
MobiltelefonMitMobileTan("M", listOf(2, 3, 4, 5)),
|
||||||
|
|
||||||
|
Secoder("S", listOf(3, 4, 5)),
|
||||||
|
|
||||||
|
BilateralVereinbart("B", listOf(5))
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package net.dankito.fints.messages.datenelemente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt an, in welchem Status sich ein TAN-Medium befindet.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum class TanMediumStatus(override val code: String) : ICodeEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Bank zeigt an, dass es eine TAN-Verifikation gegen dieses Medium vornimmt.
|
||||||
|
*/
|
||||||
|
Aktiv("1"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Das Medium kann genutzt werden, muss aber zuvor mit „TAN-Generator an- bzw. ummelden (HKTAU)“ aktiv gemeldet werden.
|
||||||
|
*/
|
||||||
|
Verfuegbar("2"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mit der ersten Nutzung der Folgekarte wird die zur Zeit aktive Karte gesperrt.
|
||||||
|
*/
|
||||||
|
AktivFolgekarte("3"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Das Medium kann mit dem Geschäftsvorfall „TAN-Medium an- bzw. ummelden (HKTAU)“ aktiv gemeldet werden.
|
||||||
|
* Die aktuelle Karte kann dann nicht mehr genutzt werden.
|
||||||
|
*/
|
||||||
|
VerfuegbarFolgekarte("4")
|
||||||
|
|
||||||
|
}
|
|
@ -13,6 +13,8 @@ enum class CustomerSegmentId(override val id: String) : ISegmentId {
|
||||||
|
|
||||||
Tan("HKTAN"),
|
Tan("HKTAN"),
|
||||||
|
|
||||||
|
TanMediaList("HKTAB"),
|
||||||
|
|
||||||
Balance("HKSAL"),
|
Balance("HKSAL"),
|
||||||
|
|
||||||
AccountTransactionsMt940("HKKAZ"),
|
AccountTransactionsMt940("HKKAZ"),
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package net.dankito.fints.messages.segmente.implementierte.tan
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.Existenzstatus
|
||||||
|
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasseVersion
|
||||||
|
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||||
|
import net.dankito.fints.messages.segmente.Segment
|
||||||
|
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||||
|
|
||||||
|
|
||||||
|
open class TanGeneratorListeAnzeigen(
|
||||||
|
segmentVersion: Int,
|
||||||
|
segmentNumber: Int,
|
||||||
|
tanMediaKind: TanMedienArtVersion = TanMedienArtVersion.Alle,
|
||||||
|
tanMediumClass: TanMediumKlasseVersion = TanMediumKlasseVersion.AlleMedien
|
||||||
|
)
|
||||||
|
: Segment(listOf(
|
||||||
|
Segmentkopf(CustomerSegmentId.TanMediaList, segmentVersion, segmentNumber),
|
||||||
|
Code(tanMediaKind, allCodes<TanMedienArtVersion>(), Existenzstatus.Mandatory),
|
||||||
|
Code(tanMediumClass, allCodes<TanMediumKlasseVersion>(), Existenzstatus.Mandatory)
|
||||||
|
)) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
val supportedMediaClasses = TanMediumKlasseVersion.values().filter { it.supportedHkTabVersions.contains(segmentVersion) }
|
||||||
|
|
||||||
|
if (supportedMediaClasses.contains(tanMediumClass) == false) {
|
||||||
|
throw UnsupportedOperationException("Value $tanMediumClass for TAN medium class is not valid for HKTAB version $segmentVersion. " +
|
||||||
|
"Supported values are: " + TanMediumKlasseVersion.values().filter { it.supportedHkTabVersions.contains(segmentVersion) }.map { it.code })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,8 @@ enum class InstituteSegmentId(override val id: String) : ISegmentId {
|
||||||
|
|
||||||
Tan("HITAN"),
|
Tan("HITAN"),
|
||||||
|
|
||||||
|
TanMediaList("HITAB"),
|
||||||
|
|
||||||
Balance("HISAL"),
|
Balance("HISAL"),
|
||||||
|
|
||||||
AccountTransactionsMt940("HIKAZ")
|
AccountTransactionsMt940("HIKAZ")
|
||||||
|
|
|
@ -93,6 +93,7 @@ open class ResponseParser @JvmOverloads constructor(
|
||||||
|
|
||||||
InstituteSegmentId.TanInfo.id -> parseTanInfo(segment, segmentId, dataElementGroups)
|
InstituteSegmentId.TanInfo.id -> parseTanInfo(segment, segmentId, dataElementGroups)
|
||||||
InstituteSegmentId.Tan.id -> parseTanResponse(segment, dataElementGroups)
|
InstituteSegmentId.Tan.id -> parseTanResponse(segment, dataElementGroups)
|
||||||
|
InstituteSegmentId.TanMediaList.id -> parseTanMediaList(segment, dataElementGroups)
|
||||||
|
|
||||||
InstituteSegmentId.Balance.id -> parseBalanceSegment(segment, dataElementGroups)
|
InstituteSegmentId.Balance.id -> parseBalanceSegment(segment, dataElementGroups)
|
||||||
InstituteSegmentId.AccountTransactionsMt940.id -> parseMt940AccountTransactions(segment, dataElementGroups)
|
InstituteSegmentId.AccountTransactionsMt940.id -> parseMt940AccountTransactions(segment, dataElementGroups)
|
||||||
|
@ -395,6 +396,52 @@ open class ResponseParser @JvmOverloads constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun parseTanMediaList(segment: String, dataElementGroups: List<String>): TanMediaList {
|
||||||
|
val usageOption = parseCodeEnum(dataElementGroups[1], TanEinsatzOption.values())
|
||||||
|
val segmentVersion = parseInt(getDataElements(dataElementGroups[0])[2])
|
||||||
|
|
||||||
|
return TanMediaList(usageOption,
|
||||||
|
parseTanMedia(segmentVersion, dataElementGroups.subList(2, dataElementGroups.size)),
|
||||||
|
segment)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun parseTanMedia(hitabVersion: Int, dataElementGroups: List<String>): List<TanMedium> {
|
||||||
|
return dataElementGroups.map { getDataElements(it) }.map { parseTanMedium(hitabVersion, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun parseTanMedium(hitabVersion: Int, dataElements: List<String>): TanMedium {
|
||||||
|
val mediumClassCode = dataElements[0]
|
||||||
|
val mediumClass = parseCodeEnum(mediumClassCode, TanMediumKlasseVersion.values())
|
||||||
|
if (mediumClass.supportedHkTabVersions.contains(hitabVersion) == false) {
|
||||||
|
throw UnsupportedOperationException("$mediumClassCode is not a valid medium class for HITAB version $hitabVersion. " +
|
||||||
|
"Supported values are: " + TanMediumKlasseVersion.values().filter { it.supportedHkTabVersions.contains(hitabVersion) }.map { it.code })
|
||||||
|
}
|
||||||
|
|
||||||
|
val status = parseCodeEnum(dataElements[1], TanMediumStatus.values())
|
||||||
|
|
||||||
|
// TODO: may also parse 'Letzte Benutzung' (second last element) and 'Freigeschaltet am' (last element)
|
||||||
|
|
||||||
|
val remainingDataElements = dataElements.subList(2, dataElements.size - 2)
|
||||||
|
|
||||||
|
return when (mediumClass) {
|
||||||
|
TanMediumKlasseVersion.TanGenerator -> parseTanGeneratorTanMedium(mediumClass, status, hitabVersion, remainingDataElements)
|
||||||
|
else -> TanMedium(mediumClass, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun parseTanGeneratorTanMedium(mediumClass: TanMediumKlasseVersion, status: TanMediumStatus,
|
||||||
|
hitabVersion: Int, dataElements: List<String>): TanGeneratorTanMedium {
|
||||||
|
|
||||||
|
val cardType = if (hitabVersion < 2) null else parseStringToNullIfEmpty(dataElements[2]) // TODO: may parse to number
|
||||||
|
// TODO: may also parse account info
|
||||||
|
val validFrom = if (hitabVersion < 2) null else parseNullableDate(dataElements[8])
|
||||||
|
val validTo = if (hitabVersion < 2) null else parseNullableDate(dataElements[9])
|
||||||
|
val mediaName = if (hitabVersion < 2) null else parseStringToNullIfEmpty(dataElements[10])
|
||||||
|
|
||||||
|
return TanGeneratorTanMedium(mediumClass, status, parseString(dataElements[0]), parseStringToNullIfEmpty(dataElements[1]),
|
||||||
|
cardType, validFrom, validTo, mediaName)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun parseBalanceSegment(segment: String, dataElementGroups: List<String>): BalanceSegment {
|
protected open fun parseBalanceSegment(segment: String, dataElementGroups: List<String>): BalanceSegment {
|
||||||
// dataElementGroups[1] is account details
|
// dataElementGroups[1] is account details
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package net.dankito.fints.response.client
|
||||||
|
|
||||||
|
import net.dankito.fints.response.Response
|
||||||
|
import net.dankito.fints.response.segments.TanMediaList
|
||||||
|
|
||||||
|
|
||||||
|
open class GetTanMediaListResponse(
|
||||||
|
response: Response,
|
||||||
|
val tanMediaList: TanMediaList?
|
||||||
|
)
|
||||||
|
: FinTsClientResponse(response)
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.dankito.fints.response.segments
|
||||||
|
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanEinsatzOption
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedium
|
||||||
|
|
||||||
|
|
||||||
|
open class TanMediaList(
|
||||||
|
val usageOption: TanEinsatzOption,
|
||||||
|
val tanMedia: List<TanMedium>,
|
||||||
|
segmentString: String
|
||||||
|
)
|
||||||
|
: ReceivedSegment(segmentString)
|
|
@ -5,6 +5,9 @@ import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Laenderkennze
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
|
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatus
|
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatus
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanEinsatzOption
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
|
||||||
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasseVersion
|
||||||
import net.dankito.fints.model.*
|
import net.dankito.fints.model.*
|
||||||
import net.dankito.fints.model.mapper.BankDataMapper
|
import net.dankito.fints.model.mapper.BankDataMapper
|
||||||
import net.dankito.fints.response.client.FinTsClientResponse
|
import net.dankito.fints.response.client.FinTsClientResponse
|
||||||
|
@ -132,6 +135,34 @@ class FinTsClientTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getTanMediaList() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = underTest.getTanMediaList(Bank, Customer, TanMedienArtVersion.Alle, TanMediumKlasseVersion.AlleMedien)
|
||||||
|
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.isSuccessful).isTrue()
|
||||||
|
|
||||||
|
assertThat(result.tanMediaList).isNotNull()
|
||||||
|
assertThat(result.tanMediaList!!.usageOption).isEqualByComparingTo(TanEinsatzOption.KundeKannGenauEinMediumZuEinerZeitNutzen) // TODO: may adjust to your value
|
||||||
|
assertThat(result.tanMediaList!!.tanMedia).isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ignore // only works with banks that don't support HKTAB version 5
|
||||||
|
@Test(expected = UnsupportedOperationException::class)
|
||||||
|
fun getTanMediaList_UnsupportedTanMediumClass() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
underTest.getTanMediaList(Bank, Customer, TanMedienArtVersion.Alle, TanMediumKlasseVersion.BilateralVereinbart)
|
||||||
|
|
||||||
|
|
||||||
|
// then
|
||||||
|
// exception gets thrown
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBankTransfer() {
|
fun testBankTransfer() {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
|
||||||
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.signatur.Sicherheitsverfahren
|
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsverfahren
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
|
import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
|
||||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanProcess
|
import net.dankito.fints.messages.datenelemente.implementierte.tan.*
|
||||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil
|
import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil
|
||||||
import net.dankito.fints.messages.segmente.id.ISegmentId
|
import net.dankito.fints.messages.segmente.id.ISegmentId
|
||||||
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
||||||
|
@ -683,6 +683,33 @@ class ResponseParserTest : FinTsTestBase() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseTanMediaListResponse() {
|
||||||
|
|
||||||
|
// given
|
||||||
|
val oldCardNumber = "5109972878"
|
||||||
|
val followUpCardNumber = "5200310149"
|
||||||
|
val mediaName = "EC-Card (Debitkarte)"
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = underTest.parse("HITAB:5:4:3+1+G:3:$oldCardNumber:$followUpCardNumber:::::::::$mediaName::::::::+G:2:$followUpCardNumber::::::::::$mediaName::::::::'")
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertSuccessfullyParsedSegment(result, InstituteSegmentId.TanMediaList, 5, 4, 3)
|
||||||
|
|
||||||
|
assertThat(result.isStrongAuthenticationRequired).isFalse()
|
||||||
|
|
||||||
|
result.getFirstSegmentById<TanMediaList>(InstituteSegmentId.TanMediaList)?.let { segment ->
|
||||||
|
assertThat(segment.usageOption).isEqualTo(TanEinsatzOption.KundeKannGenauEinMediumZuEinerZeitNutzen)
|
||||||
|
assertThat(segment.tanMedia).containsOnly(
|
||||||
|
TanGeneratorTanMedium(TanMediumKlasseVersion.TanGenerator, TanMediumStatus.AktivFolgekarte, oldCardNumber, followUpCardNumber, null, null, null, mediaName),
|
||||||
|
TanGeneratorTanMedium(TanMediumKlasseVersion.TanGenerator, TanMediumStatus.Verfuegbar, followUpCardNumber, null, null, null, null, mediaName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
?: run { Assert.fail("No segment of type TanMediaList found in ${result.receivedSegments}") }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseBalance() {
|
fun parseBalance() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue