gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] 02/02: nexus


From: gnunet
Subject: [libeufin] 02/02: nexus
Date: Sun, 19 Nov 2023 19:38:02 +0100

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

ms pushed a commit to branch master
in repository libeufin.

commit 01461521ac32e94db19a4b5dd7ca7aee0a13e1dd
Author: MS <ms@taler.net>
AuthorDate: Sun Nov 19 19:36:59 2023 +0100

    nexus
    
    - moving ISO20022 logic to own file
    - making some functions private
---
 .../main/kotlin/tech/libeufin/nexus/EbicsFetch.kt  | 165 +-------------------
 .../main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt |   2 +-
 .../main/kotlin/tech/libeufin/nexus/Iso20022.kt    | 171 ++++++++++++++++++++-
 3 files changed, 171 insertions(+), 167 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
index e3c8d37b..5112075d 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -172,7 +172,7 @@ fun maybeLogFile(
  * @param bankFrac fractional value
  * @return the Taler fractional value with at most 8 digits.
  */
-fun makeTalerFrac(bankFrac: String): Int {
+private fun makeTalerFrac(bankFrac: String): Int {
     if (bankFrac.length > 2) throw Exception("Fractional value has more than 2 
digits")
     var buf = bankFrac.toIntOrNull() ?: throw Exception("Fractional value not 
an Int: $bankFrac")
     repeat(8 - bankFrac.length) {
@@ -209,165 +209,6 @@ fun getTalerAmount(
     )
 }
 
-class WrongPaymentDirection(val msg: String) : Exception(msg)
-
-/**
- * Parses a camt.054 document looking for outgoing payments.
- *
- * @param notifXml input document.
- * @param acceptedCurrency currency accepted by Nexus
- * @return the list of outgoing payments.
- */
-private fun parseOutgoingTxNotif(
-    notifXml: String,
-    acceptedCurrency: String,
-): List<OutgoingPayment> {
-    val ret = mutableListOf<OutgoingPayment>()
-    notificationForEachTx(notifXml) { bookDate ->
-        requireUniqueChildNamed("CdtDbtInd") {
-            if (focusElement.textContent != "DBIT")
-                throw WrongPaymentDirection("The payment is not outgoing, 
won't parse it")
-        }
-        // Obtaining the amount.
-        val amount: TalerAmount = requireUniqueChildNamed("Amt") {
-            val currency = focusElement.getAttribute("Ccy")
-            if (currency != acceptedCurrency) throw Exception("Currency 
$currency not supported")
-            getTalerAmount(focusElement.textContent, currency)
-        }
-
-        /**
-         * The MsgId extracted in the block below matches the one that
-         * was specified as the MsgId element in the pain.001 that originated
-         * this outgoing payment.  MsgId is considered unique because the
-         * bank enforces its uniqueness.  Associating MsgId to this outgoing
-         * payment is also convenient to match its initiated outgoing payment
-         * in the database for reconciliation.
-         */
-        val uidFromBank = StringBuilder()
-        requireUniqueChildNamed("Refs") {
-            requireUniqueChildNamed("MsgId") {
-                uidFromBank.append(focusElement.textContent)
-            }
-        }
-
-        ret.add(OutgoingPayment(
-            amount = amount,
-            bankTransferId = uidFromBank.toString(),
-            executionTime = bookDate
-        ))
-    }
-    return ret
-}
-
-/**
- * Searches incoming payments in a camt.054 (Detailavisierung) document.
- *
- * @param notifXml camt.054 input document
- * @param acceptedCurrency currency accepted by Nexus.
- * @return the list of incoming payments to ingest in the database.
- */
-private fun parseIncomingTxNotif(
-    notifXml: String,
-    acceptedCurrency: String
-): List<IncomingPayment> {
-    val ret = mutableListOf<IncomingPayment>()
-    notificationForEachTx(notifXml) { bookDate ->
-        // Check the direction first.
-        requireUniqueChildNamed("CdtDbtInd") {
-            if (focusElement.textContent != "CRDT")
-                throw WrongPaymentDirection("The payment is not incoming, 
won't parse it")
-        }
-        val amount: TalerAmount = requireUniqueChildNamed("Amt") {
-            val currency = focusElement.getAttribute("Ccy")
-            if (currency != acceptedCurrency) throw Exception("Currency 
$currency not supported")
-            getTalerAmount(focusElement.textContent, currency)
-        }
-        // Obtaining payment UID.
-        val uidFromBank: String = requireUniqueChildNamed("Refs") {
-            requireUniqueChildNamed("AcctSvcrRef") {
-                focusElement.textContent
-            }
-        }
-        // Obtaining payment subject.
-        val subject = StringBuilder()
-        requireUniqueChildNamed("RmtInf") {
-            this.mapEachChildNamed("Ustrd") {
-                val piece = this.focusElement.textContent
-                subject.append(piece)
-            }
-        }
-
-        // Obtaining the payer's details
-        val debtorPayto = StringBuilder("payto://iban/")
-        requireUniqueChildNamed("RltdPties") {
-            requireUniqueChildNamed("DbtrAcct") {
-                requireUniqueChildNamed("Id") {
-                    requireUniqueChildNamed("IBAN") {
-                        debtorPayto.append(focusElement.textContent)
-                    }
-                }
-            }
-            // warn: it might need the postal address too..
-            requireUniqueChildNamed("Dbtr") {
-                requireUniqueChildNamed("Nm") {
-                    val urlEncName = 
URLEncoder.encode(focusElement.textContent, "utf-8")
-                    debtorPayto.append("?receiver-name=$urlEncName")
-                }
-            }
-        }
-        ret.add(
-            IncomingPayment(
-                amount = amount,
-                bankTransferId = uidFromBank,
-                debitPaytoUri = debtorPayto.toString(),
-                executionTime = bookDate,
-                wireTransferSubject = subject.toString()
-            )
-        )
-    }
-    return ret
-}
-
-/**
- * Navigates the camt.054 (Detailavisierung) until its leaves, where
- * then it invokes the related parser, according to the payment direction.
- *
- * @param notifXml the input document.
- * @return any incoming payment as a list of [IncomingPayment]
- */
-fun notificationForEachTx(
-    notifXml: String,
-    directionLambda: XmlElementDestructor.(Instant) -> Unit
-) {
-    val notifDoc = XMLUtil.parseStringIntoDom(notifXml)
-    destructXml(notifDoc) {
-        requireRootElement("Document") {
-            requireUniqueChildNamed("BkToCstmrDbtCdtNtfctn") {
-                mapEachChildNamed("Ntfctn") {
-                    mapEachChildNamed("Ntry") {
-                        requireUniqueChildNamed("Sts") {
-                            if (focusElement.textContent != "BOOK")
-                                throw Exception("Found non booked transaction, 
" +
-                                        "stop parsing.  Status was: 
${focusElement.textContent}"
-                                )
-                        }
-                        val bookDate: Instant = 
requireUniqueChildNamed("BookgDt") {
-                            requireUniqueChildNamed("Dt") {
-                                parseBookDate(focusElement.textContent)
-                            }
-                        }
-                        mapEachChildNamed("NtryDtls") {
-                            mapEachChildNamed("TxDtls") {
-                                 directionLambda(this, bookDate)
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
 /**
  * Converts valid reserve pubs to its binary representation.
  *
@@ -417,7 +258,7 @@ fun removeSubjectNoise(subject: String): String? {
  * @return [ByteArray] as the reserve public key, or null if the
  *         payment cannot lead to a Taler withdrawal.
  */
-suspend fun getTalerReservePub(
+private suspend fun getTalerReservePub(
     db: Database,
     payment: IncomingPayment
 ): ByteArray? {
@@ -511,7 +352,7 @@ private suspend fun ingestIncomingPayment(
  *         False should fail the process, since it means that
  *         the notification could not be parsed.
  */
-fun ingestNotification(
+private fun ingestNotification(
     db: Database,
     ctx: FetchContext,
     content: ByteArray
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
index e11e39c7..588d2727 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
@@ -104,7 +104,7 @@ class NexusSubmitException(
  *                   the pain.001 MsgId element), will be part of
  *                   the filename.
  */
-fun maybeLog(
+private fun maybeLog(
     maybeLogDir: String?,
     xml: String,
     requestUid: String
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
index 6a6d850d..ec0381b7 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
@@ -1,7 +1,7 @@
 package tech.libeufin.nexus
 
-import tech.libeufin.util.IbanPayto
-import tech.libeufin.util.constructXml
+import tech.libeufin.util.*
+import java.net.URLEncoder
 import java.time.Instant
 import java.time.ZoneId
 import java.time.ZonedDateTime
@@ -37,8 +37,6 @@ fun getAmountNoCurrency(amount: TalerAmount): String {
     }
 }
 
-
-
 /**
  * Create a pain.001 document.  It requires the debtor BIC.
  *
@@ -155,4 +153,169 @@ fun createPain001(
             }
         }
     }
+}
+
+/**
+ * Thrown if the parser expects DBIT but the transaction
+ * is CRDT, and vice-versa.
+ */
+class WrongPaymentDirection(val msg: String) : Exception(msg)
+
+/**
+ * Parses a camt.054 document looking for outgoing payments.
+ *
+ * @param notifXml input document.
+ * @param acceptedCurrency currency accepted by Nexus
+ * @return the list of outgoing payments.
+ */
+fun parseOutgoingTxNotif(
+    notifXml: String,
+    acceptedCurrency: String,
+): List<OutgoingPayment> {
+    val ret = mutableListOf<OutgoingPayment>()
+    notificationForEachTx(notifXml) { bookDate ->
+        requireUniqueChildNamed("CdtDbtInd") {
+            if (focusElement.textContent != "DBIT")
+                throw WrongPaymentDirection("The payment is not outgoing, 
won't parse it")
+        }
+        // Obtaining the amount.
+        val amount: TalerAmount = requireUniqueChildNamed("Amt") {
+            val currency = focusElement.getAttribute("Ccy")
+            if (currency != acceptedCurrency) throw Exception("Currency 
$currency not supported")
+            getTalerAmount(focusElement.textContent, currency)
+        }
+
+        /**
+         * The MsgId extracted in the block below matches the one that
+         * was specified as the MsgId element in the pain.001 that originated
+         * this outgoing payment.  MsgId is considered unique because the
+         * bank enforces its uniqueness.  Associating MsgId to this outgoing
+         * payment is also convenient to match its initiated outgoing payment
+         * in the database for reconciliation.
+         */
+        val uidFromBank = StringBuilder()
+        requireUniqueChildNamed("Refs") {
+            requireUniqueChildNamed("MsgId") {
+                uidFromBank.append(focusElement.textContent)
+            }
+        }
+
+        ret.add(
+            OutgoingPayment(
+            amount = amount,
+            bankTransferId = uidFromBank.toString(),
+            executionTime = bookDate
+        )
+        )
+    }
+    return ret
+}
+
+/**
+ * Searches incoming payments in a camt.054 (Detailavisierung) document.
+ *
+ * @param notifXml camt.054 input document
+ * @param acceptedCurrency currency accepted by Nexus.
+ * @return the list of incoming payments to ingest in the database.
+ */
+fun parseIncomingTxNotif(
+    notifXml: String,
+    acceptedCurrency: String
+): List<IncomingPayment> {
+    val ret = mutableListOf<IncomingPayment>()
+    notificationForEachTx(notifXml) { bookDate ->
+        // Check the direction first.
+        requireUniqueChildNamed("CdtDbtInd") {
+            if (focusElement.textContent != "CRDT")
+                throw WrongPaymentDirection("The payment is not incoming, 
won't parse it")
+        }
+        val amount: TalerAmount = requireUniqueChildNamed("Amt") {
+            val currency = focusElement.getAttribute("Ccy")
+            if (currency != acceptedCurrency) throw Exception("Currency 
$currency not supported")
+            getTalerAmount(focusElement.textContent, currency)
+        }
+        // Obtaining payment UID.
+        val uidFromBank: String = requireUniqueChildNamed("Refs") {
+            requireUniqueChildNamed("AcctSvcrRef") {
+                focusElement.textContent
+            }
+        }
+        // Obtaining payment subject.
+        val subject = StringBuilder()
+        requireUniqueChildNamed("RmtInf") {
+            this.mapEachChildNamed("Ustrd") {
+                val piece = this.focusElement.textContent
+                subject.append(piece)
+            }
+        }
+
+        // Obtaining the payer's details
+        val debtorPayto = StringBuilder("payto://iban/")
+        requireUniqueChildNamed("RltdPties") {
+            requireUniqueChildNamed("DbtrAcct") {
+                requireUniqueChildNamed("Id") {
+                    requireUniqueChildNamed("IBAN") {
+                        debtorPayto.append(focusElement.textContent)
+                    }
+                }
+            }
+            // warn: it might need the postal address too..
+            requireUniqueChildNamed("Dbtr") {
+                requireUniqueChildNamed("Nm") {
+                    val urlEncName = 
URLEncoder.encode(focusElement.textContent, "utf-8")
+                    debtorPayto.append("?receiver-name=$urlEncName")
+                }
+            }
+        }
+        ret.add(
+            IncomingPayment(
+                amount = amount,
+                bankTransferId = uidFromBank,
+                debitPaytoUri = debtorPayto.toString(),
+                executionTime = bookDate,
+                wireTransferSubject = subject.toString()
+            )
+        )
+    }
+    return ret
+}
+
+/**
+ * Navigates the camt.054 (Detailavisierung) until its leaves, where
+ * then it invokes the related parser, according to the payment direction.
+ *
+ * @param notifXml the input document.
+ * @return any incoming payment as a list of [IncomingPayment]
+ */
+private fun notificationForEachTx(
+    notifXml: String,
+    directionLambda: XmlElementDestructor.(Instant) -> Unit
+) {
+    val notifDoc = XMLUtil.parseStringIntoDom(notifXml)
+    destructXml(notifDoc) {
+        requireRootElement("Document") {
+            requireUniqueChildNamed("BkToCstmrDbtCdtNtfctn") {
+                mapEachChildNamed("Ntfctn") {
+                    mapEachChildNamed("Ntry") {
+                        requireUniqueChildNamed("Sts") {
+                            if (focusElement.textContent != "BOOK")
+                                throw Exception("Found non booked transaction, 
" +
+                                        "stop parsing.  Status was: 
${focusElement.textContent}"
+                                )
+                        }
+                        val bookDate: Instant = 
requireUniqueChildNamed("BookgDt") {
+                            requireUniqueChildNamed("Dt") {
+                                parseBookDate(focusElement.textContent)
+                            }
+                        }
+                        mapEachChildNamed("NtryDtls") {
+                            mapEachChildNamed("TxDtls") {
+                                directionLambda(this, bookDate)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
\ No newline at end of file

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