libeufin

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

commit f169ea735202c35ab3154213c853b5df41902fc8
parent 96890501bf5645281da201792f4e5acff2f5d292
Author: MS <ms@taler.net>
Date:   Wed, 20 Sep 2023 14:47:17 +0200

Making withdrawal /confirm respond.

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt | 33++++++++++++++++++++++++++++++++-
Mbank/src/test/kotlin/TalerApiTest.kt | 49+++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt b/bank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt @@ -33,6 +33,7 @@ import io.ktor.server.routing.* import net.taler.common.errorcodes.TalerErrorCode import net.taler.wallet.crypto.Base32Crockford import tech.libeufin.util.getBaseUrl +import tech.libeufin.util.getNowUs import java.util.* /** @@ -158,8 +159,38 @@ fun Routing.talerWebHandlers() { )) /* Confirmation conditions are all met, now put the operation * to the selected state _and_ wire the funds to the exchange. + * Note: 'when' helps not to omit more result codes, should more + * be added. */ - throw NotImplementedError("Need a database transaction now?") + when (db.talerWithdrawalConfirm(op.withdrawalUuid, getNowUs())) { + WithdrawalConfirmationResult.BALANCE_INSUFFICIENT -> + throw conflict( + "Insufficient funds", + TalerErrorCode.TALER_EC_END // FIXME: define EC for this. + ) + WithdrawalConfirmationResult.OP_NOT_FOUND -> + /** + * Despite previous checks, the database _still_ did not + * find the withdrawal operation, that's on the bank. + */ + throw internalServerError("Withdrawal operation (${op.withdrawalUuid}) not found") + WithdrawalConfirmationResult.EXCHANGE_NOT_FOUND -> + /** + * That can happen because the bank did not check the exchange + * exists when POST /withdrawals happened, or because the exchange + * bank account got removed before this confirmation. + */ + throw conflict( + hint = "Exchange to withdraw from not found", + talerEc = TalerErrorCode.TALER_EC_END // FIXME + ) + WithdrawalConfirmationResult.SUCCESS -> + call.respondText( + "{}", + ContentType.Application.Json + ) + } + return@post } } diff --git a/bank/src/test/kotlin/TalerApiTest.kt b/bank/src/test/kotlin/TalerApiTest.kt @@ -78,9 +78,54 @@ class TalerApiTest { } } // Testing withdrawal confirmation - @Ignore + @Test fun withdrawalConfirmation() { - assert(false) + val db = initDb() + val bankAccountBar = BankAccount( + internalPaytoUri = "BAR-IBAN-ABC", + lastNexusFetchRowId = 1L, + owningCustomerId = 2L, + hasDebt = false, + maxDebt = TalerAmount(10, 1, "KUDOS") + ) + val customerBar = Customer( + login = "bar", + passwordHash = "hash", + name = "Bar", + phone = "+00", + email = "foo@b.ar", + cashoutPayto = "payto://external-IBAN", + cashoutCurrency = "KUDOS" + ) + + // Creating Foo as the wallet owner and Bar as the exchange. + assert(db.customerCreate(customerFoo) != null) + assert(db.bankAccountCreate(bankAccountFoo)) + assert(db.customerCreate(customerBar) != null) + assert(db.bankAccountCreate(bankAccountBar)) + + // Artificially making a withdrawal operation for Foo. + val uuid = UUID.randomUUID() + assert(db.talerWithdrawalCreate( + opUUID = uuid, + walletBankAccount = 1L, + amount = TalerAmount(1, 0) + )) + // Specifying Bar as the exchange, via its Payto URI. + assert(db.talerWithdrawalSetDetails( + opUuid = uuid, + exchangePayto = "BAR-IBAN-ABC", + reservePub = "UNCHECKED-RESERVE-PUB" + )) + + // Starting the bank and POSTing as Foo to /confirm the operation. + testApplication { + application(webApp) + client.post("/accounts/foo/withdrawals/${uuid}/confirm") { + expectSuccess = true // Sufficient to assert on success. + basicAuth("foo", "pw") + } + } } // Testing the generation of taler://withdraw-URIs. @Test