Added callbacks to FinTsClientCallback methods so that they can be responded asynchronously
This commit is contained in:
parent
2889d1b0ce
commit
7424688b33
|
@ -424,22 +424,27 @@ open class FinTsClient(
|
|||
|
||||
open fun changeTanMedium(newActiveTanMedium: TanGeneratorTanMedium, bank: BankData, customer: CustomerData, callback: (FinTsClientResponse) -> Unit) {
|
||||
|
||||
var enteredAtc: EnterTanGeneratorAtcResult? = null
|
||||
|
||||
if (bank.changeTanMediumParameters?.enteringAtcAndTanRequired == true) {
|
||||
enteredAtc = this.callback.enterTanGeneratorAtc(customer, newActiveTanMedium)
|
||||
|
||||
this.callback.enterTanGeneratorAtc(customer, newActiveTanMedium) { enteredAtc ->
|
||||
if (enteredAtc.hasAtcBeenEntered == false) {
|
||||
val message = "Bank requires to enter ATC and TAN in order to change TAN medium." // TODO: translate
|
||||
callback(FinTsClientResponse(Response(false, exception = Exception(message))))
|
||||
return
|
||||
}
|
||||
else {
|
||||
sendChangeTanMediumMessage(bank, customer, newActiveTanMedium, enteredAtc, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sendChangeTanMediumMessage(bank, customer, newActiveTanMedium, null, callback)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun sendChangeTanMediumMessage(bank: BankData, customer: CustomerData, newActiveTanMedium: TanGeneratorTanMedium,
|
||||
enteredAtc: EnterTanGeneratorAtcResult?, callback: (FinTsClientResponse) -> Unit) {
|
||||
|
||||
sendMessageAndHandleResponse(bank, customer, false, { dialogContext ->
|
||||
messageBuilder.createChangeTanMediumMessage(newActiveTanMedium, dialogContext,
|
||||
enteredAtc?.tan, enteredAtc?.atc)
|
||||
messageBuilder.createChangeTanMediumMessage(newActiveTanMedium, dialogContext, enteredAtc?.tan, enteredAtc?.atc)
|
||||
}) { response ->
|
||||
callback(FinTsClientResponse(response))
|
||||
}
|
||||
|
@ -577,8 +582,10 @@ open class FinTsClient(
|
|||
}
|
||||
else {
|
||||
// we know user's supported tan procedures, now ask user which one to select
|
||||
callback.askUserForTanProcedure(customer.supportedTanProcedures, selectSuggestedTanProcedure(customer))?.let {
|
||||
customer.selectedTanProcedure = it
|
||||
callback.askUserForTanProcedure(customer.supportedTanProcedures, selectSuggestedTanProcedure(customer)) { selectedTanProcedure ->
|
||||
selectedTanProcedure?.let {
|
||||
customer.selectedTanProcedure = selectedTanProcedure
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -775,10 +782,10 @@ open class FinTsClient(
|
|||
val customer = dialogContext.customer // TODO: copy required data to TanChallenge
|
||||
val tanChallenge = createTanChallenge(tanResponse, customer)
|
||||
|
||||
val enteredTanResult = this.callback.enterTan(customer, tanChallenge) // TODO: add callback to be more flexible in regard to thread handling
|
||||
|
||||
this.callback.enterTan(customer, tanChallenge) { enteredTanResult ->
|
||||
handleEnterTanResult(enteredTanResult, tanResponse, response, dialogContext, callback)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun createTanChallenge(tanResponse: TanResponse, customer: CustomerData): TanChallenge {
|
||||
// TODO: is this true for all tan procedures?
|
||||
|
|
|
@ -16,15 +16,15 @@ interface FinTsClientCallback {
|
|||
* If you do not support an enter tan dialog or if your enter tan dialog supports selecting a TAN procedure, it's
|
||||
* best returning [suggestedTanProcedure] and to not show an extra select TAN procedure dialog.
|
||||
*/
|
||||
fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?): TanProcedure?
|
||||
fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit)
|
||||
|
||||
fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult
|
||||
fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit)
|
||||
|
||||
/**
|
||||
* This method gets called for chipTan TAN generators when the bank asks the customer to synchronize her/his TAN generator.
|
||||
*
|
||||
* If you do not support entering TAN generator ATC, return [EnterTanGeneratorAtcResult.userDidNotEnterAtc]
|
||||
*/
|
||||
fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult
|
||||
fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit)
|
||||
|
||||
}
|
|
@ -7,17 +7,17 @@ import net.dankito.banking.fints.model.*
|
|||
open class NoOpFinTsClientCallback : FinTsClientCallback {
|
||||
|
||||
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>,
|
||||
suggestedTanProcedure: TanProcedure?): TanProcedure? {
|
||||
suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit) {
|
||||
|
||||
return suggestedTanProcedure
|
||||
callback(suggestedTanProcedure)
|
||||
}
|
||||
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult {
|
||||
return EnterTanResult.userDidNotEnterTan()
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) {
|
||||
callback(EnterTanResult.userDidNotEnterTan())
|
||||
}
|
||||
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
return EnterTanGeneratorAtcResult.userDidNotEnterAtc()
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
callback(EnterTanGeneratorAtcResult.userDidNotEnterAtc())
|
||||
}
|
||||
|
||||
}
|
|
@ -11,17 +11,17 @@ open class SimpleFinTsClientCallback(
|
|||
) : FinTsClientCallback {
|
||||
|
||||
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>,
|
||||
suggestedTanProcedure: TanProcedure?): TanProcedure? {
|
||||
suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit) {
|
||||
|
||||
return askUserForTanProcedure?.invoke(supportedTanProcedures, suggestedTanProcedure) ?: suggestedTanProcedure
|
||||
callback(askUserForTanProcedure?.invoke(supportedTanProcedures, suggestedTanProcedure) ?: suggestedTanProcedure)
|
||||
}
|
||||
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult {
|
||||
return enterTan?.invoke(customer, tanChallenge) ?: EnterTanResult.userDidNotEnterTan()
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) {
|
||||
callback(enterTan?.invoke(customer, tanChallenge) ?: EnterTanResult.userDidNotEnterTan())
|
||||
}
|
||||
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
return enterTanGeneratorAtc?.invoke(customer, tanMedium) ?: EnterTanGeneratorAtcResult.userDidNotEnterAtc()
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
callback(enterTanGeneratorAtc?.invoke(customer, tanMedium) ?: EnterTanGeneratorAtcResult.userDidNotEnterAtc())
|
||||
}
|
||||
|
||||
}
|
|
@ -46,18 +46,18 @@ open class FinTsClientTestBase {
|
|||
|
||||
private val callback = object : FinTsClientCallback {
|
||||
|
||||
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?): TanProcedure? {
|
||||
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit) {
|
||||
didAskUserForTanProcedure = true
|
||||
return suggestedTanProcedure // simply return suggestedTanProcedure as in most cases it's the best fitting one
|
||||
callback(suggestedTanProcedure) // simply return suggestedTanProcedure as in most cases it's the best fitting one
|
||||
}
|
||||
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult {
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) {
|
||||
didAskUserToEnterTan = true
|
||||
|
||||
return EnterTanResult.userDidNotEnterTan()
|
||||
callback(EnterTanResult.userDidNotEnterTan())
|
||||
}
|
||||
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
fail("Bank asks you to synchronize your TAN generator for card ${tanMedium.cardNumber} " +
|
||||
"(card sequence number ${tanMedium.cardSequenceNumber}). Please do this via your online banking portal or Banking UI.")
|
||||
}
|
||||
|
|
|
@ -23,40 +23,24 @@ open class RouterAndroid(protected val activityTracker: CurrentActivityTracker)
|
|||
}
|
||||
}
|
||||
|
||||
override fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult {
|
||||
val enteredTan = AtomicReference<EnterTanResult>(null)
|
||||
val tanEnteredLatch = CountDownLatch(1)
|
||||
|
||||
override fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter, callback: (EnterTanResult) -> Unit) {
|
||||
activityTracker.currentOrNextActivity { activity ->
|
||||
activity.runOnUiThread {
|
||||
EnterTanDialog().show(customer, tanChallenge, activity, false) {
|
||||
enteredTan.set(it)
|
||||
tanEnteredLatch.countDown()
|
||||
EnterTanDialog().show(customer, tanChallenge, activity, false) { result ->
|
||||
callback(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
|
||||
|
||||
return enteredTan.get()
|
||||
}
|
||||
|
||||
override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
val result = AtomicReference<EnterTanGeneratorAtcResult>(null)
|
||||
val tanEnteredLatch = CountDownLatch(1)
|
||||
|
||||
override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
activityTracker.currentOrNextActivity { activity ->
|
||||
activity.runOnUiThread {
|
||||
EnterAtcDialog().show(tanMedium, activity, false) { enteredResult ->
|
||||
result.set(enteredResult)
|
||||
tanEnteredLatch.countDown()
|
||||
callback(enteredResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
|
||||
|
||||
return result.get()
|
||||
}
|
||||
|
||||
override fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?) {
|
||||
|
|
|
@ -28,7 +28,7 @@ open class EnterAtcDialog : DialogFragment() {
|
|||
|
||||
|
||||
open fun show(tanMedium: TanMedium, activity: AppCompatActivity,
|
||||
fullscreen: Boolean = false, atcEnteredCallback: (EnterTanGeneratorAtcResult?) -> Unit) {
|
||||
fullscreen: Boolean = false, atcEnteredCallback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
|
||||
this.tanMedium = tanMedium
|
||||
this.atcEnteredCallback = atcEnteredCallback
|
||||
|
|
|
@ -25,24 +25,16 @@ open class RouterJavaFx : IRouter {
|
|||
AddAccountDialog(presenter).show(messages["add.account.dialog.title"])
|
||||
}
|
||||
|
||||
override fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult {
|
||||
val enteredTan = AtomicReference<EnterTanResult>(null)
|
||||
val tanEnteredLatch = CountDownLatch(1)
|
||||
|
||||
override fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter, callback: (EnterTanResult) -> Unit) {
|
||||
FX.runAndWait {
|
||||
EnterTanDialog(customer, tanChallenge, presenter) {
|
||||
enteredTan.set(it)
|
||||
tanEnteredLatch.countDown()
|
||||
EnterTanDialog(customer, tanChallenge, presenter) { result ->
|
||||
callback(result)
|
||||
}.show(messages["enter.tan.dialog.title"])
|
||||
}
|
||||
|
||||
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
|
||||
|
||||
return enteredTan.get()
|
||||
}
|
||||
|
||||
override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
return EnterTanGeneratorAtcResult.userDidNotEnterAtc()
|
||||
override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
callback(EnterTanGeneratorAtcResult.userDidNotEnterAtc()) // TODO: implement EnterAtcDialog
|
||||
}
|
||||
|
||||
override fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?) {
|
||||
|
|
|
@ -9,11 +9,11 @@ import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium
|
|||
|
||||
interface BankingClientCallback {
|
||||
|
||||
fun enterTan(customer: Customer, tanChallenge: TanChallenge): EnterTanResult
|
||||
fun enterTan(customer: Customer, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit)
|
||||
|
||||
/**
|
||||
* This method gets called for chipTan TAN generators when the bank asks the customer to synchronize her/his TAN generator.
|
||||
*/
|
||||
fun enterTanGeneratorAtc(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult
|
||||
fun enterTanGeneratorAtc(tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit)
|
||||
|
||||
}
|
|
@ -14,9 +14,9 @@ interface IRouter {
|
|||
|
||||
fun showAddAccountDialog(presenter: BankingPresenter)
|
||||
|
||||
fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult
|
||||
fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter, callback: (EnterTanResult) -> Unit)
|
||||
|
||||
fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult
|
||||
fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit)
|
||||
|
||||
fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?)
|
||||
|
||||
|
|
|
@ -74,23 +74,25 @@ open class BankingPresenter(
|
|||
|
||||
protected val callback: BankingClientCallback = object : BankingClientCallback {
|
||||
|
||||
override fun enterTan(customer: Customer, tanChallenge: TanChallenge): EnterTanResult {
|
||||
override fun enterTan(customer: Customer, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) {
|
||||
if (saveAccountOnNextEnterTanInvocation) {
|
||||
persistAccount(customer)
|
||||
saveAccountOnNextEnterTanInvocation = false
|
||||
}
|
||||
|
||||
val result = router.getTanFromUserFromNonUiThread(customer, tanChallenge, this@BankingPresenter)
|
||||
|
||||
router.getTanFromUserFromNonUiThread(customer, tanChallenge, this@BankingPresenter) { result ->
|
||||
if (result.changeTanProcedureTo != null || result.changeTanMediumTo != null) { // then either selected TAN medium or procedure will change -> save account on next call to enterTan() as then changes will be visible
|
||||
saveAccountOnNextEnterTanInvocation = true
|
||||
}
|
||||
|
||||
return result
|
||||
callback(result)
|
||||
}
|
||||
}
|
||||
|
||||
override fun enterTanGeneratorAtc(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
return router.getAtcFromUserFromNonUiThread(tanMedium)
|
||||
override fun enterTanGeneratorAtc(tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
router.getAtcFromUserFromNonUiThread(tanMedium) { result ->
|
||||
callback(result)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -167,43 +167,43 @@ open class fints4kBankingClient(
|
|||
}
|
||||
|
||||
|
||||
protected open fun createFinTsClientCallback(callback: BankingClientCallback): FinTsClientCallback {
|
||||
protected open fun createFinTsClientCallback(clientCallback: BankingClientCallback): FinTsClientCallback {
|
||||
return object : FinTsClientCallback {
|
||||
|
||||
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?): TanProcedure? {
|
||||
return handleAskUserForTanProcedure(supportedTanProcedures, suggestedTanProcedure)
|
||||
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit) {
|
||||
handleAskUserForTanProcedure(supportedTanProcedures, suggestedTanProcedure, callback)
|
||||
}
|
||||
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult {
|
||||
return handleEnterTan(customer, tanChallenge, callback)
|
||||
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) {
|
||||
handleEnterTan(customer, tanChallenge, callback, clientCallback)
|
||||
}
|
||||
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
|
||||
return handleEnterTanGeneratorAtc(customer, tanMedium, callback)
|
||||
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) {
|
||||
handleEnterTanGeneratorAtc(customer, tanMedium, callback, clientCallback)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun handleAskUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?): TanProcedure? {
|
||||
protected open fun handleAskUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?, callback: (TanProcedure?) -> Unit) {
|
||||
// we simply return suggestedTanProcedure as even so it's not user's preferred TAN procedure she still can select it in EnterTanDialog
|
||||
return suggestedTanProcedure
|
||||
callback(suggestedTanProcedure)
|
||||
}
|
||||
|
||||
protected open fun handleEnterTan(customer: CustomerData, tanChallenge: TanChallenge, callback: BankingClientCallback): EnterTanResult {
|
||||
protected open fun handleEnterTan(customer: CustomerData, tanChallenge: TanChallenge, enterTanCallback: (EnterTanResult) -> Unit, clientCallback: BankingClientCallback) {
|
||||
mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, customer)
|
||||
|
||||
val result = callback.enterTan(this@fints4kBankingClient.customer, mapper.mapTanChallenge(tanChallenge))
|
||||
|
||||
return mapper.mapEnterTanResult(result, customer)
|
||||
clientCallback.enterTan(this@fints4kBankingClient.customer, mapper.mapTanChallenge(tanChallenge)) { result ->
|
||||
enterTanCallback(mapper.mapEnterTanResult(result, customer))
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun handleEnterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, callback: BankingClientCallback): EnterTanGeneratorAtcResult {
|
||||
protected open fun handleEnterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium, enterAtcCallback: (EnterTanGeneratorAtcResult) -> Unit, clientCallback: BankingClientCallback) {
|
||||
mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, customer)
|
||||
|
||||
val result = callback.enterTanGeneratorAtc(mapper.mapTanMedium(tanMedium))
|
||||
|
||||
return mapper.mapEnterTanGeneratorAtcResult(result)
|
||||
clientCallback.enterTanGeneratorAtc(mapper.mapTanMedium(tanMedium)) { result ->
|
||||
enterAtcCallback(mapper.mapEnterTanGeneratorAtcResult(result))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue