diff --git a/SampleApplications/WebApp/src/main/kotlin/AccountTransactionsView.kt b/SampleApplications/WebApp/src/main/kotlin/AccountTransactionsView.kt index 43b264fb..d10a5c89 100644 --- a/SampleApplications/WebApp/src/main/kotlin/AccountTransactionsView.kt +++ b/SampleApplications/WebApp/src/main/kotlin/AccountTransactionsView.kt @@ -2,10 +2,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.dankito.banking.client.model.AccountTransaction import net.dankito.banking.fints.model.TanChallenge -import react.RBuilder -import react.RComponent -import react.Props -import react.State +import react.* import react.dom.* import styled.styledDiv @@ -13,7 +10,8 @@ external interface AccountTransactionsViewProps : Props { var presenter: Presenter } -data class AccountTransactionsViewState(val balance: String, val transactions: Collection, val enterTanChallenge: TanChallenge? = null) : State +data class AccountTransactionsViewState(val balance: String, val transactions: Collection, var showTransferMoneyView: Boolean = false, + val enterTanChallenge: TanChallenge? = null) : State @JsExport class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent(props) { @@ -22,7 +20,7 @@ class AccountTransactionsView(props: AccountTransactionsViewProps) : RComponent< init { 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 // 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 { +"Saldo: ${state.balance}" } diff --git a/SampleApplications/WebApp/src/main/kotlin/Presenter.kt b/SampleApplications/WebApp/src/main/kotlin/Presenter.kt index 687ad197..9359c584 100644 --- a/SampleApplications/WebApp/src/main/kotlin/Presenter.kt +++ b/SampleApplications/WebApp/src/main/kotlin/Presenter.kt @@ -3,12 +3,12 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext 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.TransferMoneyResponse import net.dankito.banking.fints.FinTsClient import net.dankito.banking.fints.callback.SimpleFinTsClientCallback -import net.dankito.banking.fints.model.TanChallenge -import net.dankito.banking.fints.model.TanMethod -import net.dankito.banking.fints.model.TanMethodType +import net.dankito.banking.fints.model.* import net.dankito.banking.fints.webclient.KtorWebClient import net.dankito.banking.fints.webclient.ProxyingWebClient 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) + } + } + } + } \ No newline at end of file diff --git a/SampleApplications/WebApp/src/main/kotlin/TextInputField.kt b/SampleApplications/WebApp/src/main/kotlin/TextInputField.kt new file mode 100644 index 00000000..364c3e11 --- /dev/null +++ b/SampleApplications/WebApp/src/main/kotlin/TextInputField.kt @@ -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 { props -> + + div { + span { +"${props.label}: " } + + input { + type = react.dom.html.InputType.text + onChange = { event -> + val enteredValue = event.target.value + + props.valueChanged(enteredValue)} + } + } + +} \ No newline at end of file diff --git a/SampleApplications/WebApp/src/main/kotlin/TransferMoneyView.kt b/SampleApplications/WebApp/src/main/kotlin/TransferMoneyView.kt new file mode 100644 index 00000000..5dc5c164 --- /dev/null +++ b/SampleApplications/WebApp/src/main/kotlin/TransferMoneyView.kt @@ -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(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) { } } + } + } + } + } + +} \ No newline at end of file diff --git a/SampleApplications/WebApp/src/main/kotlin/main.kt b/SampleApplications/WebApp/src/main/kotlin/main.kt index 5bde6fd2..508d0aa4 100644 --- a/SampleApplications/WebApp/src/main/kotlin/main.kt +++ b/SampleApplications/WebApp/src/main/kotlin/main.kt @@ -1,9 +1,5 @@ import kotlinx.browser.document 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 fun main() { diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt new file mode 100644 index 00000000..71d6e2ed --- /dev/null +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt @@ -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? = null, + preferredTanMedium: String? = null, + abortIfTanIsRequired: Boolean = false, + finTsModel: BankData? = null + +) : FinTsClientParameter(bankCode, loginName, password, preferredTanMethods, preferredTanMedium, abortIfTanIsRequired, finTsModel) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/ErrorCode.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/ErrorCode.kt index 0124fb30..1a395879 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/ErrorCode.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/ErrorCode.kt @@ -21,6 +21,10 @@ enum class ErrorCode { NoneOfTheAccountsSupportsRetrievingData, - DidNotRetrieveAllAccountData + DidNotRetrieveAllAccountData, + + NoAccountSupportsMoneyTransfer, + + MoreThanOneAccountSupportsMoneyTransfer } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/FinTsClientResponse.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/FinTsClientResponse.kt index 9c12ee6e..68b8acca 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/FinTsClientResponse.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/FinTsClientResponse.kt @@ -15,4 +15,7 @@ open class FinTsClientResponse( open val successful: Boolean get() = error == null + open val errorCodeAndMessage: String + get() = "$error${errorMessage?.let { " $it" }}}" + } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/TransferMoneyResponse.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/TransferMoneyResponse.kt new file mode 100644 index 00000000..34bf213d --- /dev/null +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/response/TransferMoneyResponse.kt @@ -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, + finTsModel: BankData? = null +) : FinTsClientResponse(error, errorMessage, messageLogWithoutSensitiveData, finTsModel) \ No newline at end of file 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 ca8af7e3..814befdb 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt @@ -1,12 +1,15 @@ package net.dankito.banking.fints import kotlinx.datetime.LocalDate +import net.dankito.banking.client.model.parameter.FinTsClientParameter import net.dankito.banking.fints.callback.FinTsClientCallback import net.dankito.banking.fints.model.* import net.dankito.banking.client.model.parameter.GetAccountDataParameter 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.GetAccountDataResponse +import net.dankito.banking.client.model.response.TransferMoneyResponse import net.dankito.banking.fints.mapper.FinTsModelMapper import net.dankito.banking.fints.response.client.FinTsClientResponse import net.dankito.banking.fints.response.client.GetAccountInfoResponse @@ -109,7 +112,52 @@ open class FinTsClient @JvmOverloads constructor( 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, 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 /* First dialog: Get user's basic data like BPD, customer system ID and her TAN methods */ diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt index e5902cbf..04978b94 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClientDeprecated.kt @@ -10,9 +10,7 @@ import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.* import net.dankito.banking.fints.model.* import net.dankito.banking.fints.response.BankResponse import net.dankito.banking.fints.response.client.* -import net.dankito.banking.fints.response.segments.* 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 { val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, account) - return jobExecutor.doBankTransferAsync(context, bankTransferData) + return jobExecutor.transferMoneyAsync(context, bankTransferData) } } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsJobExecutor.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsJobExecutor.kt index 20946297..4c2ade3a 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsJobExecutor.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsJobExecutor.kt @@ -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 updatedAccount = getUpdatedAccount(context, context.account!!) diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/mapper/FinTsModelMapper.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/mapper/FinTsModelMapper.kt index 5d3508fb..639b3b37 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/mapper/FinTsModelMapper.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/mapper/FinTsModelMapper.kt @@ -2,6 +2,7 @@ package net.dankito.banking.fints.mapper import net.dankito.banking.client.model.* 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.response.ErrorCode 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 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, credentials.iban, param.loginName, null, null, "", null, null, listOf(), listOf()) // TODO: where to know from if account supports retrieving balance and transactions? accountData.setSupportsFeature(AccountFeature.RetrieveBalance, true) accountData.setSupportsFeature(AccountFeature.RetrieveAccountTransactions, true) + accountData.setSupportsFeature(AccountFeature.TransferMoney, true) + accountData.setSupportsFeature(AccountFeature.RealTimeTransfer, true) return accountData } diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt index f03cb61e..5b5e6c78 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/segmente/implementierte/sepa/SepaBankTransferBase.kt @@ -32,7 +32,7 @@ open class SepaBankTransferBase( "RecipientIban" to data.recipientAccountId.replace(" ", ""), "RecipientBic" to data.recipientBankCode.replace(" ", ""), "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 ), messageCreator diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankTransferData.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankTransferData.kt index 5ed04200..577e90cb 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankTransferData.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/model/BankTransferData.kt @@ -6,6 +6,6 @@ open class BankTransferData( val recipientAccountId: String, val recipientBankCode: String, val amount: Money, - val reference: String, + val reference: String?, val realTimeTransfer: Boolean = false ) \ No newline at end of file diff --git a/fints4k/src/nativeMain/kotlin/NativeApp.kt b/fints4k/src/nativeMain/kotlin/NativeApp.kt index 1e66319b..ed63685b 100644 --- a/fints4k/src/nativeMain/kotlin/NativeApp.kt +++ b/fints4k/src/nativeMain/kotlin/NativeApp.kt @@ -2,26 +2,29 @@ import kotlinx.datetime.LocalDate import net.dankito.banking.client.model.AccountTransaction import net.dankito.banking.client.model.CustomerAccount 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.callback.SimpleFinTsClientCallback import net.dankito.banking.fints.getAccountData import net.dankito.banking.fints.model.TanChallenge +import net.dankito.banking.fints.transferMoney import net.dankito.utils.multiplatform.extensions.* class NativeApp { + private val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) }) + + fun retrieveAccountData(bankCode: String, loginName: String, password: String) { retrieveAccountData(GetAccountDataParameter(bankCode, loginName, password)) } fun retrieveAccountData(param: GetAccountDataParameter) { - val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) }) - val response = client.getAccountData(param) if (response.error != null) { - println("An error occurred: ${response.error}${response.errorMessage?.let { " $it" }}") + println("An error occurred: ${response.errorCodeAndMessage}") } 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) { println("A TAN is required:") println(tanChallenge.messageToShowToUser) diff --git a/fints4k/src/nativeMain/kotlin/net.dankito.banking.fints/FinTsClientExtensions.kt b/fints4k/src/nativeMain/kotlin/net.dankito.banking.fints/FinTsClientExtensions.kt index 18a01138..f196d057 100644 --- a/fints4k/src/nativeMain/kotlin/net.dankito.banking.fints/FinTsClientExtensions.kt +++ b/fints4k/src/nativeMain/kotlin/net.dankito.banking.fints/FinTsClientExtensions.kt @@ -2,7 +2,9 @@ package net.dankito.banking.fints import kotlinx.coroutines.runBlocking 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.TransferMoneyResponse fun FinTsClient.getAccountData(bankCode: String, loginName: String, password: String): GetAccountDataResponse { @@ -11,4 +13,9 @@ fun FinTsClient.getAccountData(bankCode: String, loginName: String, password: St fun FinTsClient.getAccountData(param: GetAccountDataParameter): GetAccountDataResponse { return runBlocking { getAccountDataAsync(param) } +} + + +fun FinTsClient.transferMoney(param: TransferMoneyParameter): TransferMoneyResponse { + return runBlocking { transferMoneyAsync(param) } } \ No newline at end of file