libeufin

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

commit 9d15c7304e3eaea5c98373c8ed465c824203e56d
parent c553a2991ec6aeb910351658092cef1762e413d2
Author: MS <ms@taler.net>
Date:   Fri, 17 Nov 2023 17:37:49 +0100

nexus fetch: removing noise around payment subject

Diffstat:
Mnexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt | 23++++++++++++++++++++++-
Mnexus/src/test/kotlin/Parsing.kt | 47+++++++++++++++++++++++++++++++++++++++++++----
Mutil/src/main/kotlin/strings.kt | 12------------
3 files changed, 65 insertions(+), 17 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt @@ -329,6 +329,10 @@ data class OutgoingPaymentWithLink( val initiatedPaymentLink: String ) +/** + * Collects incoming and outgoing payments which are + * the result of parsing one camt.054 notification. + */ data class Camt054Result( val incoming: MutableList<IncomingPayment> = mutableListOf(), val outgoing: MutableList<OutgoingPaymentWithLink> = mutableListOf() @@ -403,6 +407,21 @@ fun isReservePub(maybeReservePub: String): ByteArray? { } return dec } + +/** + * Extract the part of the subject that might represent a + * valid Taler reserve public key. That addresses some bank + * policies of adding extra information around the payment + * subject. + * + * @param subject raw subject as read from the bank. + */ +fun removeSubjectNoise(subject: String): String? { + val re = "\\b[a-z0-9A-Z]{52}\\b".toRegex() + val result = re.find(subject.replace("[\n]+".toRegex(), "")) ?: return null + return result.value +} + /** * Checks the two conditions that may invalidate one incoming * payment: subject validity and availability. @@ -416,8 +435,10 @@ suspend fun getTalerReservePub( db: Database, payment: IncomingPayment ): ByteArray? { + // Removing noise around the potential reserve public key. + val maybeReservePub = removeSubjectNoise(payment.wireTransferSubject) ?: return null // Checking validity first. - val dec = isReservePub(payment.wireTransferSubject) ?: return null + val dec = isReservePub(maybeReservePub) ?: return null // Now checking availability. val maybeUnavailable = db.isReservePubFound(dec) if (maybeUnavailable) { diff --git a/nexus/src/test/kotlin/Parsing.kt b/nexus/src/test/kotlin/Parsing.kt @@ -1,9 +1,6 @@ import org.junit.Test import org.junit.jupiter.api.assertThrows -import tech.libeufin.nexus.TalerAmount -import tech.libeufin.nexus.getAmountNoCurrency -import tech.libeufin.nexus.getTalerAmount -import tech.libeufin.nexus.isReservePub +import tech.libeufin.nexus.* import tech.libeufin.util.parseBookDate import tech.libeufin.util.parseCamtTime import java.lang.StringBuilder @@ -24,6 +21,48 @@ class Parsing { @Test fun bookDateTest() { parseBookDate("1970-01-01") + assertThrows<Exception> { parseBookDate("1970-01-01T00:00:01Z") } + } + + @Test + fun reservePublicKey() { + assertNull(removeSubjectNoise("does not contain any reserve")) + // 4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0 + assertNotNull(removeSubjectNoise("4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0")) + assertEquals( + "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0", + removeSubjectNoise( + "noise 4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0 noise" + ) + ) + assertEquals( + "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0", + removeSubjectNoise( + "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0 noise to the right" + ) + ) + assertEquals( + "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0", + removeSubjectNoise( + "noise to the left 4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0" + ) + ) + assertEquals( + "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0", + removeSubjectNoise( + " 4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0 " + ) + ) + assertEquals( + "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0", + removeSubjectNoise(""" + noise + 4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0 + noise + """) + ) + // Got the first char removed. + assertNull(removeSubjectNoise("MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0")) } @Test // Could be moved in a dedicated Amounts.kt test module. diff --git a/util/src/main/kotlin/strings.kt b/util/src/main/kotlin/strings.kt @@ -83,15 +83,3 @@ fun getQueryParam(uriQueryString: String, param: String): String? { return null } -fun extractReservePubFromSubject(rawSubject: String): String? { - val re = "\\b[a-z0-9A-Z]{52}\\b".toRegex() - val result = re.find(rawSubject.replace("[\n]+".toRegex(), "")) ?: return null - try { - Base32Crockford.decode(result.value) - } catch (e: Exception) { - logger.debug("Not containing a reserve pub: $rawSubject") - return null - } - return result.value.uppercase() -} -