From c8f29e239000771786de9547b5e26235be3651d6 Mon Sep 17 00:00:00 2001 From: dankito Date: Wed, 12 Aug 2020 22:28:18 +0200 Subject: [PATCH] Implemented passing allowed TAN format and max TAN input length to UI so that controls can be set accordingly --- .../net/dankito/banking/fints/FinTsClient.kt | 1 + .../banking/fints/model/TanProcedure.kt | 3 +++ .../ui/android/dialogs/EnterTanDialog.kt | 13 ++++++++--- .../banking/ui/model/tan/AllowedTanFormat.kt | 10 ++++++++ .../banking/ui/model/tan/TanProcedure.kt | 7 +++++- .../BankingiOSApp.xcdatamodel/contents | 4 +++- .../BankingiOSApp/persistence/Mapper.swift | 7 +++++- .../ui/views/EnterTanDialog.swift | 8 +++---- .../BankingiOSApp/ui/views/ImageTanView.swift | 2 +- .../banking/mapper/fints4kModelMapper.kt | 23 +++++++++++++++++-- 10 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/AllowedTanFormat.kt diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt index 2ceca0c1..f576bf64 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt @@ -1138,6 +1138,7 @@ open class FinTsClient( return TanProcedure(procedureName, parameters.securityFunction, mapToTanProcedureType(parameters) ?: TanProcedureType.EnterTan, mapHhdVersion(parameters), + parameters.maxTanInputLength, parameters.allowedTanFormat, parameters.nameOfTanMediaRequired == BezeichnungDesTanMediumsErforderlich.BezeichnungDesTanMediumsMussAngegebenWerden) } diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/TanProcedure.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/TanProcedure.kt index c1c0b66f..d3f48882 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/TanProcedure.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/TanProcedure.kt @@ -1,6 +1,7 @@ package net.dankito.banking.fints.model import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion +import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat open class TanProcedure( @@ -8,6 +9,8 @@ open class TanProcedure( val securityFunction: Sicherheitsfunktion, val type: TanProcedureType, val hhdVersion: HHDVersion? = null, + val maxTanInputLength: Int? = null, + val allowedTanFormat: AllowedTanFormat = AllowedTanFormat.Alphanumeric, val nameOfTanMediaRequired: Boolean = false ) { diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt index a83c1aea..f4afb138 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt @@ -3,6 +3,7 @@ package net.dankito.banking.ui.android.dialogs import android.content.Context import android.os.Bundle import android.os.Handler +import android.text.InputFilter import android.text.InputType import android.view.KeyEvent import android.view.LayoutInflater @@ -14,11 +15,10 @@ import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.DialogFragment import kotlinx.android.synthetic.main.dialog_enter_tan.* import kotlinx.android.synthetic.main.dialog_enter_tan.view.* -import kotlinx.android.synthetic.main.dialog_enter_tan.view.flickerCodeView import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.di.BankingComponent import net.dankito.banking.ui.android.adapter.TanMediumAdapter import net.dankito.banking.ui.android.adapter.TanProceduresAdapter +import net.dankito.banking.ui.android.di.BankingComponent import net.dankito.banking.ui.android.listener.ListItemSelectedListener import net.dankito.banking.ui.model.Customer import net.dankito.banking.ui.model.responses.BankingClientResponse @@ -151,7 +151,14 @@ open class EnterTanDialog : DialogFragment() { setupImageTanView(rootView) } - rootView.edtxtEnteredTan.inputType = InputType.TYPE_CLASS_NUMBER // TODO: is this always true that TAN is a number? + + if (tanChallenge.tanProcedure.isNumericTan) { + rootView.edtxtEnteredTan.inputType = InputType.TYPE_CLASS_NUMBER + } + + tanChallenge.tanProcedure.maxTanInputLength?.let { maxInputLength -> + rootView.edtxtEnteredTan.filters = arrayOf(InputFilter.LengthFilter(maxInputLength)) + } rootView.edtxtEnteredTan.setOnKeyListener { _, keyCode, _ -> if (keyCode == KeyEvent.KEYCODE_ENTER) { diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/AllowedTanFormat.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/AllowedTanFormat.kt new file mode 100644 index 00000000..7c6c8e65 --- /dev/null +++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/AllowedTanFormat.kt @@ -0,0 +1,10 @@ +package net.dankito.banking.ui.model.tan + + +enum class AllowedTanFormat { + + Numeric, + + Alphanumeric + +} \ No newline at end of file diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanProcedure.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanProcedure.kt index 123e4d27..ac383a71 100644 --- a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanProcedure.kt +++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanProcedure.kt @@ -4,13 +4,18 @@ package net.dankito.banking.ui.model.tan open class TanProcedure( val displayName: String, val type: TanProcedureType, - val bankInternalProcedureCode: String + val bankInternalProcedureCode: String, + val maxTanInputLength: Int? = null, + val allowedTanFormat: AllowedTanFormat = AllowedTanFormat.Alphanumeric ) { internal constructor() : this("", TanProcedureType.EnterTan, "") // for object deserializers + val isNumericTan: Boolean = allowedTanFormat == AllowedTanFormat.Numeric + + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is TanProcedure) return false diff --git a/ui/BankingiOSApp/BankingiOSApp/BankingiOSApp.xcdatamodeld/BankingiOSApp.xcdatamodel/contents b/ui/BankingiOSApp/BankingiOSApp/BankingiOSApp.xcdatamodeld/BankingiOSApp.xcdatamodel/contents index 3abd187c..00a16290 100644 --- a/ui/BankingiOSApp/BankingiOSApp/BankingiOSApp.xcdatamodeld/BankingiOSApp.xcdatamodel/contents +++ b/ui/BankingiOSApp/BankingiOSApp/BankingiOSApp.xcdatamodeld/BankingiOSApp.xcdatamodel/contents @@ -73,14 +73,16 @@ + + - + \ No newline at end of file diff --git a/ui/BankingiOSApp/BankingiOSApp/persistence/Mapper.swift b/ui/BankingiOSApp/BankingiOSApp/persistence/Mapper.swift index b27fe50e..f2773577 100644 --- a/ui/BankingiOSApp/BankingiOSApp/persistence/Mapper.swift +++ b/ui/BankingiOSApp/BankingiOSApp/persistence/Mapper.swift @@ -216,7 +216,9 @@ class Mapper { let mapped = TanProcedure( displayName: map(tanProcedure.displayName), type: mapTanProcedureType(tanProcedure.type), - bankInternalProcedureCode: map(tanProcedure.bankInternalProcedureCode) + bankInternalProcedureCode: map(tanProcedure.bankInternalProcedureCode), + maxTanInputLength: map(tanProcedure.maxTanInputLength), + allowedTanFormat: tanProcedure.allowedTanFormat == "numeric" ? .numeric : .alphanumeric ) mappedTanProcedures[mapped] = tanProcedure @@ -235,6 +237,9 @@ class Mapper { mapped.type = tanProcedure.type.name mapped.bankInternalProcedureCode = tanProcedure.bankInternalProcedureCode + mapped.maxTanInputLength = map(tanProcedure.maxTanInputLength) ?? -1 + mapped.allowedTanFormat = tanProcedure.allowedTanFormat.name + mappedTanProcedures[tanProcedure] = mapped return mapped diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift b/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift index 3a0545e8..8e637c0a 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift @@ -105,7 +105,7 @@ struct EnterTanDialog: View { .padding(.vertical, 2) Section { - UIKitTextField("Enter TAN:", text: $enteredTan, actionOnReturnKeyPress: { + UIKitTextField("Enter TAN:", text: $enteredTan, keyboardType: tanChallenge.tanProcedure.isNumericTan ? .numberPad : .default, actionOnReturnKeyPress: { if self.isRequiredDataEntered() { self.enteringTanDone() return true @@ -214,9 +214,9 @@ struct EnterTanDialog_Previews: PreviewProvider { static var previews: some View { let customer = Customer(bankCode: "", customerId: "", password: "", finTsServerAddress: "") customer.supportedTanProcedures = [ - TanProcedure(displayName: "chipTAN optisch", type: .chiptanflickercode, bankInternalProcedureCode: ""), - TanProcedure(displayName: "chipTAN QR", type: .chiptanqrcode, bankInternalProcedureCode: ""), - TanProcedure(displayName: "Secure Super Duper Plus", type: .apptan, bankInternalProcedureCode: "") + TanProcedure(displayName: "chipTAN optisch", type: .chiptanflickercode, bankInternalProcedureCode: "", maxTanInputLength: 6, allowedTanFormat: .numeric), + TanProcedure(displayName: "chipTAN QR", type: .chiptanqrcode, bankInternalProcedureCode: "", maxTanInputLength: 8, allowedTanFormat: .numeric), + TanProcedure(displayName: "Secure Super Duper Plus", type: .apptan, bankInternalProcedureCode: "", maxTanInputLength: 6, allowedTanFormat: .alphanumeric) ] customer.tanMedia = [ diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/views/ImageTanView.swift b/ui/BankingiOSApp/BankingiOSApp/ui/views/ImageTanView.swift index 10090f5a..9087d105 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/views/ImageTanView.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/views/ImageTanView.swift @@ -72,7 +72,7 @@ struct ImageTanView: View { struct ImageTanView_Previews: PreviewProvider { static var previews: some View { - let tanChallenge = ImageTanChallenge(image: TanImage(mimeType: "image/png", imageBytes: KotlinByteArray(size: 0), decodingError: nil), messageToShowToUser: "", tanProcedure: TanProcedure(displayName: "", type: .phototan, bankInternalProcedureCode: "")) + let tanChallenge = ImageTanChallenge(image: TanImage(mimeType: "image/png", imageBytes: KotlinByteArray(size: 0), decodingError: nil), messageToShowToUser: "", tanProcedure: TanProcedure(displayName: "", type: .phototan, bankInternalProcedureCode: "", maxTanInputLength: 6, allowedTanFormat: .numeric)) return ImageTanView(tanChallenge) } diff --git a/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt index 314b2461..e3e34a76 100644 --- a/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt +++ b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt @@ -238,7 +238,9 @@ open class fints4kModelMapper { return TanProcedure( tanProcedure.displayName, mapTanProcedureType(tanProcedure.type), - tanProcedure.securityFunction.code + tanProcedure.securityFunction.code, + tanProcedure.maxTanInputLength, + mapAllowedTanFormat(tanProcedure.allowedTanFormat) ) } @@ -257,6 +259,13 @@ open class fints4kModelMapper { } } + open fun mapAllowedTanFormat(allowedTanFormat: net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat): AllowedTanFormat { + return when (allowedTanFormat) { + net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat.Alphanumeric -> AllowedTanFormat.Alphanumeric + net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat.Numeric -> AllowedTanFormat.Numeric + } + } + protected open fun findMappedTanProcedure(customer: Customer, tanProcedure: net.dankito.banking.fints.model.TanProcedure): TanProcedure? { return customer.supportedTanProcedures.firstOrNull { it.bankInternalProcedureCode == tanProcedure.securityFunction.code } } @@ -350,7 +359,10 @@ open class fints4kModelMapper { return net.dankito.banking.fints.model.TanProcedure( tanProcedure.displayName, Sicherheitsfunktion.values().first { it.code == tanProcedure.bankInternalProcedureCode }, - mapTanProcedureType(tanProcedure.type) + mapTanProcedureType(tanProcedure.type), + null, // TODO: where to get HDD Version from? + tanProcedure.maxTanInputLength, + mapAllowedTanFormat(tanProcedure.allowedTanFormat) ) } @@ -369,6 +381,13 @@ open class fints4kModelMapper { } } + open fun mapAllowedTanFormat(allowedTanFormat: AllowedTanFormat): net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat { + return when (allowedTanFormat) { + AllowedTanFormat.Alphanumeric -> net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat.Alphanumeric + AllowedTanFormat.Numeric -> net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat.Numeric + } + } + open fun mapEnterTanResult(result: EnterTanResult, customer: CustomerData): net.dankito.banking.fints.model.EnterTanResult { result.changeTanProcedureTo?.let { changeTanProcedureTo -> return net.dankito.banking.fints.model.EnterTanResult.userAsksToChangeTanProcedure(mapTanProcedure(changeTanProcedureTo))