diff options
author | Antoine A <> | 2024-01-08 14:52:09 +0000 |
---|---|---|
committer | Antoine A <> | 2024-01-08 14:52:09 +0000 |
commit | 6182bc939d9e0c4d15e4e1a6289c99898a2821dc (patch) | |
tree | 48152713c007703c1fa48129888b115c7b5c7e8a | |
parent | e18a3099745b17d51a7b85011f4fe2d743650ef2 (diff) | |
download | libeufin-6182bc939d9e0c4d15e4e1a6289c99898a2821dc.tar.gz libeufin-6182bc939d9e0c4d15e4e1a6289c99898a2821dc.tar.bz2 libeufin-6182bc939d9e0c4d15e4e1a6289c99898a2821dc.zip |
Semi automated test for postfinance ebics-fetch and, fix and improve fetch logic
-rw-r--r-- | integration/conf/postfinance.conf | 2 | ||||
-rw-r--r-- | integration/src/main/kotlin/Main.kt | 63 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt | 101 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt | 180 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt | 6 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt | 14 | ||||
-rw-r--r-- | nexus/src/test/kotlin/PostFinance.kt | 10 | ||||
-rw-r--r-- | util/src/main/kotlin/ebics_h005/Ebics3Request.kt | 9 |
8 files changed, 156 insertions, 229 deletions
diff --git a/integration/conf/postfinance.conf b/integration/conf/postfinance.conf index e01fdd26..71e47cfe 100644 --- a/integration/conf/postfinance.conf +++ b/integration/conf/postfinance.conf @@ -5,7 +5,7 @@ HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = test/postfinance/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/postfinance/client-keys.json #IBAN = CH2989144971918294289 -IBAN = CH9589144624243597634 +IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 diff --git a/integration/src/main/kotlin/Main.kt b/integration/src/main/kotlin/Main.kt index f6c9a890..c6cd0483 100644 --- a/integration/src/main/kotlin/Main.kt +++ b/integration/src/main/kotlin/Main.kt @@ -36,13 +36,6 @@ import kotlinx.coroutines.runBlocking import io.ktor.client.request.* import net.taler.wallet.crypto.Base32Crockford -fun CliktCommand.run(cmd: String) { - val result = test(cmd) - if (result.statusCode != 0) - throw Exception(result.output) - println(result.output) -} - fun randBytes(lenght: Int): ByteArray { val bytes = ByteArray(lenght) kotlin.random.Random.nextBytes(bytes) @@ -56,12 +49,19 @@ fun step(name: String) { println("\u001b[35m$name\u001b[0m") } +fun ask(question: String): String? { + println("\u001b[;1m$question\u001b[0m") + return readlnOrNull() +} + fun CliktCommandTestResult.assertOk(msg: String? = null) { assertEquals(0, statusCode, "msg\n$output") + println(output) } fun CliktCommandTestResult.assertErr(msg: String? = null) { assertEquals(1, statusCode, "msg\n$output") + println(output) } class PostFinanceCli : CliktCommand("Run tests on postfinance", name="postfinance") { @@ -76,8 +76,7 @@ class PostFinanceCli : CliktCommand("Run tests on postfinance", name="postfinanc var hasBankKeys = Files.exists(bankKeysPath) if (hasClientKeys || hasBankKeys) { - println("Reset keys ? y/n>") - if (readlnOrNull() == "y") { + if (ask("Reset keys ? y/n>") == "y") { if (hasClientKeys) Files.deleteIfExists(clientKeysPath) if (hasBankKeys) Files.deleteIfExists(bankKeysPath) hasClientKeys = false @@ -100,31 +99,37 @@ class PostFinanceCli : CliktCommand("Run tests on postfinance", name="postfinanc nexusCmd.test("ebics-setup --auto-accept-keys -c $conf") .assertOk("ebics-setup should succeed the second time") } - val payto = "payto://iban/CH2989144971918294289?receiver-name=Test" - - step("Test submit one transaction") - val nexusDb = NexusDb("postgresql:///libeufincheck") - nexusCmd.test("dbinit -r -c $conf").assertOk() - nexusDb.initiatedPaymentCreate(InitiatedPayment( - amount = NexusAmount(42L, 0, "CFH"), - creditPaytoUri = payto, - wireTransferSubject = "single transaction test", - initiationTime = Instant.now(), - requestUid = Base32Crockford.encode(randBytes(16)) - )) - nexusCmd.test("ebics-submit --transient -c $conf").assertOk() - - step("Test submit many transaction") - repeat(4) { - nexusDb.initiatedPaymentCreate(InitiatedPayment( - amount = NexusAmount(100L + it, 0, "CFH"), + + if (ask("Submit transactions ? y/n>") == "y") { + val payto = "payto://iban/CH2989144971918294289?receiver-name=Test" + + step("Test submit one transaction") + val nexusDb = NexusDb("postgresql:///libeufincheck") + nexusCmd.test("dbinit -r -c $conf").assertOk() + nexusDb.initiatedPaymentCreate(InitiatedPayment( + amount = NexusAmount(42L, 0, "CFH"), creditPaytoUri = payto, - wireTransferSubject = "multi transaction test $it", + wireTransferSubject = "single transaction test", initiationTime = Instant.now(), requestUid = Base32Crockford.encode(randBytes(16)) )) + nexusCmd.test("ebics-submit --transient -c $conf").assertOk() + + step("Test submit many transaction") + repeat(4) { + nexusDb.initiatedPaymentCreate(InitiatedPayment( + amount = NexusAmount(100L + it, 0, "CFH"), + creditPaytoUri = payto, + wireTransferSubject = "multi transaction test $it", + initiationTime = Instant.now(), + requestUid = Base32Crockford.encode(randBytes(16)) + )) + } + nexusCmd.test("ebics-submit --transient -c $conf").assertOk() } - nexusCmd.test("ebics-submit --transient -c $conf").assertOk() + + step("Test fetch transactions") + nexusCmd.test("ebics-fetch --transient -c $conf --pinned-start 2022-01-01").assertOk() step("Test succeed") } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt index d355c923..4d9d2d41 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt @@ -19,7 +19,6 @@ import java.time.ZoneId import java.util.UUID import kotlin.concurrent.fixedRateTimer import kotlin.io.path.createDirectories -import kotlin.system.exitProcess /** * Necessary data to perform a download. @@ -75,7 +74,7 @@ data class FetchContext( private suspend inline fun downloadHelper( ctx: FetchContext, lastExecutionTime: Instant? = null -): ByteArray? { +): ByteArray { val initXml = if (ctx.ebicsVersion == EbicsVersion.three) { createEbics3DownloadInitialization( ctx.cfg, @@ -112,7 +111,7 @@ private suspend inline fun downloadHelper( * bank side. A client with an unreliable bank is not useful, hence * failing here. */ - exitProcess(1) + throw e } } @@ -142,13 +141,12 @@ fun maybeLogFile( val subDir = "${asUtcDate.year}-${asUtcDate.monthValue}-${asUtcDate.dayOfMonth}" // Creating the combined dir. val dirs = Path.of(maybeLogDir, subDir) - doOrFail { dirs.createDirectories() } + dirs.createDirectories() fun maybeWrite(f: File, xml: String) { if (f.exists()) { - logger.error("Log file exists already at: ${f.path}") - exitProcess(1) + throw Exception("Log file exists already at: ${f.path}") } - doOrFail { f.writeText(xml) } + f.writeText(xml) } if (nonZip) { val f = File(dirs.toString(), "${now.toDbMicros()}_HAC_response.pain.002.xml") @@ -390,19 +388,8 @@ private fun ingestNotification( content.unzipForEach { fileName, xmlContent -> if (!fileName.contains("camt.054", ignoreCase = true)) throw Exception("Asked for notification but did NOT get a camt.054") - /** - * We ignore any camt.054 that does not bring Taler-relevant information, - * like camt.054-Credit, for example. - */ - if (!fileName.startsWith(filenamePrefixForIncoming) && - !fileName.startsWith(filenamePrefixForOutgoing)) { - logger.debug("Ignoring camt.054: $fileName") - return@unzipForEach - } - if (fileName.startsWith(filenamePrefixForIncoming)) - incomingPayments += parseIncomingTxNotif(xmlContent, ctx.cfg.currency) - else outgoingPayments += parseOutgoingTxNotif(xmlContent, ctx.cfg.currency) + parseTxNotif(xmlContent, ctx.cfg.currency, incomingPayments, outgoingPayments) } } catch (e: IOException) { logger.error("Could not open any ZIP archive") @@ -415,12 +402,14 @@ private fun ingestNotification( try { runBlocking { incomingPayments.forEach { + println(it) ingestIncomingPayment( db, it ) } outgoingPayments.forEach { + println(it) ingestOutgoingPayment(db, it) } } @@ -470,7 +459,7 @@ private suspend fun fetchDocuments( val lastExecutionTime: Instant? = ctx.pinnedStart ?: requestFrom logger.debug("Fetching ${ctx.whichDocument} from timestamp: $lastExecutionTime") // downloading the content - val maybeContent = downloadHelper(ctx, lastExecutionTime) ?: exitProcess(1) // client is wrong, failing. + val maybeContent = downloadHelper(ctx, lastExecutionTime) if (maybeContent.isEmpty()) return // logging, if the configuration wants. maybeLogFile( @@ -484,8 +473,7 @@ private suspend fun fetchDocuments( return } if (!ingestNotification(db, ctx, maybeContent)) { - logger.error("Ingesting notifications failed") - exitProcess(1) + throw Exception("Ingesting notifications failed") } } @@ -541,10 +529,8 @@ class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 noti * mode when no flags are passed to the invocation. * FIXME: reduce code duplication with the submit subcommand. */ - override fun run() { - val cfg: EbicsSetupConfig = doOrFail { - extractEbicsConfig(common.config) - } + override fun run() = cliCmd(logger) { + val cfg: EbicsSetupConfig = extractEbicsConfig(common.config) val dbCfg = cfg.config.extractDbConfigOrFail() val db = Database(dbCfg.dbConnStr) @@ -560,58 +546,37 @@ class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 noti val maybeStdin = generateSequence(::readLine).joinToString("\n") when(whichDoc) { SupportedDocument.CAMT_054 -> { - try { - val incomingTxs = parseIncomingTxNotif(maybeStdin, cfg.currency) - println(incomingTxs) - if (import) { - runBlocking { - incomingTxs.forEach { - ingestIncomingPayment(db, it) - } + val incomingTxs = mutableListOf<IncomingPayment>() + val outgoingTxs = mutableListOf<OutgoingPayment>() + + parseTxNotif(maybeStdin, cfg.currency, incomingTxs, outgoingTxs) + println(incomingTxs) + println(outgoingTxs) + if (import) { + runBlocking { + incomingTxs.forEach { + ingestIncomingPayment(db, it) } - } - } catch (e: WrongPaymentDirection) { - logger.info("Input doesn't contain incoming payments") - } catch (e: Exception) { - logger.error(e.message) - exitProcess(1) - } - try { - val outgoingTxs = parseOutgoingTxNotif(maybeStdin, cfg.currency) - println(outgoingTxs) - if (import) { - runBlocking { - outgoingTxs.forEach { - ingestOutgoingPayment(db, it) - } + outgoingTxs.forEach { + ingestOutgoingPayment(db, it) } } - } catch (e: WrongPaymentDirection) { - logger.debug("Input doesn't contain outgoing payments") - } catch (e: Exception) { - logger.error(e.message) - exitProcess(1) } } - else -> { - logger.error("Parsing $whichDoc not supported") - exitProcess(1) - } + else -> throw Error("Parsing $whichDoc not supported") } - return + return@cliCmd } // Fail now if keying is incomplete. - if (!isKeyingComplete(cfg)) exitProcess(1) - val bankKeys = loadBankKeys(cfg.bankPublicKeysFilename) ?: exitProcess(1) + if (!isKeyingComplete(cfg)) throw Error() + val bankKeys = loadBankKeys(cfg.bankPublicKeysFilename) ?: throw Error() if (!bankKeys.accepted && !import && !parse) { - logger.error("Bank keys are not accepted, yet. Won't fetch any records.") - exitProcess(1) + throw Error("Bank keys are not accepted, yet. Won't fetch any records.") } val clientKeys = loadPrivateKeysFromDisk(cfg.clientPrivateKeysFilename) if (clientKeys == null) { - logger.error("Client private keys not found at: ${cfg.clientPrivateKeysFilename}") - exitProcess(1) + throw Error("Client private keys not found at: ${cfg.clientPrivateKeysFilename}") } val ctx = FetchContext( @@ -639,12 +604,12 @@ class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 noti runBlocking { fetchDocuments(db, ctx) } - return + return@cliCmd } val frequency: NexusFrequency = doOrFail { val configValue = cfg.config.requireString("nexus-fetch", "frequency") val frequencySeconds = checkFrequency(configValue) - return@doOrFail NexusFrequency(frequencySeconds, configValue) + NexusFrequency(frequencySeconds, configValue) } logger.debug("Running with a frequency of ${frequency.fromConfig}") if (frequency.inSeconds == 0) { @@ -652,7 +617,7 @@ class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 noti runBlocking { fetchDocuments(db, ctx) } - return + return@cliCmd } fixedRateTimer( name = "ebics submit period", diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt index b14ecee9..70525b02 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt @@ -156,78 +156,22 @@ fun createPain001( } /** - * Thrown if the parser expects DBIT but the transaction - * is CRDT, and vice-versa. - */ -class WrongPaymentDirection(val msg: String) : Exception(msg) - -/** - * Parses a camt.054 document looking for outgoing payments. + * Searches payments in a camt.054 (Detailavisierung) document. * - * @param notifXml input document. + * @param notifXml camt.054 input document * @param acceptedCurrency currency accepted by Nexus - * @return the list of outgoing payments. + * @param incoming list of incoming payments + * @param outgoing list of outgoing payments */ -fun parseOutgoingTxNotif( +fun parseTxNotif( notifXml: String, acceptedCurrency: String, -): List<OutgoingPayment> { - val ret = mutableListOf<OutgoingPayment>() - notificationForEachTx(notifXml) { bookDate -> - requireUniqueChildNamed("CdtDbtInd") { - if (focusElement.textContent != "DBIT") - throw WrongPaymentDirection("The payment is not outgoing, won't parse it") - } - // Obtaining the amount. - val amount: TalerAmount = requireUniqueChildNamed("Amt") { - val currency = focusElement.getAttribute("Ccy") - if (currency != acceptedCurrency) throw Exception("Currency $currency not supported") - getTalerAmount(focusElement.textContent, currency) - } - - /** - * The MsgId extracted in the block below matches the one that - * was specified as the MsgId element in the pain.001 that originated - * this outgoing payment. MsgId is considered unique because the - * bank enforces its uniqueness. Associating MsgId to this outgoing - * payment is also convenient to match its initiated outgoing payment - * in the database for reconciliation. - */ - val uidFromBank = StringBuilder() - requireUniqueChildNamed("Refs") { - requireUniqueChildNamed("MsgId") { - uidFromBank.append(focusElement.textContent) - } - } - - ret.add( - OutgoingPayment( - amount = amount, - bankTransferId = uidFromBank.toString(), - executionTime = bookDate - ) - ) - } - return ret -} - -/** - * Searches incoming payments in a camt.054 (Detailavisierung) document. - * - * @param notifXml camt.054 input document - * @param acceptedCurrency currency accepted by Nexus. - * @return the list of incoming payments to ingest in the database. - */ -fun parseIncomingTxNotif( - notifXml: String, - acceptedCurrency: String -): List<IncomingPayment> { - val ret = mutableListOf<IncomingPayment>() + incoming: MutableList<IncomingPayment>, + outgoing: MutableList<OutgoingPayment> +) { notificationForEachTx(notifXml) { bookDate -> - // Check the direction first. - requireUniqueChildNamed("CdtDbtInd") { - if (focusElement.textContent != "CRDT") - throw WrongPaymentDirection("The payment is not incoming, won't parse it") + val kind = requireUniqueChildNamed("CdtDbtInd") { + focusElement.textContent } val amount: TalerAmount = requireUniqueChildNamed("Amt") { val currency = focusElement.getAttribute("Ccy") @@ -237,52 +181,80 @@ fun parseIncomingTxNotif( if (currency != acceptedCurrency) throw Exception("Currency $currency not supported") getTalerAmount(focusElement.textContent, currency) } - // Obtaining payment UID. - val uidFromBank: String = requireUniqueChildNamed("Refs") { - requireUniqueChildNamed("AcctSvcrRef") { - focusElement.textContent - } - } - // Obtaining payment subject. - val subject = StringBuilder() - requireUniqueChildNamed("RmtInf") { - this.mapEachChildNamed("Ustrd") { - val piece = this.focusElement.textContent - subject.append(piece) - } - } + when (kind) { + "CRDT" -> { + // Obtaining payment UID. + val uidFromBank: String = requireUniqueChildNamed("Refs") { + requireUniqueChildNamed("AcctSvcrRef") { + focusElement.textContent + } + } + // Obtaining payment subject. + val subject = StringBuilder() + requireUniqueChildNamed("RmtInf") { + this.mapEachChildNamed("Ustrd") { + val piece = this.focusElement.textContent + subject.append(piece) + } + } - // Obtaining the payer's details - val debtorPayto = StringBuilder("payto://iban/") - requireUniqueChildNamed("RltdPties") { - requireUniqueChildNamed("DbtrAcct") { - requireUniqueChildNamed("Id") { - requireUniqueChildNamed("IBAN") { - debtorPayto.append(focusElement.textContent) + // Obtaining the payer's details + val debtorPayto = StringBuilder("payto://iban/") + requireUniqueChildNamed("RltdPties") { + requireUniqueChildNamed("DbtrAcct") { + requireUniqueChildNamed("Id") { + requireUniqueChildNamed("IBAN") { + debtorPayto.append(focusElement.textContent) + } + } + } + // warn: it might need the postal address too.. + requireUniqueChildNamed("Dbtr") { + requireUniqueChildNamed("Pty") { + requireUniqueChildNamed("Nm") { + val urlEncName = URLEncoder.encode(focusElement.textContent, "utf-8") + debtorPayto.append("?receiver-name=$urlEncName") + } + } } } + incoming.add( + IncomingPayment( + amount = amount, + bankTransferId = uidFromBank, + debitPaytoUri = debtorPayto.toString(), + executionTime = bookDate, + wireTransferSubject = subject.toString() + ) + ) } - // warn: it might need the postal address too.. - requireUniqueChildNamed("Dbtr") { - requireUniqueChildNamed("Pty") { - requireUniqueChildNamed("Nm") { - val urlEncName = URLEncoder.encode(focusElement.textContent, "utf-8") - debtorPayto.append("?receiver-name=$urlEncName") + "DBIT" -> { + /** + * The MsgId extracted in the block below matches the one that + * was specified as the MsgId element in the pain.001 that originated + * this outgoing payment. MsgId is considered unique because the + * bank enforces its uniqueness. Associating MsgId to this outgoing + * payment is also convenient to match its initiated outgoing payment + * in the database for reconciliation. + */ + val uidFromBank = StringBuilder() + requireUniqueChildNamed("Refs") { + requireUniqueChildNamed("MsgId") { + uidFromBank.append(focusElement.textContent) } } + + outgoing.add( + OutgoingPayment( + amount = amount, + bankTransferId = uidFromBank.toString(), + executionTime = bookDate + ) + ) } - } - ret.add( - IncomingPayment( - amount = amount, - bankTransferId = uidFromBank, - debitPaytoUri = debtorPayto.toString(), - executionTime = bookDate, - wireTransferSubject = subject.toString() - ) - ) + else -> throw Exception("Unknown transaction notification kind '$kind'") + } } - return ret } /** diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt index e8705f85..e1ef647d 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt @@ -60,7 +60,7 @@ suspend fun doEbicsCustomDownload( clientKeys: ClientPrivateKeysFile, bankKeys: BankPublicKeysFile, client: HttpClient -): ByteArray? { +): ByteArray { val xmlReq = createEbics25DownloadInit(cfg, clientKeys, bankKeys, messageType) return doEbicsDownload(client, cfg, clientKeys, bankKeys, xmlReq, false) } @@ -85,10 +85,6 @@ suspend fun fetchBankAccounts( ): HTDResponseOrderData? { val xmlReq = createEbics25DownloadInit(cfg, clientKeys, bankKeys, "HTD") val bytesResp = doEbicsDownload(client, cfg, clientKeys, bankKeys, xmlReq, false) - if (bytesResp == null) { - logger.error("EBICS HTD transaction failed.") - return null - } val xmlResp = bytesResp.toString(Charsets.UTF_8) return try { logger.debug("Fetched accounts: $bytesResp") diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt index cb0e6a63..615e5a2b 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt @@ -332,20 +332,18 @@ suspend fun doEbicsDownload( reqXml: String, isEbics3: Boolean, tolerateEmptyResult: Boolean = false -): ByteArray? { +): ByteArray { val initResp = postEbics(client, cfg, bankKeys, reqXml, isEbics3) logger.debug("Download init phase done. EBICS- and bank-technical codes are: ${initResp.technicalReturnCode}, ${initResp.bankReturnCode}") if (initResp.technicalReturnCode != EbicsReturnCode.EBICS_OK) { - logger.error("Download init phase has EBICS-technical error: ${initResp.technicalReturnCode}") - return null + throw Error("Download init phase has EBICS-technical error: ${initResp.technicalReturnCode}") } if (initResp.bankReturnCode == EbicsReturnCode.EBICS_NO_DOWNLOAD_DATA_AVAILABLE && tolerateEmptyResult) { logger.info("Download content is empty") return ByteArray(0) } if (initResp.bankReturnCode != EbicsReturnCode.EBICS_OK) { - logger.error("Download init phase has bank-technical error: ${initResp.bankReturnCode}") - return null + throw Error("Download init phase has bank-technical error: ${initResp.bankReturnCode}") } val tId = initResp.transactionID ?: throw EbicsSideException( @@ -355,8 +353,7 @@ suspend fun doEbicsDownload( logger.debug("EBICS download transaction passed the init phase, got ID: $tId") val howManySegments = initResp.numSegments if (howManySegments == null) { - tech.libeufin.nexus.logger.error("Init response lacks the quantity of segments, failing.") - return null + throw Error("Init response lacks the quantity of segments, failing.") } val ebicsChunks = mutableListOf<String>() // Getting the chunk(s) @@ -388,8 +385,7 @@ suspend fun doEbicsDownload( } val chunk = transResp.orderDataEncChunk if (chunk == null) { - tech.libeufin.nexus.logger.error("EBICS transfer phase lacks chunk #$x, failing.") - return null + throw Error("EBICS transfer phase lacks chunk #$x, failing.") } ebicsChunks.add(chunk) } diff --git a/nexus/src/test/kotlin/PostFinance.kt b/nexus/src/test/kotlin/PostFinance.kt index c2ecdd55..860e8ef0 100644 --- a/nexus/src/test/kotlin/PostFinance.kt +++ b/nexus/src/test/kotlin/PostFinance.kt @@ -30,7 +30,7 @@ class Iso20022 { @Test // asks a pain.002, links with pain.001's MsgId fun getAck() { download(prepAckRequest3(startDate = yesterday) - )?.unzipForEach { name, content -> + ).unzipForEach { name, content -> println(name) println(content) } @@ -43,7 +43,7 @@ class Iso20022 { @Test fun getStatement() { val inflatedBytes = download(prepStatementRequest3()) - inflatedBytes?.unzipForEach { name, content -> + inflatedBytes.unzipForEach { name, content -> println(name) println(content) } @@ -57,7 +57,7 @@ class Iso20022 { isAppendix = true ) ) - inflatedBytes?.unzipForEach { name, content -> + inflatedBytes.unzipForEach { name, content -> println(name) println(content) } @@ -68,7 +68,7 @@ class Iso20022 { */ @Test fun getReport() { - download(prepReportRequest3(yesterday))?.unzipForEach { name, content -> + download(prepReportRequest3(yesterday)).unzipForEach { name, content -> println(name) println(content) } @@ -108,7 +108,7 @@ class Iso20022 { } } - fun download(req: Ebics3Request.OrderDetails.BTOrderParams): ByteArray? { + fun download(req: Ebics3Request.OrderDetails.BTOrderParams): ByteArray { val cfg = prep() val bankKeys = loadBankKeys(cfg.bankPublicKeysFilename)!! val myKeys = loadPrivateKeysFromDisk(cfg.clientPrivateKeysFilename)!! diff --git a/util/src/main/kotlin/ebics_h005/Ebics3Request.kt b/util/src/main/kotlin/ebics_h005/Ebics3Request.kt index f539fa96..b8fce965 100644 --- a/util/src/main/kotlin/ebics_h005/Ebics3Request.kt +++ b/util/src/main/kotlin/ebics_h005/Ebics3Request.kt @@ -198,18 +198,11 @@ class Ebics3Request { } @XmlAccessorType(XmlAccessType.NONE) + @XmlType(propOrder = ["service", "dateRange"]) class BTOrderParams { @get:XmlElement(name = "Service", required = true) lateinit var service: Service - /** - * This element activates the ES signature scheme (disabling - * hence the EDS). It *would* admit a @requestEDS attribute, - * but its omission means false. - */ - @get:XmlElement(name = "SignatureFlag", required = true) - var signatureFlag: Boolean = true - @get:XmlElement(name = "DateRange", required = true) var dateRange: DateRange? = null } |