summaryrefslogtreecommitdiff
path: root/nexus/src/main/kotlin/tech
diff options
context:
space:
mode:
authorMS <ms@taler.net>2020-06-03 18:59:58 +0200
committerMS <ms@taler.net>2020-06-03 19:09:40 +0200
commit1c89426792953a838491b4592a14cc38849e43ed (patch)
treeeca1f3be69cbedf410db408133597714064f0a8c /nexus/src/main/kotlin/tech
parent088c518e0ed7d9e5f448035fdc41426c6887b405 (diff)
downloadlibeufin-1c89426792953a838491b4592a14cc38849e43ed.tar.gz
libeufin-1c89426792953a838491b4592a14cc38849e43ed.tar.bz2
libeufin-1c89426792953a838491b4592a14cc38849e43ed.zip
Advancing for the exchange-nexus test.
Sandbox: fill CAMT values according to actual data received in payments. Nexus: fix the launching of HTTP requests (namely to obtain C53) in the background.
Diffstat (limited to 'nexus/src/main/kotlin/tech')
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt40
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt63
2 files changed, 65 insertions, 38 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index fb4d0bae..0ed44db9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -56,8 +56,7 @@ import io.ktor.server.netty.Netty
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.toByteReadChannel
import io.ktor.utils.io.jvm.javaio.toInputStream
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
+import kotlinx.coroutines.*
import kotlinx.coroutines.time.delay
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
@@ -75,6 +74,7 @@ import java.util.*
import java.util.zip.InflaterInputStream
import javax.crypto.EncryptedPrivateKeyInfo
import java.time.LocalDateTime
+import kotlin.coroutines.CoroutineContext
data class NexusError(val statusCode: HttpStatusCode, val reason: String) :
Exception("${reason} (HTTP status $statusCode)")
@@ -258,21 +258,37 @@ fun ApplicationRequest.hasBody(): Boolean {
}
return false
}
-suspend fun schedulePeriodicWork(coroutineScope: CoroutineScope) {
- while (true) {
- delay(Duration.ofMillis(100))
- downloadFacadesTransactions(coroutineScope)
- ingestTalerTransactions()
+
+fun schedulePeriodicWork() {
+ GlobalScope.launch {
+ while (true) {
+ logger.debug("Outer background job")
+ try {
+ delay(Duration.ofSeconds(1))
+ downloadFacadesTransactions(this)
+ ingestTalerTransactions()
+ } catch (e: Exception) {
+ logger.info("==== Background job exception ====\n${e.message}======")
+ }
+ }
}
}
/** Crawls all the facades, and requests history for each of its creators. */
-suspend fun downloadFacadesTransactions(coroutineScope: CoroutineScope) {
+suspend fun downloadFacadesTransactions(myScope: CoroutineScope) {
val httpClient = HttpClient()
transaction {
FacadeEntity.all().forEach {
- coroutineScope.launch {
- fetchTransactionsInternal(httpClient, it.creator, it.config.bankAccount, CollectedTransaction())
+ logger.debug(
+ "Fetching history for facade: ${it.id.value}, bank account: ${it.config.bankAccount}"
+ )
+ runBlocking {
+ fetchTransactionsInternal(
+ httpClient,
+ it.creator,
+ it.config.bankAccount,
+ CollectedTransaction(null, null, null)
+ )
}
}
}
@@ -344,9 +360,6 @@ fun serverMain(dbName: String) {
expectSuccess = false // this way, it does not throw exceptions on != 200 responses.
}
val server = embeddedServer(Netty, port = 5001) {
- launch {
- schedulePeriodicWork(this)
- }
install(CallLogging) {
this.level = Level.DEBUG
this.logger = tech.libeufin.nexus.logger
@@ -413,6 +426,7 @@ fun serverMain(dbName: String) {
return@intercept
}
+ schedulePeriodicWork()
routing {
/**
* Shows information about the requesting user.
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
index de7ea140..499743e3 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
@@ -3,9 +3,12 @@ package tech.libeufin.nexus
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import io.ktor.application.ApplicationCall
import io.ktor.application.call
+import io.ktor.client.HttpClient
+import io.ktor.client.request.post
import io.ktor.content.TextContent
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
+import io.ktor.http.contentType
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.response.respondText
@@ -226,7 +229,7 @@ fun getFacadeBankAccount(nexusUser: NexusUserEntity): NexusBankAccountEntity {
}
// /taler/transfer
-suspend fun talerTransfer(call: ApplicationCall): Unit {
+suspend fun talerTransfer(call: ApplicationCall) {
val transferRequest = call.receive<TalerTransferRequest>()
val amountObj = parseAmount(transferRequest.amount)
val creditorObj = parsePayto(transferRequest.credit_account)
@@ -260,20 +263,6 @@ suspend fun talerTransfer(call: ApplicationCall): Unit {
),
exchangeBankAccount
)
- val rawEbics = if (!isProduction()) {
- RawBankTransactionEntity.new {
- unstructuredRemittanceInformation = transferRequest.wtid
- transactionType = "DBIT"
- currency = amountObj.currency
- this.amount = amountObj.amount.toPlainString()
- counterpartBic = creditorObj.bic
- counterpartIban = creditorObj.iban
- counterpartName = creditorObj.name
- bankAccount = exchangeBankAccount
- bookingDate = System.currentTimeMillis()
- status = "BOOK"
- }
- } else null
val row = TalerRequestedPaymentEntity.new {
preparedPayment = pain001 // not really used/needed, just here to silence warnings
exchangeBaseUrl = transferRequest.exchange_base_url
@@ -281,7 +270,6 @@ suspend fun talerTransfer(call: ApplicationCall): Unit {
amount = transferRequest.amount
wtid = transferRequest.wtid
creditAccount = transferRequest.credit_account
- rawConfirmed = rawEbics
}
row.id.value
}
@@ -307,25 +295,49 @@ suspend fun talerTransfer(call: ApplicationCall): Unit {
suspend fun talerAddIncoming(call: ApplicationCall): Unit {
val addIncomingData = call.receive<TalerAdminAddIncoming>()
val debtor = parsePayto(addIncomingData.debit_account)
- val amount = parseAmount(addIncomingData.amount)
-
- val myLastSeenRawPayment = transaction {
+ val res = transaction {
val facadeID = expectNonNull(call.parameters["fcid"])
val facade = FacadeEntity.findById(facadeID) ?: throw NexusError(
- HttpStatusCode.NotFound, "Could not find facade"
+ HttpStatusCode.NotFound, "Could not find facade '$facadeID'"
+ )
+ val facadeBankAccount = NexusBankAccountEntity.findById(facade.config.bankAccount) ?: throw NexusError(
+ HttpStatusCode.NotFound,
+ "Such bank account '${facade.config.bankAccount}' wasn't found for facade '$facadeID'"
)
- facade.highestSeenMsgID
+ return@transaction object {
+ val facadeLastSeen = facade.highestSeenMsgID
+ val facadeIban = facadeBankAccount.iban
+ val facadeBic = facadeBankAccount.bankCode
+ val facadeHolderName = facadeBankAccount.accountHolder
+ }
}
+ val httpClient = HttpClient()
+ /** forward the payment information to the sandbox. */
+ httpClient.post<String>(
+ urlString = "http://localhost:5000/admin/payments",
+ block = {
+ /** FIXME: ideally Jackson should define such request body. */
+ this.body = """{
+ "creditorIban": "${res.facadeIban}",
+ "creditorBic": "${res.facadeBic}",
+ "creditorName": "${res.facadeHolderName}",
+ "debitorIban": "${debtor.iban}",
+ "debitorBic": "${debtor.bic}",
+ "debitorName": "${debtor.name}",
+ "amount": "${addIncomingData.amount}",
+ "subject": "${addIncomingData.reserve_pub}"
+ }""".trimIndent()
+ contentType(ContentType.Application.Json)
+ }
+ )
return call.respond(
TextContent(
customConverter(
TalerAddIncomingResponse(
timestamp = GnunetTimestamp(
- // warning: this value might need to come from a real last-seen payment.
- // FIXME(dold): I don't understand the comment above ^^.
System.currentTimeMillis()
),
- row_id = myLastSeenRawPayment
+ row_id = res.facadeLastSeen
)
),
ContentType.Application.Json
@@ -343,6 +355,7 @@ suspend fun talerAddIncoming(call: ApplicationCall): Unit {
*/
fun ingestTalerTransactions() {
fun ingest(subscriberAccount: NexusBankAccountEntity, facade: FacadeEntity) {
+ logger.debug("Ingesting transactions for Taler facade: ${facade.id.value}")
var lastId = facade.highestSeenMsgID
RawBankTransactionEntity.find {
/** Those with exchange bank account involved */
@@ -510,4 +523,4 @@ fun talerFacadeRoutes(route: Route) {
call.respondText("Hello, this is Taler Facade")
return@get
}
-} \ No newline at end of file
+}