[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] 02/02: Avoid retrying invalid Pain.001.
From: |
gnunet |
Subject: |
[libeufin] 02/02: Avoid retrying invalid Pain.001. |
Date: |
Tue, 29 Nov 2022 19:44:44 +0100 |
This is an automated email from the git hooks/post-receive script.
ms pushed a commit to branch master
in repository libeufin.
commit 96bbb55757be2dcc7b0c7341ffc52d14fdacec36
Author: MS <ms@taler.net>
AuthorDate: Tue Nov 29 19:44:01 2022 +0100
Avoid retrying invalid Pain.001.
---
nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 2 ++
.../tech/libeufin/nexus/bankaccount/BankAccount.kt | 13 ++++++++---
.../kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt | 25 +++++++++++++++-------
nexus/src/test/kotlin/DownloadAndSubmit.kt | 6 +++---
nexus/src/test/kotlin/MakeEnv.kt | 4 ++--
util/src/main/kotlin/XMLUtil.kt | 6 +++++-
6 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index d2a18041..30192362 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -211,6 +211,7 @@ object PaymentInitiationsTable : LongIdTable() {
val creditorBic = text("creditorBic").nullable()
val creditorName = text("creditorName")
val submitted = bool("submitted").default(false)
+ var invalid = bool("invalid").nullable()
val messageId = text("messageId")
/**
@@ -234,6 +235,7 @@ class PaymentInitiationEntity(id: EntityID<Long>) :
LongEntity(id) {
var creditorBic by PaymentInitiationsTable.creditorBic
var creditorName by PaymentInitiationsTable.creditorName
var submitted by PaymentInitiationsTable.submitted
+ var invalid by PaymentInitiationsTable.invalid
var paymentInformationId by PaymentInitiationsTable.paymentInformationId
var instructionId by PaymentInitiationsTable.instructionId
var messageId by PaymentInitiationsTable.messageId
diff --git
a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
index 10576e30..c6544d5c 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -84,21 +84,28 @@ suspend fun submitAllPaymentInitiations(httpClient:
HttpClient, accountid: Strin
HttpStatusCode.NotFound,
"account not found"
)
+ /**
+ * Skip submitted and invalid preparations.
+ */
PaymentInitiationEntity.find {
- (PaymentInitiationsTable.submitted eq false) and (
- PaymentInitiationsTable.bankAccount eq account.id)
+ // Not submitted.
+ (PaymentInitiationsTable.submitted eq false) and
+ // From the correct bank account.
+ (PaymentInitiationsTable.bankAccount eq account.id)
}.forEach {
- // Filter out non EBICS.
+ if (it.invalid == true) return@forEach
val defaultBankConnectionId =
it.bankAccount.defaultBankConnection?.id ?: throw NexusError(
HttpStatusCode.NotFound,
"Default bank connection not found. Can't submit Pain
document"
)
+ // Rare, but filter out bank accounts without a bank connection.
val bankConnection =
NexusBankConnectionEntity.findById(defaultBankConnectionId) ?: throw NexusError(
HttpStatusCode.InternalServerError,
"Bank connection '$defaultBankConnectionId' " +
"(pointed by bank account
'${it.bankAccount.bankAccountName}')" +
" not found in the database."
)
+ // Filter out non EBICS.
if (bankConnection.type != "ebics") {
logger.info("Skipping non-implemented bank connection
'${bankConnection.type}'")
return@forEach
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
index 726d94f5..a232bfd1 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -44,8 +44,10 @@ import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
+import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.transactions.transaction
import tech.libeufin.nexus.*
+import tech.libeufin.nexus.bankaccount.getPaymentInitiation
import tech.libeufin.nexus.iso20022.NexusPaymentInitiationData
import tech.libeufin.nexus.iso20022.createPain001document
import tech.libeufin.nexus.logger
@@ -531,9 +533,18 @@ class EbicsBankConnectionProtocol: BankConnectionProtocol {
)
logger.debug("Sending Pain.001:
${paymentInitiation.paymentInformationId}," +
" for payment: '${paymentInitiation.subject}'")
- if (!XMLUtil.validateFromString(painMessage)) throw NexusError(
- HttpStatusCode.InternalServerError, "Pain.001 message is
invalid."
- )
+ if (!XMLUtil.validateFromString(painMessage)) {
+ logger.error("Pain.001
${paymentInitiation.paymentInformationId}" +
+ " is invalid, not submitting it and flag as invalid.")
+ val payment = getPaymentInitiation(paymentInitiationId)
+ payment.invalid = true
+ // The following commit prevents the thrown error
+ // to lose the database transaction data.
+ TransactionManager.current().commit()
+ throw NexusError(
+ HttpStatusCode.InternalServerError, "Pain.001 message is
invalid."
+ )
+ }
object {
val subscriberDetails = subscriberDetails
val painMessage = painMessage
@@ -546,12 +557,10 @@ class EbicsBankConnectionProtocol: BankConnectionProtocol
{
r.painMessage.toByteArray(Charsets.UTF_8),
EbicsStandardOrderParams()
)
- // Mark the payment as submitted.
transaction {
- val paymentInitiation =
PaymentInitiationEntity.findById(paymentInitiationId)
- ?: throw NexusError(HttpStatusCode.NotFound, "payment
initiation not found")
- paymentInitiation.submitted = true
- paymentInitiation.submissionDate = LocalDateTime.now().millis()
+ val payment = getPaymentInitiation(paymentInitiationId)
+ payment.submitted = true
+ payment.submissionDate = LocalDateTime.now().millis()
}
}
diff --git a/nexus/src/test/kotlin/DownloadAndSubmit.kt
b/nexus/src/test/kotlin/DownloadAndSubmit.kt
index b7bdc04e..243ae0a8 100644
--- a/nexus/src/test/kotlin/DownloadAndSubmit.kt
+++ b/nexus/src/test/kotlin/DownloadAndSubmit.kt
@@ -91,7 +91,7 @@ fun getCustomEbicsServer(r: EbicsResponses, endpoint: String
= "/ebicsweb"): App
* and having had access to runTask and TaskSchedule, that
* are now 'private'.
*/
-@Ignore
+// @Ignore
class DownloadAndSubmit {
/**
* Instruct the server to return invalid CAMT content.
@@ -122,7 +122,7 @@ class DownloadAndSubmit {
level = FetchLevel.REPORT,
"foo"
),
- "mock-bank-account"
+ "foo"
)
}
}
@@ -147,7 +147,7 @@ class DownloadAndSubmit {
),
transaction {
NexusBankAccountEntity.findByName(
- "mock-bank-account"
+ "foo"
) ?: throw Exception("Test failed")
}
)
diff --git a/nexus/src/test/kotlin/MakeEnv.kt b/nexus/src/test/kotlin/MakeEnv.kt
index b7eb482a..b4a11254 100644
--- a/nexus/src/test/kotlin/MakeEnv.kt
+++ b/nexus/src/test/kotlin/MakeEnv.kt
@@ -86,7 +86,7 @@ fun prepNexusDb() {
bankAuthenticationPublicKey =
ExposedBlob(bankKeys.auth.public.encoded)
}
val a = NexusBankAccountEntity.new {
- bankAccountName = "mock-bank-account"
+ bankAccountName = "foo"
iban = FOO_USER_IBAN
bankCode = "SANDBOXX"
defaultBankConnection = c
@@ -94,7 +94,7 @@ fun prepNexusDb() {
accountHolder = "foo"
}
val b = NexusBankAccountEntity.new {
- bankAccountName = "bar-bank-account"
+ bankAccountName = "bar"
iban = BAR_USER_IBAN
bankCode = "SANDBOXX"
defaultBankConnection = c
diff --git a/util/src/main/kotlin/XMLUtil.kt b/util/src/main/kotlin/XMLUtil.kt
index 1fa993dc..c20a969a 100644
--- a/util/src/main/kotlin/XMLUtil.kt
+++ b/util/src/main/kotlin/XMLUtil.kt
@@ -252,7 +252,11 @@ class XMLUtil private constructor() {
try {
getEbicsValidator().validate(xmlDoc)
} catch (e: Exception) {
- e.printStackTrace()
+ /**
+ * Would be convenient to return also the error
+ * message to the caller, so that it can link it
+ * to a document ID in the logs.
+ */
logger.warn("Validation failed: ${e}")
return false
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.