Implemented mapping all tan procedures returned from German banks: Merged photoTAN and PushTan with appTAN, added ChipTanUsb and ChipTanPhotoTanMatrixCode, renamed ChipTanOptisch to ChipTanFlickercode
This commit is contained in:
parent
4d50ded3fa
commit
95ce20b5bb
|
@ -7,13 +7,15 @@ enum class TanProcedureType {
|
|||
|
||||
ChipTanManuell,
|
||||
|
||||
ChipTanOptisch,
|
||||
ChipTanFlickercode,
|
||||
|
||||
ChipTanUsb,
|
||||
|
||||
ChipTanQrCode,
|
||||
|
||||
PhotoTan,
|
||||
ChipTanPhotoTanMatrixCode,
|
||||
|
||||
SmsTan,
|
||||
|
||||
PushTan
|
||||
AppTan
|
||||
}
|
|
@ -29,7 +29,7 @@ import javax.inject.Inject
|
|||
open class EnterTanDialog : DialogFragment() {
|
||||
|
||||
companion object {
|
||||
val OpticalTanProcedures = listOf(TanProcedureType.ChipTanOptisch, TanProcedureType.ChipTanQrCode, TanProcedureType.PhotoTan)
|
||||
val OpticalTanProcedures = listOf(TanProcedureType.ChipTanFlickercode, TanProcedureType.ChipTanQrCode, TanProcedureType.ChipTanPhotoTanMatrixCode)
|
||||
|
||||
const val DialogTag = "EnterTanDialog"
|
||||
}
|
||||
|
|
|
@ -217,11 +217,12 @@ open class fints4javaModelMapper {
|
|||
return when (type) {
|
||||
net.dankito.fints.model.TanProcedureType.EnterTan -> TanProcedureType.EnterTan
|
||||
net.dankito.fints.model.TanProcedureType.ChipTanManuell -> TanProcedureType.ChipTanManuell
|
||||
net.dankito.fints.model.TanProcedureType.ChipTanOptisch -> TanProcedureType.ChipTanOptisch
|
||||
net.dankito.fints.model.TanProcedureType.ChipTanFlickercode -> TanProcedureType.ChipTanFlickercode
|
||||
net.dankito.fints.model.TanProcedureType.ChipTanUsb -> TanProcedureType.ChipTanUsb
|
||||
net.dankito.fints.model.TanProcedureType.ChipTanQrCode -> TanProcedureType.ChipTanQrCode
|
||||
net.dankito.fints.model.TanProcedureType.PhotoTan -> TanProcedureType.PhotoTan
|
||||
net.dankito.fints.model.TanProcedureType.ChipTanPhotoTanMatrixCode -> TanProcedureType.ChipTanPhotoTanMatrixCode
|
||||
net.dankito.fints.model.TanProcedureType.SmsTan -> TanProcedureType.SmsTan
|
||||
net.dankito.fints.model.TanProcedureType.PushTan -> TanProcedureType.PushTan
|
||||
net.dankito.fints.model.TanProcedureType.AppTan -> TanProcedureType.AppTan
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,11 +301,12 @@ open class fints4javaModelMapper {
|
|||
return when (type) {
|
||||
TanProcedureType.EnterTan -> net.dankito.fints.model.TanProcedureType.EnterTan
|
||||
TanProcedureType.ChipTanManuell -> net.dankito.fints.model.TanProcedureType.ChipTanManuell
|
||||
TanProcedureType.ChipTanOptisch -> net.dankito.fints.model.TanProcedureType.ChipTanOptisch
|
||||
TanProcedureType.ChipTanFlickercode -> net.dankito.fints.model.TanProcedureType.ChipTanFlickercode
|
||||
TanProcedureType.ChipTanUsb -> net.dankito.fints.model.TanProcedureType.ChipTanUsb
|
||||
TanProcedureType.ChipTanQrCode -> net.dankito.fints.model.TanProcedureType.ChipTanQrCode
|
||||
TanProcedureType.PhotoTan -> net.dankito.fints.model.TanProcedureType.PhotoTan
|
||||
TanProcedureType.ChipTanPhotoTanMatrixCode -> net.dankito.fints.model.TanProcedureType.ChipTanPhotoTanMatrixCode
|
||||
TanProcedureType.SmsTan -> net.dankito.fints.model.TanProcedureType.SmsTan
|
||||
TanProcedureType.PushTan -> net.dankito.fints.model.TanProcedureType.PushTan
|
||||
TanProcedureType.AppTan -> net.dankito.fints.model.TanProcedureType.AppTan
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherhe
|
|||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.ZkaTanProcedure
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.model.*
|
||||
import net.dankito.fints.response.InstituteSegmentId
|
||||
|
@ -694,10 +695,10 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
val tanProcedure = customer.selectedTanProcedure
|
||||
|
||||
return when (tanProcedure.type) {
|
||||
TanProcedureType.ChipTanOptisch, TanProcedureType.ChipTanManuell ->
|
||||
TanProcedureType.ChipTanFlickercode, TanProcedureType.ChipTanManuell ->
|
||||
FlickerCodeTanChallenge(FlickerCodeDecoder().decodeChallenge(challenge), messageToShowToUser, challenge, tanProcedure, tanResponse.tanMediaIdentifier)
|
||||
|
||||
TanProcedureType.ChipTanQrCode, TanProcedureType.PhotoTan ->
|
||||
TanProcedureType.ChipTanQrCode, TanProcedureType.ChipTanPhotoTanMatrixCode ->
|
||||
ImageTanChallenge(TanImageDecoder().decodeChallenge(challenge), messageToShowToUser, challenge, tanProcedure, tanResponse.tanMediaIdentifier)
|
||||
|
||||
else -> TanChallenge(messageToShowToUser, challenge, tanProcedure, tanResponse.tanMediaIdentifier)
|
||||
|
@ -913,28 +914,71 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
protected open fun mapToTanProcedureType(parameters: TanProcedureParameters): TanProcedureType? {
|
||||
val nameLowerCase = parameters.procedureName.toLowerCase()
|
||||
val name = parameters.procedureName.toLowerCase()
|
||||
|
||||
return when {
|
||||
nameLowerCase.contains("photo") -> TanProcedureType.PhotoTan
|
||||
// names are like 'chipTAN (comfort) manuell', 'Smart(-)TAN plus (manuell)' and
|
||||
// technical identification is 'HHD'. Exception: there's one that states itself as 'chipTAN (Manuell)'
|
||||
// but its ZkaTanProcedure is set to 'HHDOPT1' -> handle ChipTanManuell before ChipTanFlickercode
|
||||
parameters.zkaTanProcedure == ZkaTanProcedure.HHD || name.contains("manuell") ->
|
||||
TanProcedureType.ChipTanManuell
|
||||
|
||||
nameLowerCase.contains("chiptan") -> {
|
||||
return when {
|
||||
nameLowerCase.contains("qr") -> TanProcedureType.ChipTanQrCode
|
||||
nameLowerCase.contains("manuell") -> TanProcedureType.ChipTanManuell
|
||||
else -> TanProcedureType.ChipTanOptisch
|
||||
}
|
||||
// names are like 'chipTAN optisch/comfort', 'SmartTAN (plus) optic/USB', 'chipTAN (Flicker)' and
|
||||
// technical identification is 'HHDOPT1'
|
||||
parameters.zkaTanProcedure == ZkaTanProcedure.HHDOPT1 ||
|
||||
tanProcedureNameContains(name, "optisch", "optic", "comfort", "flicker") ->
|
||||
TanProcedureType.ChipTanFlickercode
|
||||
|
||||
// 'Smart-TAN plus optisch / USB' seems to be a Flickertan procedure -> test for 'optisch' first
|
||||
name.contains("usb") -> TanProcedureType.ChipTanUsb
|
||||
|
||||
// QRTAN+ from 1822 direct has nothing to do with chipTAN QR.
|
||||
name.contains("qr") -> {
|
||||
if (tanProcedureNameContains(name, "chipTAN", "Smart")) TanProcedureType.ChipTanQrCode
|
||||
else TanProcedureType.AppTan
|
||||
}
|
||||
|
||||
nameLowerCase.contains("push") -> return TanProcedureType.PushTan
|
||||
nameLowerCase.contains("sms") || nameLowerCase.contains("mobile") -> return TanProcedureType.SmsTan
|
||||
// photoTAN from Commerzbank (comdirect), Deutsche Bank, norisbank has nothing to do with chipTAN photo
|
||||
name.contains("photo") -> {
|
||||
// e.g. 'Smart-TAN photo' / description 'Challenge'
|
||||
if (tanProcedureNameContains(name, "chipTAN", "Smart")) TanProcedureType.ChipTanPhotoTanMatrixCode
|
||||
// e.g. 'photoTAN-Verfahren', description 'Freigabe durch photoTAN'
|
||||
else TanProcedureType.AppTan
|
||||
}
|
||||
|
||||
tanProcedureNameContains(name, "SMS", "mobile", "mTAN") -> TanProcedureType.SmsTan
|
||||
|
||||
// 'flateXSecure' identifies itself as 'PPTAN' instead of 'AppTAN'
|
||||
// 'activeTAN-Verfahren' can actually be used either with an app or a reader; it's like chipTAN QR but without a chip card
|
||||
tanProcedureNameContains(name, "push", "app", "BestSign", "SecureGo", "TAN2go", "activeTAN", "easyTAN", "SecurePlus", "TAN+")
|
||||
|| technicalTanProcedureIdentificationContains(parameters, "SECURESIGN", "PPTAN") ->
|
||||
TanProcedureType.AppTan
|
||||
|
||||
// TODO: what about other tan procedures we're not aware of?
|
||||
// we filter out iTAN and Einschritt-Verfahren as they are not permitted anymore according to PSD2
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun tanProcedureNameContains(name: String, vararg namesToTest: String): Boolean {
|
||||
namesToTest.forEach { nameToTest ->
|
||||
if (name.contains(nameToTest.toLowerCase())) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
protected open fun technicalTanProcedureIdentificationContains(parameters: TanProcedureParameters, vararg valuesToTest: String): Boolean {
|
||||
valuesToTest.forEach { valueToTest ->
|
||||
if (parameters.technicalTanProcedureIdentification.contains(valueToTest, true)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
protected open fun isJobSupported(account: AccountData, supportedJob: JobParameters): Boolean {
|
||||
for (allowedJobName in account.allowedJobNames) {
|
||||
if (allowedJobName == supportedJob.jobName) {
|
||||
|
|
|
@ -13,8 +13,6 @@ enum class ZkaTanProcedure {
|
|||
|
||||
// values not specified by standard but found out there in the wild
|
||||
|
||||
photoTAN,
|
||||
|
||||
appTAN
|
||||
|
||||
}
|
|
@ -7,14 +7,16 @@ enum class TanProcedureType {
|
|||
|
||||
ChipTanManuell,
|
||||
|
||||
ChipTanOptisch,
|
||||
ChipTanFlickercode,
|
||||
|
||||
ChipTanUsb,
|
||||
|
||||
ChipTanQrCode,
|
||||
|
||||
PhotoTan,
|
||||
ChipTanPhotoTanMatrixCode,
|
||||
|
||||
SmsTan,
|
||||
|
||||
PushTan
|
||||
AppTan
|
||||
|
||||
}
|
|
@ -390,7 +390,7 @@ open class ResponseParser @JvmOverloads constructor(
|
|||
return ZkaTanProcedure.mobileTAN
|
||||
}
|
||||
|
||||
if (lowerCaseMayZkaTanProcedure == "apptan") {
|
||||
if (lowerCaseMayZkaTanProcedure == "apptan" || lowerCaseMayZkaTanProcedure == "phototan") {
|
||||
return ZkaTanProcedure.appTAN
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ abstract class FinTsTestBase {
|
|||
|
||||
const val ControlReference = "4477"
|
||||
|
||||
val Customer = CustomerData(CustomerId, Pin, selectedTanProcedure = TanProcedure("chipTAN-optisch", SecurityFunction, TanProcedureType.ChipTanOptisch), selectedLanguage = Language)
|
||||
val Customer = CustomerData(CustomerId, Pin, selectedTanProcedure = TanProcedure("chipTAN-optisch", SecurityFunction, TanProcedureType.ChipTanFlickercode), selectedLanguage = Language)
|
||||
|
||||
val Currency = "EUR"
|
||||
|
||||
|
|
|
@ -88,12 +88,12 @@ open class hbci4jModelMapper {
|
|||
net.dankito.banking.ui.model.tan.TanProcedure(displayName, TanProcedureType.ChipTanQrCode, code)
|
||||
}
|
||||
else {
|
||||
net.dankito.banking.ui.model.tan.TanProcedure(displayName, TanProcedureType.ChipTanOptisch, code)
|
||||
net.dankito.banking.ui.model.tan.TanProcedure(displayName, TanProcedureType.ChipTanFlickercode, code)
|
||||
}
|
||||
}
|
||||
|
||||
displayNameLowerCase.contains("sms") -> net.dankito.banking.ui.model.tan.TanProcedure(displayName, TanProcedureType.SmsTan, code)
|
||||
displayNameLowerCase.contains("push") -> net.dankito.banking.ui.model.tan.TanProcedure(displayName, TanProcedureType.PushTan, code)
|
||||
displayNameLowerCase.contains("push") -> net.dankito.banking.ui.model.tan.TanProcedure(displayName, TanProcedureType.AppTan, code)
|
||||
|
||||
// we filter out iTAN and Einschritt-Verfahren as they are not permitted anymore according to PSD2
|
||||
else -> null
|
||||
|
|
Loading…
Reference in New Issue