commit ebc6454435ca01196c306d7fa1a446853ef25b38 parent bbcbfba4d21f97f3ef5b450f45d01bec6d06ebd1 Author: Antoine A <> Date: Tue, 12 Nov 2024 17:05:20 +0100 nexus: add software info into pain.001 messages Diffstat:
14 files changed, 38 insertions(+), 25 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/LibeufinBank.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/LibeufinBank.kt @@ -24,11 +24,11 @@ import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.options.versionOption import tech.libeufin.bank.BANK_CONFIG_SOURCE import tech.libeufin.common.CliConfigCmd -import tech.libeufin.common.getVersion +import tech.libeufin.common.VERSION class LibeufinBank : CliktCommand() { init { - versionOption(getVersion()) + versionOption(VERSION) subcommands(DbInit(), ChangePw(), CreateToken(), Serve(), CreateAccount(), EditAccount(), GC(), BenchPwh(), CliConfigCmd(BANK_CONFIG_SOURCE)) } diff --git a/common/src/main/kotlin/Config.kt b/common/src/main/kotlin/Config.kt @@ -29,8 +29,8 @@ import ch.qos.logback.core.util.Loader * Note: putting Sandbox and Nexus as Utils dependencies would result * into circular dependency. */ -fun getVersion(): String { - return Loader.getResource( +val VERSION: String by lazy { + Loader.getResource( "version.txt", ClassLoader.getSystemClassLoader() ).readText() } diff --git a/common/src/main/kotlin/helpers.kt b/common/src/main/kotlin/helpers.kt @@ -100,6 +100,8 @@ fun ByteArray.secureRand(): ByteArray { fun ByteArray.encodeHex(): String = HexFormat.of().formatHex(this) fun ByteArray.encodeUpHex(): String = HexFormat.of().withUpperCase().formatHex(this) fun ByteArray.encodeBase64(): String = Base64.getEncoder().encodeToString(this) +fun ByteArray.asUtf8(): String = this.toString(Charsets.UTF_8) +fun ByteArrayOutputStream.asUtf8(): String = this.toString(Charsets.UTF_8) /* ----- InputStream ----- */ @@ -128,7 +130,7 @@ fun InputStream.encodeBase64(): String { val encoded = Base64.getEncoder().wrap(w) transferTo(encoded) encoded.close() - return w.toString(Charsets.UTF_8) + return w.asUtf8() } /** Deflate an input stream */ @@ -139,6 +141,10 @@ fun InputStream.deflate(): DeflaterInputStream fun InputStream.inflate(): InflaterInputStream = InflaterInputStream(this) +/** Read an input stream as UTF8 text */ +fun InputStream.readText(): String + = this.reader().readText() + /* ----- Throwable ----- */ fun Throwable.fmt(): String = buildString { diff --git a/common/src/test/kotlin/ConfigTest.kt b/common/src/test/kotlin/ConfigTest.kt @@ -44,7 +44,7 @@ class ConfigTest { System.setOut(PrintStream(tmpOut)) val result = cmd.test("dump -c $configPath") System.setOut(prevOut) - val lastLog = tmpOut.toString(Charsets.UTF_8).substringAfterLast(" -- ").trimEnd('\n') + val lastLog = tmpOut.asUtf8().substringAfterLast(" -- ").trimEnd('\n') assertEquals(1, result.statusCode, lastLog) assertEquals(msg, lastLog, lastLog) } diff --git a/common/src/test/kotlin/CryptoUtilTest.kt b/common/src/test/kotlin/CryptoUtilTest.kt @@ -92,7 +92,7 @@ class CryptoUtilTest { 6E A6 0F 9F 76 11 FD 18 BE 2C E8 8B 21 03 A9 41 """.trimIndent() - val expectedHash = expectedHashStr.replace(" ", "").replace("\n", "").toByteArray(Charsets.UTF_8) + val expectedHash = expectedHashStr.replace(" ", "").replace("\n", "") val pub = CryptoUtil.RSAPublicFromComponents(moduloStr.decodeUpHex(), exponentStr.decodeUpHex()) @@ -102,9 +102,9 @@ class CryptoUtilTest { val pubHash = CryptoUtil.getEbicsPublicKeyHash(pub) println("our pubHash: ${pubHash.encodeUpHex()}") - println("expected pubHash: ${expectedHash.toString(Charsets.UTF_8)}") + println("expected pubHash: ${expectedHash}") - assertEquals(expectedHash.toString(Charsets.UTF_8), pubHash.encodeUpHex()) + assertEquals(expectedHash, pubHash.encodeUpHex()) } @Test diff --git a/nexus/sample/platform/gls_pain001.xml b/nexus/sample/platform/gls_pain001.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"><CstmrCdtTrfInitn><GrpHdr><MsgId>MESSAGE_ID</MsgId><CreDtTm>2024-09-09T00:00:00Z</CreDtTm><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><InitgPty><Nm>myname</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>NOTPROVIDED</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>false</BtchBookg><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>2024-09-09Z</Dt></ReqdExctnDt><Dbtr><Nm>myname</Nm></Dbtr><DbtrAcct><Id><IBAN>CH7789144474425692816</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>BIC</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><InstrId>TX_FIRST</InstrId><EndToEndId>TX_FIRST</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">42</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 42</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_SECOND</InstrId><EndToEndId>TX_SECOND</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">5.11</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 5.11</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_THIRD</InstrId><EndToEndId>TX_THIRD</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">0.21</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 0.21</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document> -\ No newline at end of file +<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"><CstmrCdtTrfInitn><GrpHdr><MsgId>MESSAGE_ID</MsgId><CreDtTm>2024-09-09T00:00:00Z</CreDtTm><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><InitgPty><Nm>myname</Nm></InitgPty><InitnSrc><Nm>LibEuFin</Nm><Prvdr>Taler Systems SA</Prvdr><Vrsn>VERSION</Vrsn></InitnSrc></GrpHdr><PmtInf><PmtInfId>NOTPROVIDED</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>false</BtchBookg><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>2024-09-09Z</Dt></ReqdExctnDt><Dbtr><Nm>myname</Nm></Dbtr><DbtrAcct><Id><IBAN>CH7789144474425692816</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>BIC</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><InstrId>TX_FIRST</InstrId><EndToEndId>TX_FIRST</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">42</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 42</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_SECOND</InstrId><EndToEndId>TX_SECOND</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">5.11</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 5.11</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_THIRD</InstrId><EndToEndId>TX_THIRD</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">0.21</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 0.21</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document> +\ No newline at end of file diff --git a/nexus/sample/platform/postfinance_pain001.xml b/nexus/sample/platform/postfinance_pain001.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"><CstmrCdtTrfInitn><GrpHdr><MsgId>MESSAGE_ID</MsgId><CreDtTm>2024-09-09T00:00:00Z</CreDtTm><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><InitgPty><Nm>myname</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>NOTPROVIDED</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>false</BtchBookg><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><PmtTpInf><SvcLvl><Cd>SDVA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>2024-09-09Z</Dt></ReqdExctnDt><Dbtr><Nm>myname</Nm></Dbtr><DbtrAcct><Id><IBAN>CH7789144474425692816</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>BIC</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><InstrId>TX_FIRST</InstrId><EndToEndId>TX_FIRST</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">42</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 42</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_SECOND</InstrId><EndToEndId>TX_SECOND</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">5.11</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 5.11</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_THIRD</InstrId><EndToEndId>TX_THIRD</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">0.21</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 0.21</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document> -\ No newline at end of file +<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"><CstmrCdtTrfInitn><GrpHdr><MsgId>MESSAGE_ID</MsgId><CreDtTm>2024-09-09T00:00:00Z</CreDtTm><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><InitgPty><Nm>myname</Nm></InitgPty><InitnSrc><Nm>LibEuFin</Nm><Prvdr>Taler Systems SA</Prvdr><Vrsn>VERSION</Vrsn></InitnSrc></GrpHdr><PmtInf><PmtInfId>NOTPROVIDED</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>false</BtchBookg><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><PmtTpInf><SvcLvl><Cd>SDVA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>2024-09-09Z</Dt></ReqdExctnDt><Dbtr><Nm>myname</Nm></Dbtr><DbtrAcct><Id><IBAN>CH7789144474425692816</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>BIC</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><InstrId>TX_FIRST</InstrId><EndToEndId>TX_FIRST</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">42</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 42</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_SECOND</InstrId><EndToEndId>TX_SECOND</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">5.11</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 5.11</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_THIRD</InstrId><EndToEndId>TX_THIRD</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">0.21</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 0.21</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document> +\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/LibeufinNexus.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/LibeufinNexus.kt @@ -26,7 +26,7 @@ import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.versionOption import com.github.ajalt.clikt.parameters.types.path import tech.libeufin.common.CliConfigCmd -import tech.libeufin.common.getVersion +import tech.libeufin.common.VERSION import tech.libeufin.nexus.NEXUS_CONFIG_SOURCE fun CliktCommand.ebicsLogOption() = option( @@ -43,7 +43,7 @@ fun CliktCommand.transientOption() = option( class LibeufinNexus : CliktCommand() { init { - versionOption(getVersion()) + versionOption(VERSION) subcommands(DbInit(), EbicsSetup(), EbicsSubmit(), EbicsFetch(), Serve(), InitiatePayment(), CliConfigCmd(NEXUS_CONFIG_SOURCE), TestingCmd()) } override fun run() = Unit diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt @@ -181,10 +181,10 @@ class EbicsDownload: CliktCommand("ebics-btd") { if (container == "ZIP") { stream.unzipEach { fileName, xmlContent -> println(fileName) - println(xmlContent.readBytes().toString(Charsets.UTF_8)) + println(xmlContent.readText()) } } else { - println(stream.readBytes().toString(Charsets.UTF_8)) + println(stream.readText()) } if (dryRun) throw DryRun() } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain001.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain001.kt @@ -72,6 +72,11 @@ fun createPain001( el("NbOfTxs", msg.txs.size.toString()) el("CtrlSum", totalAmount) el("InitgPty/Nm", msg.debtor.name) + el("InitnSrc") { + el("Nm", "LibEuFin") + el("Prvdr", "Taler Systems SA") + el("Vrsn", VERSION) + } } el("PmtInf") { el("PmtInfId", "NOTPROVIDED") diff --git a/nexus/src/test/kotlin/CliTest.kt b/nexus/src/test/kotlin/CliTest.kt @@ -20,6 +20,7 @@ import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import tech.libeufin.common.crypto.CryptoUtil +import tech.libeufin.common.asUtf8 import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.LibeufinNexus import java.io.ByteArrayOutputStream @@ -36,7 +37,7 @@ fun CliktCommand.testErr(cmd: String, msg: String) { System.setErr(PrintStream(tmpOut)) val result = test(cmd) System.setErr(prevOut) - val tmpStr = tmpOut.toString(Charsets.UTF_8) + val tmpStr = tmpOut.asUtf8() println(tmpStr) assertEquals(1, result.statusCode, "'$cmd' should have failed") val line = tmpStr.substringAfterLast(" - ").trimEnd('\n') diff --git a/nexus/src/test/kotlin/Iso20022Test.kt b/nexus/src/test/kotlin/Iso20022Test.kt @@ -65,9 +65,9 @@ class Iso20022Test { ) ) for (dialect in Dialect.entries) { - assertContentEquals( - Path("sample/platform/${dialect}_pain001.xml").readBytes(), - createPain001(msg, dialect) + assertEquals( + Path("sample/platform/${dialect}_pain001.xml").readText().replace("VERSION", VERSION), + createPain001(msg, dialect).asUtf8() ) } } diff --git a/nexus/src/test/kotlin/RegistrationTest.kt b/nexus/src/test/kotlin/RegistrationTest.kt @@ -174,9 +174,9 @@ class RegistrationTest { )) val msg = batchToPain001Msg(cfg.ebics.account, batch).copy(timestamp = dateToInstant("2024-09-09"),) for (dialect in Dialect.entries) { - assertContentEquals( - Path("sample/platform/${dialect}_pain001.xml").readBytes(), - createPain001(msg, dialect) + assertEquals( + Path("sample/platform/${dialect}_pain001.xml").readText().replace("VERSION", VERSION), + createPain001(msg, dialect).asUtf8() ) } } diff --git a/nexus/src/test/kotlin/XmlCombinatorsTest.kt b/nexus/src/test/kotlin/XmlCombinatorsTest.kt @@ -20,6 +20,7 @@ import org.w3c.dom.Document import org.junit.Test import tech.libeufin.nexus.* +import tech.libeufin.common.asUtf8 import kotlin.test.assertEquals class XmlCombinatorsTest { @@ -27,7 +28,7 @@ class XmlCombinatorsTest { val toBytes = XmlBuilder.toBytes(root, builder) val toDom = XmlBuilder.toDom(root, null, builder) //assertEquals(expected, toString) TODO fix empty tag being closed only with toString - assertEquals(expected, XMLUtil.convertDomToBytes(toDom).toString(Charsets.UTF_8)) + assertEquals(expected, XMLUtil.convertDomToBytes(toDom).asUtf8()) return toDom }