[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.
- [libeufin] branch master updated (aa9d92d3 -> fbcd7e2e),
gnunet <=
- [libeufin] 05/06: nexus fetch: crafting notification (camt.054) requests, gnunet, 2023/11/09
- [libeufin] 02/06: nexus fetch: indexing the execution_time column, gnunet, 2023/11/09
- [libeufin] 04/06: util: new EBICS EC, gnunet, 2023/11/09
- [libeufin] 01/06: storing pain.001 as log file, gnunet, 2023/11/09
- [libeufin] 06/06: tests, gnunet, 2023/11/09
- [libeufin] 03/06: nexus fetch: not logging pain.001 to console, gnunet, 2023/11/09