gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated (aa9d92d3 -> fbcd7e2e)


From: gnunet
Subject: [libeufin] branch master updated (aa9d92d3 -> fbcd7e2e)
Date: Thu, 09 Nov 2023 11:55:58 +0100

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

ms pushed a change to branch master
in repository libeufin.

    from aa9d92d3 Limit the length of the request body and make deflate async
     new 26c23719 storing pain.001 as log file
     new e1815ace nexus fetch: indexing the execution_time column
     new b98b055d nexus fetch: not logging pain.001 to console
     new 97e5f0a4 util: new EBICS EC
     new 792700ae nexus fetch: crafting notification (camt.054) requests
     new fbcd7e2e tests

The 6 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:
 database-versioning/libeufin-nexus-0001.sql        |  5 ++
 .../main/kotlin/tech/libeufin/nexus/EbicsFetch.kt  | 46 +++++++++++++-
 .../main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt | 34 ++++++++++
 .../kotlin/tech/libeufin/nexus/ebics/Ebics3.kt     |  1 -
 nexus/src/test/kotlin/Common.kt                    |  5 +-
 nexus/src/test/kotlin/PostFinance.kt               | 72 +++++++++++++++-------
 util/src/main/kotlin/Ebics.kt                      |  1 +
 7 files changed, 137 insertions(+), 27 deletions(-)

diff --git a/database-versioning/libeufin-nexus-0001.sql 
b/database-versioning/libeufin-nexus-0001.sql
index 4211f467..579c6900 100644
--- a/database-versioning/libeufin-nexus-0001.sql
+++ b/database-versioning/libeufin-nexus-0001.sql
@@ -98,4 +98,9 @@ CREATE TABLE IF NOT EXISTS bounced_transactions
    ,initiated_outgoing_transaction_id INT8 NOT NULL UNIQUE REFERENCES 
initiated_outgoing_transactions(initiated_outgoing_transaction_id) ON DELETE 
CASCADE
   );
 
+-- Helps to detect the last known incoming transaction.
+-- According to this value, camt.05x date ranges should be adjusted.
+CREATE INDEX IF NOT EXISTS incoming_transaction_timestamp
+  ON incoming_transactions (execution_time); 
+
 COMMIT;
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
index ac1d522d..5442ec26 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -50,6 +50,50 @@ fun getEbics3DateRange(
     }
 }
 
+/**
+ * Prepares the request for a camt.054 notification from the bank.
+ * Notifications inform the subscriber that some new events occurred
+ * on their account.  One main difference with reports/statements is
+ * that notifications - according to the ISO20022 documentation - do
+ * NOT contain any balance.
+ *
+ * @param startDate inclusive starting date for the returned notification(s).
+ * @param endDate inclusive ending date for the returned notification(s).  
NOTE:
+ *        if startDate is NOT null and endDate IS null, endDate gets defaulted
+ *        to the current UTC time.
+ * @param isAppendix if true, the responded camt.054 will be an appendix of
+ *        another camt.053 document, not therefore strictly acting as a 
notification.
+ *        For example, camt.053 may omit wire transfer subjects and its related
+ *        camt.054 appendix would instead contain those.
+ *
+ * @return [Ebics3Request.OrderDetails.BTOrderParams]
+ */
+fun prepNotificationRequest(
+    startDate: Instant? = null,
+    endDate: Instant? = null,
+    isAppendix: Boolean
+): Ebics3Request.OrderDetails.BTOrderParams {
+    val service = Ebics3Request.OrderDetails.Service().apply {
+        serviceName = "REP"
+        scope = "CH"
+        container = Ebics3Request.OrderDetails.Service.Container().apply {
+            containerType = "ZIP"
+        }
+        messageName = Ebics3Request.OrderDetails.Service.MessageName().apply {
+            value = "camt.054"
+            version = "08"
+        }
+        if (!isAppendix)
+            serviceOption = "XDCI"
+    }
+    return Ebics3Request.OrderDetails.BTOrderParams().apply {
+        this.service = service
+        this.dateRange = if (startDate != null)
+            getEbics3DateRange(startDate, endDate ?: Instant.now())
+        else null
+    }
+}
+
 /**
  * Prepares the request for a pain.002 acknowledgement from the bank.
  *
@@ -72,7 +116,7 @@ fun prepAckRequest(
         }
         messageName = Ebics3Request.OrderDetails.Service.MessageName().apply {
             value = "pain.002"
-            version = "03"
+            version = "10"
         }
     }
     return Ebics3Request.OrderDetails.BTOrderParams().apply {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
index 554de068..ba713ae2 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
@@ -29,10 +29,19 @@ import tech.libeufin.nexus.ebics.EbicsEarlyException
 import tech.libeufin.nexus.ebics.EbicsUploadException
 import tech.libeufin.nexus.ebics.submitPain001
 import tech.libeufin.util.parsePayto
+import tech.libeufin.util.toDbMicros
+import java.io.File
+import java.nio.file.Path
+import java.text.DateFormat
 import java.time.Instant
+import java.time.LocalDate
+import java.time.ZoneId
 import java.util.*
 import javax.xml.crypto.Data
 import kotlin.concurrent.fixedRateTimer
+import kotlin.io.path.createDirectories
+import kotlin.io.path.createParentDirectories
+import kotlin.math.log
 import kotlin.system.exitProcess
 
 /**
@@ -127,6 +136,31 @@ private suspend fun submitInitiatedPayment(
             cause = permanent
         )
     }
+    // Submission succeeded, storing the pain.001 to file.
+    val logDir: String? = cfg.config.lookupString(
+        "[neuxs-submit]",
+        "SUBMISSIONS_LOG_DIRECTORY"
+    )
+    if (logDir != null) {
+        try { Path.of(logDir).createDirectories() }
+        catch (e: Exception) {
+            logger.error("Could not create log directory of path: $logDir")
+            exitProcess(1)
+        }
+        val now = Instant.now()
+        val asUtcDate = LocalDate.ofInstant(now, ZoneId.of("UTC"))
+        val f = Path.of(
+            
"${asUtcDate.year}-${asUtcDate.monthValue}-${asUtcDate.dayOfMonth}",
+            
"${now.toDbMicros()}_requestUid_${initiatedPayment.requestUid}_pain.001.xml"
+        ).toFile()
+        val completePath = Path.of(logDir, f.path)
+        // Very rare: same pain.001 should not be submitted twice in the same 
microsecond.
+        if (f.exists()) {
+            logger.error("pain.001 log file exists already at: $completePath")
+            exitProcess(1)
+        }
+        completePath.toFile().writeText(xml)
+    }
 }
 
 /**
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
index 04cdbf4d..a0c75aa0 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
@@ -212,7 +212,6 @@ suspend fun submitPain001(
     bankkeys: BankPublicKeysFile,
     httpClient: HttpClient
 ) {
-    logger.debug("Submitting pain.001: $pain001xml")
     val orderService: Ebics3Request.OrderDetails.Service = 
Ebics3Request.OrderDetails.Service().apply {
         serviceName = "MCT"
         scope = "CH"
diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt
index 0ae3847d..9d1778b9 100644
--- a/nexus/src/test/kotlin/Common.kt
+++ b/nexus/src/test/kotlin/Common.kt
@@ -71,9 +71,8 @@ fun getPofiConfig(
     IBAN = CH9789144829733648596
     BIC = POFICHBE
     NAME = LibEuFin
-    BANK_PUBLIC_KEYS_FILE = /tmp/enc-auth-keys.json
-    CLIENT_PRIVATE_KEYS_FILE = /tmp/my-private-keys.json
-    ACCOUNT_META_DATA_FILE = /tmp/ebics-meta.json
+    BANK_PUBLIC_KEYS_FILE = /tmp/pofi-testplatform-bank-keys.json
+    CLIENT_PRIVATE_KEYS_FILE = /tmp/pofi-testplatform-subscriber-keys.json
     BANK_DIALECT = postfinance
 """.trimIndent()
 
diff --git a/nexus/src/test/kotlin/PostFinance.kt 
b/nexus/src/test/kotlin/PostFinance.kt
index f5d95533..aa79d111 100644
--- a/nexus/src/test/kotlin/PostFinance.kt
+++ b/nexus/src/test/kotlin/PostFinance.kt
@@ -1,6 +1,5 @@
 import io.ktor.client.*
 import kotlinx.coroutines.runBlocking
-import org.junit.Ignore
 import org.junit.Test
 import tech.libeufin.nexus.*
 import tech.libeufin.nexus.ebics.*
@@ -8,6 +7,7 @@ import tech.libeufin.util.ebics_h005.Ebics3Request
 import tech.libeufin.util.parsePayto
 import java.io.File
 import java.time.Instant
+import java.time.temporal.ChronoUnit
 import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
 
@@ -22,7 +22,55 @@ private fun prep(): EbicsSetupConfig {
 }
 
 class Iso20022 {
-    // Asks a camt.052 report to the test platform.
+
+    private val yesterday: Instant = Instant.now().minus(1, ChronoUnit.DAYS)
+
+    @Test // asks a pain.002, links with pain.001's MsgId
+    fun getAck() {
+        download(prepAckRequest(startDate = yesterday)
+        )?.unzipForEach { name, content ->
+            println(name)
+            println(content)
+        }
+    }
+
+    /**
+     * With the "mit Detailavisierung" option, each entry has an
+     * AcctSvcrRef & wire transfer subject.
+     */
+    @Test
+    fun getStatement() {
+        val inflatedBytes = download(prepStatementRequest(yesterday))
+        inflatedBytes?.unzipForEach { name, content ->
+            println(name)
+            println(content)
+        }
+    }
+
+    @Test
+    fun getNotification() {
+        val inflatedBytes = download(
+            prepNotificationRequest(
+                // startDate = yesterday,
+                isAppendix = true
+            )
+        )
+        inflatedBytes?.unzipForEach { name, content ->
+            println(name)
+            println(content)
+        }
+    }
+
+    /**
+     * Never shows the subject.
+     */
+    @Test
+    fun getReport() {
+        download(prepReportRequest(yesterday))?.unzipForEach { name, content ->
+            println(name)
+            println(content)
+        }
+    }
 
     @Test
     fun simulateIncoming() {
@@ -58,26 +106,6 @@ class Iso20022 {
         }
     }
 
-    @Test // asks a pain.002
-    fun getAck() {
-        val pain002 = download(prepAckRequest())
-        println(pain002)
-    }
-
-    @Test
-    fun getStatement() {
-        val inflatedBytes = download(prepStatementRequest())
-        inflatedBytes?.unzipForEach { name, content ->
-            println(name)
-            println(content)
-        }
-    }
-
-    @Test
-    fun getReport() {
-        println(download(prepReportRequest()))
-    }
-
     fun download(req: Ebics3Request.OrderDetails.BTOrderParams): ByteArray? {
         val cfg = prep()
         val bankKeys = loadBankKeys(cfg.bankPublicKeysFilename)!!
diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt
index 49898660..f94a6a10 100644
--- a/util/src/main/kotlin/Ebics.kt
+++ b/util/src/main/kotlin/Ebics.kt
@@ -466,6 +466,7 @@ enum class EbicsReturnCode(val errorCode: String) {
     EBICS_NO_DOWNLOAD_DATA_AVAILABLE("090005"),
     EBICS_INVALID_USER_OR_USER_STATE("091002"),
     EBICS_EBICS_INVALID_USER_STATE("091004"),
+    EBICS_INVALID_ORDER_IDENTIFIER("091005"),
     EBICS_INVALID_XML("091010"),
     EBICS_TX_MESSAGE_REPLAY("091103"),
     EBICS_PROCESSING_ERROR("091116"),

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