diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt index fdfca493..940f8ec9 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/FinTsClient.kt @@ -1,6 +1,8 @@ package net.dankito.fints import net.dankito.fints.messages.MessageBuilder +import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache +import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte import net.dankito.fints.model.BankData import net.dankito.fints.model.CustomerData import net.dankito.fints.model.DialogData @@ -8,7 +10,10 @@ import net.dankito.fints.model.ProductData import net.dankito.fints.response.InstituteSegmentId import net.dankito.fints.response.Response import net.dankito.fints.response.ResponseParser +import net.dankito.fints.response.segments.AccountInfo +import net.dankito.fints.response.segments.BankParameters import net.dankito.fints.response.segments.ReceivedSynchronization +import net.dankito.fints.response.segments.UserParameters import net.dankito.fints.util.IBase64Service import net.dankito.utils.web.client.IWebClient import net.dankito.utils.web.client.OkHttpWebClient @@ -37,6 +42,8 @@ open class FinTsClient( val response = getAndHandleResponseForMessage(requestBody, bank) if (response.successful) { + updateBankData(bank, response) + dialogData.increaseMessageNumber() response.messageHeader?.let { header -> dialogData.dialogId = header.dialogId } @@ -49,6 +56,23 @@ open class FinTsClient( } + open fun initDialog(bank: BankData, customer: CustomerData, product: ProductData, + dialogData: DialogData): Response { + + val requestBody = messageBuilder.createInitDialogMessage(bank, customer, product, dialogData) + + val response = getAndHandleResponseForMessage(requestBody, bank) + + if (response.successful) { + updateBankData(bank, response) + updateCustomerData(customer, response) + + response.messageHeader?.let { header -> dialogData.dialogId = header.dialogId } + } + + return response + } + open fun synchronizeCustomerSystemId(bank: BankData, customer: CustomerData, product: ProductData, dialogData: DialogData = DialogData()): Response { @@ -57,11 +81,10 @@ open class FinTsClient( val response = getAndHandleResponseForMessage(requestBody, bank) if (response.successful) { - response.messageHeader?.let { header -> dialogData.dialogId = header.dialogId } + updateBankData(bank, response) + updateCustomerData(customer, response) - response.getFirstSegmentById(InstituteSegmentId.Synchronization)?.customerSystemId?.let { customerSystemId -> - customer.customerSystemId = customerSystemId - } + response.messageHeader?.let { header -> dialogData.dialogId = header.dialogId } closeDialog(bank, customer, dialogData) } @@ -113,4 +136,46 @@ open class FinTsClient( return base64Service.decode(responseBody.replace("\r", "").replace("\n", "")) } + + protected open fun updateBankData(bank: BankData, response: Response) { + response.getFirstSegmentById(InstituteSegmentId.BankParameters)?.let { bankParameters -> + bank.bpdVersion = bankParameters.bpdVersion + bank.name = bankParameters.bankName +// bank.bic = bankParameters. // TODO: where's the BIC? +// bank.finTs3ServerAddress = // TODO: parse HIKOM + // TODO: save supported languages and security profiles + } + } + + protected open fun updateCustomerData(customer: CustomerData, response: Response) { + response.getFirstSegmentById(InstituteSegmentId.BankParameters)?.let { bankParameters -> + if (customer.selectedLanguage == Dialogsprache.Default && bankParameters.supportedLanguages.isNotEmpty()) { + customer.selectedLanguage = bankParameters.supportedLanguages.first() + } + } + + response.getFirstSegmentById(InstituteSegmentId.Synchronization)?.let { synchronization -> + synchronization.customerSystemId?.let { + customer.customerSystemId = it + + customer.customerSystemStatus = KundensystemStatusWerte.Benoetigt // TODO: didn't find out for sure yet, but i think i read somewhere, that this has to be set when customerSystemId is set + } + + // TODO: may also save securityReferenceNumbers + } + + response.getFirstSegmentById(InstituteSegmentId.AccountInfo)?.let { accountInfo -> + customer.iban = accountInfo.iban + customer.name = accountInfo.accountHolderName1 + + // TODO: may also make use of other info + } + + response.getFirstSegmentById(InstituteSegmentId.UserParameters)?.let { userParameters -> + customer.updVersion = userParameters.updVersion + + // TODO: may also make use of other info + } + } + } \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/MessageBuilder.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/MessageBuilder.kt index 01e5bb5a..34864f8a 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/MessageBuilder.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/messages/MessageBuilder.kt @@ -58,6 +58,15 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg } + open fun createInitDialogMessage(bank: BankData, customer: CustomerData, product: ProductData, dialogData: DialogData): String { + + return createMessage(true, true, bank, customer, dialogData, listOf( + IdentifikationsSegment(generator.resetSegmentNumber(2), bank, customer), + Verarbeitungsvorbereitung(generator.getNextSegmentNumber(), bank, customer, product), + ZweiSchrittTanEinreichung(generator.getNextSegmentNumber(), TanProcess.TanProcess4, CustomerSegmentId.Identification.id) + )) + } + open fun createSynchronizeCustomerSystemIdMessage(bank: BankData, customer: CustomerData, product: ProductData, dialogData: DialogData): String { return createMessage(true, true, bank, customer, dialogData, listOf( diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/model/BankData.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/model/BankData.kt index aa6e3b30..c7f7ecb6 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/model/BankData.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/model/BankData.kt @@ -9,6 +9,7 @@ open class BankData( val countryCode: Int, var finTs3ServerAddress: String, var bpdVersion: Int = BPDVersion.VersionNotReceivedYet, + var name: String = "", var bic: String? = null, var supportedLanguages: List = listOf() ) { diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/model/CustomerData.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/model/CustomerData.kt index 356cb9db..ac271f8e 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/model/CustomerData.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/model/CustomerData.kt @@ -9,6 +9,7 @@ open class CustomerData( val customerId: String, var pin: String, val userId: String = customerId, + var name: String = "", var iban: String? = null, var updVersion: Int = UPDVersion.VersionNotReceivedYet, var availableTanProcedures: List = listOf(), diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt index 9dbf27d1..a378c4c5 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/InstituteSegmentId.kt @@ -9,6 +9,10 @@ enum class InstituteSegmentId(override val id: String) : ISegmentId { BankParameters("HIBPA"), - SecurityMethods("HISHV") + SecurityMethods("HISHV"), + + UserParameters("HIUPA"), + + AccountInfo("HIUPD") } \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt index f8a2177b..1bdd3534 100644 --- a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -58,9 +58,14 @@ open class ResponseParser { protected open fun parseSegment(segment: String, segmentId: String, dataElementGroups: List): ReceivedSegment? { return when (segmentId) { MessageSegmentId.MessageHeader.id -> parseMessageHeaderSegment(segment, dataElementGroups) + InstituteSegmentId.Synchronization.id -> parseSynchronization(segment, dataElementGroups) InstituteSegmentId.BankParameters.id -> parseBankParameters(segment, dataElementGroups) InstituteSegmentId.SecurityMethods.id -> parseSecurityMethods(segment, dataElementGroups) + + InstituteSegmentId.UserParameters.id -> parseUserParameters(segment, dataElementGroups) + InstituteSegmentId.AccountInfo.id -> parseAccountInfo(segment, dataElementGroups) + else -> null } } @@ -110,6 +115,41 @@ open class ResponseParser { } + protected open fun parseUserParameters(segment: String, dataElementGroups: List): UserParameters { + val customerId = dataElementGroups[1] + val updVersion = dataElementGroups[2].toInt() + val areListedJobsBlocked = dataElementGroups[3] == "0" + val username = if (dataElementGroups.size > 4) returnNullIfEmpty(dataElementGroups[4]) else null + val extension = if (dataElementGroups.size > 5) returnNullIfEmpty(dataElementGroups[5]) else null + + return UserParameters(customerId, updVersion, areListedJobsBlocked, username, extension, segment) + } + + protected open fun parseAccountInfo(segment: String, dataElementGroups: List): AccountInfo { + // this is parsing a Kontoverbindung. May extract a method for it. + val accountDetails = getDataElements(dataElementGroups[1]) + val accountNumber = accountDetails[0] + val subAccountAttribute = returnNullIfEmpty(accountDetails[1]) + val bankCountryCode = accountDetails[2].toInt() + val bankCode = accountDetails[3] + + val iban = returnNullIfEmpty(dataElementGroups[2]) + val customerId = dataElementGroups[3] + val accountType = parseCodeEnum(listOf(dataElementGroups[4]), AccountTypeCode.values()).first().type + val currency = dataElementGroups[5] + val accountHolderName1 = dataElementGroups[6] + val accountHolderName2 = returnNullIfEmpty(dataElementGroups[7]) + val productName = returnNullIfEmpty(dataElementGroups[8]) + val limit = returnNullIfEmpty(dataElementGroups[9]) // TODO: parse limit + + // TODO: parse allowed jobs + // TODO: parse extension + + return AccountInfo(accountNumber, subAccountAttribute, bankCountryCode, bankCode, iban, customerId, accountType, + currency, accountHolderName1, accountHolderName2, productName, limit, null, segment) + } + + protected open fun parseBankDetails(dataElementsGroup: String): Kreditinstitutskennung { val detailsStrings = getDataElements(dataElementsGroup) @@ -119,13 +159,13 @@ open class ResponseParser { protected open fun parseLanguages(dataElementsGroup: String): List { val languageStrings = getDataElements(dataElementsGroup) - return parseFromCode(languageStrings, Dialogsprache.values()) + return parseCodeEnum(languageStrings, Dialogsprache.values()) } protected open fun parseHbciVersions(dataElementsGroup: String): List { val versionStrings = getDataElements(dataElementsGroup) - return parseFromCode(versionStrings, HbciVersion.values()) + return parseCodeEnum(versionStrings, HbciVersion.values()) } protected open fun parseSecurityProfiles(dataElementsGroups: List): List { @@ -141,7 +181,7 @@ open class ResponseParser { } protected open fun parseSecurityMethod(methodString: String): Sicherheitsverfahren { - return parseFromCode(listOf(methodString), Sicherheitsverfahren.values()).first() + return parseCodeEnum(listOf(methodString), Sicherheitsverfahren.values()).first() } protected open fun parseSecurityMethodVersion(versionString: String): VersionDesSicherheitsverfahrens { @@ -150,7 +190,7 @@ open class ResponseParser { return VersionDesSicherheitsverfahrens.values().first { it.methodNumber == versionInt } } - protected open fun parseFromCode(codeValues: List, allValues: Array): List { + protected open fun parseCodeEnum(codeValues: List, allValues: Array): List { // mapNotNull: don't crash if new, at time of implementation unknown values get introduced / returned by bank return codeValues.mapNotNull { code -> allValues.first { it.code == code } } } @@ -168,4 +208,8 @@ open class ResponseParser { return false } + protected open fun returnNullIfEmpty(string: String): String? { + return if (string.isEmpty()) null else string + } + } \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountInfo.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountInfo.kt new file mode 100644 index 00000000..e06037db --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountInfo.kt @@ -0,0 +1,22 @@ +package net.dankito.fints.response.segments + + +open class AccountInfo( + val accountNumber: String, + val subAccountAttribute: String?, + val bankCountryCode: Int, + val bankCode: String, + val iban: String?, + val customerId: String, + val accountType: AccountType, + val currency: String, // TODO: may parse to a value object + val accountHolderName1: String, + val accountHolderName2: String?, + val productName: String?, + val accountLimit: String?, // TODO: parse + val extension: String?, // TODO: parse + + segmentString: String + +) + : ReceivedSegment(segmentString) \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountType.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountType.kt new file mode 100644 index 00000000..6f3e47e8 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountType.kt @@ -0,0 +1,26 @@ +package net.dankito.fints.response.segments + + +enum class AccountType { + + Girokonto, + + Sparkonto, + + Festgeldkonto, + + Wertpapierdepot, + + Darlehenskonto, + + Kreditkartenkonto, + + FondsDepot, + + Bausparvertrag, + + Versicherungsvertrag, + + Sonstige + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountTypeCode.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountTypeCode.kt new file mode 100644 index 00000000..e8d3affc --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/AccountTypeCode.kt @@ -0,0 +1,222 @@ +package net.dankito.fints.response.segments + +import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum + + +/** + * Klassifizierung der Konten. Innerhalb der vorgegebenen Codebereiche sind kreditinstitutsindividuell bei Bedarf + * weitere Kontoarten möglich. + * + * Codierung: + * - 1 – 9: Kontokorrent-/Girokonto + * - 10 – 19: Sparkonto + * - 20 –29: Festgeldkonto (Termineinlagen) + * - 30 – 39: Wertpapierdepot + * - 40 –49: Kredit-/Darlehenskonto + * - 50 – 59: Kreditkartenkonto + * - 60 – 69: Fonds-Depot bei einer Kapitalanlagegesellschaft + * - 70 – 79: Bausparvertrag + * - 80 – 89: Versicherungsvertrag + * - 90 – 99: Sonstige (nicht zuordenbar) + */ +enum class AccountTypeCode(override val code: String, val type: AccountType) : ICodeEnum { + + Girokonto_1("1", AccountType.Girokonto), + + Girokonto_2("2", AccountType.Girokonto), + + Girokonto_3("3", AccountType.Girokonto), + + Girokonto_4("4", AccountType.Girokonto), + + Girokonto_5("5", AccountType.Girokonto), + + Girokonto_6("6", AccountType.Girokonto), + + Girokonto_7("7", AccountType.Girokonto), + + Girokonto_8("8", AccountType.Girokonto), + + Girokonto_9("9", AccountType.Girokonto), + + Sparkonto_1("10", AccountType.Sparkonto), + + Sparkonto_2("11", AccountType.Sparkonto), + + Sparkonto_3("12", AccountType.Sparkonto), + + Sparkonto_4("13", AccountType.Sparkonto), + + Sparkonto_5("14", AccountType.Sparkonto), + + Sparkonto_6("15", AccountType.Sparkonto), + + Sparkonto_7("16", AccountType.Sparkonto), + + Sparkonto_8("17", AccountType.Sparkonto), + + Sparkonto_9("18", AccountType.Sparkonto), + + Sparkonto_10("19", AccountType.Sparkonto), + + Festgeldkonto_1("20", AccountType.Festgeldkonto), + + Festgeldkonto_2("21", AccountType.Festgeldkonto), + + Festgeldkonto_3("22", AccountType.Festgeldkonto), + + Festgeldkonto_4("23", AccountType.Festgeldkonto), + + Festgeldkonto_5("24", AccountType.Festgeldkonto), + + Festgeldkonto_6("25", AccountType.Festgeldkonto), + + Festgeldkonto_7("26", AccountType.Festgeldkonto), + + Festgeldkonto_8("27", AccountType.Festgeldkonto), + + Festgeldkonto_9("28", AccountType.Festgeldkonto), + + Festgeldkonto_10("29", AccountType.Festgeldkonto), + + Wertpapierdepot_1("30", AccountType.Wertpapierdepot), + + Wertpapierdepot_2("31", AccountType.Wertpapierdepot), + + Wertpapierdepot_3("32", AccountType.Wertpapierdepot), + + Wertpapierdepot_4("33", AccountType.Wertpapierdepot), + + Wertpapierdepot_5("34", AccountType.Wertpapierdepot), + + Wertpapierdepot_6("35", AccountType.Wertpapierdepot), + + Wertpapierdepot_7("36", AccountType.Wertpapierdepot), + + Wertpapierdepot_8("37", AccountType.Wertpapierdepot), + + Wertpapierdepot_9("38", AccountType.Wertpapierdepot), + + Wertpapierdepot_10("39", AccountType.Wertpapierdepot), + + Darlehenskonto_1("40", AccountType.Darlehenskonto), + + Darlehenskonto_2("41", AccountType.Darlehenskonto), + + Darlehenskonto_3("42", AccountType.Darlehenskonto), + + Darlehenskonto_4("43", AccountType.Darlehenskonto), + + Darlehenskonto_5("44", AccountType.Darlehenskonto), + + Darlehenskonto_6("45", AccountType.Darlehenskonto), + + Darlehenskonto_7("46", AccountType.Darlehenskonto), + + Darlehenskonto_8("47", AccountType.Darlehenskonto), + + Darlehenskonto_9("48", AccountType.Darlehenskonto), + + Darlehenskonto_10("49", AccountType.Darlehenskonto), + + Kreditkartenkonto_1("50", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_2("51", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_3("52", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_4("53", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_5("54", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_6("55", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_7("56", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_8("57", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_9("58", AccountType.Kreditkartenkonto), + + Kreditkartenkonto_10("59", AccountType.Kreditkartenkonto), + + FondsDepot_1("60", AccountType.FondsDepot), + + FondsDepot_2("61", AccountType.FondsDepot), + + FondsDepot_3("62", AccountType.FondsDepot), + + FondsDepot_4("63", AccountType.FondsDepot), + + FondsDepot_5("64", AccountType.FondsDepot), + + FondsDepot_6("65", AccountType.FondsDepot), + + FondsDepot_7("66", AccountType.FondsDepot), + + FondsDepot_8("67", AccountType.FondsDepot), + + FondsDepot_9("68", AccountType.FondsDepot), + + FondsDepot_10("69", AccountType.FondsDepot), + + Bausparvertrag_1("70", AccountType.Bausparvertrag), + + Bausparvertrag_2("71", AccountType.Bausparvertrag), + + Bausparvertrag_3("72", AccountType.Bausparvertrag), + + Bausparvertrag_4("73", AccountType.Bausparvertrag), + + Bausparvertrag_5("74", AccountType.Bausparvertrag), + + Bausparvertrag_6("75", AccountType.Bausparvertrag), + + Bausparvertrag_7("76", AccountType.Bausparvertrag), + + Bausparvertrag_8("77", AccountType.Bausparvertrag), + + Bausparvertrag_9("78", AccountType.Bausparvertrag), + + Bausparvertrag_10("79", AccountType.Bausparvertrag), + + Versicherungsvertrag_1("80", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_2("81", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_3("82", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_4("83", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_5("84", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_6("85", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_7("86", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_8("87", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_9("88", AccountType.Versicherungsvertrag), + + Versicherungsvertrag_10("89", AccountType.Versicherungsvertrag), + + Sonstige_1("90", AccountType.Sonstige), + + Sonstige_2("91", AccountType.Sonstige), + + Sonstige_3("92", AccountType.Sonstige), + + Sonstige_4("93", AccountType.Sonstige), + + Sonstige_5("94", AccountType.Sonstige), + + Sonstige_6("95", AccountType.Sonstige), + + Sonstige_7("96", AccountType.Sonstige), + + Sonstige_8("97", AccountType.Sonstige), + + Sonstige_9("98", AccountType.Sonstige), + + Sonstige_10("99", AccountType.Sonstige) + +} \ No newline at end of file diff --git a/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/UserParameters.kt b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/UserParameters.kt new file mode 100644 index 00000000..5b0b2b51 --- /dev/null +++ b/fints4javaLib/src/main/kotlin/net/dankito/fints/response/segments/UserParameters.kt @@ -0,0 +1,25 @@ +package net.dankito.fints.response.segments + + +open class UserParameters( + val userIdentifier: String, + + /** + * Antwortet ein Kreditinstitut auf das Kundensegment HKVVB und der UPD-Version=0 im Segment HIUPA ebenfalls mit + * einer UPD-Version=0, so müssen im aktuellen Dialog diese übermittelten UPD verwendet werden; die UPD sind dann + * nur für diesen Dialog gültig. + */ + val updVersion: Int, + val areListedJobsBlocked: Boolean, + val username: String? = null, + + /** + * Die innere Struktur dieses Parameterfeldes ist nicht weiter spezifiziert und kann von den Partnern bilateral + * verwendet werden. Zur Selektion dieses neuen Datenelementes muss HKVVB (Verarbeitungsvorbereitung) mindestens + * in der Segmentversion 3 gesendet werden. + */ + val extension: String? = null, + segmentString: String + +) + : ReceivedSegment(segmentString) \ No newline at end of file diff --git a/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt b/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt index f301b42e..5d8c3758 100644 --- a/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt +++ b/fints4javaLib/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt @@ -7,10 +7,7 @@ import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionD import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Sicherheitsprofil import net.dankito.fints.messages.segmente.id.ISegmentId import net.dankito.fints.messages.segmente.id.MessageSegmentId -import net.dankito.fints.response.segments.BankParameters -import net.dankito.fints.response.segments.ReceivedMessageHeader -import net.dankito.fints.response.segments.ReceivedSynchronization -import net.dankito.fints.response.segments.SecurityMethods +import net.dankito.fints.response.segments.* import org.assertj.core.api.Assertions.assertThat import org.junit.Assert import org.junit.Test @@ -82,7 +79,6 @@ class ResponseParserTest { ?: run { Assert.fail("No segment of type BankParameters found in ${result.receivedSegments}") } } - @Test fun parseSecurityMethods() { @@ -107,6 +103,53 @@ class ResponseParserTest { } + @Test + fun parseUserParameters() { + + // when + val result = underTest.parse("HIUPA:6:4:4+3498443795+34+0++PERSNR0010789316542'") + + // then + assertSuccessfullyParsedSegment(result, InstituteSegmentId.UserParameters, 6, 4, 4) + + result.getFirstSegmentById(InstituteSegmentId.UserParameters)?.let { segment -> + assertThat(segment.userIdentifier).isEqualTo("3498443795") + assertThat(segment.updVersion).isEqualTo(34) + assertThat(segment.areListedJobsBlocked).isTrue() + assertThat(segment.username).isNull() + assertThat(segment.extension).isEqualTo("PERSNR0010789316542") + } + ?: run { Assert.fail("No segment of type UserParameters found in ${result.receivedSegments}") } + } + + @Test + fun parseAccountInfo() { + + // when + val result = underTest.parse("HIUPD:7:6:4+0987654321::280:12345678+DE11123456780987654321+2197654321+1+EUR+Hans Dampf++Sichteinlagen++HKSAK:1+HKISA:1+HKSSP:1+HKPAE:1+HKTSY:1+HKTAB:1+HKTAU:1+HKTAZ:1+HKSPA:1+HKPKA:1+HKPKB:1+HKPWE:1+HKPWA:1+HKPWB:1+HKPWL:1+HKCAZ:1+HKCCM:1+HKCCS:1+HKCDB:1+HKCDE:1+HKCDL:1+HKCDN:1+HKCDU:1+HKCMB:1+HKCME:1+HKCML:1+HKCSA:1+HKCSB:1+HKCSE:1+HKCSL:1+HKCUB:1+HKCUM:1+HKDSB:1+HKDSW:1+HKIPS:1+HKIPZ:1+HKPCR:1+HKPPD:1+DKPSA:1+DKPSP:1+HKTAN:1+DKANA:1+DKANL:1+DKKBA:1+DKDKL:1+DKBDK:1+DKBAZ:1+DKTCK:1+DKZDF:1+DKZDL:1+HKFRD:1+HKKDM:1+HKKAZ:1+HKKIF:1+HKSAL:1+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++{\n" + + "umsltzt\n" + + "?:'") + + // then + assertSuccessfullyParsedSegment(result, InstituteSegmentId.AccountInfo, 7, 6, 4) + + result.getFirstSegmentById(InstituteSegmentId.AccountInfo)?.let { segment -> + assertThat(segment.accountNumber).isEqualTo("0987654321") + assertThat(segment.subAccountAttribute).isNull() + assertThat(segment.bankCountryCode).isEqualTo(280) + assertThat(segment.bankCode).isEqualTo("12345678") + assertThat(segment.iban).isEqualTo("DE11123456780987654321") + assertThat(segment.customerId).isEqualTo("2197654321") + assertThat(segment.accountType).isEqualTo(AccountType.Girokonto) + assertThat(segment.currency).isEqualTo("EUR") + assertThat(segment.accountHolderName1).isEqualTo("Hans Dampf") + assertThat(segment.accountHolderName2).isNull() + assertThat(segment.productName).isEqualTo("Sichteinlagen") + } + ?: run { Assert.fail("No segment of type AccountInfo found in ${result.receivedSegments}") } + } + + private fun assertSuccessfullyParsedSegment(result: Response, segmentId: ISegmentId, segmentNumber: Int, segmentVersion: Int, referenceSegmentNumber: Int? = null) {