Created BicFinder with BankFinder so that we can determine a German BIC from bank code or a German IBAN
This commit is contained in:
parent
8671bf058d
commit
ad826941dd
|
@ -23,6 +23,8 @@ enum class ErrorCode {
|
||||||
|
|
||||||
DidNotRetrieveAllAccountData,
|
DidNotRetrieveAllAccountData,
|
||||||
|
|
||||||
|
CanNotDetermineBicForIban,
|
||||||
|
|
||||||
NoAccountSupportsMoneyTransfer,
|
NoAccountSupportsMoneyTransfer,
|
||||||
|
|
||||||
MoreThanOneAccountSupportsMoneyTransfer
|
MoreThanOneAccountSupportsMoneyTransfer
|
||||||
|
|
|
@ -15,6 +15,7 @@ import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||||
import net.dankito.banking.fints.response.client.GetAccountInfoResponse
|
import net.dankito.banking.fints.response.client.GetAccountInfoResponse
|
||||||
import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse
|
import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse
|
||||||
import net.dankito.banking.fints.response.segments.AccountType
|
import net.dankito.banking.fints.response.segments.AccountType
|
||||||
|
import net.dankito.banking.fints.util.BicFinder
|
||||||
import net.dankito.banking.fints.util.FinTsServerAddressFinder
|
import net.dankito.banking.fints.util.FinTsServerAddressFinder
|
||||||
import net.dankito.banking.fints.webclient.IWebClient
|
import net.dankito.banking.fints.webclient.IWebClient
|
||||||
import net.dankito.utils.multiplatform.extensions.minusDays
|
import net.dankito.utils.multiplatform.extensions.minusDays
|
||||||
|
@ -39,6 +40,8 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
|
|
||||||
protected open val mapper = FinTsModelMapper()
|
protected open val mapper = FinTsModelMapper()
|
||||||
|
|
||||||
|
protected open val bicFinder = BicFinder()
|
||||||
|
|
||||||
|
|
||||||
open suspend fun getAccountDataAsync(bankCode: String, loginName: String, password: String): GetAccountDataResponse {
|
open suspend fun getAccountDataAsync(bankCode: String, loginName: String, password: String): GetAccountDataResponse {
|
||||||
return getAccountDataAsync(GetAccountDataParameter(bankCode, loginName, password))
|
return getAccountDataAsync(GetAccountDataParameter(bankCode, loginName, password))
|
||||||
|
@ -50,7 +53,7 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
return GetAccountDataResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not FinTS 3.0 or we don't know its FinTS server address", null, listOf())
|
return GetAccountDataResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not FinTS 3.0 or we don't know its FinTS server address", null, listOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
val bank = BankData(param.bankCode, param.loginName, param.password, finTsServerAddress, "")
|
val bank = mapper.mapToBankData(param, finTsServerAddress)
|
||||||
val accounts = param.accounts
|
val accounts = param.accounts
|
||||||
|
|
||||||
if (accounts.isNullOrEmpty() || param.retrieveOnlyAccountInfo) { // then first retrieve customer's bank accounts
|
if (accounts.isNullOrEmpty() || param.retrieveOnlyAccountInfo) { // then first retrieve customer's bank accounts
|
||||||
|
@ -118,8 +121,14 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
if (finTsServerAddress.isNullOrBlank()) {
|
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)
|
return TransferMoneyResponse(ErrorCode.BankDoesNotSupportFinTs3, "Either bank does not FinTS 3.0 or we don't know its FinTS server address", listOf(), null)
|
||||||
}
|
}
|
||||||
|
val recipientBankIdentifier = getRecipientBankCode(param)
|
||||||
|
if (recipientBankIdentifier == null) {
|
||||||
|
return TransferMoneyResponse(ErrorCode.CanNotDetermineBicForIban, "We can only determine recipient's BIC automatically for German IBANs. If it's a German IBAN, either we " +
|
||||||
|
"cannot extract the bank code from IBAN ${param.recipientAccountIdentifier} (fourth to twelfth position) or don't know the BIC to this bank code. Please specify recipient's IBAN explicitly.", listOf())
|
||||||
|
}
|
||||||
|
|
||||||
val bank = BankData(param.bankCode, param.loginName, param.password, finTsServerAddress, "")
|
|
||||||
|
val bank = mapper.mapToBankData(param, finTsServerAddress)
|
||||||
val remittanceAccount = param.remittanceAccount
|
val remittanceAccount = param.remittanceAccount
|
||||||
|
|
||||||
if (remittanceAccount == null) { // then first retrieve customer's bank accounts
|
if (remittanceAccount == null) { // then first retrieve customer's bank accounts
|
||||||
|
@ -129,14 +138,14 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
return TransferMoneyResponse(mapper.mapErrorCode(getAccountInfoResponse), mapper.mapErrorMessages(getAccountInfoResponse),
|
return TransferMoneyResponse(mapper.mapErrorCode(getAccountInfoResponse), mapper.mapErrorMessages(getAccountInfoResponse),
|
||||||
getAccountInfoResponse.messageLogWithoutSensitiveData, bank)
|
getAccountInfoResponse.messageLogWithoutSensitiveData, bank)
|
||||||
} else {
|
} else {
|
||||||
return transferMoneyAsync(param, getAccountInfoResponse.bank, getAccountInfoResponse.bank.accounts, getAccountInfoResponse)
|
return transferMoneyAsync(param, recipientBankIdentifier, getAccountInfoResponse.bank, getAccountInfoResponse.bank.accounts, getAccountInfoResponse)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return transferMoneyAsync(param, bank, listOf(mapper.mapToAccountData(remittanceAccount, param)), null)
|
return transferMoneyAsync(param, recipientBankIdentifier, bank, listOf(mapper.mapToAccountData(remittanceAccount, param)), null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open suspend fun transferMoneyAsync(param: TransferMoneyParameter, bank: BankData, accounts: List<AccountData>, previousJobResponse: FinTsClientResponse?): TransferMoneyResponse {
|
protected open suspend fun transferMoneyAsync(param: TransferMoneyParameter, recipientBankIdentifier: String, bank: BankData, accounts: List<AccountData>, previousJobResponse: FinTsClientResponse?): TransferMoneyResponse {
|
||||||
val accountsSupportingTransfer = accounts.filter { it.supportsTransferringMoney }
|
val accountsSupportingTransfer = accounts.filter { it.supportsTransferringMoney }
|
||||||
if (accountsSupportingTransfer.isEmpty()) {
|
if (accountsSupportingTransfer.isEmpty()) {
|
||||||
return TransferMoneyResponse(ErrorCode.NoAccountSupportsMoneyTransfer, "None of the accounts $accounts supports money transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank)
|
return TransferMoneyResponse(ErrorCode.NoAccountSupportsMoneyTransfer, "None of the accounts $accounts supports money transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank)
|
||||||
|
@ -144,14 +153,27 @@ open class FinTsClient @JvmOverloads constructor(
|
||||||
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)
|
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 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))
|
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)
|
return TransferMoneyResponse(mapper.mapErrorCode(response), mapper.mapErrorMessages(response), mapper.mergeMessageLog(previousJobResponse, response), bank)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getRecipientBankCode(param: TransferMoneyParameter): String? {
|
||||||
|
param.recipientBankIdentifier?.let { return it }
|
||||||
|
|
||||||
|
val probablyIban = param.recipientAccountIdentifier.replace(" ", "")
|
||||||
|
if (probablyIban.length > 12) {
|
||||||
|
val bankCode = probablyIban.substring(4, 4 + 8) // extract bank code from IBAN. For German IBAN bank code starts at fourth position and has 8 digits
|
||||||
|
|
||||||
|
bicFinder.findBic(bankCode)?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
protected open suspend fun getAccountInfo(param: FinTsClientParameter, bank: BankData): GetAccountInfoResponse {
|
protected open suspend fun getAccountInfo(param: FinTsClientParameter, bank: BankData): GetAccountInfoResponse {
|
||||||
param.finTsModel?.let {
|
param.finTsModel?.let {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
|
|
|
@ -10,10 +10,18 @@ import net.dankito.banking.fints.model.*
|
||||||
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||||
import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse
|
import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse
|
||||||
import net.dankito.banking.fints.response.segments.AccountType
|
import net.dankito.banking.fints.response.segments.AccountType
|
||||||
|
import net.dankito.banking.fints.util.BicFinder
|
||||||
|
|
||||||
|
|
||||||
open class FinTsModelMapper {
|
open class FinTsModelMapper {
|
||||||
|
|
||||||
|
protected open val bicFinder = BicFinder()
|
||||||
|
|
||||||
|
|
||||||
|
open fun mapToBankData(param: FinTsClientParameter, finTsServerAddress: String): BankData {
|
||||||
|
return BankData(param.bankCode, param.loginName, param.password, finTsServerAddress, bicFinder.findBic(param.bankCode) ?: "")
|
||||||
|
}
|
||||||
|
|
||||||
open fun mapToAccountData(credentials: BankAccountIdentifier, param: FinTsClientParameter): 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())
|
||||||
|
|
|
@ -55,12 +55,6 @@ open class ModelMapper(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response.getFirstSegmentById<SepaAccountInfo>(InstituteSegmentId.SepaAccountInfo)?.let { sepaAccountInfo ->
|
|
||||||
sepaAccountInfo.account.bic?.let {
|
|
||||||
bank.bic = it // TODO: really set BIC on bank then?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response.getFirstSegmentById<ChangeTanMediaParameters>(InstituteSegmentId.ChangeTanMediaParameters)?.let { parameters ->
|
response.getFirstSegmentById<ChangeTanMediaParameters>(InstituteSegmentId.ChangeTanMediaParameters)?.let { parameters ->
|
||||||
bank.changeTanMediumParameters = parameters
|
bank.changeTanMediumParameters = parameters
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue