From 82628d8a6b81566f1be4b15ed06785ff9857d2f3 Mon Sep 17 00:00:00 2001 From: dankito Date: Sun, 12 Jul 2020 12:26:16 +0200 Subject: [PATCH] Converted fints4kBankingClient to a multi platform project --- ui/fints4kBankingClient/build.gradle | 129 ++++++++++++++++-- .../dankito/banking/fints4kBankingClient.kt | 32 ++--- .../banking/fints4kBankingClientCreator.kt | 7 +- .../dankito/banking/mapper/BankDataMapper.kt | 0 .../banking/mapper/fints4kModelMapper.kt | 30 ++-- 5 files changed, 147 insertions(+), 51 deletions(-) rename ui/fints4kBankingClient/src/{main => commonMain}/kotlin/net/dankito/banking/fints4kBankingClient.kt (87%) rename ui/fints4kBankingClient/src/{main => commonMain}/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt (70%) rename ui/fints4kBankingClient/src/{main => commonMain}/kotlin/net/dankito/banking/mapper/BankDataMapper.kt (100%) rename ui/fints4kBankingClient/src/{main => commonMain}/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt (95%) diff --git a/ui/fints4kBankingClient/build.gradle b/ui/fints4kBankingClient/build.gradle index 72daa4cd..fdadc2eb 100644 --- a/ui/fints4kBankingClient/build.gradle +++ b/ui/fints4kBankingClient/build.gradle @@ -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 + } + } \ No newline at end of file diff --git a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt similarity index 87% rename from ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt rename to ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt index 293911ac..7da20f38 100644 --- a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt +++ b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt @@ -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 - 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) { diff --git a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt similarity index 70% rename from ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt rename to ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt index af43a92f..e4f8c3de 100644 --- a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt +++ b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt @@ -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) } } \ No newline at end of file diff --git a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/BankDataMapper.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/BankDataMapper.kt similarity index 100% rename from ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/BankDataMapper.kt rename to ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/BankDataMapper.kt diff --git a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt similarity index 95% rename from ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt rename to ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt index e8b3a5d2..314b2461 100644 --- a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt +++ b/ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt @@ -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 + .mapValues { (it.value as Money).toBigDecimal() } as Map val bookedTransactions = response.bookedTransactions.associateBy { it.account } val mappedBookedTransactions = mutableMapOf>() @@ -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,