gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated (ee10f1d3 -> 196f7bf2)


From: gnunet
Subject: [libeufin] branch master updated (ee10f1d3 -> 196f7bf2)
Date: Mon, 03 Apr 2023 01:34:35 +0200

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

ms pushed a change to branch master
in repository libeufin.

    from ee10f1d3 x-libeufin-bank connection.
     new 5126516e CLI test harness
     new 802724f6 CLI.
     new 3519a3bc fix payto parser
     new 19dfeb67 Scheduling tasks.
     new f16ab461 x-libeufin-bank connection
     new 9b0aafb5 comments, indentation, helpers
     new 196f7bf2 comments, indentation, helpers

The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 cli/bin/libeufin-cli                               |  1 -
 cli/tests/launch_services.sh                       | 75 +++++++---------------
 .../main/kotlin/tech/libeufin/nexus/Scheduling.kt  | 39 +++++------
 nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt |  2 +-
 .../tech/libeufin/nexus/bankaccount/BankAccount.kt |  5 ++
 .../kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt |  3 +-
 .../tech/libeufin/nexus/iso20022/Iso20022.kt       |  3 +-
 .../kotlin/tech/libeufin/nexus/server/Helpers.kt   |  9 +++
 .../tech/libeufin/nexus/server/NexusServer.kt      | 12 ++--
 .../nexus/xlibeufinbank/XLibeufinBankNexus.kt      | 69 ++++++++++++++++----
 .../tech/libeufin/sandbox/XMLEbicsConverter.kt     |  2 +-
 util/src/main/kotlin/HTTP.kt                       |  8 +++
 util/src/main/kotlin/JSON.kt                       |  5 ++
 util/src/main/kotlin/Payto.kt                      |  2 +-
 14 files changed, 141 insertions(+), 94 deletions(-)

diff --git a/cli/bin/libeufin-cli b/cli/bin/libeufin-cli
index 9bbef229..ff30d62a 100755
--- a/cli/bin/libeufin-cli
+++ b/cli/bin/libeufin-cli
@@ -584,7 +584,6 @@ def connect(obj, connection_name):
         exit(1)
 
     check_response_status(resp)
-    tell_user(resp)
 
 @connections.command(help="Import one bank account, chosen from the downloaded 
ones.")
 @click.option(
diff --git a/cli/tests/launch_services.sh b/cli/tests/launch_services.sh
index 17cd81d6..f085fb26 100755
--- a/cli/tests/launch_services.sh
+++ b/cli/tests/launch_services.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
-# Convenience script to setup and run a Sandbox + Nexus
-# EBICS pair, in order to try CLI commands.
+# Convenience script to setup and run a Sandbox & Nexus
+# connected through x-libeufin-bank.
 set -eu
 
 WITH_TASKS=1
@@ -22,16 +22,7 @@ echo RUNNING SANDBOX-NEXUS EBICS PAIR
 jq --version &> /dev/null || (echo "'jq' command not found"; exit 77)
 curl --version &> /dev/null || (echo "'curl' command not found"; exit 77)
 
-SQLITE_FILE_PATH=/tmp/libeufin-cli-test.sqlite3
-getDbConn () {
-  if test withPostgres == "${1:-}"; then
-    echo "jdbc:postgresql://localhost:5432/libeufincheck?user=$(whoami)"
-    return
-  fi
-  echo "jdbc:sqlite:${SQLITE_FILE_PATH}"
-}
-
-DB_CONN=`getDbConn withPostgres`
+DB_CONN="jdbc:postgresql://localhost:5432/libeufincheck?user=$(whoami)"
 export LIBEUFIN_SANDBOX_DB_CONNECTION=$DB_CONN
 export LIBEUFIN_NEXUS_DB_CONNECTION=$DB_CONN
 
@@ -75,69 +66,51 @@ libeufin-cli \
   demobank \
   register
 echo DONE
-export LIBEUFIN_SANDBOX_USERNAME=admin
-export LIBEUFIN_SANDBOX_PASSWORD=foo
-echo -n "Create EBICS host at Sandbox..."
-libeufin-cli sandbox \
-  --sandbox-url http://localhost:5000 \
-  ebicshost create --host-id wwwebics
-echo OK
-echo -n "Create 'www' EBICS subscriber at Sandbox..."
-libeufin-cli sandbox \
-  --sandbox-url http://localhost:5000 \
-  demobank new-ebicssubscriber --host-id wwwebics \
-  --user-id wwwebics --partner-id wwwpartner \
-  --bank-account www # that's a username _and_ a bank account name
-echo OK
+echo -n Creating the x-libeufin-bank connection at Nexus...
 export LIBEUFIN_NEXUS_USERNAME=test-user
 export LIBEUFIN_NEXUS_PASSWORD=x
 export LIBEUFIN_NEXUS_URL=http://localhost:5001
-echo -n Creating the EBICS connection at Nexus...
-libeufin-cli connections new-ebics-connection \
-  --ebics-url "http://localhost:5000/ebicsweb"; \
-  --host-id wwwebics \
-  --partner-id wwwpartner \
-  --ebics-user-id wwwebics \
+# echoing the password to STDIN, as that is a "prompt" option.
+libeufin-cli connections new-xlibeufinbank-connection \
+  --bank-url "http://localhost:5000/demobanks/default/access-api"; \
+  --username www \
+  --password foo \
   wwwconn
 echo DONE
-echo -n Setup EBICS keying...
-libeufin-cli connections connect wwwconn > /dev/null
-echo OK
-echo -n Download bank account name from Sandbox...
-libeufin-cli connections download-bank-accounts wwwconn
-echo OK
-echo -n Importing bank account info into Nexus...
+echo -n Connecting the x-libeufin-bank connection...
+libeufin-cli connections connect wwwconn
+echo DONE
+# Importing the bank account under a local name at Nexus.
+echo -n Importing the x-libeufin-bank account locally..
 libeufin-cli connections import-bank-account \
   --offered-account-id www \
-  --nexus-bank-account-id www-nexus \
-  wwwconn
-echo OK
+  --nexus-bank-account-id foo-at-nexus wwwconn
+echo DONE
 echo -n Create the Taler facade at Nexus...
 libeufin-cli facades \
   new-taler-wire-gateway-facade \
   --currency TESTKUDOS --facade-name test-facade \
-  wwwconn www-nexus
-echo OK
-
+  wwwconn foo-at-nexus
+echo DONE
 if test 1 = $WITH_TASKS; then
   echo -n Creating submit transactions task..
   libeufin-cli accounts task-schedule \
     --task-type submit \
     --task-name www-payments \
     --task-cronspec "* * *" \
-    www-nexus || true
+    foo-at-nexus || true
   # Tries every second.  Ask C52
-  echo OK
+  echo DONE
   echo -n Creating fetch transactions task..
   # Not idempotent, FIXME #7739
   libeufin-cli accounts task-schedule \
     --task-type fetch \
     --task-name www-history \
     --task-cronspec "* * *" \
-    --task-param-level report \
-    --task-param-range-type latest \
-    www-nexus || true
-  echo OK
+    --task-param-level statement \
+    --task-param-range-type since-last \
+    foo-at-nexus || true
+  echo DONE
 else
   echo NOT creating background tasks!
 fi
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt
index 8d6062d1..2d3d869e 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt
@@ -32,6 +32,7 @@ import 
tech.libeufin.nexus.bankaccount.fetchBankAccountTransactions
 import tech.libeufin.nexus.bankaccount.submitAllPaymentInitiations
 import tech.libeufin.nexus.server.FetchSpecJson
 import java.lang.IllegalArgumentException
+import java.net.ConnectException
 import java.time.Duration
 import java.time.Instant
 import java.time.ZonedDateTime
@@ -53,25 +54,19 @@ private suspend fun runTask(client: HttpClient, sched: 
TaskSchedule) {
         when (sched.resourceType) {
             "bank-account" -> {
                 when (sched.type) {
-                    /**
-                     * Downloads and ingests the payment records from the bank.
-                     */
+                    // Downloads and ingests the payment records from the bank.
                     "fetch" -> {
                         @Suppress("BlockingMethodInNonBlockingContext")
                         val fetchSpec = 
jacksonObjectMapper().readValue(sched.params, FetchSpecJson::class.java)
-                        val outcome = fetchBankAccountTransactions(client, 
fetchSpec, sched.resourceId)
-                        if (outcome.errors != null && 
outcome.errors!!.isNotEmpty()) {
-                            /**
-                             * Communication with the bank had at least one 
error.  All of
-                             * them get logged when this 'outcome.errors' list 
was defined,
-                             * so not logged twice here.  Failing to bring the 
problem(s) up.
-                             */
-                            exitProcess(1)
-                        }
+                        fetchBankAccountTransactions(client, fetchSpec, 
sched.resourceId)
+                        /**
+                         * NOTE: the previous operation COULD have had 
problems but that
+                         * is tolerated because the communication with the 
backend CAN be
+                         * unreliable.  As of logging: not doing it here 
twice, since every
+                         * error should already have been logged when it 
originated.
+                         */
                     }
-                    /**
-                     * Submits the payment preparations that are found in the 
database.
-                     */
+                    // Submits the payment preparations that are found in the 
database.
                     "submit" -> {
                         submitAllPaymentInitiations(client, sched.resourceId)
                     }
@@ -82,9 +77,15 @@ private suspend fun runTask(client: HttpClient, sched: 
TaskSchedule) {
             }
             else -> logger.error("task on resource ${sched.resourceType} not 
supported")
         }
-    } catch (e: Exception) {
-        logger.error("Exception during task $sched", e)
-    } catch (so: StackOverflowError) {
+    }
+    catch (e: Exception) {
+        logger.error("Exception during task $sched: ${e.message})")
+        /**
+         *  Not exiting the process since the error can be temporary:
+         *  name resolution problem, Nexus connectivity problem, ...
+         */
+    }
+    catch (so: StackOverflowError) {
         logger.error(so.stackTraceToString())
         exitProcess(1)
     }
@@ -105,7 +106,7 @@ object NexusCron {
     }
 }
 
-// Fails whenever a unmanaged Throwable reaches the root coroutine.
+// Fails whenever an unmanaged Throwable reaches the root coroutine.
 val fallback = CoroutineExceptionHandler { _, err ->
     logger.error(err.stackTraceToString())
     exitProcess(1)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
index d630b06b..ba37d8be 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
@@ -391,7 +391,7 @@ fun maybeTalerRefunds(bankAccount: NexusBankAccountEntity, 
lastSeenId: Long) {
             NexusAssert(
                 it[NexusBankTransactionsTable.creditDebitIndicator] == "CRDT" 
&&
                         it[NexusBankTransactionsTable.bankAccount] == 
bankAccount.id,
-                "Cannot refund a _outgoing_ payment!"
+                "Cannot refund an _outgoing_ payment!"
             )
             // FIXME #7116
             addPaymentInitiation(
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 145556ed..4312e8fb 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -396,6 +396,11 @@ suspend fun fetchBankAccountTransactions(
         connectionDetails.connectionName,
         accountId
     )
+    /**
+     * Here it MIGHT just return in case of errors, but sometimes the
+     * fetcher asks for multiple results (e.g. C52 and C53), and what
+     * went through SHOULD be ingested.
+     */
 
     /**
      * This block causes new NexusBankAccountTransactions rows to be
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 ce644ddf..0dab6190 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -800,12 +800,13 @@ class EbicsBankConnectionProtocol: BankConnectionProtocol 
{
                             HttpStatusCode.NotFound,
                             "bank connection not found"
                         )
-
+                        // Avoiding to store twice one downloaded bank account.
                         val isDuplicate = OfferedBankAccountsTable.select {
                             OfferedBankAccountsTable.bankConnection eq conn.id 
and (
                                     OfferedBankAccountsTable.offeredAccountId 
eq accountInfo.id)
                         }.firstOrNull()
                         if (isDuplicate != null) return@forEach
+                        // Storing every new bank account.
                         OfferedBankAccountsTable.insert { newRow ->
                             newRow[accountHolder] = accountInfo.accountHolder 
?: "NOT GIVEN"
                             newRow[iban] =
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
index 52627b66..a543d22a 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
@@ -43,7 +43,8 @@ import java.time.ZonedDateTime
 import java.time.format.DateTimeFormatter
 
 enum class CreditDebitIndicator {
-    DBIT, CRDT
+    DBIT,
+    CRDT
 }
 
 enum class CashManagementResponseType(@get:JsonValue val jsonName: String) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/Helpers.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/Helpers.kt
index 8c01705a..08eb2b1d 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/Helpers.kt
@@ -1,11 +1,20 @@
 package tech.libeufin.nexus.server
 
+import io.ktor.http.*
 import org.jetbrains.exposed.sql.transactions.transaction
 import tech.libeufin.nexus.NexusBankConnectionEntity
 import tech.libeufin.nexus.NexusBankConnectionsTable
+import tech.libeufin.nexus.NexusError
 import tech.libeufin.util.internalServerError
 import tech.libeufin.util.notFound
 
+fun unknownBankAccount(bankAccountLabel: String): NexusError {
+    return NexusError(
+        HttpStatusCode.NotFound,
+        "Bank account $bankAccountLabel was not found"
+    )
+}
+
 /**
  * FIXME:
  * enum type names were introduced after 0.9.2 and need to
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
index fb864d3b..03f12cf6 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -456,7 +456,7 @@ val nexusApp: Application.() -> Unit = {
             resp.set<JsonNode>("schedule", ops)
             transaction {
                 NexusBankAccountEntity.findByName(accountId)
-                    ?: throw NexusError(HttpStatusCode.NotFound, "unknown bank 
account")
+                    ?: throw unknownBankAccount(accountId)
                 NexusScheduledTaskEntity.find {
                     (NexusScheduledTasksTable.resourceType eq "bank-account") 
and
                             (NexusScheduledTasksTable.resourceId eq accountId)
@@ -479,7 +479,7 @@ val nexusApp: Application.() -> Unit = {
             val accountId = ensureNonNull(call.parameters["accountId"])
             transaction {
                 NexusBankAccountEntity.findByName(accountId)
-                    ?: throw NexusError(HttpStatusCode.NotFound, "unknown bank 
account")
+                    ?: throw unknownBankAccount(accountId)
                 try {
                     NexusCron.parser.parse(schedSpec.cronspec)
                 } catch (e: IllegalArgumentException) {
@@ -550,7 +550,7 @@ val nexusApp: Application.() -> Unit = {
             transaction {
                 val bankAccount = NexusBankAccountEntity.findByName(accountId)
                 if (bankAccount == null) {
-                    throw NexusError(HttpStatusCode.NotFound, "unknown bank 
account")
+                    throw unknownBankAccount(accountId)
                 }
                 val oldSchedTask = NexusScheduledTaskEntity.find {
                     (NexusScheduledTasksTable.taskName eq taskId) and
@@ -571,7 +571,7 @@ val nexusApp: Application.() -> Unit = {
             val res = transaction {
                 val bankAccount = NexusBankAccountEntity.findByName(accountId)
                 if (bankAccount == null) {
-                    throw NexusError(HttpStatusCode.NotFound, "unknown bank 
account")
+                    throw unknownBankAccount(accountId)
                 }
                 val holderEnc = URLEncoder.encode(bankAccount.accountHolder, 
Charsets.UTF_8)
                 val lastSeenBalance = NexusBankBalanceEntity.find {
@@ -693,7 +693,7 @@ val nexusApp: Application.() -> Unit = {
             val res = transaction {
                 val bankAccount = NexusBankAccountEntity.findByName(accountId)
                 if (bankAccount == null) {
-                    throw NexusError(HttpStatusCode.NotFound, "unknown bank 
account ($accountId)")
+                    throw unknownBankAccount(accountId)
                 }
                 val amount = parseAmount(body.amount)
                 val paymentEntity = addPaymentInitiation(
@@ -767,7 +767,7 @@ val nexusApp: Application.() -> Unit = {
             transaction {
                 val bankAccount = 
NexusBankAccountEntity.findByName(bankAccountId)
                 if (bankAccount == null) {
-                    throw NexusError(HttpStatusCode.NotFound, "unknown bank 
account")
+                    throw unknownBankAccount(bankAccountId)
                 }
                 NexusBankTransactionEntity.find { 
NexusBankTransactionsTable.bankAccount eq bankAccount.id }.map {
                     val tx = jacksonObjectMapper().readValue(
diff --git 
a/nexus/src/main/kotlin/tech/libeufin/nexus/xlibeufinbank/XLibeufinBankNexus.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/xlibeufinbank/XLibeufinBankNexus.kt
index 9c2596cf..6cec7e41 100644
--- 
a/nexus/src/main/kotlin/tech/libeufin/nexus/xlibeufinbank/XLibeufinBankNexus.kt
+++ 
b/nexus/src/main/kotlin/tech/libeufin/nexus/xlibeufinbank/XLibeufinBankNexus.kt
@@ -10,6 +10,7 @@ import io.ktor.client.statement.*
 import io.ktor.http.*
 import io.ktor.server.util.*
 import io.ktor.util.*
+import io.ktor.util.date.*
 import org.jetbrains.exposed.sql.statements.api.ExposedBlob
 import org.jetbrains.exposed.sql.transactions.transaction
 import tech.libeufin.nexus.*
@@ -39,25 +40,67 @@ fun getXLibeufinBankCredentials(conn: 
NexusBankConnectionEntity): XLibeufinBankT
 fun getXLibeufinBankCredentials(connId: String): XLibeufinBankTransport {
     val conn = getBankConnection(connId)
     return getXLibeufinBankCredentials(conn)
-
 }
 
 class XlibeufinBankConnectionProtocol : BankConnectionProtocol {
+    /**
+     * Together with checking the credentials, this method downloads
+     * additional details from the bank, and stores them in the table
+     * that holds offered bank accounts.  That saves one call to the
+     * "import" method by recycling the information obtained here.
+     */
     override suspend fun connect(client: HttpClient, connId: String) {
-        // Only checking that the credentials + bank URL are correct.
         val conn = getBankConnection(connId)
-        val credentials = getXLibeufinBankCredentials(conn)
+        val connDetails = getXLibeufinBankCredentials(conn)
         // Defining the URL to request the bank account balance.
-        val url = credentials.baseUrl + "/accounts/${credentials.username}"
+        val url = connDetails.baseUrl + "/accounts/${connDetails.username}"
         // Error handling expected by the caller.
-        client.get(url) {
+        val details = client.get(url) {
             expectSuccess = true
-            basicAuth(credentials.username, credentials.password)
+            basicAuth(connDetails.username, connDetails.password)
+        }
+        val txtDetails = details.bodyAsText()
+        val jDetails = jacksonObjectMapper().readTree(txtDetails)
+        val paytoUri: String = try { jDetails.get("paytoUri").asText() }
+        catch (e: Exception) {
+            logger.error("Did not find 'paytoUri' along the connection" +
+                    " operation from x-libeufin-bank connection $connId." +
+                    "  Bank says: $txtDetails"
+            )
+            throw badGateway("Bank missed basic account information 
('paytoUri' field)")
+        }
+        val paytoObj = parsePayto(payto = paytoUri)
+        val maybeOfferedAccount = transaction {
+            OfferedBankAccountEntity.find {
+                // Sandbox reliably names the bank account with the owner's 
username
+                OfferedBankAccountsTable.offeredAccountId eq 
connDetails.username
+            }.firstOrNull()
+        }
+        // Bank account already imported.
+        if (maybeOfferedAccount != null)
+            return
+        // Import it.
+        transaction {
+            OfferedBankAccountEntity.new {
+                offeredAccountId = connDetails.username
+                bankConnection = conn
+                accountHolder = paytoObj.receiverName ?: "Not given by the 
bank"
+                bankCode = paytoObj.bic ?: "SANDBOXX"
+                iban = paytoObj.iban
+            }
         }
     }
 
+    /**
+     * This operation is carried along connect(), because as a side
+     * effect of checking the credentials it ALSO gets all the offered
+     * bank account information that this function WOULD have obtained.
+     *
+     * Therefore, this method throws error when called, in order to raise
+     * the clients' awareness not to rely on it.
+     */
     override suspend fun fetchAccounts(client: HttpClient, connId: String) {
-        throw NotImplementedError("x-libeufin-bank does not need to fetch 
accounts")
+        throw NotImplementedError("Please skip this method when using 
x-libeufin-bank.")
     }
 
     override fun createConnectionFromBackup(
@@ -72,7 +115,8 @@ class XlibeufinBankConnectionProtocol : 
BankConnectionProtocol {
     override fun createConnection(
         connId: String,
         user: NexusUserEntity,
-        data: JsonNode) {
+        data: JsonNode
+    ) {
         val bankConn = transaction {
             NexusBankConnectionEntity.new {
                 this.connectionId = connId
@@ -211,6 +255,7 @@ class XlibeufinBankConnectionProtocol : 
BankConnectionProtocol {
         val baseUrl = URL(credentials.baseUrl)
         val fetchUrl = url {
             protocol = URLProtocol(name = baseUrl.protocol, defaultPort = -1)
+            port = baseUrl.port
             appendPathSegments(
                 baseUrl.path.dropLastWhile { it == '/' },
                 "accounts/${credentials.username}/transactions")
@@ -223,10 +268,10 @@ class XlibeufinBankConnectionProtocol : 
BankConnectionProtocol {
                  * timestamp that was seen in this connection */
                 is FetchSpecSinceLastJson -> {
                     val localBankAccount = getBankAccount(accountId)
-                    val lastMessagesTimes = 
getLastMessagesTimes(localBankAccount)
-                    // Sandbox doesn't have report vs. statement, defaulting 
to report time
+                    // Sandbox doesn't have report vs. statement, defaulting 
to statement time
                     // and so does the ingestion routine when storing the last 
message time.
-                    this.parameters["from_ms"] = 
"${lastMessagesTimes.lastStatement ?: 0}"
+                    // The sought time must be incremented by one because the 
filter is _inclusive_.
+                    this.parameters["from_ms"] = 
"${localBankAccount.lastStatementCreationTimestamp?.plus(1) ?: 0}"
                 }
                 // This wants ALL the transactions, hence it sets the from_ms 
to zero.
                 is FetchSpecAllJson -> {
@@ -331,7 +376,7 @@ fun processXLibeufinBankMessage(
                 this.accountTransactionId = it.uid
                 this.transactionJson = jacksonObjectMapper(
                 ).writeValueAsString(it.exportAsCamtModel())
-                this.creditDebitIndicator = direction.direction
+                this.creditDebitIndicator = direction.exportAsCamtDirection()
                 newTxs++
                 logger.debug("x-libeufin-bank transaction with subject 
'${it.subject}' ingested.")
             }
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
index 3fb622c3..f76ad942 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
@@ -54,7 +54,7 @@ class XMLEbicsConverter : ContentConverter {
             XMLUtil.convertJaxbToString(value)
         } catch (e: Exception) {
             /**
-             * Not always a error: the content negotiation might have
+             * Not always an error: the content negotiation might have
              * only checked if this handler could convert the response.
              */
             return null
diff --git a/util/src/main/kotlin/HTTP.kt b/util/src/main/kotlin/HTTP.kt
index 374bc857..d9ff4491 100644
--- a/util/src/main/kotlin/HTTP.kt
+++ b/util/src/main/kotlin/HTTP.kt
@@ -26,6 +26,14 @@ fun notFound(msg: String): UtilError {
     )
 }
 
+fun badGateway(msg: String): UtilError {
+    return UtilError(
+        HttpStatusCode.BadGateway,
+        msg,
+        LibeufinErrorCode.LIBEUFIN_EC_NONE
+    )
+}
+
 /**
  * Returns the token (including the 'secret-token:' prefix)
  * from a Authorization header.  Throws exception on malformations
diff --git a/util/src/main/kotlin/JSON.kt b/util/src/main/kotlin/JSON.kt
index 71274ccd..b2ad4a05 100644
--- a/util/src/main/kotlin/JSON.kt
+++ b/util/src/main/kotlin/JSON.kt
@@ -51,6 +51,11 @@ enum class XLibeufinBankDirection(val direction: String) {
             }
         }
     }
+    fun exportAsCamtDirection(): String =
+        when(this) {
+            CREDIT -> "CRDT"
+            DEBIT -> "DBIT"
+        }
 }
 
 data class XLibeufinBankPaytoReq(
diff --git a/util/src/main/kotlin/Payto.kt b/util/src/main/kotlin/Payto.kt
index 9d1f401d..3b54060c 100644
--- a/util/src/main/kotlin/Payto.kt
+++ b/util/src/main/kotlin/Payto.kt
@@ -84,7 +84,7 @@ fun buildIbanPaytoUri(
     val nameUrlEnc = URLEncoder.encode(receiverName, "utf-8")
     val ret = "payto://iban/$bic/$iban?receiver-name=$nameUrlEnc"
     if (message != null) {
-        val messageUrlEnc = URLEncoder.encode(receiverName, "utf-8")
+        val messageUrlEnc = URLEncoder.encode(message, "utf-8")
         return "$ret&message=$messageUrlEnc"
     }
     return ret

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