gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]