Made TanMedium serializable

This commit is contained in:
dankito 2024-10-10 02:24:04 +02:00
parent 8346fb5077
commit 2a3b962af5
14 changed files with 63 additions and 69 deletions

View File

@ -135,7 +135,7 @@ open class FinTsClientDeprecated(
}
open suspend fun changeTanMedium(newActiveTanMedium: TanGeneratorTanMedium, bank: BankData): FinTsClientResponse {
open suspend fun changeTanMedium(newActiveTanMedium: TanMedium, bank: BankData): FinTsClientResponse {
val context = JobContext(JobContextType.ChangeTanMedium, this.callback, config, bank)
val response = config.jobExecutor.changeTanMedium(context, newActiveTanMedium)

View File

@ -341,7 +341,7 @@ open class FinTsJobExecutor(
}
open suspend fun changeTanMedium(context: JobContext, newActiveTanMedium: TanGeneratorTanMedium): BankResponse {
open suspend fun changeTanMedium(context: JobContext, newActiveTanMedium: TanMedium): BankResponse {
val bank = context.bank
if (bank.changeTanMediumParameters?.enteringAtcAndTanRequired == true) {
@ -358,7 +358,7 @@ open class FinTsJobExecutor(
}
}
protected open suspend fun sendChangeTanMediumMessage(context: JobContext, newActiveTanMedium: TanGeneratorTanMedium, enteredAtc: EnterTanGeneratorAtcResult?): BankResponse {
protected open suspend fun sendChangeTanMediumMessage(context: JobContext, newActiveTanMedium: TanMedium, enteredAtc: EnterTanGeneratorAtcResult?): BankResponse {
return sendMessageInNewDialogAndHandleResponse(context, null, true) {
messageBuilder.createChangeTanMediumMessage(context, newActiveTanMedium, enteredAtc?.tan, enteredAtc?.atc)
@ -527,7 +527,7 @@ Log.info { "Terminating waiting for TAN input" } // TODO: remove again
if (enteredTanResult.changeTanMethodTo != null) {
return handleUserAsksToChangeTanMethodAndResendLastMessage(context, enteredTanResult.changeTanMethodTo)
} else if (enteredTanResult.changeTanMediumTo is TanGeneratorTanMedium) {
} else if (enteredTanResult.changeTanMediumTo != null) {
return handleUserAsksToChangeTanMediumAndResendLastMessage(context, enteredTanResult.changeTanMediumTo,
enteredTanResult.changeTanMediumResultCallback)
} else if (enteredTanResult.userApprovedDecoupledTan == true && enteredTanResult.responseAfterApprovingDecoupledTan != null) {
@ -562,7 +562,7 @@ Log.info { "Terminating waiting for TAN input" } // TODO: remove again
return resendMessageInNewDialog(context, lastCreatedMessage)
}
protected open suspend fun handleUserAsksToChangeTanMediumAndResendLastMessage(context: JobContext, changeTanMediumTo: TanGeneratorTanMedium,
protected open suspend fun handleUserAsksToChangeTanMediumAndResendLastMessage(context: JobContext, changeTanMediumTo: TanMedium,
changeTanMediumResultCallback: ((FinTsClientResponse) -> Unit)?): BankResponse {
val lastCreatedMessage = context.dialog.currentMessage

View File

@ -1,6 +1,6 @@
package net.codinux.banking.fints.callback
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedium
import net.codinux.banking.fints.model.*
@ -25,7 +25,7 @@ interface FinTsClientCallback {
*
* If you do not support entering TAN generator ATC, return [EnterTanGeneratorAtcResult.userDidNotEnterAtc]
*/
suspend fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult
suspend fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanMedium): EnterTanGeneratorAtcResult
/**
* Gets fired when a FinTS message get sent to bank server, a FinTS message is received from bank server or an error occurred.

View File

@ -1,6 +1,6 @@
package net.codinux.banking.fints.callback
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedium
import net.codinux.banking.fints.model.*
@ -14,7 +14,7 @@ open class NoOpFinTsClientCallback : FinTsClientCallback {
return tanChallenge.userDidNotEnterTan()
}
override suspend fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
override suspend fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanMedium): EnterTanGeneratorAtcResult {
return EnterTanGeneratorAtcResult.userDidNotEnterAtc()
}

View File

@ -1,13 +1,13 @@
package net.codinux.banking.fints.callback
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedium
import net.codinux.banking.fints.model.*
open class SimpleFinTsClientCallback(
protected open val askUserForTanMethod: ((supportedTanMethods: List<TanMethod>, suggestedTanMethod: TanMethod?) -> TanMethod?)? = null,
protected open val messageLogAdded: ((MessageLogEntry) -> Unit)? = null,
protected open val enterTanGeneratorAtc: ((bank: BankData, tanMedium: TanGeneratorTanMedium) -> EnterTanGeneratorAtcResult)? = null,
protected open val enterTanGeneratorAtc: ((bank: BankData, tanMedium: TanMedium) -> EnterTanGeneratorAtcResult)? = null,
protected open val enterTan: ((tanChallenge: TanChallenge) -> Unit)? = null
) : FinTsClientCallback {
@ -25,7 +25,7 @@ open class SimpleFinTsClientCallback(
enterTan?.invoke(tanChallenge) ?: run { tanChallenge.userDidNotEnterTan() }
}
override suspend fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
override suspend fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanMedium): EnterTanGeneratorAtcResult {
return enterTanGeneratorAtc?.invoke(bank, tanMedium) ?: EnterTanGeneratorAtcResult.userDidNotEnterAtc()
}

View File

@ -4,10 +4,7 @@ import net.codinux.banking.fints.extensions.randomWithSeed
import net.codinux.banking.fints.messages.datenelemente.implementierte.Aufsetzpunkt
import net.codinux.banking.fints.messages.datenelemente.implementierte.KundensystemID
import net.codinux.banking.fints.messages.datenelemente.implementierte.Synchronisierungsmodus
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanProcess
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.*
import net.codinux.banking.fints.messages.segmente.Segment
import net.codinux.banking.fints.messages.segmente.Synchronisierung
import net.codinux.banking.fints.messages.segmente.id.CustomerSegmentId
@ -294,7 +291,7 @@ open class MessageBuilder(protected val utils: FinTsUtils = FinTsUtils()) {
}
// TODO: no HKTAN needed?
open fun createChangeTanMediumMessage(context: JobContext, newActiveTanMedium: TanGeneratorTanMedium,
open fun createChangeTanMediumMessage(context: JobContext, newActiveTanMedium: TanMedium,
tan: String? = null, atc: Int? = null): MessageBuilderResult {
val result = getSupportedVersionsOfJobForBank(CustomerSegmentId.ChangeTanMedium, context.bank, listOf(1, 2, 3))

View File

@ -1,22 +1,18 @@
package net.codinux.banking.fints.messages.datenelemente.implementierte.tan
import net.codinux.banking.fints.messages.datenelementgruppen.implementierte.account.KontoverbindungInternational
import kotlinx.serialization.Serializable
import net.dankito.banking.client.model.BankAccountIdentifier
@Serializable
open class MobilePhoneTanMedium(
mediumClass: TanMediumKlasse,
status: TanMediumStatus,
override val mediumName: String,
val concealedPhoneNumber: String?,
val phoneNumber: String?,
val smsDebitAccount: KontoverbindungInternational? = null
) : TanMedium(mediumClass, status, mediumName) {
val smsDebitAccount: BankAccountIdentifier? = null
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is MobilePhoneTanMedium) return false
if (!super.equals(other)) return false
if (concealedPhoneNumber != other.concealedPhoneNumber) return false
if (phoneNumber != other.phoneNumber) return false
@ -26,8 +22,7 @@ open class MobilePhoneTanMedium(
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + concealedPhoneNumber.hashCode()
var result = concealedPhoneNumber.hashCode()
result = 31 * result + phoneNumber.hashCode()
result = 31 * result + smsDebitAccount.hashCode()
return result
@ -35,7 +30,7 @@ open class MobilePhoneTanMedium(
override fun toString(): String {
return super.toString() + " $mediumName ${phoneNumber ?: concealedPhoneNumber ?: ""}"
return phoneNumber ?: concealedPhoneNumber ?: ""
}
}

View File

@ -1,24 +1,21 @@
package net.codinux.banking.fints.messages.datenelemente.implementierte.tan
import kotlinx.datetime.LocalDate
import kotlinx.serialization.Serializable
@Serializable
open class TanGeneratorTanMedium(
mediumClass: TanMediumKlasse,
status: TanMediumStatus,
val cardNumber: String,
val cardSequenceNumber: String?,
val cardType: Int?,
val validFrom: LocalDate?,
val validTo: LocalDate?,
mediumName: String?
) : TanMedium(mediumClass, status, mediumName) {
val validTo: LocalDate?
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
if (!super.equals(other)) return false
other as TanGeneratorTanMedium
@ -32,8 +29,7 @@ open class TanGeneratorTanMedium(
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + cardNumber.hashCode()
var result = cardNumber.hashCode()
result = 31 * result + cardSequenceNumber.hashCode()
result = 31 * result + cardType.hashCode()
result = 31 * result + validFrom.hashCode()
@ -43,7 +39,7 @@ open class TanGeneratorTanMedium(
override fun toString(): String {
return super.toString() + " $mediumName $cardNumber (card sequence number: ${cardSequenceNumber ?: "-"})"
return "$cardNumber (card sequence number: ${cardSequenceNumber ?: "-"})"
}
}

View File

@ -14,7 +14,9 @@ import kotlinx.serialization.Serializable
open class TanMedium(
open val mediumClass: TanMediumKlasse,
open val status: TanMediumStatus,
open val mediumName: String?
open val mediumName: String?,
open val tanGenerator: TanGeneratorTanMedium? = null,
open val mobilePhone: MobilePhoneTanMedium? = null
) {
@ -30,6 +32,8 @@ open class TanMedium(
if (mediumClass != other.mediumClass) return false
if (status != other.status) return false
if (mediumName != other.mediumName) return false
if (tanGenerator != other.tanGenerator) return false
if (mobilePhone != other.mobilePhone) return false
return true
}
@ -38,6 +42,8 @@ open class TanMedium(
var result = mediumClass.hashCode()
result = 31 * result + status.hashCode()
result = 31 * result + mediumName.hashCode()
result = 31 * result + tanGenerator.hashCode()
result = 31 * result + mobilePhone.hashCode()
return result
}

View File

@ -8,7 +8,7 @@ import net.codinux.banking.fints.messages.datenelemente.basisformate.Numerisches
import net.codinux.banking.fints.messages.datenelemente.implementierte.DoNotPrintDatenelement
import net.codinux.banking.fints.messages.datenelemente.implementierte.NotAllowedDatenelement
import net.codinux.banking.fints.messages.datenelemente.implementierte.allCodes
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
import net.codinux.banking.fints.messages.datenelementgruppen.implementierte.Segmentkopf
import net.codinux.banking.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
@ -34,13 +34,13 @@ import net.codinux.banking.fints.response.segments.ChangeTanMediaParameters
* chipTAN-Verfahren:
* Steht beim chipTAN-Verfahren ein Kartenwechsel an, so kann der Kunde mit diesem Geschäftsvorfall seine Karte bzw.
* Folgekarte aktivieren. Kann der Kunde mehrere Karten verwenden, dann kann mit diesem GV die Ummeldung auf eine
* andere Karte erfolgen. Das Kreditinstitut entscheidet selbst, ob dieser GV TAN-pflichtig istoder nicht.
* andere Karte erfolgen. Das Kreditinstitut entscheidet selbst, ob dieser GV TAN-pflichtig ist oder nicht.
*/
open class TanGeneratorTanMediumAnOderUmmelden(
segmentVersion: Int,
segmentNumber: Int,
bank: BankData,
newActiveTanMedium: TanGeneratorTanMedium,
newActiveTanMedium: TanMedium,
/**
* Has to be set if Eingabe von ATC und TAN erforderlich (BPD)=J
*/
@ -57,17 +57,17 @@ open class TanGeneratorTanMediumAnOderUmmelden(
)
: Segment(listOf(
Segmentkopf(CustomerSegmentId.ChangeTanMedium, segmentVersion, segmentNumber),
Code(TanMediumKlasse.TanGenerator, allCodes<TanMediumKlasse>(), Existenzstatus.Mandatory),
AlphanumerischesDatenelement(newActiveTanMedium.cardNumber, Existenzstatus.Mandatory),
AlphanumerischesDatenelement(newActiveTanMedium.cardSequenceNumber, if (parameters.enteringCardSequenceNumberRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed),
if (segmentVersion > 1) NumerischesDatenelement(newActiveTanMedium.cardType, 2, if (parameters.enteringCardTypeAllowed) Existenzstatus.Optional else Existenzstatus.NotAllowed) else DoNotPrintDatenelement(),
Code(newActiveTanMedium.mediumClass, allCodes<TanMediumKlasse>(), Existenzstatus.Mandatory),
AlphanumerischesDatenelement(newActiveTanMedium.tanGenerator?.cardNumber, if (newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator) Existenzstatus.Mandatory else Existenzstatus.NotAllowed),
AlphanumerischesDatenelement(newActiveTanMedium.tanGenerator?.cardSequenceNumber, if (newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator && parameters.enteringCardSequenceNumberRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed),
if (segmentVersion > 1) NumerischesDatenelement(newActiveTanMedium.tanGenerator?.cardType, 2, if (newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator && parameters.enteringCardTypeAllowed) Existenzstatus.Optional else Existenzstatus.NotAllowed) else DoNotPrintDatenelement(),
if (segmentVersion == 2) Kontoverbindung(bank.accounts.first()) else DoNotPrintDatenelement(),
if (segmentVersion >= 3 && parameters.accountInfoRequired) KontoverbindungInternational(bank.accounts.first(), bank) else DoNotPrintDatenelement(),
if (segmentVersion >= 2) Datum(newActiveTanMedium.validFrom, Existenzstatus.Optional) else DoNotPrintDatenelement(),
if (segmentVersion >= 2) Datum(newActiveTanMedium.validTo, Existenzstatus.Optional) else DoNotPrintDatenelement(),
if (segmentVersion >= 3) AlphanumerischesDatenelement(iccsn, Existenzstatus.Optional, 19) else DoNotPrintDatenelement(),
if (segmentVersion >= 2 && newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator) Datum(newActiveTanMedium.tanGenerator?.validFrom, Existenzstatus.Optional) else DoNotPrintDatenelement(),
if (segmentVersion >= 2 && newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator) Datum(newActiveTanMedium.tanGenerator?.validTo, Existenzstatus.Optional) else DoNotPrintDatenelement(),
if (segmentVersion >= 3 && newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator) AlphanumerischesDatenelement(iccsn, Existenzstatus.Optional, 19) else DoNotPrintDatenelement(),
NotAllowedDatenelement(), // TAN-Listennummer not supported anymore
NumerischesDatenelement(atc, 5, if (parameters.enteringAtcAndTanRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed),
NumerischesDatenelement(atc, 5, if (newActiveTanMedium.mediumClass == TanMediumKlasse.TanGenerator && parameters.enteringAtcAndTanRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed),
AlphanumerischesDatenelement(tan, if (parameters.enteringAtcAndTanRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed, 99)
)) {

View File

@ -25,6 +25,7 @@ import net.codinux.banking.fints.response.segments.*
import net.codinux.banking.fints.util.MessageUtils
import net.codinux.banking.fints.extensions.getAllExceptionMessagesJoined
import net.codinux.banking.fints.transactions.swift.Mt535Parser
import net.dankito.banking.client.model.BankAccountIdentifier
open class ResponseParser(
@ -613,34 +614,32 @@ open class ResponseParser(
val mediumName = if (hitabVersion < 2) null else parseStringToNullIfEmpty(remainingDataElements[10])
return when (mediumClass) {
TanMediumKlasse.TanGenerator -> parseTanGeneratorTanMedium(mediumClass, status, mediumName, hitabVersion, remainingDataElements)
TanMediumKlasse.MobiltelefonMitMobileTan -> parseMobilePhoneTanMedium(mediumClass, status, mediumName, hitabVersion, remainingDataElements)
else -> TanMedium(mediumClass, status, mediumName) // Sparkasse sends for pushTan now class 'AlleMedien' -> set medium name and everything just works fine
}
val tanGenerator = if (mediumClass == TanMediumKlasse.TanGenerator) parseTanGeneratorTanMedium(hitabVersion, remainingDataElements)
else null
val mobilePhone = if (mediumClass == TanMediumKlasse.MobiltelefonMitMobileTan) parseMobilePhoneTanMedium(hitabVersion, remainingDataElements)
else null
return TanMedium(mediumClass, status, mediumName, tanGenerator, mobilePhone) // Sparkasse sends for pushTan now class 'AlleMedien' -> set medium name and everything just works fine
}
protected open fun parseTanGeneratorTanMedium(mediumClass: TanMediumKlasse, status: TanMediumStatus, mediumName: String?,
hitabVersion: Int, dataElements: List<String>): TanGeneratorTanMedium {
protected open fun parseTanGeneratorTanMedium(hitabVersion: Int, dataElements: List<String>): TanGeneratorTanMedium {
val cardType = if (hitabVersion < 2) null else parseNullableInt(dataElements[2])
// 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])
return TanGeneratorTanMedium(mediumClass, status, parseString(dataElements[0]), parseStringToNullIfEmpty(dataElements[1]),
cardType, validFrom, validTo, mediumName)
return TanGeneratorTanMedium(parseString(dataElements[0]), parseStringToNullIfEmpty(dataElements[1]),
cardType, validFrom, validTo)
}
protected open fun parseMobilePhoneTanMedium(mediumClass: TanMediumKlasse, status: TanMediumStatus, mediumName: String?,
hitabVersion: Int, dataElements: List<String>): MobilePhoneTanMedium {
protected open fun parseMobilePhoneTanMedium(hitabVersion: Int, dataElements: List<String>): MobilePhoneTanMedium {
val concealedPhoneNumber = if (hitabVersion < 2) null else parseStringToNullIfEmpty(dataElements[11])
val phoneNumber = if (hitabVersion < 2) null else parseStringToNullIfEmpty(dataElements[12])
val smsDebitAccount: KontoverbindungInternational? = null // TODO: may parse 13th data element to KontoverbindungInternational
val smsDebitAccount: BankAccountIdentifier? = null // TODO: may parse 13th data element to KontoverbindungInternational and map to BankAccountIdentifier
// mediumName should actually never be unset according to spec
return MobilePhoneTanMedium(mediumClass, status, mediumName ?: "", concealedPhoneNumber, phoneNumber, smsDebitAccount)
return MobilePhoneTanMedium(concealedPhoneNumber, phoneNumber, smsDebitAccount)
}

View File

@ -149,7 +149,7 @@ abstract class FinTsTestBase {
3 -> messageBuilder.createInitDialogMessageWithoutStrongCustomerAuthentication(context, null)
4 -> messageBuilder.createSynchronizeCustomerSystemIdMessage(context)
5 -> messageBuilder.createGetTanMediaListMessage(context)
6 -> messageBuilder.createChangeTanMediumMessage(context, TanGeneratorTanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.Aktiv, "", null, null, null, null, null), null, null)
6 -> messageBuilder.createChangeTanMediumMessage(context, TanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.Aktiv, null, TanGeneratorTanMedium("", null, null, null, null)), null, null)
7 -> messageBuilder.createGetBalanceMessage(context, account)
8 -> messageBuilder.createGetTransactionsMessage(context, GetAccountTransactionsParameter(bank, account, true))
9 -> messageBuilder.createGetTransactionsMessage(context, GetAccountTransactionsParameter(bank, bank.accounts[1], true))

View File

@ -2,6 +2,7 @@ package net.codinux.banking.fints.messages.segmente.implementierte.tan
import net.codinux.banking.fints.FinTsTestBase
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMediumStatus
import net.codinux.banking.fints.response.segments.ChangeTanMediaParameters
@ -25,7 +26,7 @@ class TanGeneratorTanMediumAnOderUmmeldenTest: FinTsTestBase() {
private const val SegmentNumber = 3
private val NewActiveTanMedium = TanGeneratorTanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.Verfuegbar, CardNumber, CardSequenceNumber, CardType, null, null, "EC-Card")
private val NewActiveTanMedium = TanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.Verfuegbar, "EC-Card", TanGeneratorTanMedium(CardNumber, CardSequenceNumber, CardType, null, null))
}

View File

@ -1021,8 +1021,8 @@ class ResponseParserTest : FinTsTestBase() {
result.getFirstSegmentById<TanMediaList>(InstituteSegmentId.TanMediaList)?.let { segment ->
assertEquals(TanEinsatzOption.KundeKannGenauEinMediumZuEinerZeitNutzen, segment.usageOption)
assertContainsExactly(segment.tanMedia,
TanGeneratorTanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.AktivFolgekarte, oldCardNumber, cardSequenceNumber, null, null, null, mediaName),
TanGeneratorTanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.Verfuegbar, cardSequenceNumber, null, null, null, null, mediaName)
TanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.AktivFolgekarte, mediaName, TanGeneratorTanMedium(oldCardNumber, cardSequenceNumber, null, null, null)),
TanMedium(TanMediumKlasse.TanGenerator, TanMediumStatus.Verfuegbar, mediaName, TanGeneratorTanMedium(cardSequenceNumber, null, null, null, null))
)
}
?: run { fail("No segment of type TanMediaList found in ${result.receivedSegments}") }