diff options
author | MS <ms@taler.net> | 2023-07-19 15:53:59 +0200 |
---|---|---|
committer | MS <ms@taler.net> | 2023-07-19 15:53:59 +0200 |
commit | d13f040a2acb7b832a959f94a215b5e25340ed5b (patch) | |
tree | 7fb5caa126f842373027e43adbd0e77b275a9d43 /nexus/src/main/kotlin | |
parent | fdddd2f9f2f4d1b3daa0a74d3aeb51b51d5c8e02 (diff) | |
download | libeufin-d13f040a2acb7b832a959f94a215b5e25340ed5b.tar.gz libeufin-d13f040a2acb7b832a959f94a215b5e25340ed5b.tar.bz2 libeufin-d13f040a2acb7b832a959f94a215b5e25340ed5b.zip |
Fix /admin/add-incoming.
Avoid double-requesting in Nexus and instead
create and ingest the incoming payment within
the same handler.
Diffstat (limited to 'nexus/src/main/kotlin')
5 files changed, 61 insertions, 37 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/BankConnectionProtocol.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/BankConnectionProtocol.kt index e87e9444..8607d3c9 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/BankConnectionProtocol.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/BankConnectionProtocol.kt @@ -35,6 +35,10 @@ val bankConnectionRegistry: Map<BankConnectionType, BankConnectionProtocol> = ma ) interface BankConnectionProtocol { + // Get the bank URL in the same format that + // it was given when the connection was created. + // This helps the /admin/add-incoming handler. + fun getBankUrl(connId: String): String // Initialize the connection. Usually uploads keys to the bank. suspend fun connect(client: HttpClient, connId: String) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt index 2aa02121..670d714c 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt @@ -48,6 +48,7 @@ import tech.libeufin.nexus.bankaccount.addPaymentInitiation import tech.libeufin.nexus.bankaccount.fetchBankAccountTransactions import tech.libeufin.nexus.iso20022.* import tech.libeufin.nexus.server.* +import tech.libeufin.nexus.xlibeufinbank.ingestXLibeufinBankMessage import tech.libeufin.util.* import java.net.URL import kotlin.math.abs @@ -587,30 +588,24 @@ private suspend fun addIncoming(call: ApplicationCall) { val conn = NexusBankConnectionEntity.findByName(facadeState.bankConnection) ?: throw internalServerError( "state of facade $facadeId has no bank connection!" ) - val ebicsData = NexusEbicsSubscribersTable.select { - NexusEbicsSubscribersTable.nexusBankConnection eq conn.id - }.firstOrNull() ?: throw internalServerError( - "Connection '${conn.connectionId}' doesn't have EBICS" - ) - // Resort Sandbox URL from EBICS endpoint. - val sandboxUrl = URL(ebicsData[NexusEbicsSubscribersTable.ebicsURL]) + val sandboxUrl = URL(getConnectionPlugin(conn.type).getBankUrl(conn.connectionId)) // NOTE: the exchange username must be 'exchange', at the Sandbox. return@transaction Pair( url { protocol = URLProtocol(sandboxUrl.protocol, 80) host = sandboxUrl.host - if (sandboxUrl.port != 80) - port = sandboxUrl.port - path( - "demobanks", - "default", - "taler-wire-gateway", - "exchange", - "admin", - "add-incoming" - ) - }, - facadeState.bankAccount + if (sandboxUrl.port != 80) + port = sandboxUrl.port + path( + "demobanks", + "default", + "taler-wire-gateway", + "exchange", + "admin", + "add-incoming" + ) + }, // first + facadeState.bankAccount // second ) } val client = HttpClient { followRedirects = true } @@ -630,20 +625,26 @@ private suspend fun addIncoming(call: ApplicationCall) { logger.error("Client-side error for /admin/add-incoming. Sandbox says: ${resp.bodyAsText()}") call.respond(resp.status, resp.bodyAsText()) } - /** - * At this point, Sandbox booked the payment. Now the "row_id" - * value to put in the response needs to be resorted; that may - * be known by fetching a fresh C52 report, then let Nexus ingest - * the result, and finally _optimistically_ pick the latest entry - * in the received payments. NOTE: if this fails, the global handler - * responds 500 as this should _never_ fail. */ - fetchBankAccountTransactions( - client, - FetchSpecLatestJson( - FetchLevel.REPORT, - null - ), - fromDb.second + // x-libeufin-bank-ingest + val ingestionResult = ingestXLibeufinBankMessage( + fromDb.second, + resp.bodyAsText() + ) + if (ingestionResult.newTransactions != 1) + throw internalServerError("/admin/add-incoming was ingested into ${ingestionResult.newTransactions} new transactions, but it must have one.") + if (ingestionResult.errors != null) { + val errors = ingestionResult.errors + errors?.forEach { + logger.error(it.message) + } + throw internalServerError("/admin/add-incoming ingestion failed.") + } + // TWG ingest. + ingestFacadeTransactions( + bankAccountId = fromDb.second, + facadeType = NexusFacadeType.TALER, + incomingFilterCb = ::talerFilter, + refundCb = ::maybeTalerRefunds ) /** * The latest incoming payment should now be found among 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 8f1f6ca5..26453fac 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt @@ -431,7 +431,7 @@ suspend fun fetchBankAccountTransactions( accountId ) /** - * The following two functions further processe the banking data + * The following two functions further process the banking data * that was recently downloaded, according to the particular facade * being honored. */ 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 b1fdf816..fbb128f8 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt @@ -633,6 +633,11 @@ class EbicsBankConnectionProtocol: BankConnectionProtocol { } } } + + override fun getBankUrl(connId: String): String { + val subscriberDetails = transaction { getEbicsSubscriberDetails(connId) } + return subscriberDetails.ebicsUrl + } override suspend fun fetchTransactions( fetchSpec: FetchSpecJson, client: HttpClient, 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 2bb86643..b6f025bf 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/xlibeufinbank/XLibeufinBankNexus.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/xlibeufinbank/XLibeufinBankNexus.kt @@ -30,7 +30,7 @@ import java.net.URL import java.time.LocalDate // Gets Sandbox URL and credentials, taking the connection name as input. -fun getXLibeufinBankCredentials(conn: NexusBankConnectionEntity): XLibeufinBankTransport { +private fun getXLibeufinBankCredentials(conn: NexusBankConnectionEntity): XLibeufinBankTransport { val maybeCredentials = transaction { XLibeufinBankUserEntity.find { XLibeufinBankUsersTable.nexusBankConnection eq conn.id @@ -45,12 +45,14 @@ fun getXLibeufinBankCredentials(conn: NexusBankConnectionEntity): XLibeufinBankT baseUrl = maybeCredentials.baseUrl ) } -fun getXLibeufinBankCredentials(connId: String): XLibeufinBankTransport { +private fun getXLibeufinBankCredentials(connId: String): XLibeufinBankTransport { val conn = getBankConnection(connId) return getXLibeufinBankCredentials(conn) } - class XlibeufinBankConnectionProtocol : BankConnectionProtocol { + override fun getBankUrl(connId: String): String { + return getXLibeufinBankCredentials(connId).baseUrl + } /** * Together with checking the credentials, this method downloads * additional details from the bank, and stores them in the table @@ -316,6 +318,18 @@ class XlibeufinBankConnectionProtocol : BankConnectionProtocol { } } +fun ingestXLibeufinBankMessage( + bankAccountId: String, + data: String // JSON +): IngestedTransactionsCount { + val jMessage = try { jacksonObjectMapper().readTree(data) } + catch (e: Exception) { + logger.error("Bank message $data could not" + + " be parsed into JSON by the x-libeufin-bank ingestion.") + throw internalServerError("Could not ingest x-libeufin-bank message.") + } + return ingestXLibeufinBankMessage(bankAccountId, jMessage) +} /** * Parses one x-libeufin-bank message and INSERTs Nexus local * transaction records into the database. After this function |