summaryrefslogtreecommitdiff
path: root/nexus/src/main/kotlin/tech/libeufin/nexus
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-06-18 12:43:10 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-06-18 14:15:38 +0530
commit0cd1658bc6178a7154937268a66a34a58028492b (patch)
treea8d603a071b1f5d1daf7b2f50e4dd48a662b7d60 /nexus/src/main/kotlin/tech/libeufin/nexus
parent12c1a45ce0bb96b874d27629a7ac0ead227ac773 (diff)
downloadlibeufin-0cd1658bc6178a7154937268a66a34a58028492b.tar.gz
libeufin-0cd1658bc6178a7154937268a66a34a58028492b.tar.bz2
libeufin-0cd1658bc6178a7154937268a66a34a58028492b.zip
cleanup
Diffstat (limited to 'nexus/src/main/kotlin/tech/libeufin/nexus')
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt17
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt50
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt146
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt4
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt76
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt81
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt59
7 files changed, 305 insertions, 128 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index 81cea39f..f6315a94 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -168,12 +168,16 @@ class RawBankTransactionEntity(id: EntityID<Long>) : LongEntity(id) {
* Represents a prepared payment.
*/
object InitiatedPaymentsTable : LongIdTable() {
+ /**
+ * Bank account that wants to initiate the payment.
+ */
+ val bankAccount = reference("bankAccount", NexusBankAccountsTable)
val preparationDate = long("preparationDate")
val submissionDate = long("submissionDate").nullable()
val sum = amount("sum")
val currency = varchar("currency", length = 3).default("EUR")
val endToEndId = long("EndToEndId")
- val subject = text("subject")
+ val subject = text("subject")
val creditorIban = text("creditorIban")
val creditorBic = text("creditorBic")
val creditorName = text("creditorName")
@@ -181,13 +185,18 @@ object InitiatedPaymentsTable : LongIdTable() {
val debitorBic = text("debitorBic")
val debitorName = text("debitorName").nullable()
val submitted = bool("submitted").default(false)
- // points at the raw transaction witnessing that this
- // initiated payment was successfully performed.
+
+ /**
+ * Points at the raw transaction witnessing that this
+ * initiated payment was successfully performed.
+ */
val rawConfirmation = reference("rawConfirmation", RawBankTransactionsTable).nullable()
}
class InitiatedPaymentEntity(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<InitiatedPaymentEntity>(InitiatedPaymentsTable)
+
+ var bankAccount by NexusBankAccountEntity referencedOn InitiatedPaymentsTable.bankAccount
var preparationDate by InitiatedPaymentsTable.preparationDate
var submissionDate by InitiatedPaymentsTable.submissionDate
var sum by InitiatedPaymentsTable.sum
@@ -201,7 +210,7 @@ class InitiatedPaymentEntity(id: EntityID<Long>) : LongEntity(id) {
var creditorBic by InitiatedPaymentsTable.creditorBic
var creditorName by InitiatedPaymentsTable.creditorName
var submitted by InitiatedPaymentsTable.submitted
- var rawConfirmation by RawBankTransactionEntity optionalReferencedOn InitiatedPaymentsTable.rawConfirmation
+ var rawConfirmation by RawBankTransactionEntity optionalReferencedOn InitiatedPaymentsTable.rawConfirmation
}
/**
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index b9851bb4..177369bc 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -26,60 +26,11 @@ import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
import org.w3c.dom.Document
import tech.libeufin.util.*
-import tech.libeufin.util.ebics_h004.EbicsTypes
-import java.security.interfaces.RSAPublicKey
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
-import java.util.*
-/**
- * Skip national only-numeric bank account ids, and return the first IBAN in list
- */
-fun extractFirstIban(bankAccounts: List<EbicsTypes.AbstractAccountNumber>?): String? {
- if (bankAccounts == null)
- return null
-
- for (item in bankAccounts) {
- if (item is EbicsTypes.GeneralAccountNumber) {
- if (item.international)
- return item.value
- }
- }
- return null
-}
-
-
-fun getEbicsSubscriberDetailsInternal(subscriber: EbicsSubscriberEntity): EbicsClientSubscriberDetails {
- var bankAuthPubValue: RSAPublicKey? = null
- if (subscriber.bankAuthenticationPublicKey != null) {
- bankAuthPubValue = CryptoUtil.loadRsaPublicKey(
- subscriber.bankAuthenticationPublicKey?.bytes!!
- )
- }
- var bankEncPubValue: RSAPublicKey? = null
- if (subscriber.bankEncryptionPublicKey != null) {
- bankEncPubValue = CryptoUtil.loadRsaPublicKey(
- subscriber.bankEncryptionPublicKey?.bytes!!
- )
- }
- return EbicsClientSubscriberDetails(
- bankAuthPub = bankAuthPubValue,
- bankEncPub = bankEncPubValue,
-
- ebicsUrl = subscriber.ebicsURL,
- hostId = subscriber.hostID,
- userId = subscriber.userID,
- partnerId = subscriber.partnerID,
-
- customerSignPriv = CryptoUtil.loadRsaPrivateKey(subscriber.signaturePrivateKey.bytes),
- customerAuthPriv = CryptoUtil.loadRsaPrivateKey(subscriber.authenticationPrivateKey.bytes),
- customerEncPriv = CryptoUtil.loadRsaPrivateKey(subscriber.encryptionPrivateKey.bytes),
- ebicsIniState = subscriber.ebicsIniState,
- ebicsHiaState = subscriber.ebicsHiaState
- )
-}
/**
* Check if the transaction is already found in the database.
@@ -355,6 +306,7 @@ fun getPreparedPayment(uuid: Long): InitiatedPaymentEntity {
fun addPreparedPayment(paymentData: Pain001Data, debitorAccount: NexusBankAccountEntity): InitiatedPaymentEntity {
return transaction {
InitiatedPaymentEntity.new {
+ bankAccount = debitorAccount
subject = paymentData.subject
sum = paymentData.sum
debitorIban = debitorAccount.iban
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
index 300cd34c..b199ddea 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
@@ -26,9 +26,15 @@ package tech.libeufin.nexus
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
+import io.ktor.http.HttpStatusCode
+import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.transactions.transaction
import org.w3c.dom.Document
-import tech.libeufin.util.XmlElementDestructor
-import tech.libeufin.util.destructXml
+import tech.libeufin.util.*
+import java.time.Instant
+import java.time.ZoneId
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
enum class CreditDebitIndicator {
DBIT, CRDT
@@ -211,6 +217,142 @@ data class RelatedParties(
class CamtParsingError(msg: String) : Exception(msg)
+/**
+ * Data that the LibEuFin nexus uses for payment initiation.
+ * Subset of what ISO 20022 allows.
+ */
+data class NexusPaymentInitiationData(
+ val debtorIban: String,
+ val debtorBic: String,
+ val messageId: String,
+ val paymentInformationId: String,
+ val amount: String,
+ val currency: String,
+ val subject: String,
+ val preparationTimestamp: Long,
+ val creditorName: String,
+ val creditorIban: String
+)
+
+/**
+ * Create a PAIN.001 XML document according to the input data.
+ * Needs to be called within a transaction block.
+ */
+fun createPain001document(paymentData: NexusPaymentInitiationData): String {
+ /**
+ * Every PAIN.001 document contains at least three IDs:
+ *
+ * 1) MsgId: a unique id for the message itself
+ * 2) PmtInfId: the unique id for the payment's set of information
+ * 3) EndToEndId: a unique id to be shared between the debtor and
+ * creditor that uniquely identifies the transaction
+ *
+ * For now and for simplicity, since every PAIN entry in the database
+ * has a unique ID, and the three values aren't required to be mutually different,
+ * we'll assign the SAME id (= the row id) to all the three aforementioned
+ * PAIN id types.
+ */
+ val debitorBankAccountLabel = run {
+ val debitorBankAcount = NexusBankAccountEntity.find {
+ NexusBankAccountsTable.iban eq paymentData.debtorIban and
+ (NexusBankAccountsTable.bankCode eq paymentData.debtorBic)
+ }.firstOrNull() ?: throw NexusError(
+ HttpStatusCode.NotFound,
+ "Please download bank accounts details first (HTD)"
+ )
+ debitorBankAcount.id.value
+ }
+
+ val s = constructXml(indent = true) {
+ root("Document") {
+ attribute("xmlns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03")
+ attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
+ attribute("xsi:schemaLocation", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 pain.001.001.03.xsd")
+ element("CstmrCdtTrfInitn") {
+ element("GrpHdr") {
+ element("MsgId") {
+ text(paymentData.messageId)
+ }
+ element("CreDtTm") {
+ val dateMillis = paymentData.preparationTimestamp
+ val dateFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME
+ val instant = Instant.ofEpochSecond(dateMillis / 1000)
+ val zoned = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
+ text(dateFormatter.format(zoned))
+ }
+ element("NbOfTxs") {
+ text("1")
+ }
+ element("CtrlSum") {
+ text(paymentData.amount)
+ }
+ element("InitgPty/Nm") {
+ text(debitorBankAccountLabel)
+ }
+ }
+ element("PmtInf") {
+ element("PmtInfId") {
+ text(paymentData.paymentInformationId)
+ }
+ element("PmtMtd") {
+ text("TRF")
+ }
+ element("BtchBookg") {
+ text("true")
+ }
+ element("NbOfTxs") {
+ text("1")
+ }
+ element("CtrlSum") {
+ text(paymentData.amount)
+ }
+ element("PmtTpInf/SvcLvl/Cd") {
+ text("SEPA")
+ }
+ element("ReqdExctnDt") {
+ val dateMillis = paymentData.preparationTimestamp
+ text(importDateFromMillis(dateMillis).toDashedDate())
+ }
+ element("Dbtr/Nm") {
+ text(debitorBankAccountLabel)
+ }
+ element("DbtrAcct/Id/IBAN") {
+ text(paymentData.debtorIban)
+ }
+ element("DbtrAgt/FinInstnId/BIC") {
+ text(paymentData.debtorBic)
+ }
+ element("ChrgBr") {
+ text("SLEV")
+ }
+ element("CdtTrfTxInf") {
+ element("PmtId") {
+ element("EndToEndId") {
+ // text(pain001Entity.id.value.toString())
+ text("NOTPROVIDED")
+ }
+ }
+ element("Amt/InstdAmt") {
+ attribute("Ccy", paymentData.currency)
+ text(paymentData.amount)
+ }
+ element("Cdtr/Nm") {
+ text(paymentData.creditorName)
+ }
+ element("CdtrAcct/Id/IBAN") {
+ text(paymentData.creditorIban)
+ }
+ element("RmtInf/Ustrd") {
+ text(paymentData.subject)
+ }
+ }
+ }
+ }
+ }
+ }
+ return s
+}
+
private fun XmlElementDestructor.extractDateOrDateTime(): DateOrDateTime {
return requireOnlyChild {
when (it.localName) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index af86c005..41123111 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -66,6 +66,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.slf4j.event.Level
+import tech.libeufin.nexus.bankaccount.submitPreparedPayments
import tech.libeufin.nexus.ebics.*
import tech.libeufin.util.*
import tech.libeufin.util.CryptoUtil.hashpw
@@ -245,7 +246,7 @@ fun moreFrequentBackgroundTasks(httpClient: HttpClient) {
}
// FIXME: should be done automatically after raw ingestion
reportAndIgnoreErrors { ingestTalerTransactions() }
- reportAndIgnoreErrors { submitPreparedPaymentsViaEbics(httpClient) }
+ reportAndIgnoreErrors { submitPreparedPayments(httpClient) }
logger.debug("More frequent background jobs done")
delay(Duration.ofSeconds(1))
}
@@ -362,7 +363,6 @@ fun serverMain(dbName: String) {
indentObjectsWith(DefaultIndenter(" ", "\n"))
})
registerModule(KotlinModule(nullisSameAsDefault = true))
- //registerModule(JavaTimeModule())
}
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
new file mode 100644
index 00000000..3c938289
--- /dev/null
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -0,0 +1,76 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2020 Taler Systems S.A.
+ *
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+ *
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.nexus.bankaccount
+
+import io.ktor.client.HttpClient
+import io.ktor.http.HttpStatusCode
+import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.not
+import org.jetbrains.exposed.sql.transactions.transaction
+import tech.libeufin.nexus.*
+import tech.libeufin.nexus.ebics.doEbicsUploadTransaction
+import tech.libeufin.nexus.ebics.submitEbicsPaymentInitiation
+import tech.libeufin.util.EbicsClientSubscriberDetails
+import tech.libeufin.util.EbicsStandardOrderParams
+
+
+/**
+ * Submit all pending prepared payments.
+ */
+suspend fun submitPreparedPayments(httpClient: HttpClient) {
+ data class Submission(
+ val id: Long,
+ val type: String
+ )
+ logger.debug("auto-submitter started")
+ val workQueue = mutableListOf<Submission>()
+ transaction {
+ NexusBankAccountEntity.all().forEach {
+ val defaultBankConnectionId = it.defaultBankConnection?.id ?: throw NexusError(
+ HttpStatusCode.BadRequest,
+ "needs default bank connection"
+ )
+ val bankConnection = NexusBankConnectionEntity.findById(defaultBankConnectionId) ?: throw NexusError(
+ HttpStatusCode.InternalServerError,
+ "Bank account '${it.id.value}' doesn't map to any bank connection (named '${it.defaultBankConnection}')"
+ )
+ if (bankConnection.type != "ebics") {
+ logger.info("Skipping non-implemented bank connection '${bankConnection.type}'")
+ return@forEach
+ }
+ val bankAccount: NexusBankAccountEntity = it
+ InitiatedPaymentEntity.find {
+ InitiatedPaymentsTable.debitorIban eq bankAccount.iban and
+ not(InitiatedPaymentsTable.submitted)
+ }.forEach {
+ workQueue.add(Submission(it.id.value, bankConnection.type))
+ }
+ }
+ }
+ workQueue.forEach {
+ when (it.type) {
+ "ebics" -> {
+ submitEbicsPaymentInitiation(httpClient, it.id)
+ }
+ else -> throw NexusError(HttpStatusCode.NotImplemented, "submission for ${it.type }not supported")
+ }
+
+ }
+} \ No newline at end of file
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 2c9741df..95847984 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -49,6 +49,7 @@ import tech.libeufin.util.ebics_h004.EbicsTypes
import tech.libeufin.util.ebics_h004.HTDResponseOrderData
import java.io.ByteArrayOutputStream
import java.security.interfaces.RSAPrivateCrtKey
+import java.security.interfaces.RSAPublicKey
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@@ -219,6 +220,36 @@ fun createEbicsBankConnectionFromBackup(
return
}
+private fun getEbicsSubscriberDetailsInternal(subscriber: EbicsSubscriberEntity): EbicsClientSubscriberDetails {
+ var bankAuthPubValue: RSAPublicKey? = null
+ if (subscriber.bankAuthenticationPublicKey != null) {
+ bankAuthPubValue = CryptoUtil.loadRsaPublicKey(
+ subscriber.bankAuthenticationPublicKey?.bytes!!
+ )
+ }
+ var bankEncPubValue: RSAPublicKey? = null
+ if (subscriber.bankEncryptionPublicKey != null) {
+ bankEncPubValue = CryptoUtil.loadRsaPublicKey(
+ subscriber.bankEncryptionPublicKey?.bytes!!
+ )
+ }
+ return EbicsClientSubscriberDetails(
+ bankAuthPub = bankAuthPubValue,
+ bankEncPub = bankEncPubValue,
+
+ ebicsUrl = subscriber.ebicsURL,
+ hostId = subscriber.hostID,
+ userId = subscriber.userID,
+ partnerId = subscriber.partnerID,
+
+ customerSignPriv = CryptoUtil.loadRsaPrivateKey(subscriber.signaturePrivateKey.bytes),
+ customerAuthPriv = CryptoUtil.loadRsaPrivateKey(subscriber.authenticationPrivateKey.bytes),
+ customerEncPriv = CryptoUtil.loadRsaPrivateKey(subscriber.encryptionPrivateKey.bytes),
+ ebicsIniState = subscriber.ebicsIniState,
+ ebicsHiaState = subscriber.ebicsHiaState
+ )
+}
+
/**
* Retrieve Ebics subscriber details given a bank connection.
*/
@@ -335,7 +366,8 @@ fun Route.ebicsBankConnectionRoutes(client: HttpClient) {
payload.value.partnerInfo.accountInfoList?.forEach {
NexusBankAccountEntity.new(id = it.id) {
accountHolder = it.accountHolder ?: "NOT-GIVEN"
- iban = extractFirstIban(it.accountNumberList)
+ iban = it.accountNumberList?.filterIsInstance<EbicsTypes.GeneralAccountNumber>()
+ ?.find { it.international }?.value
?: throw NexusError(HttpStatusCode.NotFound, reason = "bank gave no IBAN")
bankCode = it.bankCodeList?.filterIsInstance<EbicsTypes.GeneralBankCode>()
?.find { it.international }?.value
@@ -426,17 +458,6 @@ fun exportEbicsKeyBackup(bankConnectionId: String, passphrase: String): Any {
)
}
-suspend fun submitEbicsPaymentInitiation(client: HttpClient, connId: String, pain001Document: String) {
- val ebicsSubscriberDetails = transaction { getEbicsSubscriberDetails(connId) }
- logger.debug("Uploading PAIN.001: ${pain001Document}")
- doEbicsUploadTransaction(
- client,
- ebicsSubscriberDetails,
- "CCT",
- pain001Document.toByteArray(Charsets.UTF_8),
- EbicsStandardOrderParams()
- )
-}
fun getEbicsConnectionDetails(conn: NexusBankConnectionEntity): Any {
val ebicsSubscriber = transaction { getEbicsSubscriberDetails(conn.id.value) }
@@ -610,4 +631,40 @@ fun getEbicsKeyLetterPdf(conn: NexusBankConnectionEntity): ByteArray {
}
pdfWriter.flush()
return po.toByteArray()
+}
+
+suspend fun submitEbicsPaymentInitiation(httpClient: HttpClient, paymentInitiationId: Long) {
+ val r = transaction {
+ val paymentInitiation = InitiatedPaymentEntity.findById(paymentInitiationId)
+ ?: throw NexusError(HttpStatusCode.NotFound, "payment initiation not found")
+ val connId = paymentInitiation.bankAccount.defaultBankConnection?.id
+ ?: throw NexusError(HttpStatusCode.NotFound, "no default bank connection available for submission")
+ val subscriberDetails = getEbicsSubscriberDetails(connId.value)
+ val painMessage = createPain001document(
+ NexusPaymentInitiationData(
+ debtorIban = paymentInitiation.debitorIban,
+ currency = paymentInitiation.currency,
+ amount = paymentInitiation.sum.toString(),
+ creditorIban = paymentInitiation.creditorIban,
+ creditorName = paymentInitiation.creditorName,
+ debtorBic = paymentInitiation.creditorBic,
+ // FIXME(dold): Put date in here as well
+ messageId = paymentInitiation.id.toString(),
+ // FIXME(dold): Put date in here as well
+ paymentInformationId = paymentInitiation.id.toString(),
+ preparationTimestamp = paymentInitiation.preparationDate,
+ subject = paymentInitiation.subject
+ ))
+ object {
+ val subscriberDetails = subscriberDetails
+ val painMessage = painMessage
+ }
+ }
+ doEbicsUploadTransaction(
+ httpClient,
+ r.subscriberDetails,
+ "CCT",
+ r.painMessage.toByteArray(Charsets.UTF_8),
+ EbicsStandardOrderParams()
+ )
} \ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
index 3d7c056d..3f2470fe 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
@@ -379,65 +379,6 @@ private suspend fun talerAddIncoming(call: ApplicationCall, httpClient: HttpClie
)
}
-/**
- * submits ALL the prepared payments from ALL the Taler facades.
- * FIXME(dold): This should not be done here.
- * -> why? It crawls the *taler* facade to find payment to submit.
- */
-suspend fun submitPreparedPaymentsViaEbics(httpClient: HttpClient) {
- data class EbicsSubmission(
- val subscriberDetails: EbicsClientSubscriberDetails,
- val pain001document: String
- )
- logger.debug("auto-submitter started")
- val workQueue = mutableListOf<EbicsSubmission>()
- transaction {
- TalerFacadeStateEntity.all().forEach {
- val bankConnection = NexusBankConnectionEntity.findById(it.bankConnection) ?: throw NexusError(
- HttpStatusCode.InternalServerError,
- "Such facade '${it.facade.id.value}' doesn't map to any bank connection (named '${it.bankConnection}')"
- )
- if (bankConnection.type != "ebics") {
- logger.info("Skipping non-implemented bank connection '${bankConnection.type}'")
- return@forEach
- }
-
- val subscriberEntity = EbicsSubscriberEntity.find {
- EbicsSubscribersTable.nexusBankConnection eq it.bankConnection
- }.firstOrNull() ?: throw NexusError(
- HttpStatusCode.InternalServerError,
- "Such facade '${it.facade.id.value}' doesn't map to any Ebics subscriber"
- )
- val bankAccount: NexusBankAccountEntity =
- NexusBankAccountEntity.findById(it.bankAccount) ?: throw NexusError(
- HttpStatusCode.InternalServerError,
- "Bank account '${it.bankAccount}' not found for facade '${it.id.value}'"
- )
- InitiatedPaymentEntity.find {
- InitiatedPaymentsTable.debitorIban eq bankAccount.iban and
- not(InitiatedPaymentsTable.submitted)
- }.forEach {
- val pain001document = createPain001document(it)
- logger.debug("Preparing payment: ${pain001document}")
- val subscriberDetails = getEbicsSubscriberDetailsInternal(subscriberEntity)
- workQueue.add(EbicsSubmission(subscriberDetails, pain001document))
- // FIXME: the payment must be flagged AFTER the submission happens.
- // -> this is an open question: see #6367.
- it.submitted = true
- }
- }
- }
- workQueue.forEach {
- println("submitting prepared payment via EBICS")
- doEbicsUploadTransaction(
- httpClient,
- it.subscriberDetails,
- "CCT",
- it.pain001document.toByteArray(Charsets.UTF_8),
- EbicsStandardOrderParams()
- )
- }
-}
private fun ingestIncoming(payment: RawBankTransactionEntity, txDtls: TransactionDetails) {
val subject = txDtls.unstructuredRemittanceInformation