Started requesting balance and account transactions, but not fully working yet
This commit is contained in:
parent
8ac4f24476
commit
5329cc8418
|
@ -101,6 +101,39 @@ open class FinTsClient(
|
|||
}
|
||||
|
||||
|
||||
open fun getTransactions(bank: BankData, customer: CustomerData, product: ProductData): Response {
|
||||
val dialogData = DialogData()
|
||||
|
||||
val initDialogResponse = initDialog(bank, customer, product, dialogData)
|
||||
|
||||
if (initDialogResponse.successful == false) {
|
||||
return initDialogResponse
|
||||
}
|
||||
|
||||
|
||||
dialogData.increaseMessageNumber()
|
||||
|
||||
val balanceRequest = messageBuilder.createGetBalanceMessage(bank, customer, product, dialogData)
|
||||
|
||||
val balanceResponse = getAndHandleResponseForMessage(balanceRequest, bank)
|
||||
|
||||
if (balanceResponse.successful == false) {
|
||||
return balanceResponse
|
||||
}
|
||||
|
||||
|
||||
dialogData.increaseMessageNumber()
|
||||
|
||||
val requestBody = messageBuilder.createGetTransactionsMessage(bank, customer, product, dialogData)
|
||||
|
||||
val response = getAndHandleResponseForMessage(requestBody, bank)
|
||||
|
||||
closeDialog(bank, customer, dialogData)
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
||||
protected open fun getAndHandleResponseForMessage(requestBody: String, bank: BankData): Response {
|
||||
val webResponse = getResponseForMessage(requestBody, bank)
|
||||
|
||||
|
@ -149,6 +182,7 @@ open class FinTsClient(
|
|||
|
||||
protected open fun updateCustomerData(customer: CustomerData, response: Response) {
|
||||
response.getFirstSegmentById<BankParameters>(InstituteSegmentId.BankParameters)?.let { bankParameters ->
|
||||
// TODO: ask user if there is more than one supported language? But it seems that almost all banks only support German.
|
||||
if (customer.selectedLanguage == Dialogsprache.Default && bankParameters.supportedLanguages.isNotEmpty()) {
|
||||
customer.selectedLanguage = bankParameters.supportedLanguages.first()
|
||||
}
|
||||
|
|
|
@ -8,10 +8,12 @@ import net.dankito.fints.messages.segmente.SegmentNumberGenerator
|
|||
import net.dankito.fints.messages.segmente.Synchronisierung
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.messages.segmente.implementierte.*
|
||||
import net.dankito.fints.messages.segmente.implementierte.umsaetze.KontoumsaetzeZeitraumMt940Version5
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
import net.dankito.fints.model.DialogData
|
||||
import net.dankito.fints.model.ProductData
|
||||
import net.dankito.fints.messages.segmente.implementierte.umsaetze.Saldenabfrage
|
||||
import net.dankito.fints.util.FinTsUtils
|
||||
import java.util.concurrent.ThreadLocalRandom
|
||||
|
||||
|
@ -85,6 +87,28 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
}
|
||||
|
||||
|
||||
open fun createGetTransactionsMessage(bank: BankData, customer: CustomerData, product: ProductData, dialogData: DialogData): String {
|
||||
|
||||
return createSignedMessage(bank, customer, dialogData, listOf(
|
||||
KontoumsaetzeZeitraumMt940Version5(generator.resetSegmentNumber(2), bank, customer),
|
||||
ZweiSchrittTanEinreichung(generator.getNextSegmentNumber(), TanProcess.TanProcess4, CustomerSegmentId.AccountTransactionsMt940)
|
||||
))
|
||||
}
|
||||
|
||||
open fun createGetBalanceMessage(bank: BankData, customer: CustomerData, product: ProductData, dialogData: DialogData): String {
|
||||
|
||||
return createSignedMessage(bank, customer, dialogData, listOf(
|
||||
Saldenabfrage(
|
||||
generator.resetSegmentNumber(2),
|
||||
bank,
|
||||
customer,
|
||||
false
|
||||
),
|
||||
ZweiSchrittTanEinreichung(generator.getNextSegmentNumber(), TanProcess.TanProcess4, CustomerSegmentId.Balance)
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
open fun createSignedMessage(bank: BankData, customer: CustomerData, dialogData: DialogData,
|
||||
payloadSegments: List<Segment>): String {
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Information darüber, wie die Beantwortung des Kundenauftrags an einem bestimmten Punkt kontrolliert
|
||||
* beendet und aufgesetzt werden kann, falls die Rückmeldung des Kreditinstituts nicht in einem
|
||||
* einzigen Auftragssegment erfolgen kann (s. [Formals]).
|
||||
*/
|
||||
open class Aufsetzpunkt(continuationId: String, existenzstatus: Existenzstatus)
|
||||
: AlphanumerischesDatenelement(continuationId, existenzstatus, 35)
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.JaNein
|
||||
|
||||
|
||||
/**
|
||||
* Mit dieser Option kann gewählt werden, ob die angeforderten Informationen (z.B. Salden, Umsätze)
|
||||
* nur zu dem angegebenen oder zu allen Anlagekonten des Kunden, für die er eine
|
||||
* Zugriffsberechtigung besitzt, zurückgemeldet werden sollen.
|
||||
*/
|
||||
open class AlleKonten(allAccounts: Boolean, existenzstatus: Existenzstatus) : JaNein(allAccounts, existenzstatus)
|
|
@ -0,0 +1,7 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
open class BIC(bic: String, existenzstatus: Existenzstatus) : AlphanumerischesDatenelement(bic, existenzstatus, 11)
|
|
@ -0,0 +1,7 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
open class IBAN(iban: String, existenzstatus: Existenzstatus) : AlphanumerischesDatenelement(iban, existenzstatus, 34)
|
|
@ -0,0 +1,15 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation
|
||||
|
||||
|
||||
/**
|
||||
* Identifikationsnummer des Kontos (Kontonummer, Depotnummer, Kreditkartennummer etc.).
|
||||
* Das DE dient auch zur Aufnahme von internationalen (alphanumerischen) Kontonummern und
|
||||
* zukünftig 20-stelligen Kreditkartenkontonummern.
|
||||
*
|
||||
* Es ist zu beachten, dass Kontonummern auch führende Nullen beinhalten können, die
|
||||
* bankfachlich relevant sind und nicht abgeschnitten werden dürfen.
|
||||
*/
|
||||
open class KontoDepotnummer(number: String, existenzstatus: Existenzstatus) : Identifikation(number, existenzstatus)
|
|
@ -0,0 +1,11 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Maximale Anzahl rückzumeldender Einträge bei Abholaufträgen, Kreditinstitutsangeboten
|
||||
* oder –informationen (vgl. [Formals], Kap. B.6.3).
|
||||
*/
|
||||
open class MaximaleAnzahlEintraege(maxAmount: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(maxAmount, 4, existenzstatus)
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation
|
||||
|
||||
|
||||
/**
|
||||
* Unterkontonummer, falls unter einer Kontonummer verschiedene Unterkonten (z.B. Währungskonten)
|
||||
* geführt werden. Anstatt einer Kontonummer kann auch ein anderes identifizierendes Merkmal
|
||||
* angegeben werden (z.B. der entsprechende ISO-Währungscode bei Währungskonten).
|
||||
*/
|
||||
open class Unterkontomerkmal(attribute: String, existenzstatus: Existenzstatus) : Identifikation(attribute, existenzstatus)
|
|
@ -0,0 +1,29 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.KontoDepotnummer
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.Unterkontomerkmal
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung
|
||||
|
||||
|
||||
/**
|
||||
* Anhand dieses Formats können sowohl deutsche als auch internationale Bankverbindungen beschrieben
|
||||
* werden. Die Belegung für wichtige europäische Länder ist dem Kapitel E.5 zu entnehmen.
|
||||
*
|
||||
* Falls bei einem Institut unter einer Kontonummer verschiedene Konten mit unterschiedlichen Merkmalen
|
||||
* geführt werden (z.B. verschiedene Währungen oder Festgeldanlagen), wird von diesem Institut in den
|
||||
* UPD zu jeder dieser Kontonummern zur Unterscheidung zusätzlich ein „Unterkontomerkmal“ angegeben.
|
||||
* Dieser ist dann bei jeder Auftraggeberkontoverbindung anzugeben.
|
||||
*/
|
||||
open class Kontoverbindung(
|
||||
bankCountryCode: Int,
|
||||
bankCode: String,
|
||||
accountNumber: String,
|
||||
subAccountAttribute: String? = null
|
||||
|
||||
) : Datenelementgruppe(listOf(
|
||||
KontoDepotnummer(accountNumber, Existenzstatus.Mandatory),
|
||||
Unterkontomerkmal(subAccountAttribute ?: "", Existenzstatus.Optional),
|
||||
Kreditinstitutskennung(bankCountryCode, bankCode)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,37 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.account
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.BIC
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.IBAN
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.KontoDepotnummer
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.Unterkontomerkmal
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
|
||||
|
||||
/**
|
||||
* Die Kontoverbindung international dient zur Verwendung von IBAN und BIC sowie auch der
|
||||
* nationalen Elemente Kreditinstitutskennung und Konto-/Depotnummer mit optionalem
|
||||
* Unterkontomerkmal, strukturell angelehnt an das Aggregate „Account“ in ISO20022.
|
||||
*/
|
||||
open class KontoverbindungInternational(
|
||||
iban: String?,
|
||||
bic: String?,
|
||||
bankCountryCode: Int? = null,
|
||||
bankCode: String? = null,
|
||||
accountNumber: String? = null,
|
||||
subAccountAttribute: String? = null
|
||||
|
||||
) : Datenelementgruppe(listOf(
|
||||
IBAN(iban ?: "", Existenzstatus.Optional),
|
||||
BIC(bic ?: "", Existenzstatus.Optional),
|
||||
KontoDepotnummer(accountNumber ?: "", Existenzstatus.Optional),
|
||||
Unterkontomerkmal(subAccountAttribute ?: "", Existenzstatus.Optional),
|
||||
Kreditinstitutskennung(bankCountryCode ?: 0, bankCode ?: "", Existenzstatus.Optional)
|
||||
), Existenzstatus.Mandatory) {
|
||||
|
||||
constructor(bank: BankData, customer: CustomerData, subAccountAttribute: String?)
|
||||
: this(customer.iban, bank.bic, bank.countryCode, bank.bankCode, customer.customerId, subAccountAttribute)
|
||||
}
|
|
@ -11,6 +11,10 @@ enum class CustomerSegmentId(override val id: String) : ISegmentId {
|
|||
|
||||
Synchronization("HKSYN"),
|
||||
|
||||
Tan("HKTAN")
|
||||
Tan("HKTAN"),
|
||||
|
||||
Balance("HKSAL"),
|
||||
|
||||
AccountTransactionsMt940("HKKAZ")
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Datum
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.AlleKonten
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
|
||||
|
||||
/**
|
||||
* Die Lösung bietet dem Kunden die Möglichkeit, auf seinem System verlorengegangene Buchungen erneut zu erhalten.
|
||||
*
|
||||
* Die maximale Anzahl der rückzumeldenden Buchungspositionen kann begrenzt werden. Eine Buchungsposition besteht
|
||||
* aus einem :61:/:86:-Block eines MT 940-Formats. Es muss davon unabhängig immer ein gültiges MT 940-Format
|
||||
* zurückgemeldet werden, d.h. die Felder :20: bis :60: und :62: bis :86: sind obligatorischer Bestandteil der Rückmeldung.
|
||||
*
|
||||
* Der maximale Zeitraum, für den rückwirkend Buchungen beim Kreditinstitut gespeichert sind, wird in den
|
||||
* Bankparameterdaten übermittelt.
|
||||
*/
|
||||
abstract class KontoumsaetzeZeitraumMt940Base(
|
||||
segmentVersion: Int,
|
||||
segmentNumber: Int,
|
||||
account: Datenelementgruppe,
|
||||
allAccounts: Boolean = false,
|
||||
fromDate: Int? = null,
|
||||
toDate: Int? = null,
|
||||
maxAmount: Int? = null,
|
||||
continuationId: String? = null
|
||||
)
|
||||
: Segment(listOf(
|
||||
Segmentkopf(CustomerSegmentId.AccountTransactionsMt940, segmentVersion, segmentNumber),
|
||||
account,
|
||||
AlleKonten(allAccounts, Existenzstatus.Mandatory),
|
||||
Datum(fromDate ?: 0, Existenzstatus.Optional)
|
||||
// Datum(toDate ?: 0, Existenzstatus.Optional),
|
||||
// MaximaleAnzahlEintraege(maxAmount ?: 0, Existenzstatus.Optional), // > 0. O: „Eingabe Anzahl Einträge erlaubt“ (BPD) = „J“. N: sonst
|
||||
// Aufsetzpunkt(continuationId ?: "", Existenzstatus.Optional) // M: vom Institut wurde ein Aufsetzpunkt rückgemeldet. N: sonst
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,38 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
|
||||
|
||||
/**
|
||||
* Die Lösung bietet dem Kunden die Möglichkeit, auf seinem System verlorengegangene Buchungen erneut zu erhalten.
|
||||
*
|
||||
* Die maximale Anzahl der rückzumeldenden Buchungspositionen kann begrenzt werden. Eine Buchungsposition besteht
|
||||
* aus einem :61:/:86:-Block eines MT 940-Formats. Es muss davon unabhängig immer ein gültiges MT 940-Format
|
||||
* zurückgemeldet werden, d.h. die Felder :20: bis :60: und :62: bis :86: sind obligatorischer Bestandteil der Rückmeldung.
|
||||
*
|
||||
* Der maximale Zeitraum, für den rückwirkend Buchungen beim Kreditinstitut gespeichert sind, wird in den
|
||||
* Bankparameterdaten übermittelt.
|
||||
*/
|
||||
open class KontoumsaetzeZeitraumMt940Version5(
|
||||
segmentNumber: Int,
|
||||
bank: BankData,
|
||||
customer: CustomerData,
|
||||
subAccountAttribute: String? = null,
|
||||
allAccounts: Boolean = false,
|
||||
fromDate: Int? = null,
|
||||
toDate: Int? = null,
|
||||
maxAmount: Int? = null,
|
||||
continuationId: String? = null
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(
|
||||
5,
|
||||
segmentNumber,
|
||||
Kontoverbindung(bank.countryCode, bank.bankCode, customer.customerId, subAccountAttribute),
|
||||
allAccounts,
|
||||
fromDate,
|
||||
toDate,
|
||||
maxAmount,
|
||||
continuationId
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.KontoverbindungInternational
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
|
||||
|
||||
/**
|
||||
* Die Lösung bietet dem Kunden die Möglichkeit, auf seinem System verlorengegangene Buchungen erneut zu erhalten.
|
||||
*
|
||||
* Die maximale Anzahl der rückzumeldenden Buchungspositionen kann begrenzt werden. Eine Buchungsposition besteht
|
||||
* aus einem :61:/:86:-Block eines MT 940-Formats. Es muss davon unabhängig immer ein gültiges MT 940-Format
|
||||
* zurückgemeldet werden, d.h. die Felder :20: bis :60: und :62: bis :86: sind obligatorischer Bestandteil der Rückmeldung.
|
||||
*
|
||||
* Der maximale Zeitraum, für den rückwirkend Buchungen beim Kreditinstitut gespeichert sind, wird in den
|
||||
* Bankparameterdaten übermittelt.
|
||||
*/
|
||||
open class KontoumsaetzeZeitraumMt940Version7(
|
||||
segmentNumber: Int,
|
||||
bank: BankData,
|
||||
customer: CustomerData,
|
||||
subAccountAttribute: String? = null, // TODO: move to CustomerData.accounts
|
||||
allAccounts: Boolean = false,
|
||||
fromDate: Int? = null,
|
||||
toDate: Int? = null,
|
||||
maxAmount: Int? = null,
|
||||
continuationId: String? = null
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(
|
||||
7,
|
||||
segmentNumber,
|
||||
KontoverbindungInternational(bank, customer, subAccountAttribute),
|
||||
allAccounts,
|
||||
fromDate,
|
||||
toDate,
|
||||
maxAmount,
|
||||
continuationId
|
||||
)
|
|
@ -0,0 +1,26 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.account.AlleKonten
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
|
||||
|
||||
open class Saldenabfrage(
|
||||
segmentNumber: Int,
|
||||
bank: BankData,
|
||||
customer: CustomerData, // TODO: pass AccountData instead
|
||||
allAccounts: Boolean,
|
||||
maxAmountEntries: Int? = null
|
||||
)
|
||||
: Segment(listOf(
|
||||
Segmentkopf(CustomerSegmentId.Balance, 5, segmentNumber),
|
||||
Kontoverbindung(bank.countryCode, bank.bankCode, customer.customerId),
|
||||
AlleKonten(allAccounts, Existenzstatus.Mandatory)
|
||||
// MaximaleAnzahlEintraege(maxAmountEntries ?: 0, Existenzstatus.Optional),
|
||||
// Aufsetzpunkt("", Existenzstatus.Optional)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,37 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.FinTsTestBase
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class SaldenabfrageTest : FinTsTestBase() {
|
||||
|
||||
@Test
|
||||
fun format_NotAllAccounts() {
|
||||
|
||||
// given
|
||||
val underTest =
|
||||
Saldenabfrage(3, Bank, Customer, false)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("HKSAL:3:5+$CustomerId::280:$BankCode+N")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun format_AllAccounts() {
|
||||
|
||||
// given
|
||||
val underTest =
|
||||
Saldenabfrage(3, Bank, Customer, true)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("HKSAL:3:5+$CustomerId::280:$BankCode+J")
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue