diff options
Diffstat (limited to 'bank/src/main/kotlin/tech/libeufin')
5 files changed, 18 insertions, 5 deletions
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt index 48fc3992..7a192308 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt @@ -40,7 +40,7 @@ const val IBAN_ALLOCATION_RETRY_COUNTER: Int = 5 const val MAX_BODY_LENGTH: Long = 4 * 1024 // 4kB // API version -const val COREBANK_API_VERSION: String = "4:3:0" +const val COREBANK_API_VERSION: String = "4:4:0" const val CONVERSION_API_VERSION: String = "0:0:0" const val INTEGRATION_API_VERSION: String = "2:0:2" const val WIRE_GATEWAY_API_VERSION: String = "0:2:0" diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt index 0284266b..ce459baa 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt @@ -380,7 +380,8 @@ data class AccountData( @Serializable data class TransactionCreateRequest( val payto_uri: Payto, - val amount: TalerAmount? + val amount: TalerAmount?, + val request_uid: ShortHashCode? ) @Serializable diff --git a/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt index dd6aab4b..a3bb8265 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt @@ -459,6 +459,7 @@ private fun Routing.coreBankTransactionsApi(db: Database, ctx: BankConfig) { subject = subject, amount = amount, timestamp = Instant.now(), + requestUid = req.request_uid, is2fa = challenge != null ) when (res) { @@ -479,6 +480,10 @@ private fun Routing.coreBankTransactionsApi(db: Database, ctx: BankConfig) { "Insufficient funds", TalerErrorCode.BANK_UNALLOWED_DEBIT ) + BankTransactionResult.RequestUidReuse -> throw conflict( + "request_uid used already", + TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED + ) is BankTransactionResult.Success -> call.respond(TransactionCreateResponse(res.id)) } } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt index 13bc1e09..f78947e7 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt @@ -157,7 +157,7 @@ class AccountDAO(private val db: Database) { if (bonus.value != 0L || bonus.frac != 0) { conn.prepareStatement(""" SELECT out_balance_insufficient - FROM bank_transaction(?,'admin','bonus',(?,?)::taler_amount,?,true) + FROM bank_transaction(?,'admin','bonus',(?,?)::taler_amount,?,true,NULL) """).run { setString(1, internalPayto.canonical) setLong(2, bonus.value) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt index 9b03cd2d..81fd558f 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt @@ -38,6 +38,7 @@ class TransactionDAO(private val db: Database) { data object BothPartySame: BankTransactionResult data object BalanceInsufficient: BankTransactionResult data object TanRequired: BankTransactionResult + data object RequestUidReuse: BankTransactionResult } /** Create a new transaction */ @@ -47,7 +48,8 @@ class TransactionDAO(private val db: Database) { subject: String, amount: TalerAmount, timestamp: Instant, - is2fa: Boolean + is2fa: Boolean, + requestUid: ShortHashCode?, ): BankTransactionResult = db.serializable { conn -> val now = timestamp.toDbMicros() ?: throw faultyTimestampByBank() conn.transaction { @@ -57,6 +59,7 @@ class TransactionDAO(private val db: Database) { ,out_debtor_not_found ,out_same_account ,out_balance_insufficient + ,out_request_uid_reuse ,out_tan_required ,out_credit_bank_account_id ,out_debit_bank_account_id @@ -65,7 +68,8 @@ class TransactionDAO(private val db: Database) { ,out_creditor_is_exchange ,out_debtor_is_exchange ,out_creditor_admin - FROM bank_transaction(?,?,?,(?,?)::taler_amount,?,?) + ,out_idempotent + FROM bank_transaction(?,?,?,(?,?)::taler_amount,?,?,?) """ ) stmt.setString(1, creditAccountPayto.canonical) @@ -75,6 +79,7 @@ class TransactionDAO(private val db: Database) { stmt.setInt(5, amount.frac) stmt.setLong(6, now) stmt.setBoolean(7, is2fa) + stmt.setBytes(8, requestUid?.raw) stmt.executeQuery().use { when { !it.next() -> throw internalServerError("Bank transaction didn't properly return") @@ -83,6 +88,8 @@ class TransactionDAO(private val db: Database) { it.getBoolean("out_same_account") -> BankTransactionResult.BothPartySame it.getBoolean("out_balance_insufficient") -> BankTransactionResult.BalanceInsufficient it.getBoolean("out_creditor_admin") -> BankTransactionResult.AdminCreditor + it.getBoolean("out_request_uid_reuse") -> BankTransactionResult.RequestUidReuse + it.getBoolean("out_idempotent") -> BankTransactionResult.Success(it.getLong("out_debit_row_id")) it.getBoolean("out_tan_required") -> BankTransactionResult.TanRequired else -> { val creditAccountId = it.getLong("out_credit_bank_account_id") |