Implemented transferMoney()
This commit is contained in:
parent
6512f45955
commit
8671bf058d
|
@ -2,10 +2,7 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.dankito.banking.client.model.AccountTransaction
|
import net.dankito.banking.client.model.AccountTransaction
|
||||||
import net.dankito.banking.fints.model.TanChallenge
|
import net.dankito.banking.fints.model.TanChallenge
|
||||||
import react.RBuilder
|
import react.*
|
||||||
import react.RComponent
|
|
||||||
import react.Props
|
|
||||||
import react.State
|
|
||||||
import react.dom.*
|
import react.dom.*
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
|
@ -13,7 +10,8 @@ external interface AccountTransactionsViewProps : Props {
|
||||||
var presenter: Presenter
|
var presenter: Presenter
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AccountTransactionsViewState(val balance: String, val transactions: Collection<AccountTransaction>, val enterTanChallenge: TanChallenge? = null) : State
|
data class AccountTransactionsViewState(val balance: String, val transactions: Collection<AccountTransaction>, var showTransferMoneyView: Boolean = false,
|
||||||
|
val enterTanChallenge: TanChallenge? = null) : State
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent<AccountTransactionsViewProps, AccountTransactionsViewState>(props) {
|
class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent<AccountTransactionsViewProps, AccountTransactionsViewState>(props) {
|
||||||
|
@ -22,7 +20,7 @@ class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent<
|
||||||
init {
|
init {
|
||||||
state = AccountTransactionsViewState("", listOf())
|
state = AccountTransactionsViewState("", listOf())
|
||||||
|
|
||||||
props.presenter.enterTanCallback = { setState(AccountTransactionsViewState(state.balance, state.transactions, it)) }
|
props.presenter.enterTanCallback = { setState(AccountTransactionsViewState(state.balance, state.transactions, state.showTransferMoneyView, it)) }
|
||||||
|
|
||||||
// due to CORS your bank's servers can not be requested directly from browser -> set a CORS proxy url in main.kt
|
// due to CORS your bank's servers can not be requested directly from browser -> set a CORS proxy url in main.kt
|
||||||
// TODO: set your credentials here
|
// TODO: set your credentials here
|
||||||
|
@ -47,6 +45,21 @@ class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
span { +"Transfer Money" }
|
||||||
|
attrs {
|
||||||
|
onMouseUp = { setState { showTransferMoneyView = !showTransferMoneyView } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.showTransferMoneyView) {
|
||||||
|
child(TransferMoneyView::class) {
|
||||||
|
attrs {
|
||||||
|
presenter = props.presenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
+"Saldo: ${state.balance}"
|
+"Saldo: ${state.balance}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,12 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
||||||
|
import net.dankito.banking.client.model.parameter.TransferMoneyParameter
|
||||||
import net.dankito.banking.client.model.response.GetAccountDataResponse
|
import net.dankito.banking.client.model.response.GetAccountDataResponse
|
||||||
|
import net.dankito.banking.client.model.response.TransferMoneyResponse
|
||||||
import net.dankito.banking.fints.FinTsClient
|
import net.dankito.banking.fints.FinTsClient
|
||||||
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
||||||
import net.dankito.banking.fints.model.TanChallenge
|
import net.dankito.banking.fints.model.*
|
||||||
import net.dankito.banking.fints.model.TanMethod
|
|
||||||
import net.dankito.banking.fints.model.TanMethodType
|
|
||||||
import net.dankito.banking.fints.webclient.KtorWebClient
|
import net.dankito.banking.fints.webclient.KtorWebClient
|
||||||
import net.dankito.banking.fints.webclient.ProxyingWebClient
|
import net.dankito.banking.fints.webclient.ProxyingWebClient
|
||||||
import net.dankito.utils.multiplatform.log.LoggerFactory
|
import net.dankito.utils.multiplatform.log.LoggerFactory
|
||||||
|
@ -44,4 +44,23 @@ open class Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun transferMoney(recipientName: String, recipientAccountIdentifier: String, recipientBankIdentifier: String?, reference: String?,
|
||||||
|
amount: String, instantPayment: Boolean = false, response: (TransferMoneyResponse) -> Unit) {
|
||||||
|
GlobalScope.launch(Dispatchers.Unconfined) {
|
||||||
|
// TODO: set your credentials here
|
||||||
|
val transferMoneyResponse = fintsClient.transferMoneyAsync(TransferMoneyParameter("", "", "", null, recipientName,
|
||||||
|
recipientAccountIdentifier, recipientBankIdentifier, Money(Amount(amount), Currency.DefaultCurrencyCode), reference, instantPayment))
|
||||||
|
|
||||||
|
if (transferMoneyResponse.successful) {
|
||||||
|
log.info("Successfully transferred $amount to $recipientName")
|
||||||
|
} else {
|
||||||
|
log.error("Could not transfer $amount to $recipientName: ${transferMoneyResponse.error} ${transferMoneyResponse.errorMessage}")
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
response(transferMoneyResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import react.*
|
||||||
|
import react.dom.html.ReactHTML.div
|
||||||
|
import react.dom.html.ReactHTML.input
|
||||||
|
import react.dom.html.ReactHTML.span
|
||||||
|
|
||||||
|
external interface TextInputFieldProps : Props {
|
||||||
|
var label: String
|
||||||
|
var valueChanged: (String) -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val TextInputField = FC<TextInputFieldProps> { props ->
|
||||||
|
|
||||||
|
div {
|
||||||
|
span { +"${props.label}: " }
|
||||||
|
|
||||||
|
input {
|
||||||
|
type = react.dom.html.InputType.text
|
||||||
|
onChange = { event ->
|
||||||
|
val enteredValue = event.target.value
|
||||||
|
|
||||||
|
props.valueChanged(enteredValue)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
import react.*
|
||||||
|
import react.dom.*
|
||||||
|
|
||||||
|
external interface TransferMoneyViewProps : Props {
|
||||||
|
var presenter: Presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
class TransferMoneyViewState(var recipientName: String = "", var recipientAccountIdentifier: String = "", var recipientBankIdentifier: String? = null,
|
||||||
|
var reference: String = "", var amount: String = "", var instantPayment: Boolean = false) : State
|
||||||
|
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class TransferMoneyView(props: TransferMoneyViewProps) : RComponent<TransferMoneyViewProps, TransferMoneyViewState>(props) {
|
||||||
|
|
||||||
|
override fun RBuilder.render() {
|
||||||
|
div {
|
||||||
|
TextInputField {
|
||||||
|
attrs {
|
||||||
|
label = "Recipient name"
|
||||||
|
valueChanged = { newValue -> setState { recipientName = newValue } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInputField {
|
||||||
|
attrs {
|
||||||
|
label = "IBAN"
|
||||||
|
valueChanged = { newValue -> setState { recipientAccountIdentifier = newValue } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInputField {
|
||||||
|
attrs {
|
||||||
|
label = "Amount"
|
||||||
|
valueChanged = { newValue -> setState { amount = newValue } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInputField {
|
||||||
|
attrs {
|
||||||
|
label = "Reference"
|
||||||
|
valueChanged = { newValue -> setState { reference = newValue } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
button {
|
||||||
|
span { +"Transfer" }
|
||||||
|
attrs {
|
||||||
|
onMouseUp = {
|
||||||
|
props.presenter.transferMoney(state.recipientName, state.recipientAccountIdentifier, state.recipientBankIdentifier, state.reference, state.amount, state.instantPayment) { } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,5 @@
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.browser.window
|
import kotlinx.browser.window
|
||||||
import net.dankito.banking.fints.FinTsClientDeprecated
|
|
||||||
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
|
||||||
import net.dankito.banking.fints.webclient.KtorWebClient
|
|
||||||
import net.dankito.banking.fints.webclient.ProxyingWebClient
|
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package net.dankito.banking.client.model.parameter
|
||||||
|
|
||||||
|
import net.dankito.banking.client.model.BankAccountIdentifier
|
||||||
|
import net.dankito.banking.fints.model.BankData
|
||||||
|
import net.dankito.banking.fints.model.Money
|
||||||
|
import net.dankito.banking.fints.model.TanMethodType
|
||||||
|
|
||||||
|
|
||||||
|
open class TransferMoneyParameter(
|
||||||
|
bankCode: String,
|
||||||
|
loginName: String,
|
||||||
|
password: String,
|
||||||
|
/**
|
||||||
|
* The account from which the money should be withdrawn.
|
||||||
|
* If not specified fints4k retrieves all bank accounts and checks if there is exactly one that supports money transfer.
|
||||||
|
* If no or more than one bank account supports money transfer, the error codes NoAccountSupportsMoneyTransfer or MoreThanOneAccountSupportsMoneyTransfer are returned.
|
||||||
|
*/
|
||||||
|
open val remittanceAccount: BankAccountIdentifier? = null,
|
||||||
|
|
||||||
|
open val recipientName: String,
|
||||||
|
/**
|
||||||
|
* The identifier of recipient's account. In most cases the IBAN.
|
||||||
|
*/
|
||||||
|
open val recipientAccountIdentifier: String,
|
||||||
|
/**
|
||||||
|
* The identifier of recipient's bank. In most cases the BIC.
|
||||||
|
* Can be omitted for German banks as the BIC can be derived from IBAN.
|
||||||
|
*/
|
||||||
|
open val recipientBankIdentifier: String? = null,
|
||||||
|
|
||||||
|
open val amount: Money,
|
||||||
|
open val reference: String? = null,
|
||||||
|
open val instantPayment: Boolean = false,
|
||||||
|
|
||||||
|
preferredTanMethods: List<TanMethodType>? = null,
|
||||||
|
preferredTanMedium: String? = null,
|
||||||
|
abortIfTanIsRequired: Boolean = false,
|
||||||
|
finTsModel: BankData? = null
|
||||||
|
|
||||||
|
) : FinTsClientParameter(bankCode, loginName, password, preferredTanMethods, preferredTanMedium, abortIfTanIsRequired, finTsModel)
|
|
@ -21,6 +21,10 @@ enum class ErrorCode {
|
||||||
|
|
||||||
NoneOfTheAccountsSupportsRetrievingData,
|
NoneOfTheAccountsSupportsRetrievingData,
|
||||||
|
|
||||||
DidNotRetrieveAllAccountData
|
DidNotRetrieveAllAccountData,
|
||||||
|
|
||||||
|
NoAccountSupportsMoneyTransfer,
|
||||||
|
|
||||||
|
MoreThanOneAccountSupportsMoneyTransfer
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,4 +15,7 @@ open class FinTsClientResponse(
|
||||||
open val successful: Boolean
|
open val successful: Boolean
|
||||||
get() = error == null
|
get() = error == null
|
||||||
|
|
||||||
|
open val errorCodeAndMessage: String
|
||||||
|
get() = "$error${errorMessage?.let { " $it" }}}"
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.dankito.banking.client.model.response
|
||||||
|
|
||||||
|
import net.dankito.banking.fints.model.BankData
|
||||||
|
import net.dankito.banking.fints.model.MessageLogEntry
|
||||||
|
|
||||||
|
|
||||||
|
open class TransferMoneyResponse(
|
||||||
|
error: ErrorCode?,
|
||||||
|
errorMessage: String?,
|
||||||
|
messageLogWithoutSensitiveData: List<MessageLogEntry>,
|
||||||
|
finTsModel: BankData? = null
|
||||||
|
) : FinTsClientResponse(error, errorMessage, messageLogWithoutSensitiveData, finTsModel)
|
|
@ -1,12 +1,15 @@
|
||||||
package net.dankito.banking.fints
|
package net.dankito.banking.fints
|
||||||
|
|
||||||
import kotlinx.datetime.LocalDate
|
import kotlinx.datetime.LocalDate
|
||||||
|
import net.dankito.banking.client.model.parameter.FinTsClientParameter
|
||||||
import net.dankito.banking.fints.callback.FinTsClientCallback
|
import net.dankito.banking.fints.callback.FinTsClientCallback
|
||||||
import net.dankito.banking.fints.model.*
|
import net.dankito.banking.fints.model.*
|
||||||
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
||||||
import net.dankito.banking.client.model.parameter.RetrieveTransactions
|
import net.dankito.banking.client.model.parameter.RetrieveTransactions
|
||||||
|
import net.dankito.banking.client.model.parameter.TransferMoneyParameter
|
||||||
import net.dankito.banking.client.model.response.ErrorCode
|
import net.dankito.banking.client.model.response.ErrorCode
|
||||||
import net.dankito.banking.client.model.response.GetAccountDataResponse
|
import net.dankito.banking.client.model.response.GetAccountDataResponse
|
||||||
|
import net.dankito.banking.client.model.response.TransferMoneyResponse
|
||||||
import net.dankito.banking.fints.mapper.FinTsModelMapper
|
import net.dankito.banking.fints.mapper.FinTsModelMapper
|
||||||
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||||
import net.dankito.banking.fints.response.client.GetAccountInfoResponse
|
import net.dankito.banking.fints.response.client.GetAccountInfoResponse
|
||||||
|
@ -109,7 +112,52 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
return LocalDate.todayAtEuropeBerlin().minusDays(90)
|
return LocalDate.todayAtEuropeBerlin().minusDays(90)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open suspend fun getAccountInfo(param: GetAccountDataParameter, bank: BankData): GetAccountInfoResponse {
|
|
||||||
|
open suspend fun transferMoneyAsync(param: TransferMoneyParameter): TransferMoneyResponse {
|
||||||
|
val finTsServerAddress = finTsServerAddressFinder.findFinTsServerAddress(param.bankCode)
|
||||||
|
if (finTsServerAddress.isNullOrBlank()) {
|
||||||
|
return TransferMoneyResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not FinTS 3.0 or we don't know its FinTS server address", listOf(), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bank = BankData(param.bankCode, param.loginName, param.password, finTsServerAddress, "")
|
||||||
|
val remittanceAccount = param.remittanceAccount
|
||||||
|
|
||||||
|
if (remittanceAccount == null) { // then first retrieve customer's bank accounts
|
||||||
|
val getAccountInfoResponse = getAccountInfo(param, bank)
|
||||||
|
|
||||||
|
if (getAccountInfoResponse.successful == false) {
|
||||||
|
return TransferMoneyResponse(mapper.mapErrorCode(getAccountInfoResponse), mapper.mapErrorMessages(getAccountInfoResponse),
|
||||||
|
getAccountInfoResponse.messageLogWithoutSensitiveData, bank)
|
||||||
|
} else {
|
||||||
|
return transferMoneyAsync(param, getAccountInfoResponse.bank, getAccountInfoResponse.bank.accounts, getAccountInfoResponse)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return transferMoneyAsync(param, bank, listOf(mapper.mapToAccountData(remittanceAccount, param)), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open suspend fun transferMoneyAsync(param: TransferMoneyParameter, bank: BankData, accounts: List<AccountData>, previousJobResponse: FinTsClientResponse?): TransferMoneyResponse {
|
||||||
|
val accountsSupportingTransfer = accounts.filter { it.supportsTransferringMoney }
|
||||||
|
if (accountsSupportingTransfer.isEmpty()) {
|
||||||
|
return TransferMoneyResponse(ErrorCode.NoAccountSupportsMoneyTransfer, "None of the accounts $accounts supports money transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank)
|
||||||
|
} else if (accountsSupportingTransfer.size > 1) {
|
||||||
|
return TransferMoneyResponse(ErrorCode.MoreThanOneAccountSupportsMoneyTransfer, "More than one of the accounts $accountsSupportingTransfer supports money transfer, so we cannot clearly determine which one to use for this transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank)
|
||||||
|
}
|
||||||
|
|
||||||
|
val recipientBankIdentifier = param.recipientBankIdentifier ?: "" // TODO: determine BIC from recipientBankCode if it's a German bank
|
||||||
|
val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, accountsSupportingTransfer.first())
|
||||||
|
|
||||||
|
val response = jobExecutor.transferMoneyAsync(context, BankTransferData(param.recipientName, param.recipientAccountIdentifier, recipientBankIdentifier, param.amount, param.reference, param.instantPayment))
|
||||||
|
|
||||||
|
return TransferMoneyResponse(mapper.mapErrorCode(response), mapper.mapErrorMessages(response), mapper.mergeMessageLog(previousJobResponse, response), bank)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open suspend fun getAccountInfo(param: FinTsClientParameter, bank: BankData): GetAccountInfoResponse {
|
||||||
|
param.finTsModel?.let {
|
||||||
|
// TODO: implement
|
||||||
|
// return GetAccountInfoResponse(it)
|
||||||
|
}
|
||||||
|
|
||||||
val context = JobContext(JobContextType.AddAccount, this.callback, product, bank) // TODO: add / change JobContextType
|
val context = JobContext(JobContextType.AddAccount, this.callback, product, bank) // TODO: add / change JobContextType
|
||||||
|
|
||||||
/* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */
|
/* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */
|
||||||
|
|
|
@ -10,9 +10,7 @@ import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.*
|
||||||
import net.dankito.banking.fints.model.*
|
import net.dankito.banking.fints.model.*
|
||||||
import net.dankito.banking.fints.response.BankResponse
|
import net.dankito.banking.fints.response.BankResponse
|
||||||
import net.dankito.banking.fints.response.client.*
|
import net.dankito.banking.fints.response.client.*
|
||||||
import net.dankito.banking.fints.response.segments.*
|
|
||||||
import net.dankito.banking.fints.webclient.IWebClient
|
import net.dankito.banking.fints.webclient.IWebClient
|
||||||
import kotlin.jvm.JvmOverloads
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,7 +164,7 @@ open class FinTsClientDeprecated(
|
||||||
open suspend fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData, account: AccountData): FinTsClientResponse {
|
open suspend fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData, account: AccountData): FinTsClientResponse {
|
||||||
val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, account)
|
val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, account)
|
||||||
|
|
||||||
return jobExecutor.doBankTransferAsync(context, bankTransferData)
|
return jobExecutor.transferMoneyAsync(context, bankTransferData)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -342,7 +342,7 @@ open class FinTsJobExecutor(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open suspend fun doBankTransferAsync(context: JobContext, bankTransferData: BankTransferData): FinTsClientResponse {
|
open suspend fun transferMoneyAsync(context: JobContext, bankTransferData: BankTransferData): FinTsClientResponse {
|
||||||
|
|
||||||
val response = sendMessageInNewDialogAndHandleResponse(context, null, true) {
|
val response = sendMessageInNewDialogAndHandleResponse(context, null, true) {
|
||||||
val updatedAccount = getUpdatedAccount(context, context.account!!)
|
val updatedAccount = getUpdatedAccount(context, context.account!!)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.dankito.banking.fints.mapper
|
||||||
|
|
||||||
import net.dankito.banking.client.model.*
|
import net.dankito.banking.client.model.*
|
||||||
import net.dankito.banking.client.model.AccountTransaction
|
import net.dankito.banking.client.model.AccountTransaction
|
||||||
|
import net.dankito.banking.client.model.parameter.FinTsClientParameter
|
||||||
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
||||||
import net.dankito.banking.client.model.response.ErrorCode
|
import net.dankito.banking.client.model.response.ErrorCode
|
||||||
import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Laenderkennzeichen
|
import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Laenderkennzeichen
|
||||||
|
@ -13,13 +14,15 @@ import net.dankito.banking.fints.response.segments.AccountType
|
||||||
|
|
||||||
open class FinTsModelMapper {
|
open class FinTsModelMapper {
|
||||||
|
|
||||||
open fun mapToAccountData(credentials: BankAccountIdentifier, param: GetAccountDataParameter): AccountData {
|
open fun mapToAccountData(credentials: BankAccountIdentifier, param: FinTsClientParameter): AccountData {
|
||||||
val accountData = AccountData(credentials.identifier, credentials.subAccountNumber, Laenderkennzeichen.Germany, param.bankCode,
|
val accountData = AccountData(credentials.identifier, credentials.subAccountNumber, Laenderkennzeichen.Germany, param.bankCode,
|
||||||
credentials.iban, param.loginName, null, null, "", null, null, listOf(), listOf())
|
credentials.iban, param.loginName, null, null, "", null, null, listOf(), listOf())
|
||||||
|
|
||||||
// TODO: where to know from if account supports retrieving balance and transactions?
|
// TODO: where to know from if account supports retrieving balance and transactions?
|
||||||
accountData.setSupportsFeature(AccountFeature.RetrieveBalance, true)
|
accountData.setSupportsFeature(AccountFeature.RetrieveBalance, true)
|
||||||
accountData.setSupportsFeature(AccountFeature.RetrieveAccountTransactions, true)
|
accountData.setSupportsFeature(AccountFeature.RetrieveAccountTransactions, true)
|
||||||
|
accountData.setSupportsFeature(AccountFeature.TransferMoney, true)
|
||||||
|
accountData.setSupportsFeature(AccountFeature.RealTimeTransfer, true)
|
||||||
|
|
||||||
return accountData
|
return accountData
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ open class SepaBankTransferBase(
|
||||||
"RecipientIban" to data.recipientAccountId.replace(" ", ""),
|
"RecipientIban" to data.recipientAccountId.replace(" ", ""),
|
||||||
"RecipientBic" to data.recipientBankCode.replace(" ", ""),
|
"RecipientBic" to data.recipientBankCode.replace(" ", ""),
|
||||||
"Amount" to data.amount.amount.string.replace(',', '.'), // TODO: check if ',' or '.' should be used as decimal separator
|
"Amount" to data.amount.amount.string.replace(',', '.'), // TODO: check if ',' or '.' should be used as decimal separator
|
||||||
"Reference" to if (data.reference.isEmpty()) " " else messageCreator.convertDiacriticsAndReservedXmlCharacters(data.reference),
|
"Reference" to if (data.reference.isNullOrBlank()) " " else messageCreator.convertDiacriticsAndReservedXmlCharacters(data.reference),
|
||||||
"RequestedExecutionDate" to RequestedExecutionDateValueForNotScheduledTransfers
|
"RequestedExecutionDate" to RequestedExecutionDateValueForNotScheduledTransfers
|
||||||
),
|
),
|
||||||
messageCreator
|
messageCreator
|
||||||
|
|
|
@ -6,6 +6,6 @@ open class BankTransferData(
|
||||||
val recipientAccountId: String,
|
val recipientAccountId: String,
|
||||||
val recipientBankCode: String,
|
val recipientBankCode: String,
|
||||||
val amount: Money,
|
val amount: Money,
|
||||||
val reference: String,
|
val reference: String?,
|
||||||
val realTimeTransfer: Boolean = false
|
val realTimeTransfer: Boolean = false
|
||||||
)
|
)
|
|
@ -2,26 +2,29 @@ import kotlinx.datetime.LocalDate
|
||||||
import net.dankito.banking.client.model.AccountTransaction
|
import net.dankito.banking.client.model.AccountTransaction
|
||||||
import net.dankito.banking.client.model.CustomerAccount
|
import net.dankito.banking.client.model.CustomerAccount
|
||||||
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
||||||
|
import net.dankito.banking.client.model.parameter.TransferMoneyParameter
|
||||||
import net.dankito.banking.fints.FinTsClient
|
import net.dankito.banking.fints.FinTsClient
|
||||||
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
import net.dankito.banking.fints.callback.SimpleFinTsClientCallback
|
||||||
import net.dankito.banking.fints.getAccountData
|
import net.dankito.banking.fints.getAccountData
|
||||||
import net.dankito.banking.fints.model.TanChallenge
|
import net.dankito.banking.fints.model.TanChallenge
|
||||||
|
import net.dankito.banking.fints.transferMoney
|
||||||
import net.dankito.utils.multiplatform.extensions.*
|
import net.dankito.utils.multiplatform.extensions.*
|
||||||
|
|
||||||
|
|
||||||
class NativeApp {
|
class NativeApp {
|
||||||
|
|
||||||
|
private val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) })
|
||||||
|
|
||||||
|
|
||||||
fun retrieveAccountData(bankCode: String, loginName: String, password: String) {
|
fun retrieveAccountData(bankCode: String, loginName: String, password: String) {
|
||||||
retrieveAccountData(GetAccountDataParameter(bankCode, loginName, password))
|
retrieveAccountData(GetAccountDataParameter(bankCode, loginName, password))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun retrieveAccountData(param: GetAccountDataParameter) {
|
fun retrieveAccountData(param: GetAccountDataParameter) {
|
||||||
val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) })
|
|
||||||
|
|
||||||
val response = client.getAccountData(param)
|
val response = client.getAccountData(param)
|
||||||
|
|
||||||
if (response.error != null) {
|
if (response.error != null) {
|
||||||
println("An error occurred: ${response.error}${response.errorMessage?.let { " $it" }}")
|
println("An error occurred: ${response.errorCodeAndMessage}")
|
||||||
}
|
}
|
||||||
|
|
||||||
response.customerAccount?.let { account ->
|
response.customerAccount?.let { account ->
|
||||||
|
@ -32,6 +35,17 @@ class NativeApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun transferMoney(param: TransferMoneyParameter) {
|
||||||
|
val response = client.transferMoney(param)
|
||||||
|
|
||||||
|
if (response.error != null) {
|
||||||
|
println("Could not transfer ${param.amount} to ${param.recipientName}: ${response.errorCodeAndMessage}")
|
||||||
|
} else {
|
||||||
|
println("Successfully transferred ${param.amount} to ${param.recipientName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun enterTan(tanChallenge: TanChallenge) {
|
private fun enterTan(tanChallenge: TanChallenge) {
|
||||||
println("A TAN is required:")
|
println("A TAN is required:")
|
||||||
println(tanChallenge.messageToShowToUser)
|
println(tanChallenge.messageToShowToUser)
|
||||||
|
|
|
@ -2,7 +2,9 @@ package net.dankito.banking.fints
|
||||||
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
import net.dankito.banking.client.model.parameter.GetAccountDataParameter
|
||||||
|
import net.dankito.banking.client.model.parameter.TransferMoneyParameter
|
||||||
import net.dankito.banking.client.model.response.GetAccountDataResponse
|
import net.dankito.banking.client.model.response.GetAccountDataResponse
|
||||||
|
import net.dankito.banking.client.model.response.TransferMoneyResponse
|
||||||
|
|
||||||
|
|
||||||
fun FinTsClient.getAccountData(bankCode: String, loginName: String, password: String): GetAccountDataResponse {
|
fun FinTsClient.getAccountData(bankCode: String, loginName: String, password: String): GetAccountDataResponse {
|
||||||
|
@ -12,3 +14,8 @@ fun FinTsClient.getAccountData(bankCode: String, loginName: String, password: St
|
||||||
fun FinTsClient.getAccountData(param: GetAccountDataParameter): GetAccountDataResponse {
|
fun FinTsClient.getAccountData(param: GetAccountDataParameter): GetAccountDataResponse {
|
||||||
return runBlocking { getAccountDataAsync(param) }
|
return runBlocking { getAccountDataAsync(param) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun FinTsClient.transferMoney(param: TransferMoneyParameter): TransferMoneyResponse {
|
||||||
|
return runBlocking { transferMoneyAsync(param) }
|
||||||
|
}
|
Loading…
Reference in New Issue