Converted fints4kBankingClient to a multi platform project

This commit is contained in:
dankito 2020-07-12 12:26:16 +02:00
parent 42f9e5f018
commit 82628d8a6b
5 changed files with 147 additions and 51 deletions

View File

@ -1,22 +1,127 @@
apply plugin: 'java-library'
apply plugin: 'kotlin'
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "com.android.library"
id "maven-publish"
}
ext.artifactName = "fints4k-banking-client"
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
kotlin {
jvm {
compilations.main.kotlinOptions {
jvmTarget = "1.6"
}
}
compileKotlin {
kotlinOptions.jvmTarget = "1.6"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.6"
targets {
// Select iOS target for real device or emulator.
final def iOSIsRealDevice = System.getenv('SDK_NAME')?.startsWith("iphoneos")
final def iOSTarget = iOSIsRealDevice ? presets.iosArm64 : presets.iosX64
// iOS target.
fromPreset(iOSTarget, 'ios') {
binaries {
framework {
baseName = "fints4kBankingClient"
}
}
}
}
sourceSets {
commonMain {
dependencies {
implementation kotlin("stdlib-common")
implementation project(":BankingUiCommon")
implementation project(":fints4k")
}
}
jvmMain {
dependencies {
api kotlin("stdlib-jdk7")
}
}
iosMain {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion"
}
}
}
}
dependencies {
api project(':BankingUiCommon')
api project(':fints4k')
// Task to generate iOS framework for xcode projects.
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
final def framework = kotlin.targets.ios.binaries.getFramework("", mode)
inputs.property "mode", mode
dependsOn framework.linkTask
from { framework.outputFile.parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
setExecutable(true)
}
}
}
// Run packForXCode when building.
tasks.build.dependsOn packForXCode
android {
compileSdkVersion androidCompileSdkVersion
defaultConfig {
minSdkVersion androidMinSdkVersion
targetSdkVersion androidTargetSdkVersion
versionName version
versionCode appVersionCode
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
pickFirst 'META-INF/ktor-http.kotlin_module'
pickFirst 'META-INF/kotlinx-io.kotlin_module'
pickFirst 'META-INF/atomicfu.kotlin_module'
pickFirst 'META-INF/ktor-utils.kotlin_module'
pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module'
pickFirst 'META-INF/ktor-client-core.kotlin_module'
pickFirst 'META-INF/DEPENDENCIES'
pickFirst 'META-INF/NOTICE'
pickFirst 'META-INF/LICENSE'
pickFirst 'META-INF/LICENSE.txt'
pickFirst 'META-INF/NOTICE.txt'
}
lintOptions {
abortOnError false
}
}

View File

@ -1,7 +1,5 @@
package net.dankito.banking
import com.soywiz.klock.jvm.toDate
import net.dankito.banking.extensions.toKlockDate
import net.dankito.banking.ui.BankingClientCallback
import net.dankito.banking.ui.IBankingClient
import net.dankito.banking.ui.model.Customer
@ -19,17 +17,14 @@ import net.dankito.banking.fints.model.*
import net.dankito.banking.mapper.BankDataMapper
import net.dankito.banking.fints.util.IBase64Service
import net.dankito.banking.fints.util.PureKotlinBase64Service
import net.dankito.utils.serialization.JacksonJsonSerializer
import net.dankito.banking.fints.webclient.IWebClient
import net.dankito.banking.fints.webclient.KtorWebClient
import net.dankito.banking.bankfinder.BankInfo
import net.dankito.banking.extensions.toAmount
import net.dankito.banking.extensions.toMoney
import net.dankito.utils.multiplatform.log.Slf4jLoggerFactory
import net.dankito.utils.multiplatform.toDate
import org.slf4j.LoggerFactory
import java.io.File
import java.math.BigDecimal
import net.dankito.banking.util.ISerializer
import net.dankito.utils.multiplatform.Date
import net.dankito.utils.multiplatform.File
import net.dankito.utils.multiplatform.log.LoggerFactory
open class fints4kBankingClient(
@ -37,6 +32,7 @@ open class fints4kBankingClient(
customerId: String,
pin: String,
protected val dataFolder: File,
protected val serializer: ISerializer,
webClient: IWebClient = KtorWebClient(),
base64Service: IBase64Service = PureKotlinBase64Service(),
callback: BankingClientCallback
@ -46,12 +42,7 @@ open class fints4kBankingClient(
companion object {
val fints4kClientDataFilename = "fints4kClientData.json"
private val log = LoggerFactory.getLogger(fints4kBankingClient::class.java)
init {
net.dankito.banking.fints.util.log.LoggerFactory.loggerFactory = net.dankito.banking.fints.util.log.Slf4jLoggerFactory()
}
private val log = LoggerFactory.getLogger(fints4kBankingClient::class)
}
@ -59,8 +50,6 @@ open class fints4kBankingClient(
protected val bankDataMapper = BankDataMapper()
protected val serializer = JacksonJsonSerializer()
protected val bank = bankDataMapper.mapFromBankInfo(bankInfo)
@ -96,7 +85,7 @@ open class fints4kBankingClient(
override val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = client.messageLogWithoutSensitiveData.map { MessageLogEntry(it.message, it.time.toDate(), customer) }
get() = client.messageLogWithoutSensitiveData.map { MessageLogEntry(it.message, it.time, customer) }
override fun addAccountAsync(callback: (AddAccountResponse) -> Unit) {
@ -117,7 +106,8 @@ open class fints4kBankingClient(
callback(GetTransactionsResponse(bankAccount, false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate
}
else {
client.getTransactionsAsync(GetTransactionsParameter(parameter.alsoRetrieveBalance, parameter.fromDate?.toKlockDate(), parameter.toDate?.toKlockDate(), null, parameter.abortIfTanIsRequired,
client.getTransactionsAsync(GetTransactionsParameter(parameter.alsoRetrieveBalance, parameter.fromDate,
parameter.toDate, null, parameter.abortIfTanIsRequired,
{ parameter.retrievedChunkListener?.invoke(mapper.mapTransactions(bankAccount, it)) } ), account) { response ->
val mappedResponse = mapper.mapResponse(bankAccount, response)
@ -148,7 +138,7 @@ open class fints4kBankingClient(
override fun restoreData() {
val deserializedCustomer = serializer.deserializeObject(getFints4kClientDataFile(), CustomerData::class.java)
val deserializedCustomer = serializer.deserializeObject(getFints4kClientDataFile(), CustomerData::class)
deserializedCustomer?.let {
mapper.updateCustomer(fints4kCustomer, deserializedCustomer)
@ -161,7 +151,7 @@ open class fints4kBankingClient(
try {
val clientDataFile = getFints4kClientDataFile()
clientDataFile.parentFile.mkdirs()
clientDataFile.parent?.mkdirs()
serializer.serializeObject(fints4kCustomer, clientDataFile)
} catch (e: Exception) {

View File

@ -5,10 +5,11 @@ import net.dankito.banking.ui.IBankingClient
import net.dankito.banking.ui.IBankingClientCreator
import net.dankito.banking.bankfinder.BankInfo
import net.dankito.banking.util.IAsyncRunner
import java.io.File
import net.dankito.banking.util.ISerializer
import net.dankito.utils.multiplatform.File
open class fints4kBankingClientCreator : IBankingClientCreator {
open class fints4kBankingClientCreator(protected val serializer: ISerializer) : IBankingClientCreator {
override fun createClient(
bankInfo: BankInfo,
@ -19,7 +20,7 @@ open class fints4kBankingClientCreator : IBankingClientCreator {
callback: BankingClientCallback
): IBankingClient {
return fints4kBankingClient(bankInfo, customerId, pin, dataFolder, callback = callback)
return fints4kBankingClient(bankInfo, customerId, pin, dataFolder, serializer, callback = callback)
}
}

View File

@ -1,7 +1,7 @@
package net.dankito.banking.mapper
import net.dankito.banking.extensions.toJavaBigDecimal
import net.dankito.banking.extensions.toJavaUtilDate
import net.dankito.utils.multiplatform.BigDecimal
import net.dankito.banking.extensions.toBigDecimal
import net.dankito.banking.ui.model.*
import net.dankito.banking.ui.model.responses.AddAccountResponse
import net.dankito.banking.ui.model.responses.BankingClientResponse
@ -15,14 +15,13 @@ import net.dankito.banking.fints.model.CustomerData
import net.dankito.banking.fints.model.Money
import net.dankito.banking.fints.response.client.FinTsClientResponse
import net.dankito.banking.fints.response.segments.AccountType
import net.dankito.utils.exception.ExceptionHelper
import java.math.BigDecimal
//import net.dankito.utils.exception.ExceptionHelper
open class fints4kModelMapper {
private val exceptionHelper = ExceptionHelper()
// private val exceptionHelper = ExceptionHelper()
open fun mapResponse(response: FinTsClientResponse): BankingClientResponse {
@ -31,7 +30,7 @@ open class fints4kModelMapper {
open fun mapResponse(customer: Customer, response: net.dankito.banking.fints.response.client.AddAccountResponse): AddAccountResponse {
val balances = response.balances.mapKeys { findMatchingBankAccount(customer, it.key) }.filter { it.key != null }
.mapValues { (it.value as Money).toJavaBigDecimal() } as Map<BankAccount, BigDecimal>
.mapValues { (it.value as Money).toBigDecimal() } as Map<BankAccount, BigDecimal>
val bookedTransactions = response.bookedTransactions.associateBy { it.account }
val mappedBookedTransactions = mutableMapOf<BankAccount, List<AccountTransaction>>()
@ -56,14 +55,15 @@ open class fints4kModelMapper {
return GetTransactionsResponse(bankAccount, response.isSuccessful, mapErrorToShowToUser(response),
mapTransactions(bankAccount, response.bookedTransactions),
listOf(), // TODO: map unbooked transactions
response.balance?.toJavaBigDecimal(),
response.balance?.toBigDecimal(),
response.exception, response.userCancelledAction, response.tanRequiredButWeWereToldToAbortIfSo)
}
open fun mapErrorToShowToUser(response: FinTsClientResponse): String? {
val innerException = response.exception?.let { exception -> exceptionHelper.getInnerException(exception) }
// val innerException = response.exception?.let { exception -> exceptionHelper.getInnerException(exception) }
val innerException = response.exception // TODO
return innerException?.localizedMessage ?: response.errorsToShowToUser.joinToString("\n")
return innerException?.message ?: response.errorsToShowToUser.joinToString("\n")
}
@ -102,7 +102,7 @@ open class fints4kModelMapper {
open fun mapBankAccount(customer: Customer, accountData: AccountData): BankAccount {
return BankAccount(customer, accountData.accountIdentifier, accountData.accountHolderName, accountData.iban,
accountData.subAccountAttribute, accountData.customerId, BigDecimal.ZERO, accountData.currency ?: "EUR",
accountData.subAccountAttribute, accountData.customerId, BigDecimal.Zero, accountData.currency ?: "EUR",
mapBankAccountType(accountData.accountType), accountData.productName, accountData.accountLimit,
null, accountData.supportsFeature(AccountFeature.RetrieveAccountTransactions),
accountData.supportsFeature(AccountFeature.RetrieveBalance), accountData.supportsFeature(AccountFeature.TransferMoney),
@ -176,19 +176,19 @@ open class fints4kModelMapper {
open fun mapTransaction(bankAccount: BankAccount, transaction: net.dankito.banking.fints.model.AccountTransaction): AccountTransaction {
return AccountTransaction(
bankAccount,
transaction.amount.toJavaBigDecimal(),
transaction.amount.toBigDecimal(),
transaction.amount.currency.code,
transaction.unparsedUsage,
transaction.bookingDate.toJavaUtilDate(),
transaction.bookingDate,
transaction.otherPartyName,
transaction.otherPartyBankCode,
transaction.otherPartyAccountId,
transaction.bookingText,
transaction.valueDate.toJavaUtilDate(),
transaction.valueDate,
transaction.statementNumber,
transaction.sequenceNumber,
transaction.openingBalance?.toJavaBigDecimal(),
transaction.closingBalance?.toJavaBigDecimal(),
transaction.openingBalance?.toBigDecimal(),
transaction.closingBalance?.toBigDecimal(),
transaction.endToEndReference,
transaction.customerReference,