libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 37725bb893974f0a0c566b7acd9db435611c94bb
parent f23911edb73eddbbedca29d03196c95a10e419ed
Author: MS <ms@taler.net>
Date:   Sat,  7 Jan 2023 13:42:11 +0100

Debit check at server side EBICS.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 27+++++++++++++++++++++++----
Mutil/src/main/kotlin/Ebics.kt | 1+
2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -67,7 +67,7 @@ data class PainParseResult( open class EbicsRequestError( val errorText: String, val errorCode: String -) : Exception("$errorText ($errorCode)") +) : Exception("$errorText (EBICS error code: $errorCode)") class EbicsNoDownloadDataAvailable(reason: String? = null) : EbicsRequestError( "[EBICS_NO_DOWNLOAD_DATA_AVAILABLE]" + if (reason != null) " $reason" else "", @@ -126,6 +126,11 @@ class EbicsProcessingError(detail: String) : EbicsRequestError( "091116" ) +class EbicsAmountCheckError(detail: String): EbicsRequestError( + "[EBICS_AMOUNT_CHECK_FAILED] $detail", + "091303" +) + suspend fun respondEbicsTransfer( call: ApplicationCall, errorText: String, @@ -697,8 +702,12 @@ private fun parsePain001(paymentRequest: String): PainParseResult { } /** - * Process a payment request in the pain.001 format. - */ + * Process a payment request in the pain.001 format. Note: + * the receiver IBAN is NOT checked to have one account at + * the Sandbox. That's because (1) it leaves open to send + * payments outside of the running Sandbox and (2) may ease + * tests where the preparation logic can skip creating also + * the receiver account. */ private fun handleCct(paymentRequest: String, requestingSubscriber: EbicsSubscriberEntity ) { @@ -731,7 +740,17 @@ private fun handleCct(paymentRequest: String, "[EBICS_PROCESSING_ERROR] Currency (${parseResult.currency}) not supported.", "091116" ) - // FIXME: check that debtor IBAN _is_ the requesting subscriber. + // Check for the debit case. + val maybeAmount = try { + BigDecimal(parseResult.amount) + } catch (e: Exception) { + logger.warn("Although PAIN validated, BigDecimal didn't parse its amount (${parseResult.amount})!") + throw EbicsProcessingError("The CCT request contains an invalid amount: ${parseResult.amount}") + } + if (maybeDebit(bankAccount.label, maybeAmount)) + throw EbicsAmountCheckError("The requested amount (${parseResult.amount}) would exceed the debit threshold") + + // Get the two parties. BankAccountTransactionEntity.new { account = bankAccount demobank = bankAccount.demoBank diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt @@ -366,6 +366,7 @@ enum class EbicsReturnCode(val errorCode: String) { EBICS_INVALID_USER_OR_USER_STATE("091002"), EBICS_PROCESSING_ERROR("091116"), EBICS_ACCOUNT_AUTHORISATION_FAILED("091302"), + EBICS_AMOUNT_CHECK_FAILED("091303"), EBICS_NO_DOWNLOAD_DATA_AVAILABLE("090005"); companion object {