[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] 01/06: Remove notion of "bank customer" from Sandbox.
From: |
gnunet |
Subject: |
[libeufin] 01/06: Remove notion of "bank customer" from Sandbox. |
Date: |
Wed, 29 Apr 2020 21:44:40 +0200 |
This is an automated email from the git hooks/post-receive script.
marcello pushed a commit to branch master
in repository libeufin.
commit 46d92a7f5212014266351aaf77e9f9b48e357e27
Author: Marcello Stanisci <address@hidden>
AuthorDate: Wed Apr 29 16:14:28 2020 +0200
Remove notion of "bank customer" from Sandbox.
---
integration-tests/test.py | 61 ------
nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 7 +-
nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt | 22 +-
nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 35 +++-
nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt | 4 +-
.../src/main/kotlin/tech/libeufin/sandbox/DB.kt | 99 ++-------
.../tech/libeufin/sandbox/EbicsProtocolBackend.kt | 48 +++--
.../src/main/kotlin/tech/libeufin/sandbox/JSON.kt | 128 ++----------
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 230 +++++----------------
sandbox/src/test/kotlin/CamtGeneration.kt | 45 ----
sandbox/src/test/kotlin/DbTest.kt | 137 ------------
util/src/main/kotlin/ebics_h004/EbicsResponse.kt | 1 -
12 files changed, 163 insertions(+), 654 deletions(-)
diff --git a/integration-tests/test.py b/integration-tests/test.py
deleted file mode 100755
index 2bb4623..0000000
--- a/integration-tests/test.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python3
-
-from requests import post, get
-
-#1 Create a Nexus user
-USERNAME="person"
-
-resp = post(
- "http://localhost:5001/users/{}".format(USERNAME),
- json=dict(
- password="secret"
- )
-)
-
-assert(resp.status_code == 200)
-
-#2 Create a EBICS user
-
-resp = post(
- "http://localhost:5001/ebics/subscribers/{}".format(USERNAME),
- json=dict(
- ebicsURL="http://localhost:5000/ebicsweb",
- hostID="HOST01",
- partnerID="PARTNER1",
- userID="USER1"
- )
-)
-
-assert(resp.status_code == 200)
-
-#3 Upload keys to the bank INI & HIA
-resp = post(
- "http://localhost:5001/ebics/subscribers/{}/sendINI".format(USERNAME),
- json=dict()
-)
-
-assert(resp.status_code == 200)
-
-resp = post(
- "http://localhost:5001/ebics/subscribers/{}/sendHIA".format(USERNAME),
- json=dict()
-)
-
-assert(resp.status_code == 200)
-
-#4 Download keys from the bank HPB
-resp = post(
- "http://localhost:5001/ebics/subscribers/{}/sync".format(USERNAME),
- json=dict()
-)
-
-assert(resp.status_code == 200)
-
-#5 Request history
-#6 Prepare a payment
-#7 Execute such payment via EBICS
-#8 Request history again
-#9 Exit
-
-# The Nexus should connect to the Sandbox for
-# these tests!
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index 8eafd3a..c850ea4 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -5,9 +5,6 @@ import org.jetbrains.exposed.dao.*
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.transactions.transaction
-import tech.libeufin.nexus.EbicsSubscribersTable.entityId
-import tech.libeufin.nexus.EbicsSubscribersTable.nullable
-import tech.libeufin.nexus.EbicsSubscribersTable.primaryKey
import tech.libeufin.util.IntIdTableWithAmount
import java.sql.Connection
@@ -86,7 +83,7 @@ class TalerIncomingPaymentEntity(id: EntityID<Long>) :
LongEntity(id) {
* CAMT message.
*/
object RawBankTransactionsTable : LongIdTable() {
- val nexusSubscriber = reference("subscriber", EbicsSubscribersTable)
+ val nexusUser = reference("nexusUser", NexusUsersTable)
val sourceFileName = text("sourceFileName") /* ZIP entry's name */
val unstructuredRemittanceInformation =
text("unstructuredRemittanceInformation")
val transactionType = text("transactionType") /* DBIT or CRDT */
@@ -114,7 +111,7 @@ class RawBankTransactionEntity(id: EntityID<Long>) :
LongEntity(id) {
var creditorIban by RawBankTransactionsTable.creditorIban
var counterpartBic by RawBankTransactionsTable.counterpartBic
var bookingDate by RawBankTransactionsTable.bookingDate
- var nexusSubscriber by EbicsSubscriberEntity referencedOn
RawBankTransactionsTable.nexusSubscriber
+ var nexusUser by NexusUserEntity referencedOn
RawBankTransactionsTable.nexusUser
var status by RawBankTransactionsTable.status
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
index 7336045..188aa2d 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
@@ -138,8 +138,11 @@ class TestSubscriber()
/** PAYMENT INSTRUCTIONS TYPES */
/** Represents a prepared payment at the nexus. This structure is
- * used to SHOW a prepared payment to the called. */
+ * used to SHOW a prepared payment to the caller. */
data class PaymentInfoElement(
+ /**
+ * This field is the mnemonic value that bank accounts usually have.
+ */
val debtorAccount: String,
val creditorIban: String,
val creditorBic: String,
@@ -160,4 +163,21 @@ data class Pain001Data(
val sum: Amount,
val currency: String = "EUR",
val subject: String
+)
+
+/**
+ * This type is more of a debug one, and it shows details
+ * about one payment that was accounted by the bank (typically
+ * in a CAMT.05x entry)
+ */
+data class RawPayment(
+ val creditorIban: String,
+ val debitorIban: String,
+ val amount: String,
+ val subject: String,
+ val date: String
+)
+
+data class RawPayments(
+ var payments: MutableList<RawPayment> = mutableListOf()
)
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index a5dc64a..1b87c27 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -45,6 +45,7 @@ import kotlinx.coroutines.io.jvm.javaio.toInputStream
import kotlinx.io.core.ExperimentalIoApi
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
+import org.joda.time.DateTime
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.slf4j.event.Level
@@ -285,6 +286,31 @@ fun main() {
)
return@post
}
+ get("/users/{id}/raw-payments") {
+ val nexusUser = extractNexusUser(call.parameters["id"])
+ var ret = RawPayments()
+ transaction {
+ RawBankTransactionEntity.find {
+ RawBankTransactionsTable.nexusUser eq
nexusUser.id.value
+ }.forEach {
+ ret.payments.add(
+ RawPayment(
+ creditorIban = it.creditorIban,
+ debitorIban = it.debitorIban,
+ subject = it.unstructuredRemittanceInformation,
+ date = DateTime(it.bookingDate).toDashedDate(),
+ amount = it.amount + " " + it.currency
+ )
+ )
+ }
+ }
+ call.respond(
+ HttpStatusCode.OK,
+ ret
+ )
+ return@get
+ }
+
/** Associate a EBICS subscriber to the existing user */
post("/ebics/subscribers/{id}") {
val nexusUser = extractNexusUser(call.parameters["id"])
@@ -587,10 +613,6 @@ fun main() {
)
return@post
}
- post("/ebics/subscribers/{id}/collect-transactions-c52") {
- // FIXME(florian): Download C52 and store the result in the
right database table
-
- }
/** exports keys backup copy */
post("/ebics/subscribers/{id}/backup") {
val body = call.receive<EbicsBackupRequestJson>()
@@ -628,7 +650,6 @@ fun main() {
response
)
}
-
/** Download keys from bank */
post("/ebics/subscribers/{id}/sync") {
val nexusUser = extractNexusUser(call.parameters["id"])
@@ -696,13 +717,13 @@ fun main() {
transaction {
RawBankTransactionEntity.new {
sourceFileName = fileName
- unstructuredRemittanceInformation =
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']/@Ccy")
+ unstructuredRemittanceInformation =
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Ustrd']")
transactionType =
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='CdtDbtInd']")
currency =
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']/@Ccy")
amount =
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']")
status =
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Sts']")
bookingDate =
parseDate(camt53doc.pickString("//*[local-name()='BookgDt']//*[local-name()='Dt']")).millis
- nexusSubscriber =
getSubscriberEntityFromNexusUserId(id)
+ nexusUser = extractNexusUser(id)
creditorName =
camt53doc.pickString("//*[local-name()='RltdPties']//*[local-name()='Dbtr']//*[local-name()='Nm']")
creditorIban =
camt53doc.pickString("//*[local-name()='CdtrAcct']//*[local-name()='IBAN']")
debitorName =
camt53doc.pickString("//*[local-name()='RltdPties']//*[local-name()='Dbtr']//*[local-name()='Nm']")
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
index 6e4b110..db8ad63 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
@@ -282,7 +282,7 @@ class Taler(app: Route) {
creditorIban = creditorObj.iban
counterpartBic = creditorObj.bic
bookingDate = DateTime.now().millis
- nexusSubscriber = getEbicsSubscriberFromUser(nexusUser)
+ this.nexusUser = nexusUser
status = "BOOK"
}
} else null
@@ -338,7 +338,7 @@ class Taler(app: Route) {
counterpartBic = debtor.bic
bookingDate = DateTime.now().millis
status = "BOOK"
- nexusSubscriber =
getSubscriberEntityFromNexusUserId(exchangeId)
+ nexusUser = extractNexusUser(exchangeId)
}
/** This payment is "valid by default" and will be returned
* as soon as the exchange will ask for new payments. */
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
index b9d872b..d91f1b2 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
@@ -19,27 +19,12 @@
package tech.libeufin.sandbox
-import io.ktor.http.HttpStatusCode
import org.jetbrains.exposed.dao.*
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.transactions.transaction
-import tech.libeufin.util.IntIdTableWithAmount
-import java.lang.ArithmeticException
-import java.math.BigDecimal
-import java.math.MathContext
-import java.math.RoundingMode
-import java.sql.Blob
import java.sql.Connection
-const val CUSTOMER_NAME_MAX_LENGTH = 20
-const val EBICS_HOST_ID_MAX_LENGTH = 10
-const val EBICS_USER_ID_MAX_LENGTH = 10
-const val EBICS_PARTNER_ID_MAX_LENGTH = 10
-const val EBICS_SYSTEM_ID_MAX_LENGTH = 10
-const val MAX_ID_LENGTH = 21 // enough to contain IBANs
-const val MAX_SUBJECT_LENGTH = 140 // okay?
-
/**
* All the states to give a subscriber.
*/
@@ -93,48 +78,6 @@ enum class KeyState {
RELEASED
}
-
-object BankTransactionsTable : IntIdTableWithAmount() {
- /* Using varchar to store the IBAN - or possibly other formats
- * - from the counterpart. */
- val counterpart = varchar("counterpart", MAX_ID_LENGTH)
- val amount = amount("amount")
- val subject = varchar("subject", MAX_SUBJECT_LENGTH)
- val operationDate = long("operationDate")
- val valueDate = long("valueDate")
- val localCustomer = reference("localCustomer", BankCustomersTable)
-}
-
-class BankTransactionEntity(id: EntityID<Int>) : IntEntity(id) {
- companion object :
IntEntityClass<BankTransactionEntity>(BankTransactionsTable)
- /* the id of the local customer involved in this transaction,
- * either as the credit or the debit part; makes lookups easier */
- var localCustomer by BankCustomerEntity referencedOn
BankTransactionsTable.localCustomer
- /* keeping as strings, as to allow hosting IBANs and/or other
- * unobvious formats. */
- var counterpart by BankTransactionsTable.counterpart
- var subject by BankTransactionsTable.subject
- var operationDate by BankTransactionsTable.operationDate
- var valueDate by BankTransactionsTable.valueDate
- var amount by BankTransactionsTable.amount
-}
-
-
-/**
- * This table information *not* related to EBICS, for all
- * its customers.
- */
-object BankCustomersTable : IntIdTable() {
- // Customer ID is the default 'id' field provided by the constructor.
- val customerName = varchar("customerName", CUSTOMER_NAME_MAX_LENGTH)
-}
-
-class BankCustomerEntity(id: EntityID<Int>) : IntEntity(id) {
- companion object : IntEntityClass<BankCustomerEntity>(BankCustomersTable)
- var customerName by BankCustomersTable.customerName
-}
-
-
/**
* This table stores RSA public keys of subscribers.
*/
@@ -142,10 +85,6 @@ object EbicsSubscriberPublicKeysTable : IntIdTable() {
val rsaPublicKey = blob("rsaPublicKey")
val state = enumeration("state", KeyState::class)
}
-
-/**
- * Definition of a row in the [EbicsSubscriberPublicKeyEntity] table
- */
class EbicsSubscriberPublicKeyEntity(id: EntityID<Int>) : IntEntity(id) {
companion object :
IntEntityClass<EbicsSubscriberPublicKeyEntity>(EbicsSubscriberPublicKeysTable)
@@ -153,7 +92,9 @@ class EbicsSubscriberPublicKeyEntity(id: EntityID<Int>) :
IntEntity(id) {
var state by EbicsSubscriberPublicKeysTable.state
}
-
+/**
+ * Ebics 'host'(s) that are served by one Sandbox instance.
+ */
object EbicsHostsTable : IntIdTable() {
val hostID = text("hostID")
val ebicsVersion = text("ebicsVersion")
@@ -161,11 +102,8 @@ object EbicsHostsTable : IntIdTable() {
val encryptionPrivateKey = blob("encryptionPrivateKey")
val authenticationPrivateKey = blob("authenticationPrivateKey")
}
-
-
class EbicsHostEntity(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<EbicsHostEntity>(EbicsHostsTable)
-
var hostId by EbicsHostsTable.hostID
var ebicsVersion by EbicsHostsTable.ebicsVersion
var signaturePrivateKey by EbicsHostsTable.signaturePrivateKey
@@ -174,8 +112,7 @@ class EbicsHostEntity(id: EntityID<Int>) : IntEntity(id) {
}
/**
- * Subscribers table. This table associates users with partners
- * and systems. Each value can appear multiple times in the same column.
+ * Ebics Subscribers table.
*/
object EbicsSubscribersTable : IntIdTable() {
val userId = text("userID")
@@ -187,28 +124,23 @@ object EbicsSubscribersTable : IntIdTable() {
val authenticationKey = reference("authorizationKey",
EbicsSubscriberPublicKeysTable).nullable()
val nextOrderID = integer("nextOrderID")
val state = enumeration("state", SubscriberState::class)
- val bankCustomer = reference("bankCustomer", BankCustomersTable)
}
-
-
class EbicsSubscriberEntity(id: EntityID<Int>) : IntEntity(id) {
companion object :
IntEntityClass<EbicsSubscriberEntity>(EbicsSubscribersTable)
-
var userId by EbicsSubscribersTable.userId
var partnerId by EbicsSubscribersTable.partnerId
var systemId by EbicsSubscribersTable.systemId
var hostId by EbicsSubscribersTable.hostId
-
var signatureKey by EbicsSubscriberPublicKeyEntity optionalReferencedOn
EbicsSubscribersTable.signatureKey
var encryptionKey by EbicsSubscriberPublicKeyEntity optionalReferencedOn
EbicsSubscribersTable.encryptionKey
var authenticationKey by EbicsSubscriberPublicKeyEntity
optionalReferencedOn EbicsSubscribersTable.authenticationKey
-
var nextOrderID by EbicsSubscribersTable.nextOrderID
var state by EbicsSubscribersTable.state
- var bankCustomer by BankCustomerEntity referencedOn
EbicsSubscribersTable.bankCustomer
}
-
+/**
+ * Details of a download order.
+ */
object EbicsDownloadTransactionsTable : IdTable<String>() {
override val id = text("transactionID").entityId()
val orderType = text("orderType")
@@ -220,7 +152,6 @@ object EbicsDownloadTransactionsTable : IdTable<String>() {
val segmentSize = integer("segmentSize")
val receiptReceived = bool("receiptReceived")
}
-
class EbicsDownloadTransactionEntity(id: EntityID<String>) :
Entity<String>(id) {
companion object : EntityClass<String,
EbicsDownloadTransactionEntity>(EbicsDownloadTransactionsTable)
var orderType by EbicsDownloadTransactionsTable.orderType
@@ -233,6 +164,9 @@ class EbicsDownloadTransactionEntity(id: EntityID<String>)
: Entity<String>(id)
var receiptReceived by EbicsDownloadTransactionsTable.receiptReceived
}
+/**
+ * Details of a upload order.
+ */
object EbicsUploadTransactionsTable : IdTable<String>() {
override val id = text("transactionID").entityId()
val orderType = text("orderType")
@@ -243,10 +177,8 @@ object EbicsUploadTransactionsTable : IdTable<String>() {
val lastSeenSegment = integer("lastSeenSegment")
val transactionKeyEnc = blob("transactionKeyEnc")
}
-
class EbicsUploadTransactionEntity(id: EntityID<String>) : Entity<String>(id) {
companion object : EntityClass<String,
EbicsUploadTransactionEntity>(EbicsUploadTransactionsTable)
-
var orderType by EbicsUploadTransactionsTable.orderType
var orderID by EbicsUploadTransactionsTable.orderID
var host by EbicsHostEntity referencedOn EbicsUploadTransactionsTable.host
@@ -256,6 +188,9 @@ class EbicsUploadTransactionEntity(id: EntityID<String>) :
Entity<String>(id) {
var transactionKeyEnc by EbicsUploadTransactionsTable.transactionKeyEnc
}
+/**
+ * FIXME: document this.
+ */
object EbicsOrderSignaturesTable : IntIdTable() {
val orderID = text("orderID")
val orderType = text("orderType")
@@ -264,7 +199,6 @@ object EbicsOrderSignaturesTable : IntIdTable() {
val signatureAlgorithm = text("signatureAlgorithm")
val signatureValue = blob("signatureValue")
}
-
class EbicsOrderSignatureEntity(id: EntityID<Int>) : IntEntity(id) {
companion object :
IntEntityClass<EbicsOrderSignatureEntity>(EbicsOrderSignaturesTable)
var orderID by EbicsOrderSignaturesTable.orderID
@@ -275,13 +209,15 @@ class EbicsOrderSignatureEntity(id: EntityID<Int>) :
IntEntity(id) {
var signatureValue by EbicsOrderSignaturesTable.signatureValue
}
+/**
+ * FIXME: document this.
+ */
object EbicsUploadTransactionChunksTable : IdTable<String>() {
override val id =
text("transactionID").entityId()
val chunkIndex = integer("chunkIndex")
val chunkContent = blob("chunkContent")
}
-
class EbicsUploadTransactionChunkEntity(id : EntityID<String>):
Entity<String>(id) {
companion object : EntityClass<String,
EbicsUploadTransactionChunkEntity>(EbicsUploadTransactionChunksTable)
var chunkIndex by EbicsUploadTransactionChunksTable.chunkIndex
@@ -292,12 +228,9 @@ class EbicsUploadTransactionChunkEntity(id :
EntityID<String>): Entity<String>(i
fun dbCreateTables() {
Database.connect("jdbc:sqlite:libeufin-sandbox.sqlite3", "org.sqlite.JDBC")
TransactionManager.manager.defaultIsolationLevel =
Connection.TRANSACTION_SERIALIZABLE
-
transaction {
addLogger(StdOutSqlLogger)
SchemaUtils.create(
- BankCustomersTable,
- BankTransactionsTable,
EbicsSubscribersTable,
EbicsHostsTable,
EbicsDownloadTransactionsTable,
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
index 0113413..b7d309c 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
@@ -140,7 +140,7 @@ private suspend fun
ApplicationCall.respondEbicsKeyManagement(
respondText(text, ContentType.Application.Xml, HttpStatusCode.OK)
}
-fun buildCamtString(history: SizedIterable<BankTransactionEntity>, type: Int):
String {
+fun buildCamtString(type: Int): String {
/**
* Booking period: we keep two "lines" of booking periods; one for c52 and
one for c53.
@@ -409,22 +409,14 @@ fun buildCamtString(history:
SizedIterable<BankTransactionEntity>, type: Int): S
* @param history the list of all the history elements
* @param type 52 or 53.
*/
-private fun constructCamtResponse(type: Int, customerId: Int, header:
EbicsRequest.Header): String {
-
+private fun constructCamtResponse(type: Int, header: EbicsRequest.Header):
String {
val dateRange = (header.static.orderDetails?.orderParams as
EbicsRequest.StandardOrderParams).dateRange
val (start: org.joda.time.DateTime, end: org.joda.time.DateTime) = if
(dateRange != null) {
Pair(DateTime(dateRange.start.toGregorianCalendar().time),
DateTime(dateRange.end.toGregorianCalendar().time))
} else Pair(DateTime(0), DateTime.now())
- val history = extractHistory(
- customerId,
- start,
- end
- )
- logger.debug("${history.count()} history elements found for account
$customerId")
- return buildCamtString(history, type)
+ return buildCamtString(type)
}
-
private fun handleEbicsTSD(requestContext: RequestContext): ByteArray {
return "Hello World".toByteArray()
}
@@ -433,11 +425,36 @@ private fun handleEbicsPTK(requestContext:
RequestContext): ByteArray {
return "Hello I am a dummy PTK response.".toByteArray()
}
+/**
+ * Process a payment request in the pain.001 format.
+ */
+private fun handleCct(paymentRequest: String, ebicsSubscriberEntity:
EbicsSubscriberEntity) {
+ /**
+ * NOTE: this function is ONLY required to store some details
+ * to put then in the camt report. IBANs / amount / subject / names?
+ */
+ val painDoc = XMLUtil.parseStringIntoDom(paymentRequest)
+ val creditorIban =
painDoc.pickString("//*[local-name()='CdtrAcct']//*[local-name()='IBAN']")
+ val debitorIban =
painDoc.pickString("//*[local-name()='DbtrAcct']//*[local-name()='IBAN']")
+ val subject = painDoc.pickString("//*[local-name()='Ustrd']")
+ val currency = painDoc.pickString("//*[local-name()='InstdAmt']/@ccy")
+ val amount = painDoc.pickString("//*[local-name()='InstdAmt']")
+
+ /*
+ transaction {
+ PaymentEntity.new {
+ this.creditorIban = creditorIban
+ this.debitorIban = debitorIban
+ this.subject = subject
+ this.amount = "${currency}:${amount}"
+ }
+ }*/
+}
+
private fun handleEbicsC52(requestContext: RequestContext): ByteArray {
val subscriber = requestContext.subscriber
val camt = constructCamtResponse(
52,
- subscriber.bankCustomer.id.value,
requestContext.requestObject.header
)
return camt.toByteArray().zip()
@@ -447,7 +464,6 @@ private fun handleEbicsC53(requestContext: RequestContext):
ByteArray {
val subscriber = requestContext.subscriber
val camt = constructCamtResponse(
53,
- subscriber.bankCustomer.id.value,
requestContext.requestObject.header
)
return camt.toByteArray().zip()
@@ -612,7 +628,6 @@ private suspend fun ApplicationCall.receiveEbicsXml():
Document {
return requestDocument
}
-
fun handleEbicsHtd(): ByteArray {
val htd = HTDResponseOrderData().apply {
this.partnerInfo = EbicsTypes.PartnerInfo().apply {
@@ -909,7 +924,6 @@ private fun
handleEbicsUploadTransactionInitialization(requestContext: RequestCo
return EbicsResponse.createForUploadInitializationPhase(transactionID,
orderID)
}
-
private fun handleEbicsUploadTransactionTransmission(requestContext:
RequestContext): EbicsResponse {
val uploadTransaction = requestContext.uploadTransaction ?: throw
EbicsInvalidRequestError()
val requestObject = requestContext.requestObject
@@ -952,6 +966,10 @@ private fun
handleEbicsUploadTransactionTransmission(requestContext: RequestCont
}
}
+ /** Handling a payment request */
+ if ("CCT" ==
requestContext.requestObject.header.static.orderDetails?.orderType) {
+ handleCct(unzippedData.toString(Charsets.UTF_8),
requestContext.subscriber)
+ }
return EbicsResponse.createForUploadTransferPhase(
requestTransactionID,
requestSegmentNumber,
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
index 997cf57..1440afc 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
@@ -19,122 +19,23 @@
package tech.libeufin.sandbox
-/**
- * Error message.
- */
+/** Error message */
data class SandboxError(
val message: String
)
/**
- * Request for POST /admin/customers
- */
-data class CustomerRequest(
- val name: String
-)
-
-data class CustomerResponse(
- val id: Int
-)
-
-data class CustomerBalance(
- val name: String,
- val balance: String
-)
-
-/**
- * Response for GET /admin/customers/:id
- */
-data class CustomerInfo(
- val name: String,
- val ebicsInfo: CustomerEbicsInfo
-)
-
-data class CustomerEbicsInfo(
- val userId: String
-)
-
-data class CustomerHistoryRequest(
- val start: String?,
- val end: String?
-)
-
-data class CustomerHistoryResponseElement(
- var amount: String,
- val subject: String,
- val counterpart: String,
- val operationDate: String,
- val valueDate: String
-)
-
-data class CustomerHistoryResponse(
- var history: MutableList<CustomerHistoryResponseElement> = mutableListOf()
-)
-
-/**
- * Wrapper type around initialization letters
- * for RSA keys.
+ * Used to show the list of Ebics hosts that exist
+ * in the system.
*/
-data class IniHiaLetters(
- val ini: IniLetter,
- val hia: HiaLetter
-)
-
-/**
- * Request for INI letter.
- */
-data class IniLetter(
- val userId: String,
- val customerId: String,
- val name: String,
- val date: String,
- val time: String,
- val recipient: String,
- val public_exponent_length: Int,
- val public_exponent: String,
- val public_modulus_length: Int,
- val public_modulus: String,
- val hash: String
-)
-
-/**
- * Request for HIA letter.
- */
-data class HiaLetter(
- val userId: String,
- val customerId: String,
- val name: String,
- val date: String,
- val time: String,
- val recipient: String,
- val ia_public_exponent_length: Int,
- val ia_public_exponent: String,
- val ia_public_modulus_length: Int,
- val ia_public_modulus: String,
- val ia_hash: String,
- val enc_public_exponent_length: Int,
- val enc_public_exponent: String,
- val enc_public_modulus_length: Int,
- val enc_public_modulus: String,
- val enc_hash: String
-)
-
-data class EbicsSubscribersResponse(
- val subscribers: List<String>
-)
-
-data class EbicsSubscriberResponse(
- val id: String,
- val partnerID: String,
- val userID: String,
- val systemID: String?,
- val state: String
-)
-
data class EbicsHostsResponse(
val ebicsHosts: List<String>
)
+/**
+ * Used to show information about ONE particular
+ * Ebics host that is active in the system.
+ */
data class EbicsHostResponse(
val hostID: String,
val ebicsVersion: String
@@ -145,21 +46,16 @@ data class EbicsHostCreateRequest(
val ebicsVersion: String
)
-data class AdminAddSubscriberRequest(
- val name: String, // person's name
+/**
+ * Used to create AND show one Ebics subscriber in the system.
+ */
+data class EbicsSubscriberElement(
val hostID: String,
val partnerID: String,
val userID: String,
val systemID: String? = null
)
-data class AdminSubscriberElement(
- var name: String,
- var userId: String,
- var partnerID: String,
- var hostID: String
-)
-
data class AdminGetSubscribers(
- var subscribers: MutableList<AdminSubscriberElement> = mutableListOf()
+ var subscribers: MutableList<EbicsSubscriberElement> = mutableListOf()
)
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 2af9c6a..23fec93 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -60,20 +60,6 @@ class UnacceptableFractional(badNumber: BigDecimal) :
Exception(
"Unacceptable fractional part ${badNumber}"
)
val LOGGER: Logger = LoggerFactory.getLogger("tech.libeufin.sandbox")
-fun findCustomer(id: String?): BankCustomerEntity {
-
- val idN = try {
- id!!.toInt()
- } catch (e: Exception) {
- e.printStackTrace()
- throw BadInputData(id)
- }
-
- return transaction {
- addLogger(StdOutSqlLogger)
- BankCustomerEntity.findById(idN) ?: throw CustomerNotFound(id)
- }
-}
fun findEbicsSubscriber(partnerID: String, userID: String, systemID: String?):
EbicsSubscriberEntity? {
return if (systemID == null) {
@@ -120,82 +106,8 @@ fun BigDecimal.signToString(): String {
// minus sign is added by default already.
}
-fun sampleData() {
- transaction {
- val pairA = CryptoUtil.generateRsaKeyPair(2048)
- val pairB = CryptoUtil.generateRsaKeyPair(2048)
- val pairC = CryptoUtil.generateRsaKeyPair(2048)
- EbicsHostEntity.new {
- hostId = "host01"
- ebicsVersion = "H004"
- authenticationPrivateKey = SerialBlob(pairA.private.encoded)
- encryptionPrivateKey = SerialBlob(pairB.private.encoded)
- signaturePrivateKey = SerialBlob(pairC.private.encoded)
- }
- val customerEntity = BankCustomerEntity.new {
- addLogger(StdOutSqlLogger)
- customerName = "Mina"
- }
- LOGGER.debug("Creating customer number: ${customerEntity.id}")
- EbicsSubscriberEntity.new {
- partnerId = "PARTNER1"
- userId = "USER1"
- systemId = null
- hostId = "HOST01"
- state = SubscriberState.NEW
- nextOrderID = 1
- bankCustomer = customerEntity
- }
- for (i in listOf(Amount("-0.44"), Amount("6.02"))) {
- BankTransactionEntity.new {
- counterpart = "IBAN"
- amount = i
- subject = "transaction $i"
- operationDate = DateTime.now().millis
- valueDate = DateTime.now().millis
- localCustomer = customerEntity
- }
- }
- }
-}
-
-/**
- * @param id the customer whose history must be returned. This
- * id is local to the bank and is not reused/encoded into other
- * EBICS id values.
- *
- * @return result set of all the operations related to the customer
- * identified by @p id.
- */
-fun extractHistory(id: Int, start: DateTime, end: DateTime):
SizedIterable<BankTransactionEntity> {
- LOGGER.debug("Fetching history from ${start.toLocalDateTime()} to
${end.toLocalDateTime()}")
- return transaction {
- addLogger(StdOutSqlLogger)
- BankTransactionEntity.find {
- BankTransactionsTable.localCustomer eq id and
BankTransactionsTable.valueDate.between(start.millis, end.millis)
- }
- }
-}
-
-fun calculateBalance(id: Int, start: String?, end: String?): BigDecimal {
- val s = if (start != null) DateTime.parse(start) else DateTime(0)
- val e = if (end != null) DateTime.parse(end) else DateTime.now()
-
- var ret = BigDecimal(0)
-
- transaction {
- BankTransactionEntity.find {
- BankTransactionsTable.localCustomer eq id and
BankTransactionsTable.operationDate.between(s.millis, e.millis)
- }.forEach { ret += it.amount }
- }
- return ret
-}
-
fun main() {
-
dbCreateTables()
- sampleData()
-
val server = embeddedServer(Netty, port = 5000) {
install(CallLogging) {
this.level = Level.DEBUG
@@ -225,87 +137,65 @@ fun main() {
}
}
routing {
- post("/{id}/history") {
- val req = call.receive<CustomerHistoryRequest>()
- val customer = findCustomer(call.parameters["id"])
- val ret = CustomerHistoryResponse()
- val history = extractHistory(
- customer.id.value,
- DateTime.parse(req.start ?: "1970-01-01"),
- DateTime.parse(req.end ?: "3000-01-01")
- )
+ get("/") {
+ call.respondText("Hello Sandbox!\n", ContentType.Text.Plain)
+ }
+ /** EBICS ADMIN ENDPOINTS */
+
+ post("/admin/ebics-subscriber") {
+ val body = call.receive<EbicsSubscriberElement>()
transaction {
- history.forEach {
- ret.history.add(
- CustomerHistoryResponseElement(
- subject = it.subject,
- amount =
"${it.amount.signToString()}${it.amount} EUR",
- counterpart = it.counterpart,
- operationDate =
DateTime(it.operationDate).toString("Y-M-d"),
- valueDate =
DateTime(it.valueDate).toString("Y-M-d")
- )
- )
+ EbicsSubscriberEntity.new {
+ partnerId = body.partnerID
+ userId = body.userID
+ systemId = null
+ hostId = body.hostID
+ state = SubscriberState.NEW
+ nextOrderID = 1
}
}
- call.respond(ret)
- return@post
- }
- get("/{id}/balance") {
- val customer = findCustomer(call.parameters["id"])
- val balance = calculateBalance(customer.id.value, null, null)
- call.respond(
- CustomerBalance(
- name = customer.customerName,
- balance = "${balance} EUR"
- )
+ call.respondText(
+ "Subscriber created.",
+ ContentType.Text.Plain, HttpStatusCode.OK
)
- return@get
+ return@post
}
- get("/admin/subscribers") {
+ get("/admin/ebics-subscribers") {
var ret = AdminGetSubscribers()
transaction {
EbicsSubscriberEntity.all().forEach {
ret.subscribers.add(
- AdminSubscriberElement(
- userId = it.userId, partnerID = it.partnerId,
hostID = it.hostId, name = it.bankCustomer.customerName))
+ EbicsSubscriberElement(
+ userID = it.userId,
+ partnerID = it.partnerId,
+ hostID = it.hostId
+ )
+ )
}
}
call.respond(ret)
return@get
}
- post("/admin/add/subscriber") {
- val body = call.receive<AdminAddSubscriberRequest>()
- transaction {
- val customerEntity = BankCustomerEntity.new {
- addLogger(StdOutSqlLogger)
- customerName = body.name
- }
- EbicsSubscriberEntity.new {
- partnerId = body.partnerID
- userId = body.userID
- systemId = null
- hostId = body.hostID
- state = SubscriberState.NEW
- nextOrderID = 1
- bankCustomer = customerEntity
- }
+ /* Show details about ONE Ebics host */
+ get("/ebics/hosts/{id}") {
+ val resp = transaction {
+ val host = EbicsHostEntity.find { EbicsHostsTable.hostID
eq call.parameters["id"]!! }.firstOrNull()
+ if (host == null) null
+ else EbicsHostResponse(
+ host.hostId,
+ host.ebicsVersion
+ )
}
-
- call.respondText("Subscriber created.",
ContentType.Text.Plain, HttpStatusCode.OK)
- return@post
+ if (resp == null) call.respond(
+ HttpStatusCode.NotFound,
+ SandboxError("host not found")
+ )
+ else call.respond(resp)
}
- get("/") {
- call.respondText("Hello LibEuFin!\n", ContentType.Text.Plain)
- }
- get("/ebics/hosts") {
- val ebicsHosts = transaction {
- EbicsHostEntity.all().map { it.hostId }
- }
- call.respond(EbicsHostsResponse(ebicsHosts))
- }
+ /** Create a new EBICS host. */
post("/ebics/hosts") {
val req = call.receive<EbicsHostCreateRequest>()
val pairA = CryptoUtil.generateRsaKeyPair(2048)
@@ -323,47 +213,25 @@ fun main() {
}
}
call.respondText(
- "Host created.",
+ "Host '${req.hostId}' created.",
ContentType.Text.Plain,
HttpStatusCode.OK
)
return@post
}
- get("/ebics/hosts/{id}") {
- val resp = transaction {
- val host = EbicsHostEntity.find { EbicsHostsTable.hostID
eq call.parameters["id"]!! }.firstOrNull()
- if (host == null) null
- else EbicsHostResponse(host.hostId, host.ebicsVersion)
- }
- if (resp == null) call.respond(
- HttpStatusCode.NotFound,
- SandboxError("host not found")
- )
- else call.respond(resp)
- }
- get("/ebics/subscribers") {
- val subscribers = transaction {
- EbicsSubscriberEntity.all().map { it.id.value.toString() }
- }
- call.respond(EbicsSubscribersResponse(subscribers))
- }
- get("/ebics/subscribers/{id}") {
- val resp = transaction {
- val id = call.parameters["id"]!!
- val subscriber =
EbicsSubscriberEntity.findById(id.toInt())!!
- EbicsSubscriberResponse(
- id,
- subscriber.partnerId,
- subscriber.userId,
- subscriber.systemId,
- subscriber.state.name
- )
+ /* Show ONLY names of all the Ebics hosts */
+ get("/ebics/hosts") {
+ val ebicsHosts = transaction {
+ EbicsHostEntity.all().map { it.hostId }
}
- call.respond(resp)
+ call.respond(EbicsHostsResponse(ebicsHosts))
}
+
+ /** MAIN EBICS handler. */
post("/ebicsweb") {
call.ebicsweb()
}
+
}
}
LOGGER.info("Up and running")
diff --git a/sandbox/src/test/kotlin/CamtGeneration.kt
b/sandbox/src/test/kotlin/CamtGeneration.kt
deleted file mode 100644
index 2b789ab..0000000
--- a/sandbox/src/test/kotlin/CamtGeneration.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package tech.libeufin.sandbox
-
-import org.jetbrains.exposed.sql.transactions.transaction
-import org.joda.time.DateTime
-import org.junit.Test
-import org.junit.Before
-import tech.libeufin.util.Amount
-import org.jetbrains.exposed.sql.SchemaUtils
-import org.jetbrains.exposed.sql.Database
-
-class CamtGeneration {
-
- @Before
- fun connectAndMakeTables() {
- Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver =
"org.h2.Driver")
- transaction {
- SchemaUtils.create(BankCustomersTable)
- SchemaUtils.create(BankTransactionsTable)
- }
- }
-
- @Test
- fun generateCamt() {
- transaction {
- val customer = BankCustomerEntity.new {
- customerName = "payer"
- }
- for (iter in 1..5) {
- BankTransactionEntity.new {
- localCustomer = customer
- counterpart = "IBAN${iter}"
- subject = "subject #${iter}"
- operationDate = DateTime.parse("3000-01-01").millis
- valueDate = DateTime.parse("3000-01-02").millis
- amount = Amount("${iter}.0")
- }
- }
- val string = buildCamtString(
- BankTransactionEntity.all(),
- 53
- )
- println(string)
- }
- }
-}
\ No newline at end of file
diff --git a/sandbox/src/test/kotlin/DbTest.kt
b/sandbox/src/test/kotlin/DbTest.kt
deleted file mode 100644
index a0ff853..0000000
--- a/sandbox/src/test/kotlin/DbTest.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-package tech.libeufin.sandbox
-
-import org.jetbrains.exposed.exceptions.ExposedSQLException
-import org.jetbrains.exposed.sql.Database
-import org.jetbrains.exposed.sql.SchemaUtils
-import org.jetbrains.exposed.sql.transactions.transaction
-import org.joda.time.DateTime
-import org.junit.Before
-import org.junit.Test
-import java.io.ByteArrayOutputStream
-import java.io.PrintStream
-import java.math.BigDecimal
-import java.math.BigInteger
-import java.math.MathContext
-import java.math.RoundingMode
-import kotlin.math.abs
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertTrue
-import tech.libeufin.util.Amount
-import tech.libeufin.util.BadAmount
-
-
-class DbTest {
-
- @Before
- fun muteStderr() {
- System.setErr(PrintStream(ByteArrayOutputStream()))
- }
-
- @Before
- fun connectAndMakeTables() {
- Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver =
"org.h2.Driver")
- transaction {
- SchemaUtils.create(BankTransactionsTable)
- SchemaUtils.create(BankCustomersTable)
- }
- }
-
- @Test
- fun customers() {
- transaction {
- BankCustomerEntity.new {
- customerName = "Test Name"
- }
- findCustomer("1")
- }
- }
-
-
- @Test
- fun goodAmount() {
-
- transaction {
- BankTransactionEntity.new {
- amount = Amount("1")
- counterpart = "IBAN"
- subject = "Salary"
- operationDate = DateTime.now().millis
- valueDate = DateTime.now().millis
- localCustomer = BankCustomerEntity.new {
- customerName = "employee"
- }
- }
-
- BankTransactionEntity.new {
- amount = Amount("1.11")
- counterpart = "IBAN"
- subject = "Salary"
- operationDate = DateTime.now().millis
- valueDate = DateTime.now().millis
- localCustomer = BankCustomerEntity.new {
- customerName = "employee"
- }
- }
-
- BankTransactionEntity.new {
- amount = Amount("1.110000000000") // BigDecimal does not crop
the trailing zeros
- counterpart = "IBAN"
- subject = "Salary"
- operationDate = DateTime.now().millis
- valueDate = DateTime.now().millis
- localCustomer = BankCustomerEntity.new {
- customerName = "employee"
- }
- }
- }
- }
-
- @Test
- fun badAmount() {
- assertFailsWith<BadAmount> {
- transaction {
- BankTransactionEntity.new {
- amount = Amount("1.10001")
- counterpart = "IBAN"
- subject = "Salary"
- operationDate = DateTime.now().millis
- valueDate = DateTime.now().millis
- localCustomer = BankCustomerEntity.new {
- customerName = "employee"
- }
- }
- }
- }
- }
-
- @Test
- fun timeBasedQuery() {
-
-
- val NQUERIES = 10
-
- transaction {
-
- for (i in 1..NQUERIES) {
- BankTransactionEntity.new {
- amount = Amount("1")
- counterpart = "IBAN"
- subject = "Salary"
- operationDate = DateTime.now().millis
- valueDate = DateTime.now().millis
- localCustomer = BankCustomerEntity.new {
- customerName = "employee"
- }
- }
- }
-
- assertEquals(
- NQUERIES,
- BankTransactionEntity.find {
-
BankTransactionsTable.valueDate.between(DateTime.parse("1970-01-01").millis,
DateTime.parse("2999-12-31").millis)
- }.count()
- )
- }
- }
-}
\ No newline at end of file
diff --git a/util/src/main/kotlin/ebics_h004/EbicsResponse.kt
b/util/src/main/kotlin/ebics_h004/EbicsResponse.kt
index 67a8b02..bdc17b0 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsResponse.kt
+++ b/util/src/main/kotlin/ebics_h004/EbicsResponse.kt
@@ -150,7 +150,6 @@ class EbicsResponse {
}
}
-
fun createForDownloadReceiptPhase(transactionID: String, positiveAck:
Boolean): EbicsResponse {
return EbicsResponse().apply {
this.version = "H004"
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [libeufin] branch master updated (b6e9340 -> 13bfc9f), gnunet, 2020/04/29
- [libeufin] 02/06: remove empty lines, gnunet, 2020/04/29
- [libeufin] 03/06: Integration test., gnunet, 2020/04/29
- [libeufin] 06/06: Abstracting on "bank account"., gnunet, 2020/04/29
- [libeufin] 04/06: Integration test., gnunet, 2020/04/29
- [libeufin] 01/06: Remove notion of "bank customer" from Sandbox.,
gnunet <=
- [libeufin] 05/06: More "history logic" to the Sandbox., gnunet, 2020/04/29