aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-01-08 14:52:09 +0000
committerAntoine A <>2024-01-08 14:52:09 +0000
commit6182bc939d9e0c4d15e4e1a6289c99898a2821dc (patch)
tree48152713c007703c1fa48129888b115c7b5c7e8a
parente18a3099745b17d51a7b85011f4fe2d743650ef2 (diff)
downloadlibeufin-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.conf2
-rw-r--r--integration/src/main/kotlin/Main.kt63
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt101
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt180
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt6
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt14
-rw-r--r--nexus/src/test/kotlin/PostFinance.kt10
-rw-r--r--util/src/main/kotlin/ebics_h005/Ebics3Request.kt9
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
}