commit bfd94d8055b3b154a45744e8b9a289bce7bc38fa
parent eaeb60386b9b2d04695f8c8c84ee6079b4cd1a86
Author: MS <ms@taler.net>
Date: Mon, 28 Nov 2022 14:15:38 +0100
logging
Diffstat:
8 files changed, 220 insertions(+), 180 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -88,7 +88,7 @@ class Serve : CliktCommand("Run nexus HTTP server") {
}
}
-class ParseCamt : CliktCommand("Parse a camt file") {
+class ParseCamt : CliktCommand("Parse CAMT file, outputs JSON in libEufin internal representation.") {
private val logLevel by option()
private val filename by argument("FILENAME", "File in CAMT format")
override fun run() {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -149,7 +149,6 @@ data class CamtTransactionsCount(
fun processCamtMessage(
bankAccountId: String, camtDoc: Document, code: String
): CamtTransactionsCount {
- logger.info("processing CAMT message")
var newTransactions = 0
var downloadedTransactions = 0
transaction {
@@ -371,7 +370,10 @@ suspend fun fetchBankAccountTransactions(
val connectionName = conn.connectionId
}
}
- // abstracts over the connection type: ebics or others.
+ /**
+ * Collects transactions from the bank and stores the (camt)
+ * document into the database.
+ */
getConnectionPlugin(res.connectionType).fetchTransactions(
fetchSpec,
client,
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
@@ -121,9 +121,9 @@ suspend fun doEbicsDownloadTransaction(
val transactionID =
initResponse.transactionID ?: throw NexusError(
HttpStatusCode.InternalServerError,
- "initial response must contain transaction ID"
+ "Initial response must contain transaction ID"
)
-
+ logger.debug("Bank acknowledges EBICS download initialization. Transaction ID: $transactionID.")
val encryptionInfo = initResponse.dataEncryptionInfo
?: throw NexusError(HttpStatusCode.InternalServerError, "initial response did not contain encryption info")
@@ -139,10 +139,10 @@ suspend fun doEbicsDownloadTransaction(
?: throw NexusError(HttpStatusCode.FailedDependency, "missing segment number in EBICS download init response")
// Transfer phase
-
for (x in 2 .. numSegments) {
val transferReqStr =
createEbicsRequestForDownloadTransferPhase(subscriberDetails, transactionID, x, numSegments)
+ logger.debug("EBICS download transfer phase of ${transactionID}: sending segment $x")
val transferResponseStr = client.postToBank(subscriberDetails.ebicsUrl, transferReqStr)
val transferResponse = parseAndValidateEbicsResponse(subscriberDetails, transferResponseStr)
when (transferResponse.technicalReturnCode) {
@@ -171,6 +171,7 @@ suspend fun doEbicsDownloadTransaction(
"transfer response for download transaction does not contain data transfer"
)
payloadChunks.add(transferOrderDataEncChunk)
+ logger.debug("Download transfer phase of ${transactionID}: bank acknowledges $x")
}
val respPayload = decryptAndDecompressResponse(subscriberDetails, encryptionInfo, payloadChunks)
@@ -193,10 +194,13 @@ suspend fun doEbicsDownloadTransaction(
)
}
}
+ logger.debug("Bank acknowledges EBICS download receipt. Transaction ID: $transactionID.")
return EbicsDownloadSuccessResult(respPayload)
}
-
+/**
+ * Currently only 1-segment requests.
+ */
suspend fun doEbicsUploadTransaction(
client: HttpClient,
subscriberDetails: EbicsClientSubscriberDetails,
@@ -221,8 +225,7 @@ suspend fun doEbicsUploadTransaction(
HttpStatusCode.InternalServerError,
"init response must have transaction ID"
)
-
- logger.debug("INIT phase passed!")
+ logger.debug("Bank acknowledges EBICS upload initialization. Transaction ID: $transactionID.")
/* now send actual payload */
val payload = createEbicsRequestForUploadTransferPhase(
@@ -231,14 +234,12 @@ suspend fun doEbicsUploadTransaction(
preparedUploadData,
0
)
-
val txRespStr = client.postToBank(
subscriberDetails.ebicsUrl,
payload
)
val txResp = parseAndValidateEbicsResponse(subscriberDetails, txRespStr)
-
when (txResp.technicalReturnCode) {
EbicsReturnCode.EBICS_OK -> {
}
@@ -248,6 +249,7 @@ suspend fun doEbicsUploadTransaction(
)
}
}
+ logger.debug("Bank acknowledges EBICS upload transfer. Transaction ID: $transactionID")
}
suspend fun doEbicsHostVersionQuery(client: HttpClient, ebicsBaseUrl: String, ebicsHostId: String): EbicsHevDetails {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -73,7 +73,7 @@ private data class EbicsFetchSpec(
fun storeCamt(bankConnectionId: String, camt: String, historyType: String) {
val camt53doc = XMLUtil.parseStringIntoDom(camt)
val msgId = camt53doc.pickStringWithRootNs("/*[1]/*[1]/root:GrpHdr/root:MsgId")
- logger.info("msg id $msgId")
+ logger.info("camt document '$msgId' received.")
transaction {
val conn = NexusBankConnectionEntity.findByName(bankConnectionId)
if (conn == null) {
@@ -102,7 +102,6 @@ private suspend fun fetchEbicsC5x(
orderParams: EbicsOrderParams,
subscriberDetails: EbicsClientSubscriberDetails
) {
- logger.debug("Requesting $historyType")
val response = try {
doEbicsDownloadTransaction(
client,
@@ -529,6 +528,7 @@ class EbicsBankConnectionProtocol: BankConnectionProtocol {
messageId = paymentInitiation.messageId
)
)
+ logger.debug("Sending Pain.001: ${paymentInitiation.paymentInformationId}")
if (!XMLUtil.validateFromString(painMessage)) throw NexusError(
HttpStatusCode.InternalServerError, "Pain.001 message is invalid."
)
diff --git a/nexus/src/test/kotlin/DownloadAndSubmit.kt b/nexus/src/test/kotlin/DownloadAndSubmit.kt
@@ -0,0 +1,150 @@
+import io.ktor.application.*
+import io.ktor.client.*
+import io.ktor.client.request.*
+import io.ktor.features.*
+import io.ktor.http.*
+import io.ktor.request.*
+import io.ktor.response.*
+import io.ktor.routing.*
+import io.ktor.server.testing.*
+import kotlinx.coroutines.runBlocking
+import org.jetbrains.exposed.sql.transactions.transaction
+import org.junit.Ignore
+import org.junit.Test
+import org.w3c.dom.Document
+import tech.libeufin.nexus.*
+import tech.libeufin.nexus.bankaccount.addPaymentInitiation
+import tech.libeufin.nexus.bankaccount.fetchBankAccountTransactions
+import tech.libeufin.nexus.ebics.EbicsBankConnectionProtocol
+import tech.libeufin.nexus.server.FetchLevel
+import tech.libeufin.nexus.server.FetchSpecAllJson
+import tech.libeufin.nexus.server.FetchSpecJson
+import tech.libeufin.nexus.server.Pain001Data
+import tech.libeufin.sandbox.*
+import tech.libeufin.util.*
+import tech.libeufin.util.ebics_h004.EbicsRequest
+import tech.libeufin.util.ebics_h004.EbicsResponse
+import tech.libeufin.util.ebics_h004.EbicsTypes
+
+/**
+ * This source is NOT a test case -- as it uses no assertions --
+ * but merely a tool to download and submit payments to the bank
+ * via Nexus.
+ * /
+
+ */
+/**
+ * Data to make the test server return for EBICS
+ * phases. Currently only init is supported.
+ */
+data class EbicsResponses(
+ val init: String,
+ val download: String? = null,
+ val receipt: String? = null
+)
+
+/**
+ * Minimal server responding always the 'init' field of a EbicsResponses
+ * object along a download EBICS message. Suitable to set arbitrary data
+ * in said response. Signs the response assuming the client is the one
+ * created a MakeEnv.kt.
+ */
+fun getCustomEbicsServer(r: EbicsResponses, endpoint: String = "/ebicsweb"): Application.() -> Unit {
+ val ret: Application.() -> Unit = {
+ install(ContentNegotiation) {
+ register(ContentType.Text.Xml, XMLEbicsConverter())
+ register(ContentType.Text.Plain, XMLEbicsConverter())
+ }
+ routing {
+ post(endpoint) {
+ val requestDocument = this.call.receive<Document>()
+ val req = requestDocument.toObject<EbicsRequest>()
+ val clientKey = CryptoUtil.loadRsaPublicKey(userKeys.enc.public.encoded)
+ val msgId = EbicsOrderUtil.generateTransactionId()
+ val resp: EbicsResponse = if (
+ req.header.mutable.transactionPhase == EbicsTypes.TransactionPhaseType.INITIALISATION
+ ) {
+ val payload = prepareEbicsPayload(r.init, clientKey)
+ EbicsResponse.createForDownloadInitializationPhase(
+ msgId,
+ 1,
+ 4096,
+ payload.second, // for key material
+ payload.first // actual payload
+ )
+ } else {
+ // msgId doesn't have to match the one used for the init phase.
+ EbicsResponse.createForDownloadReceiptPhase(msgId, true)
+ }
+ val sigEbics = XMLUtil.signEbicsResponse(
+ resp,
+ CryptoUtil.loadRsaPrivateKey(bankKeys.auth.private.encoded)
+ )
+ call.respond(sigEbics)
+ }
+ }
+ }
+ return ret
+}
+
+/**
+ * Remove @Ignore, after having put asserts along tests,
+ * and having had access to runTask and TaskSchedule, that
+ * are now 'private'.
+ */
+// @Ignore
+class SchedulingTest {
+ /**
+ * Instruct the server to return invalid CAMT content.
+ */
+ @Test
+ fun download() {
+ withNexusAndSandboxUser {
+ withTestApplication(sandboxApp) {
+ val conn = EbicsBankConnectionProtocol()
+ runBlocking {
+ conn.fetchTransactions(
+ fetchSpec = FetchSpecAllJson(
+ level = FetchLevel.REPORT,
+ "foo"
+ ),
+ client,
+ "foo",
+ "mock-bank-account"
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun upload() {
+ withNexusAndSandboxUser {
+ withTestApplication(sandboxApp) {
+ val conn = EbicsBankConnectionProtocol()
+ runBlocking {
+ // Create Pain.001 to be submitted.
+ addPaymentInitiation(
+ Pain001Data(
+ creditorIban = getIban(),
+ creditorBic = "SANDBOXX",
+ creditorName = "Tester",
+ subject = "test payment",
+ sum = Amount(1),
+ currency = "TESTKUDOS"
+ ),
+ transaction {
+ NexusBankAccountEntity.findByName(
+ "mock-bank-account"
+ ) ?: throw Exception("Test failed")
+ }
+ )
+ conn.submitPaymentInitiation(
+ client,
+ 1L
+ )
+ }
+ }
+ }
+ }
+}
+\ No newline at end of file
diff --git a/nexus/src/test/kotlin/SchedulingTest.kt b/nexus/src/test/kotlin/SchedulingTest.kt
@@ -1,142 +0,0 @@
-import io.ktor.application.*
-import io.ktor.features.*
-import io.ktor.http.*
-import io.ktor.request.*
-import io.ktor.response.*
-import io.ktor.routing.*
-import io.ktor.server.testing.*
-import kotlinx.coroutines.runBlocking
-import org.junit.Ignore
-import org.junit.Test
-import org.w3c.dom.Document
-import tech.libeufin.nexus.*
-import tech.libeufin.sandbox.*
-import tech.libeufin.util.*
-import tech.libeufin.util.ebics_h004.EbicsRequest
-import tech.libeufin.util.ebics_h004.EbicsResponse
-import tech.libeufin.util.ebics_h004.EbicsTypes
-
-
-/**
- * Data to make the test server return for EBICS
- * phases. Currently only init is supported.
- */
-data class EbicsResponses(
- val init: String,
- val download: String? = null,
- val receipt: String? = null
-)
-
-/**
- * Minimal server responding always the 'init' field of a EbicsResponses
- * object along a download EBICS message. Suitable to set arbitrary data
- * in said response. Signs the response assuming the client is the one
- * created a MakeEnv.kt.
- */
-fun getCustomEbicsServer(r: EbicsResponses, endpoint: String = "/ebicsweb"): Application.() -> Unit {
- val ret: Application.() -> Unit = {
- install(ContentNegotiation) {
- register(ContentType.Text.Xml, XMLEbicsConverter())
- register(ContentType.Text.Plain, XMLEbicsConverter())
- }
- routing {
- post(endpoint) {
- val requestDocument = this.call.receive<Document>()
- val req = requestDocument.toObject<EbicsRequest>()
- val clientKey = CryptoUtil.loadRsaPublicKey(userKeys.enc.public.encoded)
- val msgId = EbicsOrderUtil.generateTransactionId()
- val resp: EbicsResponse = if (
- req.header.mutable.transactionPhase == EbicsTypes.TransactionPhaseType.INITIALISATION
- ) {
- val payload = prepareEbicsPayload(r.init, clientKey)
- EbicsResponse.createForDownloadInitializationPhase(
- msgId,
- 1,
- 4096,
- payload.second, // for key material
- payload.first // actual payload
- )
- } else {
- // msgId doesn't have to match the one used for the init phase.
- EbicsResponse.createForDownloadReceiptPhase(msgId, true)
- }
- val sigEbics = XMLUtil.signEbicsResponse(
- resp,
- CryptoUtil.loadRsaPrivateKey(bankKeys.auth.private.encoded)
- )
- call.respond(sigEbics)
- }
- }
- }
- return ret
-}
-
-/**
- * Remove @Ignore, after having put asserts along tests,
- * and having had access to runTask and TaskSchedule, that
- * are now 'private'.
- */
-@Ignore
-class SchedulingTest {
- /**
- * Instruct the server to return invalid CAMT content.
- */
- @Test
- fun inject() {
- withNexusAndSandboxUser {
- val payload = """
- Invalid Camt Document
- """.trimIndent()
- withTestApplication(
- getCustomEbicsServer(EbicsResponses(payload))
- ) {
- runBlocking {
- runTask(
- client,
- TaskSchedule(
- 0L,
- "test-schedule",
- "fetch",
- "bank-account",
- "mock-bank-account",
- params = "{\"level\":\"report\",\"rangeType\":\"all\"}"
- )
- )
- }
- }
- }
- }
- /**
- * Create two payments and asks for C52.
- */
- @Test
- fun ordinary() {
- withNexusAndSandboxUser { // DB prep
- for (t in 1 .. 2) {
- wireTransfer(
- "bank",
- "foo",
- "default",
- "1HJX78AH7WAGBDJTCXJ4JKX022DBCHERA051KH7D3EC48X09G4RG",
- "TESTKUDOS:5",
- "xxx"
- )
- }
- withTestApplication(sandboxApp) {
- runBlocking {
- runTask(
- client,
- TaskSchedule(
- 0L,
- "test-schedule",
- "fetch",
- "bank-account",
- "mock-bank-account",
- params = "{\"level\":\"report\",\"rangeType\":\"all\"}"
- )
- )
- }
- }
- }
- }
-}
-\ No newline at end of file
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
@@ -544,17 +544,19 @@ private fun constructCamtResponse(
baseBalance = lastBalance
)
+ val camtData = buildCamtString(
+ type,
+ bankAccount.iban,
+ history,
+ balancePrcd = lastBalance,
+ balanceClbd = freshBalance
+ )
+ logger.debug("camt.052 document '${camtData.messageId}' generated.")
return listOf(
- buildCamtString(
- type,
- bankAccount.iban,
- history,
- balancePrcd = lastBalance,
- balanceClbd = freshBalance
- ).camtMessage
+ camtData.camtMessage
)
}
- SandboxAssert(type == 53, "Didn't catch unsupported Camt type")
+ SandboxAssert(type == 53, "Didn't catch unsupported CAMT type")
logger.debug("Finding C$type records")
/**
@@ -569,7 +571,7 @@ private fun constructCamtResponse(
* time range given as a function's parameter.
*/
if (dateRange != null) {
- logger.debug("Querying c$type with date range: $dateRange")
+ logger.debug("Querying C$type with date range: $dateRange")
BankAccountStatementEntity.find {
BankAccountStatementsTable.creationTime.between(
dateRange.first,
@@ -696,8 +698,8 @@ private fun parsePain001(paymentRequest: String): PainParseResult {
* Process a payment request in the pain.001 format.
*/
private fun handleCct(paymentRequest: String) {
- logger.debug("Handling CCT")
val parseResult = parsePain001(paymentRequest)
+ logger.debug("Handling Pain.001: ${parseResult.pmtInfId}")
transaction(Connection.TRANSACTION_SERIALIZABLE, repetitionAttempts = 10) {
val maybeExist = BankAccountTransactionEntity.find {
BankAccountTransactionsTable.pmtInfId eq parseResult.pmtInfId
@@ -761,7 +763,6 @@ private fun handleCct(paymentRequest: String) {
* to the querying subscriber.
*/
private fun handleEbicsC52(requestContext: RequestContext): ByteArray {
- logger.debug("Handling C52 request")
// Ignoring any dateRange parameter. (FIXME)
val report = constructCamtResponse(52, requestContext.subscriber, dateRange = null)
SandboxAssert(
@@ -776,8 +777,6 @@ private fun handleEbicsC52(requestContext: RequestContext): ByteArray {
}
private fun handleEbicsC53(requestContext: RequestContext): ByteArray {
- logger.debug("Handling C53 request")
-
// Fetch date range.
val orderParams = requestContext.requestObject.header.static.orderDetails?.orderParams // as EbicsRequest.StandardOrderParams
val dateRange = if (orderParams != null) {
@@ -1094,7 +1093,6 @@ private fun handleEbicsHkd(requestContext: RequestContext): ByteArray {
return str.toByteArray()
}
-
private data class RequestContext(
val ebicsHost: EbicsHostEntity,
val subscriber: EbicsSubscriberEntity,
@@ -1108,6 +1106,10 @@ private data class RequestContext(
val downloadTransaction: EbicsDownloadTransactionEntity?
)
+/**
+ * Get segmentation values and the EBICS transaction ID, before
+ * handing the response to 'createForDownloadTransferPhase()'.
+ */
private fun handleEbicsDownloadTransactionTransfer(requestContext: RequestContext): EbicsResponse {
val segmentNumber =
requestContext.requestObject.header.mutable.segmentNumber?.value ?: throw EbicsInvalidRequestError()
@@ -1128,7 +1130,7 @@ private fun handleEbicsDownloadTransactionTransfer(requestContext: RequestContex
private fun handleEbicsDownloadTransactionInitialization(requestContext: RequestContext): EbicsResponse {
val orderType =
requestContext.requestObject.header.static.orderDetails?.orderType ?: throw EbicsInvalidRequestError()
- logger.debug("handling initialization for order type $orderType")
+ val nonce = requestContext.requestObject.header.static.nonce
val response = when (orderType) {
"HTD" -> handleEbicsHtd(requestContext)
"HKD" -> handleEbicsHkd(requestContext)
@@ -1139,10 +1141,14 @@ private fun handleEbicsDownloadTransactionInitialization(requestContext: Request
else -> throw EbicsInvalidXmlError()
}
val transactionID = EbicsOrderUtil.generateTransactionId()
+ logger.debug(
+ "Handling download initialization for order type $orderType, " +
+ "nonce: ${nonce?.toHexString() ?: "not given"}, " +
+ "transaction ID: $transactionID"
+ )
val compressedResponse = DeflaterInputStream(response.inputStream()).use {
it.readAllBytes()
}
-
val enc = CryptoUtil.encryptEbicsE002(compressedResponse, requestContext.clientEncPub)
val encodedResponse = Base64.getEncoder().encodeToString(enc.encryptedData)
@@ -1169,11 +1175,14 @@ private fun handleEbicsDownloadTransactionInitialization(requestContext: Request
)
}
-
private fun handleEbicsUploadTransactionInitialization(requestContext: RequestContext): EbicsResponse {
val orderType =
requestContext.requestObject.header.static.orderDetails?.orderType ?: throw EbicsInvalidRequestError()
val transactionID = EbicsOrderUtil.generateTransactionId()
+ logger.debug("Handling upload initialization for order $orderType, " +
+ "transactionID $transactionID, nonce: " +
+ (requestContext.requestObject.header.static.nonce?.toHexString() ?: "not given")
+ )
val oidn = requestContext.subscriber.nextOrderID++
if (EbicsOrderUtil.checkOrderIDOverflow(oidn)) throw NotImplementedError()
val orderID = EbicsOrderUtil.computeOrderIDFromNumber(oidn)
@@ -1197,7 +1206,6 @@ private fun handleEbicsUploadTransactionInitialization(requestContext: RequestCo
val plainSigData = InflaterInputStream(decryptedSignatureData.inputStream()).use {
it.readAllBytes()
}
- logger.debug("creating upload transaction for transactionID $transactionID")
EbicsUploadTransactionEntity.new(transactionID) {
this.host = requestContext.ebicsHost
this.subscriber = requestContext.subscriber
@@ -1209,7 +1217,7 @@ private fun handleEbicsUploadTransactionInitialization(requestContext: RequestCo
}
val sigObj = XMLUtil.convertStringToJaxb<UserSignatureData>(plainSigData.toString(Charsets.UTF_8))
for (sig in sigObj.value.orderSignatureList ?: listOf()) {
- logger.debug("inserting order signature for orderID $orderID and orderType $orderType")
+ logger.debug("inserting order signature for orderID $orderID, order type $orderType, transaction '$transactionID'")
EbicsOrderSignatureEntity.new {
this.orderID = orderID
this.orderType = orderType
@@ -1238,7 +1246,6 @@ private fun handleEbicsUploadTransactionTransmission(requestContext: RequestCont
)
val unzippedData =
InflaterInputStream(zippedData.inputStream()).use { it.readAllBytes() }
- // logger.debug("got upload data: ${unzippedData.toString(Charsets.UTF_8)}")
val sigs = EbicsOrderSignatureEntity.find {
(EbicsOrderSignaturesTable.orderID eq uploadTransaction.orderID) and
@@ -1415,9 +1422,12 @@ suspend fun ApplicationCall.ebicsweb() {
requestObject.header.static.transactionID ?: throw EbicsInvalidRequestError()
if (requestContext.downloadTransaction == null)
throw EbicsInvalidRequestError()
+ logger.debug("Handling download receipt for EBICS transaction: " +
+ requestTransactionID)
val receiptCode =
requestObject.body.transferReceipt?.receiptCode ?: throw EbicsInvalidRequestError()
EbicsResponse.createForDownloadReceiptPhase(requestTransactionID, receiptCode == 0)
+
}
}
signEbicsResponse(ebicsResponse, requestContext.hostAuthPriv)
diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt
@@ -156,7 +156,6 @@ private fun signOrder(
return userSignatureData
}
-
fun createEbicsRequestForDownloadReceipt(
subscriberDetails: EbicsClientSubscriberDetails,
transactionID: String
@@ -232,11 +231,12 @@ fun createEbicsRequestForUploadInitialization(
orderParams: EbicsOrderParams,
preparedUploadData: PreparedUploadData
): String {
+ val nonce = getNonce(128)
val req = EbicsRequest.createForUploadInitializationPhase(
preparedUploadData.transactionKey,
preparedUploadData.userSignatureDataEncrypted,
subscriberDetails.hostId,
- getNonce(128),
+ nonce,
subscriberDetails.partnerId,
subscriberDetails.userId,
DatatypeFactory.newInstance().newXMLGregorianCalendar(GregorianCalendar()),
@@ -246,6 +246,15 @@ fun createEbicsRequestForUploadInitialization(
orderType,
makeOrderParams(orderParams)
)
+ /**
+ * FIXME: this log should be made by the caller.
+ * That way, all the EBICS transaction steps would be logged in only one function,
+ * as opposed to have them spread through the helpers here. This function
+ * returning a string blocks now, since the caller should parse and stringify
+ * again the message, only to get its nonce.
+ */
+ logger.debug("Created EBICS $orderType document for upload initialization," +
+ " nonce: ${nonce.toHexString()}")
val doc = XMLUtil.convertJaxbToDocument(req)
XMLUtil.signEbicsDocument(doc, subscriberDetails.customerAuthPriv)
return XMLUtil.convertDomToString(doc)
@@ -257,11 +266,12 @@ fun createEbicsRequestForDownloadInitialization(
orderType: String,
orderParams: EbicsOrderParams
): String {
+ val nonce = getNonce(128)
val req = EbicsRequest.createForDownloadInitializationPhase(
subscriberDetails.userId,
subscriberDetails.partnerId,
subscriberDetails.hostId,
- getNonce(128),
+ nonce,
DatatypeFactory.newInstance().newXMLGregorianCalendar(GregorianCalendar()),
subscriberDetails.bankEncPub ?: throw EbicsProtocolError(
HttpStatusCode.BadRequest,
@@ -274,6 +284,15 @@ fun createEbicsRequestForDownloadInitialization(
orderType,
makeOrderParams(orderParams)
)
+ /**
+ * FIXME: this log should be made by the caller.
+ * That way, all the EBICS transaction steps would be logged in only one function,
+ * as opposed to have them spread through the helpers here. This function
+ * returning a string blocks now, since the caller should parse and stringify
+ * again the message, only to get its nonce.
+ */
+ logger.debug("Created EBICS $orderType document for download initialization," +
+ " nonce: ${nonce.toHexString()}")
val doc = XMLUtil.convertJaxbToDocument(req)
XMLUtil.signEbicsDocument(doc, subscriberDetails.customerAuthPriv)
return XMLUtil.convertDomToString(doc)
@@ -296,7 +315,6 @@ fun createEbicsRequestForDownloadTransferPhase(
return XMLUtil.convertDomToString(doc)
}
-
fun createEbicsRequestForUploadTransferPhase(
subscriberDetails: EbicsClientSubscriberDetails,
transactionID: String,