libeufin

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

commit c73f750472139b7ec872c1bf16a284de143ef998
parent e1e8a3b2e28321a56ddc0206b7485e754e6f8f77
Author: Antoine A <>
Date:   Fri, 26 Apr 2024 13:28:41 +0900

Unify payto logic

Diffstat:
Mcommon/src/main/kotlin/TalerCommon.kt | 16++++++++--------
Mnexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt | 8++------
Mnexus/src/main/kotlin/tech/libeufin/nexus/api/WireGatewayApi.kt | 15+++++----------
Mnexus/src/test/kotlin/Iso20022Test.kt | 10+++++-----
4 files changed, 20 insertions(+), 29 deletions(-)

diff --git a/common/src/main/kotlin/TalerCommon.kt b/common/src/main/kotlin/TalerCommon.kt @@ -232,10 +232,7 @@ sealed class Payto { /** Transform a payto URI to its bank form, using [name] as the receiver-name and the bank [ctx] */ fun bank(name: String, ctx: BankPaytoCtx): String = when (this) { - is IbanPayto -> { - val bic = if (ctx.bic != null) "${ctx.bic}/" else "" - "payto://iban/$bic$iban?receiver-name=${name.encodeURLParameter()}" - } + is IbanPayto -> IbanPayto.build(iban.toString(), ctx.bic, name) is XTalerBankPayto -> "payto://x-taler-bank/${ctx.hostname ?: "localhost"}/$username?receiver-name=${name.encodeURLParameter()}" } @@ -333,10 +330,7 @@ class IbanPayto internal constructor( override fun toString(): String = parsed.toString() /** Transform an IBAN payto URI to its full form, using [defaultName] if receiver-name is missing */ - fun full(defaultName: String): String { - val bic = if (this.bic != null) "$bic/" else "" - return "payto://iban/$bic$iban?receiver-name=${(receiverName ?: defaultName).encodeURLParameter()}" - } + fun full(defaultName: String): String = build(iban.toString(), bic, receiverName ?: defaultName) internal object Serializer : KSerializer<IbanPayto> { override val descriptor: SerialDescriptor = @@ -352,6 +346,12 @@ class IbanPayto internal constructor( } companion object { + fun build(iban: String, bic: String?, name: String?): String { + val bic = if (bic != null) "$bic/" else "" + val name = if (name != null) "?receiver-name=${name.encodeURLParameter()}" else "" + return "payto://iban/$bic$iban$name" + } + fun rand(): IbanPayto { return parse("payto://iban/SANDBOXX/${IBAN.rand()}").expectIban() } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt @@ -300,13 +300,9 @@ data class OutgoingPayment( private fun XmlDestructor.payto(prefix: String): String? { val iban = opt("${prefix}Acct")?.one("Id")?.one("IBAN")?.text() return if (iban != null) { - val payto = StringBuilder("payto://iban/$iban") val name = opt(prefix) { opt("Nm")?.text() ?: opt("Pty")?.one("Nm")?.text() } - if (name != null) { - val urlEncName = URLEncoder.encode(name, "utf-8") - payto.append("?receiver-name=$urlEncName") - } - return payto.toString() + // Parse bic ? + IbanPayto.build(iban, null, name) } else { null } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/api/WireGatewayApi.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/api/WireGatewayApi.kt @@ -66,28 +66,23 @@ fun Routing.wireGatewayApi(db: Database, cfg: NexusConfig) { ) } } - /*suspend fun <T> PipelineContext<Unit, ApplicationCall>.historyEndpoint( + /* + suspend fun <T> PipelineContext<Unit, ApplicationCall>.historyEndpoint( reduce: (List<T>, String) -> Any, dbLambda: suspend ExchangeDAO.(HistoryParams, Long, BankPaytoCtx) -> List<T> ) { val params = HistoryParams.extract(context.request.queryParameters) val bankAccount = call.bankInfo(db, ctx.payto) - - if (!bankAccount.isTalerExchange) - throw conflict( - "$username is not an exchange account.", - TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE - ) val items = db.exchange.dbLambda(params, bankAccount.bankAccountId, ctx.payto) - + val if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(reduce(items, bankAccount.payto)) } - }*/ - /*get("/taler-wire-gateway/history/incoming") { + } + get("/taler-wire-gateway/history/incoming") { historyEndpoint(::IncomingHistory, ExchangeDAO::incomingHistory) } get("/taler-wire-gateway/history/outgoing") { diff --git a/nexus/src/test/kotlin/Iso20022Test.kt b/nexus/src/test/kotlin/Iso20022Test.kt @@ -55,14 +55,14 @@ class Iso20022Test { amount = TalerAmount("CHF:10"), wireTransferSubject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YBG", executionTime = instant("2023-12-19"), - debitPaytoUri = "payto://iban/CH7389144832588726658?receiver-name=Mr+Test" + debitPaytoUri = "payto://iban/CH7389144832588726658?receiver-name=Mr%20Test" ), IncomingPayment( bankId = "62e2b511-7313-4ccd-8d40-c9d8e612cd71", amount = TalerAmount("CHF:2.53"), wireTransferSubject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YB", executionTime = instant("2023-12-19"), - debitPaytoUri = "payto://iban/CH7389144832588726658?receiver-name=Mr+Test" + debitPaytoUri = "payto://iban/CH7389144832588726658?receiver-name=Mr%20Test" ) ), txs @@ -101,21 +101,21 @@ class Iso20022Test { amount = TalerAmount("EUR:2"), wireTransferSubject = "TestABC123", executionTime = instant("2024-04-18"), - creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John+Smith" + creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John%20Smith" ), OutgoingPayment( messageId = "YF5QBARGQ0MNY0VK59S477VDG4", amount = TalerAmount("EUR:1.1"), wireTransferSubject = "This should fail because dummy", executionTime = instant("2024-04-18"), - creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John+Smith" + creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John%20Smith" ), IncomingPayment( bankId = "BYLADEM1WOR-G2910276709458A2", amount = TalerAmount("EUR:3"), wireTransferSubject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", executionTime = instant("2024-04-12"), - debitPaytoUri = "payto://iban/DE84500105177118117964?receiver-name=John+Smith" + debitPaytoUri = "payto://iban/DE84500105177118117964?receiver-name=John%20Smith" ), Reversal( msgId = "G27KNKZAR5DV7HRB085YMA9GB4",