gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated: Initiated payments UID.


From: gnunet
Subject: [libeufin] branch master updated: Initiated payments UID.
Date: Wed, 25 Oct 2023 14:09:18 +0200

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 a752f81a Initiated payments UID.
a752f81a is described below

commit a752f81acf05d1610452913e84f685eafbc43571
Author: MS <ms@taler.net>
AuthorDate: Wed Oct 25 14:05:05 2023 +0200

    Initiated payments UID.
    
    Every initiated payment gets one UID in the 'request_uid'
    column.  This value could come either from a nexus-httpd client
    (the Taler exchange, for example) or from Nexus itself, in
    case the initiated payment bounces an incoming one.
---
 database-versioning/libeufin-nexus-0001.sql        | 12 ++++++---
 database-versioning/libeufin-nexus-procedures.sql  | 10 ++++++--
 .../main/kotlin/tech/libeufin/nexus/Database.kt    | 29 ++++++++++++++--------
 nexus/src/test/kotlin/Common.kt                    |  6 ++---
 nexus/src/test/kotlin/DatabaseTest.kt              | 23 +++++++++--------
 5 files changed, 51 insertions(+), 29 deletions(-)

diff --git a/database-versioning/libeufin-nexus-0001.sql 
b/database-versioning/libeufin-nexus-0001.sql
index b1002d09..10324718 100644
--- a/database-versioning/libeufin-nexus-0001.sql
+++ b/database-versioning/libeufin-nexus-0001.sql
@@ -56,11 +56,15 @@ CREATE TABLE IF NOT EXISTS initiated_outgoing_transactions
   ,outgoing_transaction_id INT8 REFERENCES outgoing_transactions 
(outgoing_transaction_id)
   ,submitted BOOL DEFAULT FALSE 
   ,hidden BOOL DEFAULT FALSE -- FIXME: explain this.
-  ,client_request_uuid TEXT UNIQUE -- only there for HTTP requests idempotence.
+  ,request_uid TEXT NOT NULL UNIQUE
   ,failure_message TEXT -- NOTE: that may mix soon failures (those found at 
initiation time), or late failures (those found out along a fetch operation)
   );
 
 COMMENT ON COLUMN initiated_outgoing_transactions.outgoing_transaction_id
-    IS 'Points to the bank transaction that was found via nexus-fetch.  If 
"submitted" is false or nexus-fetch could not download this initiation, this 
column is expected to be NULL.';
-
-COMMIT;
+  IS 'Points to the bank transaction that was found via nexus-fetch.  If 
"submitted" is false or nexus-fetch could not download this initiation, this 
column is expected to be NULL.';
+COMMENT ON COLUMN initiated_outgoing_transactions.request_uid
+  IS 'Unique identifier of this outgoing transaction initiation.
+This value could come both from a nexus-httpd client or directly
+generated when nexus-fetch bounces one payment.  In both cases, this
+value will be used as a unique identifier for its related pain.001 document.';
+COMMIT;
\ No newline at end of file
diff --git a/database-versioning/libeufin-nexus-procedures.sql 
b/database-versioning/libeufin-nexus-procedures.sql
index d9e547cd..84dbcfc6 100644
--- a/database-versioning/libeufin-nexus-procedures.sql
+++ b/database-versioning/libeufin-nexus-procedures.sql
@@ -8,6 +8,7 @@ CREATE OR REPLACE FUNCTION create_incoming_and_bounce(
   ,IN in_debit_payto_uri TEXT
   ,IN in_bank_transfer_id TEXT
   ,IN in_timestamp BIGINT
+  ,IN in_request_uid TEXT
 ) RETURNS void
 LANGUAGE plpgsql AS $$
 BEGIN
@@ -33,15 +34,17 @@ INSERT INTO initiated_outgoing_transactions (
   ,wire_transfer_subject
   ,credit_payto_uri
   ,initiation_time
+  ,request_uid
   ) VALUES (
     in_amount
     ,'refund: ' || in_wire_transfer_subject
     ,in_debit_payto_uri
     ,in_timestamp
+    ,in_request_uid
   );
 END $$;
 
-COMMENT ON FUNCTION create_incoming_and_bounce(taler_amount, TEXT, BIGINT, 
TEXT, TEXT, BIGINT)
+COMMENT ON FUNCTION create_incoming_and_bounce(taler_amount, TEXT, BIGINT, 
TEXT, TEXT, BIGINT, TEXT)
   IS 'creates one incoming transaction with a bounced state and initiates its 
related refund.';
 
 CREATE OR REPLACE FUNCTION create_outgoing_payment(
@@ -100,6 +103,7 @@ COMMENT ON FUNCTION create_outgoing_payment(taler_amount, 
TEXT, BIGINT, TEXT, TE
 CREATE OR REPLACE FUNCTION bounce_payment(
   IN in_incoming_transaction_id BIGINT
   ,IN in_initiation_time BIGINT
+  ,IN in_request_uid TEXT
   ,OUT out_nx_incoming_payment BOOLEAN
 )
 LANGUAGE plpgsql AS $$
@@ -110,12 +114,14 @@ INSERT INTO initiated_outgoing_transactions (
   ,wire_transfer_subject
   ,credit_payto_uri
   ,initiation_time
+  ,request_uid
   )
   SELECT
     amount
     ,'refund: ' || wire_transfer_subject
     ,debit_payto_uri
     ,in_initiation_time
+    ,in_request_uid
     FROM incoming_transactions
     WHERE incoming_transaction_id = in_incoming_transaction_id;
 
@@ -134,4 +140,4 @@ UPDATE incoming_transactions
   WHERE incoming_transaction_id = in_incoming_transaction_id;
 END $$;
 
-COMMENT ON FUNCTION bounce_payment(BIGINT, BIGINT) IS 'Marks an incoming 
payment as bounced and initiates its refunding payment';
+COMMENT ON FUNCTION bounce_payment(BIGINT, BIGINT, TEXT) IS 'Marks an incoming 
payment as bounced and initiates its refunding payment';
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
index d6ad81fa..0b053603 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
@@ -42,7 +42,7 @@ data class InitiatedPayment(
     val wireTransferSubject: String?,
     val creditPaytoUri: String,
     val initiationTime: Instant,
-    val clientRequestUuid: String? = null
+    val requestUid: String
 )
 
 /**
@@ -207,18 +207,21 @@ class Database(dbConfig: String): java.io.Closeable {
      * means that the actual value was returned to the initial debtor.
      *
      * @param rowId row ID of the payment to flag as bounced.
+     * @param initiatedRequestUid unique identifier for the outgoing payment to
+     *                            initiate for this bouncing.
      * @return true if the payment could be set as bounced, false otherwise.
      */
-    suspend fun incomingPaymentSetAsBounced(rowId: Long): Boolean = runConn { 
conn ->
+    suspend fun incomingPaymentSetAsBounced(rowId: Long, initiatedRequestUid: 
String): Boolean = runConn { conn ->
         val timestamp = Instant.now().toDbMicros()
             ?: throw Exception("Could not convert Instant.now() to 
microseconds, won't bounce this payment.")
         val stmt = conn.prepareStatement("""
              SELECT out_nx_incoming_payment
-               FROM bounce_payment(?,?)
+               FROM bounce_payment(?,?,?)
              """
         )
         stmt.setLong(1, rowId)
         stmt.setLong(2, timestamp)
+        stmt.setString(3, initiatedRequestUid)
         stmt.executeQuery().use { maybeResult ->
             if (!maybeResult.next()) throw Exception("Expected outcome from 
the SQL bounce_payment function")
             return@runConn !maybeResult.getBoolean("out_nx_incoming_payment")
@@ -227,12 +230,16 @@ class Database(dbConfig: String): java.io.Closeable {
 
     /**
      * Creates an incoming payment as bounced _and_ initiates its
-     * reimbursement.  Throws exception on unique constraint violation,
-     * or other errors.
+     * reimbursement.
      *
      * @param paymentData information related to the incoming payment.
+     * @param requestUid unique identifier of the outgoing payment to
+     *                   initiate, in order to reimburse the bounced tx.
      */
-    suspend fun incomingPaymentCreateBounced(paymentData: IncomingPayment) = 
runConn { conn ->
+    suspend fun incomingPaymentCreateBounced(
+        paymentData: IncomingPayment,
+        requestUid: String
+        ) = runConn { conn ->
         val refundTimestamp = Instant.now().toDbMicros()
             ?: throw Exception("Could not convert refund execution time from 
Instant.now() to microsends.")
         val executionTime = paymentData.executionTime.toDbMicros()
@@ -245,6 +252,7 @@ class Database(dbConfig: String): java.io.Closeable {
               ,?
               ,?
               ,?
+              ,?
             )""")
         stmt.setLong(1, paymentData.amount.value)
         stmt.setInt(2, paymentData.amount.fraction)
@@ -253,6 +261,7 @@ class Database(dbConfig: String): java.io.Closeable {
         stmt.setString(5, paymentData.debitPaytoUri)
         stmt.setString(6, paymentData.bankTransferId)
         stmt.setLong(7, refundTimestamp)
+        stmt.setString(8, requestUid)
         stmt.executeQuery()
     }
 
@@ -325,7 +334,7 @@ class Database(dbConfig: String): java.io.Closeable {
              ,wire_transfer_subject
              ,credit_payto_uri
              ,initiation_time
-             ,client_request_uuid
+             ,request_uid
              FROM initiated_outgoing_transactions
              WHERE submitted=false;
         """)
@@ -347,7 +356,7 @@ class Database(dbConfig: String): java.io.Closeable {
                     creditPaytoUri = it.getString("credit_payto_uri"),
                     wireTransferSubject = 
it.getString("wire_transfer_subject"),
                     initiationTime = initiationTime,
-                    clientRequestUuid = it.getString("client_request_uuid")
+                    requestUid = it.getString("request_uid")
                 )
             } while (it.next())
         }
@@ -368,7 +377,7 @@ class Database(dbConfig: String): java.io.Closeable {
              ,wire_transfer_subject
              ,credit_payto_uri
              ,initiation_time
-             ,client_request_uuid
+             ,request_uid
            ) VALUES (
              (?,?)::taler_amount
              ,?
@@ -389,7 +398,7 @@ class Database(dbConfig: String): java.io.Closeable {
             throw Exception("Initiation time could not be converted to 
microseconds for the database.")
         }
         stmt.setLong(5, initiationTime)
-        stmt.setString(6, paymentData.clientRequestUuid) // can be null.
+        stmt.setString(6, paymentData.requestUid) // can be null.
         if (stmt.maybeUpdate())
             return@runConn PaymentInitiationOutcome.SUCCESS
         /**
diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt
index c8f88fca..2c3d84e2 100644
--- a/nexus/src/test/kotlin/Common.kt
+++ b/nexus/src/test/kotlin/Common.kt
@@ -72,17 +72,17 @@ fun getPofiConfig(userId: String, partnerId: String) = """
 """.trimIndent()
 
 // Generates a payment initiation, given its subject.
-fun genInitPay(subject: String? = null, rowUuid: String? = null) =
+fun genInitPay(subject: String? = null, rowUid: String = "unique") =
     InitiatedPayment(
         amount = TalerAmount(44, 0, "KUDOS"),
         creditPaytoUri = "payto://iban/not-used",
         wireTransferSubject = subject,
         initiationTime = Instant.now(),
-        clientRequestUuid = rowUuid
+        requestUid = rowUid
     )
 
 // Generates an incoming payment, given its subject.
-fun genIncPay(subject: String? = null, rowUuid: String? = null) =
+fun genIncPay(subject: String? = null) =
     IncomingPayment(
         amount = TalerAmount(44, 0, "KUDOS"),
         debitPaytoUri = "payto://iban/not-used",
diff --git a/nexus/src/test/kotlin/DatabaseTest.kt 
b/nexus/src/test/kotlin/DatabaseTest.kt
index 9aedb99a..474c1f1b 100644
--- a/nexus/src/test/kotlin/DatabaseTest.kt
+++ b/nexus/src/test/kotlin/DatabaseTest.kt
@@ -49,7 +49,10 @@ class IncomingPaymentsTest {
         val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
         runBlocking {
             // creating and bouncing one incoming transaction.
-            db.incomingPaymentCreateBounced(genIncPay("incoming and bounced"))
+            db.incomingPaymentCreateBounced(
+                genIncPay("incoming and bounced"),
+                "UID"
+            )
             db.runConn {
                 // check the bounced flaag is true
                 val checkBounced = it.prepareStatement("""
@@ -86,13 +89,13 @@ class IncomingPaymentsTest {
                 assertTrue(expectNotBounced.next())
                 assertFalse(expectNotBounced.getBoolean("bounced"))
                 // now bouncing it.
-                assertTrue(db.incomingPaymentSetAsBounced(1))
+                assertTrue(db.incomingPaymentSetAsBounced(1, "unique 0"))
                 // asserting it got flagged as bounced.
                 val expectBounced = it.execSQLQuery(bouncedSql)
                 assertTrue(expectBounced.next())
                 assertTrue(expectBounced.getBoolean("bounced"))
                 // Trying to bounce a non-existing payment.
-                assertFalse(db.incomingPaymentSetAsBounced(5))
+                assertFalse(db.incomingPaymentSetAsBounced(5, "unique 1"))
             }
         }
     }
@@ -168,7 +171,7 @@ class PaymentInitiationsTest {
             amount = TalerAmount(44, 0, "KUDOS"),
             creditPaytoUri = "payto://iban/not-used",
             wireTransferSubject = "test",
-            clientRequestUuid = "unique",
+            requestUid = "unique",
             initiationTime = Instant.now()
         )
         runBlocking {
@@ -178,7 +181,7 @@ class PaymentInitiationsTest {
             assertTrue {
                 haveOne.size == 1
                         && haveOne.containsKey(1)
-                        && haveOne[1]?.clientRequestUuid == "unique"
+                        && haveOne[1]?.requestUid == "unique"
             }
         }
     }
@@ -189,11 +192,11 @@ class PaymentInitiationsTest {
     fun paymentInitiationsMultiple() {
         val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
         runBlocking {
-            assertEquals(db.initiatedPaymentCreate(genInitPay("#1")), 
PaymentInitiationOutcome.SUCCESS)
-            assertEquals(db.initiatedPaymentCreate(genInitPay("#2")), 
PaymentInitiationOutcome.SUCCESS)
-            assertEquals(db.initiatedPaymentCreate(genInitPay("#3")), 
PaymentInitiationOutcome.SUCCESS)
-            assertEquals(db.initiatedPaymentCreate(genInitPay("#4")), 
PaymentInitiationOutcome.SUCCESS)
-            assertEquals(db.initiatedPaymentCreate(genInitPay()), 
PaymentInitiationOutcome.SUCCESS) // checking the nullable subject
+            assertEquals(db.initiatedPaymentCreate(genInitPay("#1", 
"unique1")), PaymentInitiationOutcome.SUCCESS)
+            assertEquals(db.initiatedPaymentCreate(genInitPay("#2", 
"unique2")), PaymentInitiationOutcome.SUCCESS)
+            assertEquals(db.initiatedPaymentCreate(genInitPay("#3", 
"unique3")), PaymentInitiationOutcome.SUCCESS)
+            assertEquals(db.initiatedPaymentCreate(genInitPay("#4", 
"unique4")), PaymentInitiationOutcome.SUCCESS)
+            assertEquals(db.initiatedPaymentCreate(genInitPay(rowUid = 
"unique5")), PaymentInitiationOutcome.SUCCESS) // checking the nullable subject
 
             // Marking one as submitted, hence not expecting it in the results.
             db.runConn { conn ->

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