[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: extend Payto parser
From: |
gnunet |
Subject: |
[libeufin] branch master updated: extend Payto parser |
Date: |
Thu, 21 Oct 2021 16:39:32 +0200 |
This is an automated email from the git hooks/post-receive script.
ms pushed a commit to branch master
in repository libeufin.
The following commit(s) were added to refs/heads/master by this push:
new b041de6 extend Payto parser
b041de6 is described below
commit b041de6e185e334e37572b33e31966028ae50bb6
Author: ms <ms@taler.net>
AuthorDate: Thu Oct 21 16:39:21 2021 +0200
extend Payto parser
---
nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt | 1 +
util/src/main/kotlin/Payto.kt | 62 +++++++++++++++-------
util/src/test/kotlin/PaytoTest.kt | 27 +++++++---
3 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
index 31fff08..6cd34a0 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
@@ -181,6 +181,7 @@ private suspend fun talerTransfer(call: ApplicationCall) {
val transferRequest = call.receive<TalerTransferRequest>()
val amountObj = parseAmount(transferRequest.amount)
// FIXME: Right now we only parse the credit_account, should we also
validate that it matches our account info?
+ // FIXME, another parse happens below; is this really useful here?
parsePayto(transferRequest.credit_account)
val facadeId = expectNonNull(call.parameters["fcid"])
val opaqueRowId = transaction {
diff --git a/util/src/main/kotlin/Payto.kt b/util/src/main/kotlin/Payto.kt
index 1c10263..3fcecff 100644
--- a/util/src/main/kotlin/Payto.kt
+++ b/util/src/main/kotlin/Payto.kt
@@ -1,21 +1,40 @@
package tech.libeufin.util
import java.net.URI
+import java.net.URLDecoder
/**
- * Helper data structures.
+ * Payto information.
*/
data class Payto(
- // Can represent a the sender or a receiver.
+ // represent query param "sender-name" or "receiver-name".
val name: String?,
val iban: String,
- val bic: String?
+ val bic: String?,
+ // Typically, a wire transfer's subject.
+ val message: String?,
+ val amount: String?
)
class InvalidPaytoError(msg: String) : Exception(msg)
+// Return the value of query string parameter 'name', or null if not found.
+// 'params' is the a list of key-value elements of all the query parameters
found in the URI.
+private fun getQueryParamOrNull(name: String, params: List<Pair<String,
String>>?): String? {
+ if (params == null) return null
+ return params.firstNotNullOfOrNull { pair ->
+ URLDecoder.decode(pair.second, Charsets.UTF_8).takeIf { pair.first ==
name }
+ }
+}
+
fun parsePayto(paytoLine: String): Payto {
+ /**
+ * This check is due because URIs having a "payto:" prefix without
+ * slashes are correctly parsed by the Java 'URI' class. 'mailto'
+ * for example lacks the double-slash part.
+ */
if (!paytoLine.startsWith("payto://"))
throw InvalidPaytoError("Invalid payto URI: $paytoLine")
+
val javaParsedUri = try {
URI(paytoLine)
} catch (e: java.lang.Exception) {
@@ -25,22 +44,9 @@ fun parsePayto(paytoLine: String): Payto {
throw InvalidPaytoError("'${paytoLine}' is not payto")
}
val wireMethod = javaParsedUri.host
- if (wireMethod != "sepa") {
- throw InvalidPaytoError("Only SEPA is supported, not '$wireMethod'")
+ if (wireMethod != "iban") {
+ throw InvalidPaytoError("Only 'iban' is supported, not '$wireMethod'")
}
- val accountOwner = if (javaParsedUri.query != null) {
- val queryStringAsList = javaParsedUri.query.split("&")
- // admit only ONE parameter: receiver-name.
- if (queryStringAsList.size != 1) {
- throw InvalidPaytoError("'${paytoLine}' has unsupported query
string")
- }
- val splitParameter = queryStringAsList.first().split("=")
- if (splitParameter.first() != "receiver-name" &&
splitParameter.first() != "sender-name") {
- throw InvalidPaytoError("'${paytoLine}' has unsupported query
string")
- }
- splitParameter.last()
- } else null
-
val splitPath = javaParsedUri.path.split("/").filter { it.isNotEmpty() }
if (splitPath.size > 2) {
throw InvalidPaytoError("too many path segments in iban payto URI")
@@ -48,5 +54,23 @@ fun parsePayto(paytoLine: String): Payto {
val (iban, bic) = if (splitPath.size == 1) {
Pair(splitPath[0], null)
} else Pair(splitPath[1], splitPath[0])
- return Payto(iban = iban, bic = bic, name = accountOwner)
+
+ val params: List<Pair<String, String>>? = if (javaParsedUri.query != null)
{
+ val queryString: List<String> = javaParsedUri.query.split("&")
+ queryString.map {
+ val split = it.split("="); Pair(split[0], split[1])
+ }
+ } else null
+
+ val receiverName = getQueryParamOrNull("receiver-name", params)
+ val senderName = getQueryParamOrNull("sender-name", params)
+ if (receiverName != null && senderName != null) throw
InvalidPaytoError("URI had both sender and receiver")
+
+ return Payto(
+ iban = iban,
+ bic = bic,
+ amount = getQueryParamOrNull("amount", params),
+ message = getQueryParamOrNull("message", params),
+ name = listOf(receiverName, senderName).firstNotNullOfOrNull { it }
+ )
}
\ No newline at end of file
diff --git a/util/src/test/kotlin/PaytoTest.kt
b/util/src/test/kotlin/PaytoTest.kt
index 635966d..ebc031b 100644
--- a/util/src/test/kotlin/PaytoTest.kt
+++ b/util/src/test/kotlin/PaytoTest.kt
@@ -21,19 +21,21 @@ class PaytoTest {
}
try {
parsePayto(
-
"payto://iban/BIC123/IBAN123?receiver-name=The%20Name&address=house"
+
"payto:iban/BIC123/IBAN123?receiver-name=The%20Name&address=house"
)
} catch (e: InvalidPaytoError) {
println(e)
- println("more than one parameter isn't allowed")
+ println("'://' missing, invalid Payto")
}
try {
- parsePayto(
-
"payto:iban/BIC123/IBAN123?receiver-name=The%20Name&address=house"
- )
+
parsePayto("payto://iban/BIC123/IBAN123?sender-name=Foo&receiver-name=Foo")
+ } catch (e: InvalidPaytoError) {
+ println(e)
+ }
+ try {
+
parsePayto("payto://wrong/BIC123/IBAN123?sender-name=Foo&receiver-name=Foo")
} catch (e: InvalidPaytoError) {
println(e)
- println("'://' missing, invalid Payto")
}
}
@@ -43,5 +45,18 @@ class PaytoTest {
assert(withBic.iban == "IBAN123")
assert(withBic.bic == "BIC123")
assert(withBic.name == "The Name")
+ val complete =
parsePayto("payto://iban/BIC123/IBAN123?sender-name=The%20Name&amount=EUR:1&message=donation")
+ assert(withBic.iban == "IBAN123")
+ assert(withBic.bic == "BIC123")
+ assert(withBic.name == "The Name")
+ assert(complete.message == "donation")
+ assert(complete.amount == "EUR:1")
+ val withoutOptionals = parsePayto(
+ "payto://iban/IBAN123"
+ )
+ assert(withoutOptionals.bic == null)
+ assert(withoutOptionals.message == null)
+ assert(withoutOptionals.name == null)
+ assert(withoutOptionals.amount == null)
}
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated: extend Payto parser,
gnunet <=