gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] 02/02: start with HKD


From: gnunet
Subject: [libeufin] 02/02: start with HKD
Date: Fri, 08 Nov 2019 20:08:51 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository libeufin.

commit 2ae33e7e5c60094a3c150ed77dbf38c33f1e0751
Author: Florian Dold <address@hidden>
AuthorDate: Fri Nov 8 20:08:34 2019 +0100

    start with HKD
---
 .idea/gradle.xml                                   |   1 -
 sandbox/build.gradle                               |   1 +
 .../kotlin/tech/libeufin/sandbox/CryptoUtil.kt     |   8 +-
 .../src/main/kotlin/tech/libeufin/sandbox/DB.kt    |  16 +-
 .../kotlin/tech/libeufin/sandbox/EbicsOrderUtil.kt |   2 +-
 .../tech/libeufin/sandbox/EbicsProtocolBackend.kt  | 229 +++++++++------------
 .../main/kotlin/tech/libeufin/sandbox/XMLUtil.kt   |  11 +
 .../libeufin/schema/ebics_h004/EbicsResponse.kt    | 152 +++++++++++++-
 .../tech/libeufin/schema/ebics_h004/EbicsTypes.kt  | 186 +++++++++++++++++
 .../schema/ebics_h004/HKDResponseOrderData.kt      |  15 ++
 .../schema/ebics_h004/HTDResponseOrderData.kt      | 190 +----------------
 sandbox/src/test/kotlin/EbicsMessagesTest.kt       |  20 +-
 12 files changed, 487 insertions(+), 344 deletions(-)

diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 70bf921..49f0342 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -17,7 +17,6 @@
             <option value="$PROJECT_DIR$/sandbox" />
           </set>
         </option>
-        <option name="useAutoImport" value="true" />
         <option name="useQualifiedModuleNames" value="true" />
       </GradleProjectSettings>
     </option>
diff --git a/sandbox/build.gradle b/sandbox/build.gradle
index 71e4896..b02a96b 100644
--- a/sandbox/build.gradle
+++ b/sandbox/build.gradle
@@ -39,6 +39,7 @@ dependencies {
     implementation "org.glassfish.jaxb:jaxb-runtime:2.3.1"
     implementation 'org.apache.santuario:xmlsec:2.1.4'
     implementation group: 'org.bouncycastle', name: 'bcprov-jdk16', version: 
'1.45'
+    implementation group: 'org.xerial', name: 'sqlite-jdbc', version: '3.28.0'
 
     testImplementation group: 'junit', name: 'junit', version: '4.12'
     testImplementation 'org.jetbrains.kotlin:kotlin-test-junit:1.3.50'
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
index b3ca595..5843356 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt
@@ -151,14 +151,18 @@ object CryptoUtil {
     }
 
     fun decryptEbicsE002(enc: EncryptionResult, privateKey: RSAPrivateCrtKey): 
ByteArray {
+        return decryptEbicsE002(enc.encryptedTransactionKey, 
enc.encryptedData, privateKey)
+    }
+
+    fun decryptEbicsE002(encryptedTransactionKey: ByteArray, encryptedData: 
ByteArray, privateKey: RSAPrivateCrtKey): ByteArray {
         val asymmetricCipher = Cipher.getInstance("RSA/None/PKCS1Padding", 
bouncyCastleProvider)
         asymmetricCipher.init(Cipher.DECRYPT_MODE, privateKey)
-        val transactionKeyBytes = 
asymmetricCipher.doFinal(enc.encryptedTransactionKey)
+        val transactionKeyBytes = 
asymmetricCipher.doFinal(encryptedTransactionKey)
         val secretKeySpec = SecretKeySpec(transactionKeyBytes, "AES")
         val symmetricCipher = Cipher.getInstance("AES/CBC/X9.23Padding", 
bouncyCastleProvider)
         val ivParameterSpec = IvParameterSpec(ByteArray(16))
         symmetricCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, 
ivParameterSpec)
-        val data = symmetricCipher.doFinal(enc.encryptedData)
+        val data = symmetricCipher.doFinal(encryptedData)
         return data
     }
 }
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
index b4cb2f6..2b48dd7 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
@@ -21,10 +21,11 @@ package tech.libeufin.sandbox
 
 import org.jetbrains.exposed.dao.*
 import org.jetbrains.exposed.sql.Database
-import org.jetbrains.exposed.sql.ReferenceOption
+import org.jetbrains.exposed.sql.transactions.TransactionManager
 import org.jetbrains.exposed.sql.SchemaUtils
 import org.jetbrains.exposed.sql.transactions.transaction
 import java.sql.Blob
+import java.sql.Connection
 
 const val CUSTOMER_NAME_MAX_LENGTH = 20
 const val EBICS_HOST_ID_MAX_LENGTH = 10
@@ -229,13 +230,13 @@ class EbicsUploadTransactionEntity(id: EntityID<String>) 
: Entity<String>(id) {
     var subscriber by EbicsSubscriberEntity referencedOn 
EbicsUploadTransactionsTable.subscriber
     var numSegments by EbicsUploadTransactionsTable.numSegments
     var lastSeenSegment by EbicsUploadTransactionsTable.lastSeenSegment
-    var transactionKeyEnc by EbicsDownloadTransactionsTable.transactionKeyEnc
+    var transactionKeyEnc by EbicsUploadTransactionsTable.transactionKeyEnc
 }
 
 
 object EbicsUploadTransactionChunksTable : IdTable<String>() {
     override val id =
-        
text("transactionID").entityId().references(EbicsUploadTransactionsTable.id, 
ReferenceOption.CASCADE)
+        text("transactionID").entityId()
     val chunkIndex = integer("chunkIndex")
     val chunkContent = blob("chunkContent")
 }
@@ -250,16 +251,19 @@ class EbicsUploadTransactionChunkEntity(id : 
EntityID<String>): Entity<String>(i
 
 
 fun dbCreateTables() {
-    Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = 
"org.h2.Driver")
+    Database.connect("jdbc:sqlite:libeufin-sandbox.sqlite3", "org.sqlite.JDBC")
+    TransactionManager.manager.defaultIsolationLevel = 
Connection.TRANSACTION_SERIALIZABLE
 
     transaction {
         // addLogger(StdOutSqlLogger)
 
-        SchemaUtils.create(
+        SchemaUtils.createMissingTablesAndColumns(
             BankCustomersTable,
             EbicsSubscribersTable,
             EbicsHostsTable,
-            EbicsDownloadTransactionsTable
+            EbicsDownloadTransactionsTable,
+            EbicsUploadTransactionsTable,
+            EbicsUploadTransactionChunksTable
         )
     }
 }
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsOrderUtil.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsOrderUtil.kt
index 7fcd812..2edfd8e 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsOrderUtil.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsOrderUtil.kt
@@ -46,7 +46,7 @@ object EbicsOrderUtil {
         val rng = SecureRandom()
         val res = ByteArray(16)
         rng.nextBytes(res)
-        return res.toHexString()
+        return res.toHexString().toUpperCase()
     }
 
     /**
diff --git 
a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
index cd6a922..73b031d 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
@@ -28,15 +28,20 @@ import io.ktor.response.respond
 import io.ktor.response.respondText
 import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
 import org.apache.xml.security.binding.xmldsig.SignatureType
+import org.jetbrains.exposed.sql.lowerCase
 import org.jetbrains.exposed.sql.transactions.transaction
+import org.jetbrains.exposed.sql.upperCase
 import org.w3c.dom.Document
 import tech.libeufin.schema.ebics_h004.*
 import tech.libeufin.schema.ebics_hev.HEVResponse
 import tech.libeufin.schema.ebics_hev.SystemReturnCodeType
 import tech.libeufin.schema.ebics_s001.SignaturePubKeyOrderData
 import java.math.BigInteger
+import java.security.PrivateKey
+import java.security.interfaces.RSAPrivateCrtKey
 import java.util.*
 import java.util.zip.DeflaterInputStream
+import java.util.zip.InflaterInputStream
 import javax.sql.rowset.serial.SerialBlob
 
 
@@ -225,7 +230,7 @@ private suspend fun ApplicationCall.handleEbicsHpb(
  */
 private fun ApplicationCall.ensureEbicsHost(requestHostID: String): 
EbicsHostPublicInfo {
     return transaction {
-        val ebicsHost = EbicsHostEntity.find { EbicsHostsTable.hostID eq 
requestHostID }.firstOrNull()
+        val ebicsHost = EbicsHostEntity.find { 
EbicsHostsTable.hostID.upperCase() eq requestHostID.toUpperCase() 
}.firstOrNull()
         if (ebicsHost == null) {
             logger.warn("client requested unknown HostID")
             throw EbicsKeyManagementError("[EBICS_INVALID_HOST_ID]", "091011")
@@ -254,13 +259,13 @@ private suspend fun ApplicationCall.receiveEbicsXml(): 
Document {
 
 fun handleEbicsHtd(): ByteArray {
     val htd = HTDResponseOrderData().apply {
-        this.partnerInfo = HTDResponseOrderData.PartnerInfo().apply {
+        this.partnerInfo = EbicsTypes.PartnerInfo().apply {
             this.accountInfoList = listOf(
-                HTDResponseOrderData.AccountInfo().apply {
+                EbicsTypes.AccountInfo().apply {
                     this.id = "acctid1"
                     this.accountHolder = "Mina Musterfrau"
                     this.accountNumberList = listOf(
-                        HTDResponseOrderData.GeneralAccountNumber().apply {
+                        EbicsTypes.GeneralAccountNumber().apply {
                             this.international = true
                             this.value = "DE21500105174751659277"
                         }
@@ -268,17 +273,17 @@ fun handleEbicsHtd(): ByteArray {
                     this.currency = "EUR"
                     this.description = "ACCT"
                     this.bankCodeList = listOf(
-                        HTDResponseOrderData.GeneralBankCode().apply {
+                        EbicsTypes.GeneralBankCode().apply {
                             this.international = true
                             this.value = "INGDDEFFXXX"
                         }
                     )
                 },
-                HTDResponseOrderData.AccountInfo().apply {
+                EbicsTypes.AccountInfo().apply {
                     this.id = "glsdemo"
                     this.accountHolder = "Mina Musterfrau"
                     this.accountNumberList = listOf(
-                        HTDResponseOrderData.GeneralAccountNumber().apply {
+                        EbicsTypes.GeneralAccountNumber().apply {
                             this.international = true
                             this.value = "DE91430609670123123123"
                         }
@@ -286,45 +291,45 @@ fun handleEbicsHtd(): ByteArray {
                     this.currency = "EUR"
                     this.description = "glsdemoacct"
                     this.bankCodeList = listOf(
-                        HTDResponseOrderData.GeneralBankCode().apply {
+                        EbicsTypes.GeneralBankCode().apply {
                             this.international = true
                             this.value = "GENODEM1GLS"
                         }
                     )
                 }
             )
-            this.addressInfo = HTDResponseOrderData.AddressInfo().apply {
+            this.addressInfo = EbicsTypes.AddressInfo().apply {
                 this.name = "Foo"
             }
-            this.bankInfo = HTDResponseOrderData.BankInfo().apply {
+            this.bankInfo = EbicsTypes.BankInfo().apply {
                 this.hostID = "host01"
             }
             this.orderInfoList = listOf(
-                HTDResponseOrderData.AuthOrderInfoType().apply {
+                EbicsTypes.AuthOrderInfoType().apply {
                     this.description = "foo"
                     this.orderType = "C53"
                     this.transferType = "Download"
                 },
-                HTDResponseOrderData.AuthOrderInfoType().apply {
+                EbicsTypes.AuthOrderInfoType().apply {
                     this.description = "foo"
                     this.orderType = "C52"
                     this.transferType = "Download"
                 },
-                HTDResponseOrderData.AuthOrderInfoType().apply {
+                EbicsTypes.AuthOrderInfoType().apply {
                     this.description = "foo"
                     this.orderType = "CCC"
                     this.transferType = "Upload"
                 }
             )
         }
-        this.userInfo = HTDResponseOrderData.UserInfo().apply {
+        this.userInfo = EbicsTypes.UserInfo().apply {
             this.name = "Some User"
-            this.userID = HTDResponseOrderData.UserIDType().apply {
+            this.userID = EbicsTypes.UserIDType().apply {
                 this.status = 5
                 this.value = "USER1"
             }
             this.permissionList = listOf(
-                HTDResponseOrderData.UserPermission().apply {
+                EbicsTypes.UserPermission().apply {
                     this.orderTypes = "C54 C53 C52 CCC"
                 }
             )
@@ -336,111 +341,22 @@ fun handleEbicsHtd(): ByteArray {
 }
 
 
-fun createEbicsResponseForDownloadInitializationPhase(
-    transactionID: String,
-    numSegments: Int,
-    segmentSize: Int,
-    enc: CryptoUtil.EncryptionResult,
-    encodedData: String
-): EbicsResponse {
-    return EbicsResponse().apply {
-        this.version = "H004"
-        this.revision = 1
-        this.header = EbicsResponse.Header().apply {
-            this.authenticate = true
-            this._static = EbicsResponse.StaticHeaderType().apply {
-                this.transactionID = transactionID
-                this.numSegments = BigInteger.valueOf(numSegments.toLong())
-            }
-            this.mutable = EbicsResponse.MutableHeaderType().apply {
-                this.transactionPhase = 
EbicsTypes.TransactionPhaseType.INITIALISATION
-                this.segmentNumber = EbicsResponse.SegmentNumber().apply {
-                    this.lastSegment = (numSegments == 1)
-                    this.value = BigInteger.valueOf(1)
-                }
-                this.reportText = "[EBICS_OK] OK"
-                this.returnCode = "000000"
-            }
-        }
-        this.authSignature = SignatureType()
-        this.body = EbicsResponse.Body().apply {
-            this.returnCode = EbicsResponse.ReturnCode().apply {
-                this.authenticate = true
-                this.value = "000000"
-            }
-            this.dataTransfer = EbicsResponse.DataTransferResponseType().apply 
{
-                this.dataEncryptionInfo = 
EbicsTypes.DataEncryptionInfo().apply {
-                    this.authenticate = true
-                    this.encryptionPubKeyDigest = 
EbicsTypes.PubKeyDigest().apply {
-                        this.algorithm = 
"http://www.w3.org/2001/04/xmlenc#sha256";
-                        this.version = "E002"
-                        this.value = enc.pubKeyDigest
-                    }
-                    this.transactionKey = enc.encryptedTransactionKey
-                }
-                this.orderData = EbicsResponse.OrderData().apply {
-                    this.value = encodedData.substring(0, 
Math.min(segmentSize, encodedData.length))
-                }
-            }
-        }
-    }
+fun signEbicsResponseX002(ebicsResponse: EbicsResponse, privateKey: 
RSAPrivateCrtKey): String {
+    val doc = XMLUtil.convertJaxbToDocument(ebicsResponse)
+    XMLUtil.signEbicsDocument(doc, privateKey)
+    val signedDoc = XMLUtil.convertDomToString(doc)
+    println("response: $signedDoc")
+    return signedDoc
 }
 
 
-fun createEbicsResponseForDownloadReceiptPhase(transactionID: String, 
positiveAck: Boolean): EbicsResponse {
-    return EbicsResponse().apply {
-        this.version = "H004"
-        this.revision = 1
-        this.header = EbicsResponse.Header().apply {
-            this.authenticate = true
-            this._static = EbicsResponse.StaticHeaderType().apply {
-                this.transactionID = transactionID
-            }
-            this.mutable = EbicsResponse.MutableHeaderType().apply {
-                this.transactionPhase = EbicsTypes.TransactionPhaseType.RECEIPT
-                if (positiveAck) {
-                    this.reportText = "[EBICS_DOWNLOAD_POSTPROCESS_DONE] 
Received positive receipt"
-                    this.returnCode = "011000"
-                } else {
-                    this.reportText = "[EBICS_DOWNLOAD_POSTPROCESS_SKIPPED] 
Received negative receipt"
-                    this.returnCode = "011001"
-                }
-            }
-        }
-        this.authSignature = SignatureType()
-        this.body = EbicsResponse.Body().apply {
-            this.returnCode = EbicsResponse.ReturnCode().apply {
-                this.authenticate = true
-                this.value = "000000"
-            }
-        }
-    }
-}
+class EbicsTransactionDetails(
 
-fun createEbicsResponseForUploadInitializationPhase(transactionID: String, 
orderID: String): EbicsResponse {
-    return EbicsResponse().apply {
-        this.version = "H004"
-        this.revision = 1
-        this.header = EbicsResponse.Header().apply {
-            this.authenticate = true
-            this._static = EbicsResponse.StaticHeaderType().apply {
-                this.transactionID = transactionID
-            }
-            this.mutable = EbicsResponse.MutableHeaderType().apply {
-                this.transactionPhase = 
EbicsTypes.TransactionPhaseType.INITIALISATION
-                this.orderID = orderID
-                this.reportText = "[EBICS_OK] OK"
-                this.returnCode = "000000"
-            }
-        }
-        this.authSignature = SignatureType()
-        this.body = EbicsResponse.Body().apply {
-            this.returnCode = EbicsResponse.ReturnCode().apply {
-                this.authenticate = true
-                this.value = "000000"
-            }
-        }
-    }
+)
+
+
+fun queryEbicsTransactionDetails(ebicsRequest: EbicsRequest): 
EbicsTransactionDetails {
+    throw NotImplementedError()
 }
 
 
@@ -492,12 +408,14 @@ suspend fun ApplicationCall.ebicsweb() {
             val responseXmlStr = transaction {
                 // Step 1 of 3:  Get information about the host and subscriber
 
-                val ebicsHost = EbicsHostEntity.find { EbicsHostsTable.hostID 
eq requestedHostId }.firstOrNull()
+                val ebicsHost = EbicsHostEntity.find { 
EbicsHostsTable.hostID.upperCase() eq requestedHostId.toUpperCase() 
}.firstOrNull()
                 val requestTransactionID = 
requestObject.header.static.transactionID
                 var downloadTransaction: EbicsDownloadTransactionEntity? = null
-                var uploadTransaction: EbicsUploadTransactionEntity? = null
+                var uploadTransaction: EbicsUploadTransactionEntity? =
+                    null
                 val subscriber = if (requestTransactionID != null) {
-                    downloadTransaction = 
EbicsDownloadTransactionEntity.findById(requestTransactionID)
+                    println("finding subscriber by transactionID 
$requestTransactionID")
+                    downloadTransaction = 
EbicsDownloadTransactionEntity.findById(requestTransactionID.toUpperCase())
                     if (downloadTransaction != null) {
                         downloadTransaction.subscriber
                     } else {
@@ -517,6 +435,10 @@ suspend fun ApplicationCall.ebicsweb() {
                     ebicsHost.authenticationPrivateKey
                         .toByteArray()
                 )
+                val hostEncPriv = CryptoUtil.loadRsaPrivateKey(
+                    ebicsHost.encryptionPrivateKey
+                        .toByteArray()
+                )
                 val clientAuthPub =
                     
CryptoUtil.loadRsaPublicKey(subscriber.authenticationKey!!.rsaPublicKey.toByteArray())
                 val clientEncPub =
@@ -534,6 +456,7 @@ suspend fun ApplicationCall.ebicsweb() {
                         val orderType =
                             
requestObject.header.static.orderDetails?.orderType ?: throw 
EbicsInvalidRequestError()
                         if (staticHeader.numSegments == null) {
+                            println("handling initialization for order type 
$orderType")
                             val response = when (orderType) {
                                 "HTD" -> handleEbicsHtd()
                                 else -> throw EbicsInvalidXmlError()
@@ -560,7 +483,7 @@ suspend fun ApplicationCall.ebicsweb() {
                                 this.numSegments = numSegments
                                 this.receiptReceived = false
                             }
-                            createEbicsResponseForDownloadInitializationPhase(
+                            EbicsResponse.createForDownloadInitializationPhase(
                                 transactionID,
                                 numSegments,
                                 segmentSize,
@@ -571,15 +494,30 @@ suspend fun ApplicationCall.ebicsweb() {
                             val oidn = subscriber.nextOrderID++
                             if (EbicsOrderUtil.checkOrderIDOverflow(oidn)) 
throw NotImplementedError()
                             val orderID = 
EbicsOrderUtil.computeOrderIDFromNumber(oidn)
-                            val signatureData = 
requestObject.body.dataTransfer?.signatureData
-                            if (signatureData != null) {
-                                println("signature data: 
${signatureData.toString(Charsets.UTF_8)}")
-                            }
                             val numSegments =
                                 requestObject.header.static.numSegments ?: 
throw EbicsInvalidRequestError()
                             val transactionKeyEnc =
                                 
requestObject.body.dataTransfer?.dataEncryptionInfo?.transactionKey
                                     ?: throw EbicsInvalidRequestError()
+                            val encPubKeyDigest =
+                                
requestObject.body.dataTransfer?.dataEncryptionInfo?.encryptionPubKeyDigest?.value
+                            if (encPubKeyDigest == null)
+                                throw EbicsInvalidRequestError()
+                            val encSigData = 
requestObject.body.dataTransfer?.signatureData
+                            if (encSigData == null)
+                                throw EbicsInvalidRequestError()
+                            val decryptedSignatureData = 
CryptoUtil.decryptEbicsE002(
+                                CryptoUtil.EncryptionResult(
+                                    transactionKeyEnc,
+                                    encPubKeyDigest,
+                                    encSigData
+                                ), hostEncPriv
+                            )
+                            val plainSigData = 
InflaterInputStream(decryptedSignatureData.inputStream()).use {
+                                it.readAllBytes()
+                            }
+                            println("signature data: 
${plainSigData.toString(Charsets.UTF_8)}")
+                            println("creating upload transaction for 
transactionID $transactionID")
                             EbicsUploadTransactionEntity.new(transactionID) {
                                 this.host = ebicsHost
                                 this.subscriber = subscriber
@@ -589,11 +527,39 @@ suspend fun ApplicationCall.ebicsweb() {
                                 this.numSegments = numSegments.toInt()
                                 this.transactionKeyEnc = 
SerialBlob(transactionKeyEnc)
                             }
-                            
createEbicsResponseForUploadInitializationPhase(transactionID, orderID)
+                            
EbicsResponse.createForUploadInitializationPhase(transactionID, orderID)
                         }
                     }
                     EbicsTypes.TransactionPhaseType.TRANSFER -> {
-                        throw NotImplementedError()
+                        requestTransactionID ?: throw 
EbicsInvalidRequestError()
+                        val requestSegmentNumber =
+                            
requestObject.header.mutable.segmentNumber?.toInt() ?: throw 
EbicsInvalidRequestError()
+                        if (uploadTransaction != null) {
+                            if (requestSegmentNumber == 1 && 
uploadTransaction.numSegments == 1) {
+                                val encOrderData =
+                                    requestObject.body.dataTransfer?.orderData 
?: throw EbicsInvalidRequestError()
+                                val zippedData = CryptoUtil.decryptEbicsE002(
+                                    
uploadTransaction.transactionKeyEnc.toByteArray(),
+                                    encOrderData,
+                                    hostEncPriv
+                                )
+                                val unzippedData =
+                                    
InflaterInputStream(zippedData.inputStream()).use { it.readAllBytes() }
+                                println("got upload data: 
${unzippedData.toString(Charsets.UTF_8)}")
+                                EbicsResponse.createForUploadTransferPhase(
+                                    requestTransactionID,
+                                    requestSegmentNumber,
+                                    true,
+                                    uploadTransaction.orderID
+                                )
+                            } else {
+                                throw NotImplementedError()
+                            }
+                        } else if (downloadTransaction != null) {
+                            throw NotImplementedError()
+                        } else {
+                            throw AssertionError()
+                        }
                     }
                     EbicsTypes.TransactionPhaseType.RECEIPT -> {
                         requestTransactionID ?: throw 
EbicsInvalidRequestError()
@@ -601,15 +567,10 @@ suspend fun ApplicationCall.ebicsweb() {
                             throw EbicsInvalidRequestError()
                         val receiptCode =
                             requestObject.body.transferReceipt?.receiptCode ?: 
throw EbicsInvalidRequestError()
-                        
createEbicsResponseForDownloadReceiptPhase(requestTransactionID, receiptCode == 
0)
+                        
EbicsResponse.createForDownloadReceiptPhase(requestTransactionID, receiptCode 
== 0)
                     }
                 }
-                val docText = XMLUtil.convertJaxbToString(ebicsResponse)
-                val doc = XMLUtil.parseStringIntoDom(docText)
-                XMLUtil.signEbicsDocument(doc, hostAuthPriv)
-                val signedDoc = XMLUtil.convertDomToString(doc)
-                println("response: $signedDoc")
-                docText
+                signEbicsResponseX002(ebicsResponse, hostAuthPriv)
             }
             respondText(responseXmlStr, ContentType.Application.Xml, 
HttpStatusCode.OK)
         }
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLUtil.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLUtil.kt
index 5195478..0538984 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLUtil.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLUtil.kt
@@ -203,6 +203,17 @@ class XMLUtil private constructor() {
             return sw.toString()
         }
 
+        inline fun <reified T> convertJaxbToDocument(obj: T): Document {
+            val dbf: DocumentBuilderFactory  = 
DocumentBuilderFactory.newInstance()
+            dbf.isNamespaceAware = true
+            val doc = dbf.newDocumentBuilder().newDocument()
+            val jc = JAXBContext.newInstance(T::class.java)
+            val m = jc.createMarshaller()
+            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)
+            m.marshal(obj, doc)
+            return doc
+        }
+
         /**
          * Convert a XML string to the JAXB representation.
          *
diff --git 
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
index 4ef5d2e..1e088da 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
@@ -1,6 +1,7 @@
 package tech.libeufin.schema.ebics_h004
 
 import org.apache.xml.security.binding.xmldsig.SignatureType
+import tech.libeufin.sandbox.CryptoUtil
 import java.math.BigInteger
 import javax.xml.bind.annotation.*
 import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
@@ -91,8 +92,8 @@ class EbicsResponse {
         @XmlValue
         lateinit var value: BigInteger
 
-        @XmlAttribute(name = "lastSegment", required = true)
-        var lastSegment: Boolean = false
+        @XmlAttribute(name = "lastSegment")
+        var lastSegment: Boolean? = null
     }
 
     @XmlAccessorType(XmlAccessType.NONE)
@@ -132,4 +133,151 @@ class EbicsResponse {
         @get:XmlSchemaType(name = "positiveInteger")
         var numSegments: BigInteger? = null
     }
+
+    companion object {
+        fun createForUploadInitializationPhase(transactionID: String, orderID: 
String): EbicsResponse {
+            return EbicsResponse().apply {
+                this.version = "H004"
+                this.revision = 1
+                this.header = EbicsResponse.Header().apply {
+                    this.authenticate = true
+                    this._static = EbicsResponse.StaticHeaderType().apply {
+                        this.transactionID = transactionID
+                    }
+                    this.mutable = EbicsResponse.MutableHeaderType().apply {
+                        this.transactionPhase = 
EbicsTypes.TransactionPhaseType.INITIALISATION
+                        this.orderID = orderID
+                        this.reportText = "[EBICS_OK] OK"
+                        this.returnCode = "000000"
+                    }
+                }
+                this.authSignature = SignatureType()
+                this.body = EbicsResponse.Body().apply {
+                    this.returnCode = EbicsResponse.ReturnCode().apply {
+                        this.authenticate = true
+                        this.value = "000000"
+                    }
+                }
+            }
+        }
+
+
+        fun createForDownloadReceiptPhase(transactionID: String, positiveAck: 
Boolean): EbicsResponse {
+            return EbicsResponse().apply {
+                this.version = "H004"
+                this.revision = 1
+                this.header = EbicsResponse.Header().apply {
+                    this.authenticate = true
+                    this._static = EbicsResponse.StaticHeaderType().apply {
+                        this.transactionID = transactionID
+                    }
+                    this.mutable = EbicsResponse.MutableHeaderType().apply {
+                        this.transactionPhase = 
EbicsTypes.TransactionPhaseType.RECEIPT
+                        if (positiveAck) {
+                            this.reportText = 
"[EBICS_DOWNLOAD_POSTPROCESS_DONE] Received positive receipt"
+                            this.returnCode = "011000"
+                        } else {
+                            this.reportText = 
"[EBICS_DOWNLOAD_POSTPROCESS_SKIPPED] Received negative receipt"
+                            this.returnCode = "011001"
+                        }
+                    }
+                }
+                this.authSignature = SignatureType()
+                this.body = EbicsResponse.Body().apply {
+                    this.returnCode = EbicsResponse.ReturnCode().apply {
+                        this.authenticate = true
+                        this.value = "000000"
+                    }
+                }
+            }
+        }
+
+
+        fun createForUploadTransferPhase(
+            transactionID: String,
+            segmentNumber: Int,
+            lastSegment: Boolean,
+            orderID: String
+        ): EbicsResponse {
+            return EbicsResponse().apply {
+                this.version = "H004"
+                this.revision = 1
+                this.header = EbicsResponse.Header().apply {
+                    this.authenticate = true
+                    this._static = EbicsResponse.StaticHeaderType().apply {
+                        this.transactionID = transactionID
+                    }
+                    this.mutable = EbicsResponse.MutableHeaderType().apply {
+                        this.transactionPhase = 
EbicsTypes.TransactionPhaseType.TRANSFER
+                        this.segmentNumber = 
EbicsResponse.SegmentNumber().apply {
+                            this.value = 
BigInteger.valueOf(segmentNumber.toLong())
+                            if (lastSegment) {
+                                this.lastSegment = true
+                            }
+                        }
+                        this.orderID = orderID
+                        this.reportText = "[EBICS_OK] OK"
+                        this.returnCode = "000000"
+                    }
+                }
+                this.authSignature = SignatureType()
+                this.body = EbicsResponse.Body().apply {
+                    this.returnCode = EbicsResponse.ReturnCode().apply {
+                        this.authenticate = true
+                        this.value = "000000"
+                    }
+                }
+            }
+        }
+
+        fun createForDownloadInitializationPhase(
+            transactionID: String,
+            numSegments: Int,
+            segmentSize: Int,
+            enc: CryptoUtil.EncryptionResult,
+            encodedData: String
+        ): EbicsResponse {
+            return EbicsResponse().apply {
+                this.version = "H004"
+                this.revision = 1
+                this.header = EbicsResponse.Header().apply {
+                    this.authenticate = true
+                    this._static = EbicsResponse.StaticHeaderType().apply {
+                        this.transactionID = transactionID
+                        this.numSegments = 
BigInteger.valueOf(numSegments.toLong())
+                    }
+                    this.mutable = EbicsResponse.MutableHeaderType().apply {
+                        this.transactionPhase = 
EbicsTypes.TransactionPhaseType.INITIALISATION
+                        this.segmentNumber = 
EbicsResponse.SegmentNumber().apply {
+                            this.lastSegment = (numSegments == 1)
+                            this.value = BigInteger.valueOf(1)
+                        }
+                        this.reportText = "[EBICS_OK] OK"
+                        this.returnCode = "000000"
+                    }
+                }
+                this.authSignature = SignatureType()
+                this.body = EbicsResponse.Body().apply {
+                    this.returnCode = EbicsResponse.ReturnCode().apply {
+                        this.authenticate = true
+                        this.value = "000000"
+                    }
+                    this.dataTransfer = 
EbicsResponse.DataTransferResponseType().apply {
+                        this.dataEncryptionInfo = 
EbicsTypes.DataEncryptionInfo().apply {
+                            this.authenticate = true
+                            this.encryptionPubKeyDigest = 
EbicsTypes.PubKeyDigest().apply {
+                                this.algorithm = 
"http://www.w3.org/2001/04/xmlenc#sha256";
+                                this.version = "E002"
+                                this.value = enc.pubKeyDigest
+                            }
+                            this.transactionKey = enc.encryptedTransactionKey
+                        }
+                        this.orderData = EbicsResponse.OrderData().apply {
+                            this.value = encodedData.substring(0, 
Math.min(segmentSize, encodedData.length))
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
diff --git 
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsTypes.kt 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsTypes.kt
index b8b7b2c..0d25014 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsTypes.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsTypes.kt
@@ -202,4 +202,190 @@ class EbicsTypes private constructor() {
         @get:XmlElement(name = "Value", required = true)
         lateinit var value: String
     }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["addressInfo", "bankInfo", 
"accountInfoList", "orderInfoList"])
+    class PartnerInfo {
+        @get:XmlElement(name = "AddressInfo", required = true)
+        lateinit var addressInfo: AddressInfo
+
+        @get:XmlElement(name = "BankInfo", required = true)
+        lateinit var bankInfo: BankInfo
+
+        @get:XmlElement(name = "AccountInfo", required = true)
+        var accountInfoList: List<AccountInfo>? = null
+
+        @get:XmlElement(name = "OrderInfo")
+        lateinit var orderInfoList: List<AuthOrderInfoType>
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(
+        name = "",
+        propOrder = ["orderType", "fileFormat", "transferType", "orderFormat", 
"description", "numSigRequired"]
+    )
+    class AuthOrderInfoType {
+        @get:XmlElement(name = "OrderType")
+        lateinit var orderType: String
+
+        @get:XmlElement(name = "FileFormat")
+        val fileFormat: EbicsTypes.FileFormatType? = null
+
+        @get:XmlElement(name = "TransferType")
+        lateinit var transferType: String
+
+        @get:XmlElement(name = "OrderFormat", required = false)
+        var orderFormat: String? = null
+
+        @get:XmlElement(name = "Description")
+        lateinit var description: String
+
+        @get:XmlElement(name = "NumSigRequired")
+        var numSigRequired: Int? = null
+
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    class UserIDType {
+        @get:XmlValue
+        lateinit var value: String;
+
+        @get:XmlAttribute(name = "Status")
+        var status: Int? = null
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["userID", "name", "permissionList"])
+    class UserInfo {
+        @get:XmlElement(name = "UserID", required = true)
+        lateinit var userID: UserIDType
+
+        @get:XmlElement(name = "Name")
+        var name: String? = null
+
+        @get:XmlElement(name = "Permission", type = UserPermission::class)
+        var permissionList: List<UserPermission>? = null
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["orderTypes", "fileFormat", "accountID", 
"maxAmount"])
+    class UserPermission {
+        @get:XmlAttribute(name = "AuthorizationLevel")
+        var authorizationLevel: String? = null
+
+        @get:XmlElement(name = "OrderTypes")
+        var orderTypes: String? = null
+
+        @get:XmlElement(name = "FileFormat")
+        val fileFormat: EbicsTypes.FileFormatType? = null
+
+        @get:XmlElement(name = "AccountID")
+        val accountID: String? = null
+
+        @get:XmlElement(name = "MaxAmount")
+        val maxAmount: String? = null
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["name", "street", "postCode", "city", 
"region", "country"])
+    class AddressInfo {
+        @get:XmlElement(name = "Name")
+        var name: String? = null
+
+        @get:XmlElement(name = "Street")
+        var street: String? = null
+
+        @get:XmlElement(name = "PostCode")
+        var postCode: String? = null
+
+        @get:XmlElement(name = "City")
+        var city: String? = null
+
+        @get:XmlElement(name = "Region")
+        var region: String? = null
+
+        @get:XmlElement(name = "Country")
+        var country: String? = null
+    }
+
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    class BankInfo {
+        @get:XmlElement(name = "HostID")
+        lateinit var hostID: String
+
+        @get:XmlElement(type = EbicsTypes.Parameter::class)
+        var parameters: List<EbicsTypes.Parameter>? = null
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["accountNumberList", "bankCodeList", 
"accountHolder"])
+    class AccountInfo {
+        @get:XmlAttribute(name = "Currency")
+        var currency: String? = null
+
+        @get:XmlAttribute(name = "ID")
+        lateinit var id: String
+
+        @get:XmlAttribute(name = "Description")
+        var description: String? = null
+
+        @get:XmlElements(
+            XmlElement(name = "AccountNumber", type = 
GeneralAccountNumber::class),
+            XmlElement(name = "NationalAccountNumber", type = 
NationalAccountNumber::class)
+        )
+        var accountNumberList: List<AbstractAccountNumber>? = null
+
+        @get:XmlElements(
+            XmlElement(name = "BankCode", type = GeneralBankCode::class),
+            XmlElement(name = "NationalBankCode", type = 
NationalBankCode::class)
+        )
+        var bankCodeList: List<AbstractBankCode>? = null
+
+        @get:XmlElement(name = "AccountHolder")
+        var accountHolder: String? = null
+    }
+
+    interface AbstractAccountNumber
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    class GeneralAccountNumber : AbstractAccountNumber {
+        @get:XmlAttribute(name = "international")
+        var international: Boolean = false
+
+        @get:XmlValue
+        lateinit var value: String
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    class NationalAccountNumber : AbstractAccountNumber {
+        @get:XmlAttribute(name = "format")
+        lateinit var format: String
+
+        @get:XmlValue
+        lateinit var value: String
+    }
+
+    interface AbstractBankCode
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    class GeneralBankCode : AbstractBankCode {
+        @get:XmlAttribute(name = "prefix")
+        var prefix: String? = null
+
+        @get:XmlAttribute(name = "international")
+        var international: Boolean = false
+
+        @get:XmlValue
+        lateinit var value: String
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    class NationalBankCode : AbstractBankCode {
+        @get:XmlValue
+        lateinit var value: String
+
+        @get:XmlAttribute(name = "format")
+        lateinit var format: String
+    }
 }
\ No newline at end of file
diff --git 
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HKDResponseOrderData.kt
 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HKDResponseOrderData.kt
new file mode 100644
index 0000000..6cbf05a
--- /dev/null
+++ 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HKDResponseOrderData.kt
@@ -0,0 +1,15 @@
+package tech.libeufin.schema.ebics_h004
+
+import java.security.Permission
+import javax.xml.bind.annotation.*
+
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlType(name = "", propOrder = ["partnerInfo", "userInfo"])
+@XmlRootElement(name = "HTDResponseOrderData")
+class HKDResponseOrderData {
+    @get:XmlElement(name = "PartnerInfo", required = true)
+    lateinit var partnerInfo: EbicsTypes.PartnerInfo
+
+    @get:XmlElement(name = "UserInfo", type = EbicsTypes.UserInfo::class, 
required = true)
+    lateinit var userInfoList: List<EbicsTypes.UserInfo>
+}
diff --git 
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HTDResponseOrderData.kt
 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HTDResponseOrderData.kt
index 8928071..9031e58 100644
--- 
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HTDResponseOrderData.kt
+++ 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/HTDResponseOrderData.kt
@@ -8,194 +8,8 @@ import javax.xml.bind.annotation.*
 @XmlRootElement(name = "HTDResponseOrderData")
 class HTDResponseOrderData {
     @get:XmlElement(name = "PartnerInfo", required = true)
-    lateinit var partnerInfo: PartnerInfo
+    lateinit var partnerInfo: EbicsTypes.PartnerInfo
 
     @get:XmlElement(name = "UserInfo", required = true)
-    lateinit var userInfo: UserInfo
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    @XmlType(name = "", propOrder = ["addressInfo", "bankInfo", 
"accountInfoList", "orderInfoList"])
-    class PartnerInfo {
-        @get:XmlElement(name = "AddressInfo", required = true)
-        lateinit var addressInfo: AddressInfo
-
-        @get:XmlElement(name = "BankInfo", required = true)
-        lateinit var bankInfo: BankInfo
-
-        @get:XmlElement(name = "AccountInfo", required = true)
-        var accountInfoList: List<AccountInfo>? = null
-
-        @get:XmlElement(name = "OrderInfo")
-        lateinit var orderInfoList: List<AuthOrderInfoType>
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    @XmlType(
-        name = "",
-        propOrder = ["orderType", "fileFormat", "transferType", "orderFormat", 
"description", "numSigRequired"]
-    )
-    class AuthOrderInfoType {
-        @get:XmlElement(name = "OrderType")
-        lateinit var orderType: String
-
-        @get:XmlElement(name = "FileFormat")
-        val fileFormat: EbicsTypes.FileFormatType? = null
-
-        @get:XmlElement(name = "TransferType")
-        lateinit var transferType: String
-
-        @get:XmlElement(name = "OrderFormat", required = false)
-        var orderFormat: String? = null
-
-        @get:XmlElement(name = "Description")
-        lateinit var description: String
-
-        @get:XmlElement(name = "NumSigRequired")
-        var numSigRequired: Int? = null
-
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class UserIDType {
-        @get:XmlValue
-        lateinit var value: String;
-
-        @get:XmlAttribute(name = "Status")
-        var status: Int? = null
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    @XmlType(name = "", propOrder = ["userID", "name", "permissionList"])
-    class UserInfo {
-        @get:XmlElement(name = "UserID", required = true)
-        lateinit var userID: UserIDType
-
-        @get:XmlElement(name = "Name")
-        var name: String? = null
-
-        @get:XmlElement(name = "Permission", type = UserPermission::class)
-        var permissionList: List<UserPermission>? = null
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    @XmlType(name = "", propOrder = ["orderTypes", "fileFormat", "accountID", 
"maxAmount"])
-    class UserPermission {
-        @get:XmlAttribute(name = "AuthorizationLevel")
-        var authorizationLevel: String? = null
-
-        @get:XmlElement(name = "OrderTypes")
-        var orderTypes: String? = null
-
-        @get:XmlElement(name = "FileFormat")
-        val fileFormat: EbicsTypes.FileFormatType? = null
-
-        @get:XmlElement(name = "AccountID")
-        val accountID: String? = null
-
-        @get:XmlElement(name = "MaxAmount")
-        val maxAmount: String? = null
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    @XmlType(name = "", propOrder = ["name", "street", "postCode", "city", 
"region", "country"])
-    class AddressInfo {
-        @get:XmlElement(name = "Name")
-        var name: String? = null
-
-        @get:XmlElement(name = "Street")
-        var street: String? = null
-
-        @get:XmlElement(name = "PostCode")
-        var postCode: String? = null
-
-        @get:XmlElement(name = "City")
-        var city: String? = null
-
-        @get:XmlElement(name = "Region")
-        var region: String? = null
-
-        @get:XmlElement(name = "Country")
-        var country: String? = null
-    }
-
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class BankInfo {
-        @get:XmlElement(name = "HostID")
-        lateinit var hostID: String
-
-        @get:XmlElement(type = EbicsTypes.Parameter::class)
-        var parameters: List<EbicsTypes.Parameter>? = null
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    @XmlType(name = "", propOrder = ["accountNumberList", "bankCodeList", 
"accountHolder"])
-    class AccountInfo {
-        @get:XmlAttribute(name = "Currency")
-        var currency: String? = null
-
-        @get:XmlAttribute(name = "ID")
-        lateinit var id: String
-
-        @get:XmlAttribute(name = "Description")
-        var description: String? = null
-
-        @get:XmlElements(
-            XmlElement(name = "AccountNumber", type = 
GeneralAccountNumber::class),
-            XmlElement(name = "NationalAccountNumber", type = 
NationalAccountNumber::class)
-        )
-        var accountNumberList: List<AbstractAccountNumber>? = null
-
-        @get:XmlElements(
-            XmlElement(name = "BankCode", type = GeneralBankCode::class),
-            XmlElement(name = "NationalBankCode", type = 
NationalBankCode::class)
-        )
-        var bankCodeList: List<AbstractBankCode>? = null
-
-        @get:XmlElement(name = "AccountHolder")
-        var accountHolder: String? = null
-    }
-
-    interface AbstractAccountNumber
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class GeneralAccountNumber : AbstractAccountNumber {
-        @get:XmlAttribute(name = "international")
-        var international: Boolean = false
-
-        @get:XmlValue
-        lateinit var value: String
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class NationalAccountNumber : AbstractAccountNumber {
-        @get:XmlAttribute(name = "format")
-        lateinit var format: String
-
-        @get:XmlValue
-        lateinit var value: String
-    }
-
-    interface AbstractBankCode
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class GeneralBankCode : AbstractBankCode {
-        @get:XmlAttribute(name = "prefix")
-        var prefix: String? = null
-
-        @get:XmlAttribute(name = "international")
-        var international: Boolean = false
-
-        @get:XmlValue
-        lateinit var value: String
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class NationalBankCode : AbstractBankCode {
-        @get:XmlValue
-        lateinit var value: String
-
-        @get:XmlAttribute(name = "format")
-        lateinit var format: String
-    }
+    lateinit var userInfo: EbicsTypes.UserInfo
 }
diff --git a/sandbox/src/test/kotlin/EbicsMessagesTest.kt 
b/sandbox/src/test/kotlin/EbicsMessagesTest.kt
index 3ab7ce5..d3009d6 100644
--- a/sandbox/src/test/kotlin/EbicsMessagesTest.kt
+++ b/sandbox/src/test/kotlin/EbicsMessagesTest.kt
@@ -177,13 +177,13 @@ class EbicsMessagesTest {
     @Test
     fun testHtd() {
         val htd = HTDResponseOrderData().apply {
-            this.partnerInfo = HTDResponseOrderData.PartnerInfo().apply {
+            this.partnerInfo = EbicsTypes.PartnerInfo().apply {
                 this.accountInfoList = listOf(
-                    HTDResponseOrderData.AccountInfo().apply {
+                    EbicsTypes.AccountInfo().apply {
                         this.id = "acctid1"
                         this.accountHolder = "Mina Musterfrau"
                         this.accountNumberList = listOf(
-                            HTDResponseOrderData.GeneralAccountNumber().apply {
+                            EbicsTypes.GeneralAccountNumber().apply {
                                 this.international = true
                                 this.value = "AT411100000237571500"
                             }
@@ -191,21 +191,21 @@ class EbicsMessagesTest {
                         this.currency = "EUR"
                         this.description = "some account"
                         this.bankCodeList = listOf(
-                            HTDResponseOrderData.GeneralBankCode().apply {
+                            EbicsTypes.GeneralBankCode().apply {
                                 this.international = true
                                 this.value = "ABAGATWWXXX"
                             }
                         )
                     }
                 )
-                this.addressInfo = HTDResponseOrderData.AddressInfo().apply {
+                this.addressInfo = EbicsTypes.AddressInfo().apply {
                     this.name = "Foo"
                 }
-                this.bankInfo = HTDResponseOrderData.BankInfo().apply {
+                this.bankInfo = EbicsTypes.BankInfo().apply {
                     this.hostID = "MYHOST"
                 }
                 this.orderInfoList = listOf(
-                    HTDResponseOrderData.AuthOrderInfoType().apply {
+                    EbicsTypes.AuthOrderInfoType().apply {
                         this.description = "foo"
                         this.orderType = "CCC"
                         this.orderFormat = "foo"
@@ -213,14 +213,14 @@ class EbicsMessagesTest {
                     }
                 )
             }
-            this.userInfo = HTDResponseOrderData.UserInfo().apply {
+            this.userInfo = EbicsTypes.UserInfo().apply {
                 this.name = "Some User"
-                this.userID = HTDResponseOrderData.UserIDType().apply {
+                this.userID = EbicsTypes.UserIDType().apply {
                     this.status = 2
                     this.value = "myuserid"
                 }
                 this.permissionList = listOf(
-                    HTDResponseOrderData.UserPermission().apply {
+                    EbicsTypes.UserPermission().apply {
                         this.orderTypes = "CCC ABC"
                     }
                 )

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]