[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.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated: Initiated payments UID.,
gnunet <=