gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] branch master updated: nexus fetch: ignoring seen payments


From: gnunet
Subject: [libeufin] branch master updated: nexus fetch: ignoring seen payments
Date: Wed, 15 Nov 2023 10:50:31 +0100

This is an automated email from the git hooks/post-receive script.

ms pushed a commit to branch master
in repository libeufin.

The following commit(s) were added to refs/heads/master by this push:
     new 3eaa7331 nexus fetch: ignoring seen payments
3eaa7331 is described below

commit 3eaa7331d444122787ae54ec382b5bf01e3705a1
Author: MS <ms@taler.net>
AuthorDate: Wed Nov 15 10:50:04 2023 +0100

    nexus fetch: ignoring seen payments
---
 database-versioning/libeufin-nexus-0001.sql        |  2 +-
 .../main/kotlin/tech/libeufin/nexus/Database.kt    | 39 ++++++++++++----------
 .../main/kotlin/tech/libeufin/nexus/EbicsFetch.kt  |  6 +++-
 .../main/kotlin/tech/libeufin/nexus/Iso20022.kt    | 28 ++++++++++++----
 4 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/database-versioning/libeufin-nexus-0001.sql 
b/database-versioning/libeufin-nexus-0001.sql
index 579c6900..5c6f3082 100644
--- a/database-versioning/libeufin-nexus-0001.sql
+++ b/database-versioning/libeufin-nexus-0001.sql
@@ -47,7 +47,7 @@ COMMENT ON TYPE submission_state
 CREATE TABLE IF NOT EXISTS incoming_transactions
   (incoming_transaction_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE
   ,amount taler_amount NOT NULL
-  ,wire_transfer_subject TEXT
+  ,wire_transfer_subject TEXT NOT NULL
   ,execution_time INT8 NOT NULL
   ,debit_payto_uri TEXT NOT NULL
   ,bank_transfer_id TEXT NOT NULL -- EBICS or Depolymerizer (generic)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
index 9b83a707..d13cf4b1 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
@@ -11,27 +11,10 @@ import java.time.Instant
 
 data class TalerAmount(
     val value: Long,
-    val fraction: Int,
+    val fraction: Int, // has at most 8 digits.
     val currency: String
 )
 
-/**
- * Stringifies TalerAmount's.  NOTE: the caller must enforce
- * length-checks on the output fractional part, to ensure compatibility
- * with the bank.
- *
- * @return the amount in the $currency:x.y format.
- */
-fun TalerAmount.stringify(): String {
-    if (fraction == 0) {
-        return "$currency:$value"
-    } else {
-        val fractionFormat = this.fraction.toString().padStart(8, 
'0').dropLastWhile { it == '0' }
-        if (fractionFormat.length > 2) throw Exception("Sub-cent amounts not 
supported")
-        return "$currency:$value.$fractionFormat"
-    }
-}
-
 // INCOMING PAYMENTS STRUCTS
 
 /**
@@ -332,6 +315,26 @@ class Database(dbConfig: String): java.io.Closeable {
         }
     }
 
+    /**
+     * Checks if the incoming payment was already processed by Nexus.
+     *
+     * @param bankUid unique identifier assigned by the bank to the payment.
+     *        Normally, that's the <AcctSvcrRef> value found in camt.05x 
records.
+     * @return true if found, false otherwise
+     */
+    suspend fun isIncomingPaymentSeen(bankUid: String): Boolean = runConn { 
conn ->
+        val stmt = conn.prepareStatement("""
+             SELECT 1
+               FROM incoming_transactions
+               WHERE bank_transfer_id = ?;
+        """)
+        stmt.setString(1, bankUid)
+        val res = stmt.executeQuery()
+        res.use {
+            return@runConn it.next()
+        }
+    }
+
     /**
      * Checks if the reserve public key already exists.
      *
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
index 138a695a..6596e8f4 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -374,6 +374,10 @@ fun ingestNotification(
     try {
         incomingPayments.forEach {
             runBlocking {
+                if (db.isIncomingPaymentSeen(it.bankTransferId)) {
+                    logger.debug("Incoming payment with UID 
'${it.bankTransferId}' already seen.")
+                    return@runBlocking
+                }
                 val reservePub = isTalerable(db, it)
                 if (reservePub == null) {
                     db.incomingPaymentCreateBounced(
@@ -429,7 +433,7 @@ private suspend fun fetchDocuments(
     )
     // Parsing the XML: only camt.054 (Detailavisierung) supported currently.
     if (ctx.whichDocument != SupportedDocument.CAMT_054) {
-        logger.warn("Not parsing ${ctx.whichDocument}.  Only camt.054 
notifications supported.")
+        logger.warn("Not ingesting ${ctx.whichDocument}.  Only camt.054 
notifications supported.")
         return
     }
     if (!ingestNotification(db, ctx, maybeContent)) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
index cf25787c..bc3199e6 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
@@ -13,6 +13,26 @@ data class Pain001Namespaces(
     val xsdFilename: String
 )
 
+/**
+ * Gets the amount number, also converting it from the
+ * Taler-friendly 8 fractional digits to the more bank
+ * friendly with 2.
+ *
+ * @param amount the Taler amount where to extract the number
+ * @return [String] of the amount number without the currency.
+ */
+fun getAmountNoCurrency(amount: TalerAmount): String {
+    if (amount.fraction == 0) {
+        return amount.value.toString()
+    } else {
+        val fractionFormat = amount.fraction.toString().padStart(8, 
'0').dropLastWhile { it == '0' }
+        if (fractionFormat.length > 2) throw Exception("Sub-cent amounts not 
supported")
+        return "${amount.value}.${fractionFormat}"
+    }
+}
+
+
+
 /**
  * Create a pain.001 document.  It requires the debtor BIC.
  *
@@ -43,13 +63,7 @@ fun createPain001(
         xsdFilename = "pain.001.001.09.ch.03.xsd"
     )
     val zonedTimestamp = ZonedDateTime.ofInstant(initiationTimestamp, 
ZoneId.of("UTC"))
-    val amountWithoutCurrency: String = amount.stringify().split(":").run {
-        if (this.size != 2) throw NexusSubmitException(
-            "Invalid stringified amount: $amount",
-            stage=NexusSubmissionStage.pain
-        )
-        return@run this[1]
-    }
+    val amountWithoutCurrency: String = getAmountNoCurrency(amount)
     val creditorName: String = creditAccount.receiverName
         ?: throw NexusSubmitException(
             "Cannot operate without the creditor name",

-- 
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]