2020-01-02 21:39:02 +00:00
package net.dankito.banking
2020-01-02 23:35:36 +00:00
import net.dankito.banking.ui.BankingClientCallback
2020-01-02 21:39:02 +00:00
import net.dankito.banking.ui.IBankingClient
2020-01-02 23:35:36 +00:00
import net.dankito.banking.ui.model.Account
2020-01-02 21:39:02 +00:00
import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.parameters.GetTransactionsParameter
import net.dankito.banking.ui.model.parameters.TransferMoneyData
import net.dankito.banking.ui.model.responses.AddAccountResponse
import net.dankito.banking.ui.model.responses.BankingClientResponse
import net.dankito.banking.ui.model.responses.GetTransactionsResponse
import net.dankito.fints.FinTsClientCallback
import net.dankito.fints.FinTsClientForCustomer
2020-01-02 23:35:36 +00:00
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.dankito.fints.model.*
2020-01-02 21:39:02 +00:00
import net.dankito.fints.model.mapper.BankDataMapper
import net.dankito.fints.util.IBase64Service
import net.dankito.utils.IThreadPool
import net.dankito.utils.ThreadPool
2020-01-25 19:29:44 +00:00
import net.dankito.utils.serialization.JacksonJsonSerializer
2020-01-02 21:39:02 +00:00
import net.dankito.utils.web.client.IWebClient
import net.dankito.utils.web.client.OkHttpWebClient
2020-01-25 19:29:44 +00:00
import org.slf4j.LoggerFactory
import java.io.File
2020-01-02 21:39:02 +00:00
open class fints4javaBankingClient (
bankInfo : BankInfo ,
customerId : String ,
pin : String ,
2020-01-25 19:29:44 +00:00
protected val dataFolder : File ,
2020-01-02 21:39:02 +00:00
webClient : IWebClient = OkHttpWebClient ( ) ,
base64Service : IBase64Service ,
threadPool : IThreadPool = ThreadPool ( ) ,
2020-01-02 23:35:36 +00:00
callback : BankingClientCallback
2020-01-02 21:39:02 +00:00
) : IBankingClient {
2020-01-25 19:29:44 +00:00
companion object {
val fints4javaClientDataFilename = " fints4javaClientData.json "
private val log = LoggerFactory . getLogger ( fints4javaBankingClient :: class . java )
}
2020-01-02 21:39:02 +00:00
protected val mapper = net . dankito . banking . mapper . fints4javaModelMapper ( )
protected val bankDataMapper = BankDataMapper ( )
2020-01-25 19:29:44 +00:00
protected val serializer = JacksonJsonSerializer ( )
2020-01-02 21:39:02 +00:00
protected val bank = bankDataMapper . mapFromBankInfo ( bankInfo )
protected val customer = CustomerData ( customerId , pin )
2020-04-28 16:17:47 +00:00
protected var account : Account = mapper . mapAccount ( customer , bank ) // temporary save temp account, we update with data from server response like BankAccounts later
2020-01-02 23:35:36 +00:00
protected val client = FinTsClientForCustomer ( bank , customer , webClient , base64Service , threadPool , object : FinTsClientCallback {
2020-01-19 15:50:26 +00:00
override fun askUserForTanProcedure ( supportedTanProcedures : List < TanProcedure > , suggestedTanProcedure : TanProcedure ? ) : TanProcedure ? {
// we simply return suggestedTanProcedure as even so it's not user's preferred TAN procedure she still can select it in EnterTanDialog
return suggestedTanProcedure
}
2020-01-02 23:35:36 +00:00
override fun enterTan ( customer : CustomerData , tanChallenge : TanChallenge ) : EnterTanResult {
2020-01-19 15:22:43 +00:00
mapper . updateTanMediaAndProcedures ( account , customer )
2020-01-02 23:35:36 +00:00
val result = callback . enterTan ( account , mapper . mapTanChallenge ( tanChallenge ) )
return mapper . mapEnterTanResult ( result , customer )
}
override fun enterTanGeneratorAtc ( customer : CustomerData , tanMedium : TanGeneratorTanMedium ) : EnterTanGeneratorAtcResult {
2020-01-19 15:22:43 +00:00
mapper . updateTanMediaAndProcedures ( account , customer )
2020-01-02 23:35:36 +00:00
val result = callback . enterTanGeneratorAtc ( mapper . mapTanMedium ( tanMedium ) )
return mapper . mapEnterTanGeneratorAtcResult ( result )
}
} )
2020-01-02 21:39:02 +00:00
override fun addAccountAsync ( callback : ( AddAccountResponse ) -> Unit ) {
client . addAccountAsync { response ->
2020-01-02 23:35:36 +00:00
this . account = mapper . mapAccount ( customer , bank )
2020-01-02 21:39:02 +00:00
val mappedResponse = mapper . mapResponse ( account , response )
2020-01-25 19:29:44 +00:00
saveData ( )
2020-01-02 21:39:02 +00:00
callback ( mappedResponse )
}
}
override fun getTransactionsAsync ( bankAccount : BankAccount , parameter : GetTransactionsParameter , callback : ( GetTransactionsResponse ) -> Unit ) {
2020-01-20 23:54:06 +00:00
val account = mapper . findAccountForBankAccount ( customer , bankAccount )
2020-01-02 21:39:02 +00:00
2020-01-20 23:54:06 +00:00
if ( account == null ) {
callback ( GetTransactionsResponse ( false , " Cannot find account for ${bankAccount.identifier} " ) ) // TODO: translate
}
else {
client . getTransactionsAsync ( net . dankito . fints . model . GetTransactionsParameter ( parameter . alsoRetrieveBalance , parameter . fromDate , parameter . toDate ) , account ) { response ->
2020-01-02 21:39:02 +00:00
2020-01-20 23:54:06 +00:00
val mappedResponse = mapper . mapResponse ( bankAccount , response )
2020-01-25 19:29:44 +00:00
saveData ( )
2020-01-20 23:54:06 +00:00
callback ( mappedResponse )
}
2020-01-02 21:39:02 +00:00
}
}
2020-01-20 23:54:06 +00:00
override fun transferMoneyAsync ( data : TransferMoneyData , bankAccount : BankAccount , callback : ( BankingClientResponse ) -> Unit ) {
val account = mapper . findAccountForBankAccount ( customer , bankAccount )
if ( account == null ) {
callback ( BankingClientResponse ( false , " Cannot find account for ${bankAccount.identifier} " ) ) // TODO: translate
}
else {
val mappedData = BankTransferData ( data . creditorName , data . creditorIban , data . creditorBic , data . amount , data . usage )
2020-01-02 21:39:02 +00:00
2020-01-20 23:54:06 +00:00
client . doBankTransferAsync ( mappedData , account ) { response ->
2020-01-25 19:29:44 +00:00
saveData ( )
2020-01-20 23:54:06 +00:00
callback ( mapper . mapResponse ( response ) )
}
2020-01-02 21:39:02 +00:00
}
}
2020-01-19 15:22:43 +00:00
2020-01-25 19:29:44 +00:00
override fun restoreData ( ) {
val deserializedCustomer = serializer . deserializeObject ( getFints4javaClientDataFile ( ) , CustomerData :: class . java )
deserializedCustomer ?. let {
mapper . updateCustomer ( customer , deserializedCustomer )
2020-04-28 16:17:47 +00:00
account = mapper . mapAccount ( customer , bank )
2020-01-25 19:29:44 +00:00
}
}
protected open fun saveData ( ) {
try {
serializer . serializeObject ( customer , getFints4javaClientDataFile ( ) )
} catch ( e : Exception ) {
log . error ( " Could not save customer data for $customer " , e )
}
}
protected open fun getFints4javaClientDataFile ( ) : File {
return File ( dataFolder , " ${bank.bankCode} _ ${customer.customerId} _ $fints4javaClientDataFilename " )
}
2020-01-02 21:39:02 +00:00
}