Added all available TanMedia to TanChallenge

This commit is contained in:
dankito 2024-08-27 02:15:24 +02:00
parent 046a0c90eb
commit f54c03b7bf
6 changed files with 81 additions and 7 deletions

View File

@ -1,10 +1,13 @@
package net.codinux.banking.client.model.tan
import net.codinux.banking.client.model.BankAccountIdentifier
import net.codinux.banking.client.model.config.NoArgConstructor
@NoArgConstructor
open class MobilePhoneTanMedium(
val phoneNumber: String?
val phoneNumber: String?,
val concealedPhoneNumber: String? = null,
val smsDebitAccount: BankAccountIdentifier? = null
) {
override fun toString() = phoneNumber ?: "No phone number"
}

View File

@ -29,7 +29,14 @@ open class TanChallenge(
*/
val availableTanMethods: List<TanMethod>,
// TODO: add available TanMedia - which frontend cannot know when adding an account - and selected TanMedium
/**
* Identifier of selected TanMedium.
*
* As [availableTanMedia] also contains selected TanMedium, we didn't want to duplicate this object. Use
* [selectedTanMedium] to get selected TanMedium or iterate over [availableTanMedia] and filter selected one by this medium name.
*/
val selectedTanMediumName: String? = null,
val availableTanMedia: List<TanMedium> = emptyList(),
val tanImage: TanImage? = null,
val flickerCode: FlickerCode? = null,
@ -41,6 +48,10 @@ open class TanChallenge(
val selectedTanMethod: TanMethod
get() = availableTanMethods.first { it.identifier == selectedTanMethodId }
@get:JsonIgnore
val selectedTanMedium: TanMedium?
get() = availableTanMedia.firstOrNull { it.mediumName == selectedTanMediumName }
override fun toString(): String {
return "$selectedTanMethod $forAction: $messageToShowToUser" + when (type) {

View File

@ -1,10 +1,15 @@
package net.codinux.banking.client.model.tan
import kotlinx.datetime.LocalDate
import net.codinux.banking.client.model.config.NoArgConstructor
@NoArgConstructor
open class TanGeneratorTanMedium(
val cardNumber: String
val cardNumber: String,
val cardSequenceNumber: String? = null,
val cardType: Int? = null,
val validFrom: LocalDate? = null,
val validTo: LocalDate? = null
) {
override fun toString() = cardNumber
}

View File

@ -5,7 +5,7 @@ import net.codinux.banking.client.model.config.NoArgConstructor
@NoArgConstructor
open class TanMedium(
val type: TanMediumType,
val displayName: String,
val mediumName: String?,
val status: TanMediumStatus,
/**
* Only set if [type] is [TanMediumType.TanGenerator].
@ -16,5 +16,5 @@ open class TanMedium(
*/
val mobilePhone: MobilePhoneTanMedium? = null
) {
override fun toString() = "$displayName $status"
override fun toString() = "$mediumName $status"
}

View File

@ -1,7 +1,25 @@
package net.codinux.banking.client.model.tan
enum class TanMediumStatus {
/**
* Die Bank zeigt an, dass es eine TAN-Verifikation gegen dieses Medium vornimmt.
*/
Used,
Available
/**
* Das Medium kann genutzt werden, muss aber zuvor mit TAN-Generator an- bzw. ummelden (HKTAU) aktiv gemeldet werden.
*/
Available,
/**
* Mit der ersten Nutzung der Folgekarte wird die zur Zeit aktive Karte gesperrt.
*/
ActiveFollowUpCard,
/**
* 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.
*/
AvailableFollowUpCard
}

View File

@ -17,6 +17,10 @@ import net.dankito.banking.client.model.parameter.RetrieveTransactions
import net.dankito.banking.client.model.response.ErrorCode
import net.codinux.banking.fints.mapper.FinTsModelMapper
import net.codinux.banking.fints.model.*
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.MobilePhoneTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.codinux.banking.fints.messages.datenelemente.implementierte.tan.TanMediumStatus
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
@ -124,13 +128,16 @@ open class FinTs4kMapper {
val tanMethods = challenge.bank.tanMethodsAvailableForUser.map { mapTanMethod(it) }
val selectedTanMethodId = challenge.tanMethod.securityFunction.code
val tanMedia = challenge.bank.tanMedia.map { mapTanMedium(it) }
val selectedTanMediumName = challenge.bank.selectedTanMedium?.mediumName
val customer = mapToCustomerAccountViewInfo(challenge.bank)
val account = challenge.account?.let { mapToBankAccountViewInfo(it) }
val tanImage = if (challenge is ImageTanChallenge) mapTanImage(challenge.image) else null
val flickerCode = if (challenge is FlickerCodeTanChallenge) mapFlickerCode(challenge.flickerCode) else null
return TanChallenge(type, action, challenge.messageToShowToUser, selectedTanMethodId, tanMethods, tanImage, flickerCode, customer, account)
return TanChallenge(type, action, challenge.messageToShowToUser, selectedTanMethodId, tanMethods, selectedTanMediumName, tanMedia, tanImage, flickerCode, customer, account)
}
protected open fun mapTanChallengeType(challenge: net.codinux.banking.fints.model.TanChallenge): TanChallengeType = when {
@ -160,6 +167,36 @@ open class FinTs4kMapper {
return Base64.Default.encode(bytes)
}
protected open fun mapTanMedium(tanMedium: TanMedium) = net.codinux.banking.client.model.tan.TanMedium(
mapTanMediumType(tanMedium), tanMedium.mediumName, mapTanMediumStatus(tanMedium.status),
(tanMedium as? TanGeneratorTanMedium)?.let { mapTanGeneratorTanMedium(it) },
(tanMedium as? MobilePhoneTanMedium)?.let { mapMobilePhoneTanMedium(it) }
)
protected open fun mapTanMediumStatus(status: TanMediumStatus): net.codinux.banking.client.model.tan.TanMediumStatus = when (status) {
TanMediumStatus.Aktiv -> net.codinux.banking.client.model.tan.TanMediumStatus.Used
TanMediumStatus.Verfuegbar -> net.codinux.banking.client.model.tan.TanMediumStatus.Available
TanMediumStatus.AktivFolgekarte -> net.codinux.banking.client.model.tan.TanMediumStatus.ActiveFollowUpCard
TanMediumStatus.VerfuegbarFolgekarte -> net.codinux.banking.client.model.tan.TanMediumStatus.AvailableFollowUpCard
}
protected open fun mapMobilePhoneTanMedium(tanMedium: MobilePhoneTanMedium) = net.codinux.banking.client.model.tan.MobilePhoneTanMedium(
tanMedium.phoneNumber, tanMedium.concealedPhoneNumber,
// TODO (but with very low priority): Map smsDebitAccount from segment
// tanMedium.smsDebitAccount?.let { BankAccountIdentifier(it.accountNumber, it.subAccountAttribute, it.iban) }
)
protected open fun mapTanGeneratorTanMedium(tanMedium: TanGeneratorTanMedium) = net.codinux.banking.client.model.tan.TanGeneratorTanMedium(
tanMedium.cardNumber, tanMedium.cardSequenceNumber, tanMedium.cardType,
tanMedium.validFrom, tanMedium.validTo
)
protected open fun mapTanMediumType(tanMedium: TanMedium): TanMediumType = when {
tanMedium is MobilePhoneTanMedium -> TanMediumType.MobilePhone
tanMedium is TanGeneratorTanMedium -> TanMediumType.TanGenerator
else -> TanMediumType.Generic
}
protected open fun mapFlickerCode(flickerCode: net.codinux.banking.fints.tan.FlickerCode): FlickerCode =
FlickerCode(flickerCode.challengeHHD_UC, flickerCode.parsedDataSet, mapException(flickerCode.decodingError))