libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 4f7ad1304847068479ee58f786a73cd603b2dba7
parent 14f5c806bda33cdbea41abb821a9962a8f3b22d7
Author: MS <ms@taler.net>
Date:   Mon, 18 Sep 2023 14:26:47 +0200

Testing:

POST /transactions
GET /transactions/T_ID

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/Database.kt | 6+++---
Mbank/src/main/kotlin/tech/libeufin/bank/Main.kt | 1+
Mbank/src/main/kotlin/tech/libeufin/bank/transactionsHandlers.kt | 8+++++---
Mbank/src/test/kotlin/LibeuFinApiTest.kt | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
4 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Database.kt b/bank/src/main/kotlin/tech/libeufin/bank/Database.kt @@ -353,7 +353,7 @@ class Database(private val dbConfig: String) { reconnect() val stmt = prepare(""" SELECT - ,bank_account_id + bank_account_id ,owning_customer_id ,is_public ,is_taler_exchange @@ -452,7 +452,7 @@ class Database(private val dbConfig: String) { ,payment_information_id ,end_to_end_id ,direction - ,owning_customer_id + ,bank_account_id FROM bank_account_transactions WHERE bank_transaction_id=? """) @@ -478,7 +478,7 @@ class Database(private val dbConfig: String) { else -> throw internalServerError("Wrong direction in transaction: $this") } }, - bankAccountId = it.getLong("owning_customer_id"), + bankAccountId = it.getLong("bank_account_id"), paymentInformationId = it.getString("payment_information_id"), subject = it.getString("subject"), transactionDate = it.getLong("transaction_date") diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -194,6 +194,7 @@ val webApp: Application.() -> Unit = { } // Catch-all branch to mean that the bank wasn't able to manage one error. exception<Exception> {call, cause -> + cause.printStackTrace() logger.error(cause.message) call.respond( status = HttpStatusCode.InternalServerError, diff --git a/bank/src/main/kotlin/tech/libeufin/bank/transactionsHandlers.kt b/bank/src/main/kotlin/tech/libeufin/bank/transactionsHandlers.kt @@ -18,12 +18,14 @@ fun Routing.transactionsHandlers() { if ((c.login != resourceName) && (call.getAuthToken() == null)) throw forbidden() val txData = call.receive<BankAccountTransactionCreate>() - val payto = parsePayto(txData.payto_uri) - val subject = payto?.message ?: throw badRequest("Wire transfer lacks subject") + // FIXME: make payto parser IBAN-agnostic? + val payto = parsePayto(txData.payto_uri) ?: throw badRequest("Invalid creditor Payto") + val paytoWithoutParams = "payto://iban/${payto.bic}/${payto.iban}" + val subject = payto.message ?: throw badRequest("Wire transfer lacks subject") val debtorId = c.dbRowId ?: throw internalServerError("Debtor database ID not found") // This performs already a SELECT on the bank account, // like the wire transfer will do as well later! - val creditorCustomerData = db.bankAccountGetFromInternalPayto(txData.payto_uri) + val creditorCustomerData = db.bankAccountGetFromInternalPayto(paytoWithoutParams) ?: throw notFound( "Creditor account not found", TalerErrorCode.TALER_EC_END // FIXME: define this EC. diff --git a/bank/src/test/kotlin/LibeuFinApiTest.kt b/bank/src/test/kotlin/LibeuFinApiTest.kt @@ -1,10 +1,8 @@ -import io.ktor.auth.* import io.ktor.client.plugins.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* -import io.netty.handler.codec.http.HttpResponseStatus import kotlinx.serialization.json.Json import net.taler.wallet.crypto.Base32Crockford import org.junit.Test @@ -16,14 +14,63 @@ import kotlin.random.Random class LibeuFinApiTest { private val customerFoo = Customer( - login = "foo", - passwordHash = CryptoUtil.hashpw("pw"), - name = "Foo", - phone = "+00", - email = "foo@b.ar", - cashoutPayto = "payto://external-IBAN", - cashoutCurrency = "KUDOS" + login = "foo", + passwordHash = CryptoUtil.hashpw("pw"), + name = "Foo", + phone = "+00", + email = "foo@b.ar", + cashoutPayto = "payto://external-IBAN", + cashoutCurrency = "KUDOS" ) + private val customerBar = Customer( + login = "bar", + passwordHash = CryptoUtil.hashpw("pw"), + name = "Bar", + phone = "+99", + email = "bar@example.com", + cashoutPayto = "payto://external-IBAN", + cashoutCurrency = "KUDOS" + ) + private fun genBankAccount(rowId: Long) = BankAccount( + hasDebt = false, + internalPaytoUri = "payto://iban/SANDBOXX/${rowId}-IBAN", + maxDebt = TalerAmount(100, 0), + owningCustomerId = rowId + ) + + // Testing the creation of bank transactions. + @Test + fun postTransactionsTest() { + val db = initDb() + // foo account + val fooId = db.customerCreate(customerFoo); assert(fooId != null) + assert(db.bankAccountCreate(genBankAccount(fooId!!))) + // bar account + val barId = db.customerCreate(customerBar); assert(barId != null) + assert(db.bankAccountCreate(genBankAccount(barId!!))) + // accounts exist, now create one transaction. + testApplication { + application(webApp) + client.post("/accounts/foo/transactions") { + expectSuccess = true + basicAuth("foo", "pw") + contentType(ContentType.Application.Json) + // expectSuccess = true + setBody("""{ + "payto_uri": "payto://iban/SANDBOXX/${barId}-IBAN?message=payout", + "amount": "KUDOS:3.3" + } + """.trimIndent()) + } + // Getting the only tx that exists in the DB, hence has ID == 1. + val r = client.get("/accounts/foo/transactions/1") { + basicAuth("foo", "pw") + expectSuccess = true + } + val obj: BankAccountTransactionInfo = Json.decodeFromString(r.bodyAsText()) + assert(obj.subject == "payout") + } + } // Checking the POST /token handling. @Test fun tokenTest() {