libeufin

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

commit a726581fd09950b3feb373b4266057fe24ac8679
parent c8363449c3d11534b249727874a18fd97b2ea152
Author: Florian Dold <florian.dold@gmail.com>
Date:   Tue,  9 Jun 2020 01:29:18 +0530

sandbox support for multi-segment EBICS download transactions

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 15++++++++++++++-
Mutil/src/main/kotlin/CryptoUtil.kt | 1+
Mutil/src/main/kotlin/ebics_h004/EbicsResponse.kt | 49++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -786,6 +786,19 @@ private data class RequestContext( val downloadTransaction: EbicsDownloadTransactionEntity? ) +private fun handleEbicsDownloadTransactionTransfer(requestContext: RequestContext): EbicsResponse { + val segmentNumber = requestContext.requestObject.header.mutable.segmentNumber?.value ?: throw EbicsInvalidRequestError() + val transactionID = requestContext.requestObject.header.static.transactionID ?: throw EbicsInvalidRequestError() + val downloadTransaction = requestContext.downloadTransaction ?: throw AssertionError() + return EbicsResponse.createForDownloadTransferPhase( + transactionID, + downloadTransaction.numSegments, + downloadTransaction.segmentSize, + downloadTransaction.encodedResponse, + segmentNumber.toInt() + ) +} + private fun handleEbicsDownloadTransactionInitialization(requestContext: RequestContext): EbicsResponse { val orderType = @@ -1072,7 +1085,7 @@ suspend fun ApplicationCall.ebicsweb() { if (requestContext.uploadTransaction != null) { handleEbicsUploadTransactionTransmission(requestContext) } else if (requestContext.downloadTransaction != null) { - throw NotImplementedError() + handleEbicsDownloadTransactionTransfer(requestContext) } else { throw AssertionError() } diff --git a/util/src/main/kotlin/CryptoUtil.kt b/util/src/main/kotlin/CryptoUtil.kt @@ -45,6 +45,7 @@ object CryptoUtil { */ data class RsaCrtKeyPair(val private: RSAPrivateCrtKey, val public: RSAPublicKey) + // FIXME(dold): This abstraction needs to be improved. class EncryptionResult( val encryptedTransactionKey: ByteArray, val pubKeyDigest: ByteArray, diff --git a/util/src/main/kotlin/ebics_h004/EbicsResponse.kt b/util/src/main/kotlin/ebics_h004/EbicsResponse.kt @@ -7,6 +7,7 @@ import javax.xml.bind.annotation.* import javax.xml.bind.annotation.adapters.CollapsedStringAdapter import javax.xml.bind.annotation.adapters.NormalizedStringAdapter import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter +import kotlin.math.min @XmlAccessorType(XmlAccessType.NONE) @XmlType(name = "", propOrder = ["header", "authSignature", "body"]) @@ -220,6 +221,52 @@ class EbicsResponse { } } + /** + * @param requestedSegment requested segment as a 1-based index + */ + fun createForDownloadTransferPhase( + transactionID: String, + numSegments: Int, + segmentSize: Int, + encodedData: String, + requestedSegment: Int + ): EbicsResponse { + return EbicsResponse().apply { + this.version = "H004" + this.revision = 1 + this.header = Header().apply { + this.authenticate = true + this._static = StaticHeaderType().apply { + this.transactionID = transactionID + this.numSegments = BigInteger.valueOf(numSegments.toLong()) + } + this.mutable = MutableHeaderType().apply { + this.transactionPhase = + EbicsTypes.TransactionPhaseType.TRANSFER + this.segmentNumber = EbicsTypes.SegmentNumber().apply { + this.lastSegment = numSegments == requestedSegment + this.value = BigInteger.valueOf(requestedSegment.toLong()) + } + this.reportText = "[EBICS_OK] OK" + this.returnCode = "000000" + } + } + this.authSignature = SignatureType() + this.body = Body().apply { + this.returnCode = ReturnCode().apply { + this.authenticate = true + this.value = "000000" + } + this.dataTransfer = DataTransferResponseType().apply { + this.orderData = OrderData().apply { + val start = segmentSize * (requestedSegment - 1) + this.value = encodedData.substring(start, min(start + segmentSize, encodedData.length)) + } + } + } + } + } + fun createForDownloadInitializationPhase( transactionID: String, numSegments: Int, @@ -265,7 +312,7 @@ class EbicsResponse { this.transactionKey = enc.encryptedTransactionKey } this.orderData = OrderData().apply { - this.value = encodedData.substring(0, Math.min(segmentSize, encodedData.length)) + this.value = encodedData.substring(0, min(segmentSize, encodedData.length)) } } }