mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 15:27:01 +00:00
#243 Added Iban in SEPA details reponse and fixed the FROM_FORM data format
This commit is contained in:
parent
a664dd3b91
commit
a895c10aec
2
pom.xml
2
pom.xml
@ -89,7 +89,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.4-1206-jdbc4</version>
|
||||
<version>9.4.1211</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
|
||||
@ -93,6 +93,7 @@ object ErrorMessages {
|
||||
val CustomerNumberAlreadyExists = "OBP-30006: Customer Number already exists. Please specify a different value for BANK_ID or CUSTOMER_NUMBER."
|
||||
val CustomerAlreadyExistsForUser = "OBP-30007: The User is already linked to a Customer at the bank specified by BANK_ID"
|
||||
val CustomerDoNotExistsForUser = "OBP-30008: User is not linked to a Customer at the bank specified by BANK_ID"
|
||||
val CounterpartyNotFoundByIban = "OBP-30009: Counterparty not found. The IBan specified does not exist on this server."
|
||||
|
||||
val MeetingsNotSupported = "OBP-30101: Meetings are not supported on this server."
|
||||
val MeetingApiKeyNotConfigured = "OBP-30102: Meeting provider API Key is not configured."
|
||||
|
||||
@ -14,16 +14,19 @@ import code.api.v2_1_0.JSONFactory210._
|
||||
import code.bankconnectors.Connector
|
||||
import code.entitlement.Entitlement
|
||||
import code.fx.fx
|
||||
import code.metadata.counterparties.MappedCounterpartyMetadata
|
||||
import code.model.dataAccess.OBPUser
|
||||
import code.model.{BankId, _}
|
||||
import net.liftweb.http.{CurrentReq, Req}
|
||||
import net.liftweb.json.Extraction
|
||||
import net.liftweb.json.JsonAST.JValue
|
||||
import net.liftweb.json.Serialization._
|
||||
import net.liftweb.mapper.By
|
||||
import net.liftweb.util.Props
|
||||
|
||||
import scala.collection.immutable.Nil
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
// Makes JValue assignment to Nil work
|
||||
import code.util.Helper._
|
||||
import net.liftweb.json.JsonDSL._
|
||||
@ -44,7 +47,6 @@ import net.liftweb.json.Serialization.{read, write}
|
||||
trait APIMethods210 {
|
||||
//needs to be a RestHelper to get access to JsonGet, JsonPost, etc.
|
||||
self: RestHelper =>
|
||||
|
||||
// helper methods begin here
|
||||
// helper methods end here
|
||||
|
||||
@ -214,8 +216,8 @@ trait APIMethods210 {
|
||||
|
|
||||
|""",
|
||||
Extraction.decompose(TransactionRequestBodyJSON (
|
||||
TransactionRequestAccountJSON("BANK_ID", "ACCOUNT_ID"),
|
||||
AmountOfMoneyJSON("EUR", "100.53"),
|
||||
TransactionRequestAccountJSON("bank_id", "account_id"),
|
||||
AmountOfMoneyJSON("eur", "100.53"),
|
||||
"A description for the transaction to be created"
|
||||
)
|
||||
),
|
||||
@ -277,16 +279,7 @@ trait APIMethods210 {
|
||||
// Prevent default value for transaction request type (at least).
|
||||
transferCurrencyEqual <- tryo(assert(transDetailsJson.value.currency == fromAccount.currency)) ?~! {s"${ErrorMessages.InvalidTransactionRequestCurrency} From Account Currency is ${fromAccount.currency} Requested Transaction Currency is: ${transDetailsJson.value.currency}"}
|
||||
|
||||
transDetailsSerialized <- transactionRequestType.value match {
|
||||
case "FREE_FORM" => tryo{
|
||||
implicit val formats = Serialization.formats(NoTypeHints)
|
||||
write(json)
|
||||
}
|
||||
case _ => tryo{
|
||||
implicit val formats = Serialization.formats(NoTypeHints)
|
||||
write(transDetailsJson)
|
||||
}
|
||||
}
|
||||
amountOfMoneyJSON <- Full(AmountOfMoneyJSON(transDetails.value.currency, transDetails.value.amount))
|
||||
|
||||
// Note: These store in the table TransactionRequestv210
|
||||
createdTransactionRequest <- transactionRequestType.value match {
|
||||
@ -295,16 +288,52 @@ trait APIMethods210 {
|
||||
toBankId <- Full(BankId(transDetailsJson.asInstanceOf[TransactionRequestDetailsSandBoxTanJSON].to.bank_id))
|
||||
toAccountId <- Full(AccountId(transDetailsJson.asInstanceOf[TransactionRequestDetailsSandBoxTanJSON].to.account_id))
|
||||
toAccount <- BankAccount(toBankId, toAccountId) ?~! {ErrorMessages.CounterpartyNotFound}
|
||||
|
||||
transDetailsSerialized <- tryo {
|
||||
implicit val formats = Serialization.formats(NoTypeHints)
|
||||
write(json)
|
||||
}
|
||||
createdTransactionRequest <- Connector.connector.vend.createTransactionRequestv210(u, fromAccount, Full(toAccount), transactionRequestType, transDetails, transDetailsSerialized)
|
||||
} yield createdTransactionRequest
|
||||
|
||||
}
|
||||
case "SEPA" => {
|
||||
Connector.connector.vend.createTransactionRequestv210(u, fromAccount, Empty, transactionRequestType, transDetails, transDetailsSerialized)
|
||||
for {
|
||||
//for SEPA, the user do not send the Bank_ID and Acound_ID,so this will search for the bank firstly.
|
||||
toIban<- Full(transDetailsJson.asInstanceOf[TransactionRequestDetailsSEPAJSON].iban)
|
||||
mappedCounterpartyMetadata <- MappedCounterpartyMetadata.find(By(MappedCounterpartyMetadata.accountNumber, toIban)) ?~! {ErrorMessages.CounterpartyNotFoundByIban}
|
||||
toBankId <- Full(BankId(mappedCounterpartyMetadata.thisAccountBankId))
|
||||
toAccountId <- Full(AccountId(mappedCounterpartyMetadata.thisAccountId))
|
||||
toAccount <- BankAccount(toBankId, toAccountId) ?~! {ErrorMessages.CounterpartyNotFound}
|
||||
|
||||
// Following four lines: just transfer the details body ,add Bank_Id and Account_Id in the Detail part.
|
||||
transactionRequestAccountJSON = TransactionRequestAccountJSON(toBankId.value, toAccountId.value)
|
||||
detailDescription = transDetailsJson.asInstanceOf[TransactionRequestDetailsSEPAJSON].description
|
||||
transactionRequestDetailsAddedTobankSEPAJSON = TransactionRequestDetailsSEPAResponseJSON(toIban.toString,transactionRequestAccountJSON, amountOfMoneyJSON, detailDescription.toString)
|
||||
transResponseDetails = getTransactionRequestDetailsAddedTobankSEPAJSONFromJson(transactionRequestDetailsAddedTobankSEPAJSON)
|
||||
|
||||
//Serialize the new format SEPA data.
|
||||
transDetailsResponseSerialized <-tryo{
|
||||
implicit val formats = Serialization.formats(NoTypeHints)
|
||||
write(transResponseDetails)
|
||||
}
|
||||
createdTransactionRequest <- Connector.connector.vend.createTransactionRequestv210(u, fromAccount, Full(toAccount), transactionRequestType, transResponseDetails, transDetailsResponseSerialized)
|
||||
} yield createdTransactionRequest
|
||||
}
|
||||
case "FREE_FORM" => {
|
||||
Connector.connector.vend.createTransactionRequestv210(u, fromAccount, Empty, transactionRequestType, transDetails, transDetailsSerialized)
|
||||
for {
|
||||
// Following three lines: just transfer the details body ,add Bank_Id and Account_Id in the Detail part.
|
||||
transactionRequestAccountJSON <- Full(TransactionRequestAccountJSON(fromAccount.bankId.value, fromAccount.accountId.value))
|
||||
// the Free form the discription is empty, so make it "" in the following code
|
||||
transactionRequestDetailsFreeFormResponseJSON = TransactionRequestDetailsFreeFormResponseJSON(transactionRequestAccountJSON,amountOfMoneyJSON,"")
|
||||
transResponseDetails <- Full(getTransactionRequestDetailsFreeFormAddedTobankJson(transactionRequestDetailsFreeFormResponseJSON))
|
||||
|
||||
transDetailsResponseSerialized<-tryo{
|
||||
implicit val formats = Serialization.formats(NoTypeHints)
|
||||
write(transResponseDetails)
|
||||
}
|
||||
createdTransactionRequest <- Connector.connector.vend.createTransactionRequestv210(u, fromAccount, Full(fromAccount), transactionRequestType, transResponseDetails, transDetailsResponseSerialized)
|
||||
} yield
|
||||
createdTransactionRequest
|
||||
}
|
||||
}
|
||||
} yield {
|
||||
@ -609,7 +638,7 @@ trait APIMethods210 {
|
||||
u <- user ?~! ErrorMessages.UserNotLoggedIn
|
||||
putData <- tryo{json.extract[PutEnabledJSON]} ?~! ErrorMessages.InvalidJsonFormat
|
||||
hasEntitlement <- putData.enabled match {
|
||||
case true => booleanToBox(hasEntitlement("", u.userId, ApiRole.CanEnableConsumers), s"$CanEnableConsumers entitlement required")
|
||||
case true => booleanToBox(hasEntitlement("", u.userId, ApiRole.CanEnableConsumers), s"$CanEnableConsumers entitlement required")
|
||||
case false => booleanToBox(hasEntitlement("", u.userId, ApiRole.CanDisableConsumers), s"$CanDisableConsumers entitlement required")
|
||||
}
|
||||
consumer <- Consumer.find(By(Consumer.id, consumerId.toLong))
|
||||
@ -624,7 +653,6 @@ trait APIMethods210 {
|
||||
}
|
||||
|
||||
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
addCardsForBank,
|
||||
apiVersion,
|
||||
@ -758,7 +786,7 @@ trait APIMethods210 {
|
||||
| * charge : The charge to the customer for each one of these
|
||||
|
|
||||
|${authenticationRequiredMessage(getTransactionTypesIsPublic)}""",
|
||||
Extraction.decompose(TransactionTypeJSON(TransactionTypeId("wuwjfuha234678"), "1", "2", "3", "4", AmountOfMoneyJSON("EUR", "123"))),
|
||||
Extraction.decompose(TransactionTypeJSON(TransactionTypeId("wuwjfuha234678"), "1", "2", "3", "4", AmountOfMoneyJSON("eur", "123"))),
|
||||
emptyObjectJson,
|
||||
emptyObjectJson :: Nil,
|
||||
false,
|
||||
@ -768,7 +796,6 @@ trait APIMethods210 {
|
||||
)
|
||||
|
||||
|
||||
|
||||
lazy val createTransactionType: PartialFunction[Req, Box[User] => Box[JsonResponse]] = {
|
||||
case "banks" :: BankId(bankId) :: "transaction-types" :: Nil JsonPut json -> _ => {
|
||||
user => {
|
||||
|
||||
@ -37,7 +37,7 @@ import code.api.util.ApiRole
|
||||
import code.api.v1_2_1.AmountOfMoneyJSON
|
||||
import code.api.v1_4_0.JSONFactory1_4_0.{ChallengeJSON, TransactionRequestAccountJSON}
|
||||
import code.api.v2_0_0.TransactionRequestChargeJSON
|
||||
import code.model.{AmountOfMoney, Consumer}
|
||||
import code.model.{AmountOfMoney, Consumer, CounterpartyMetadataIban, Iban}
|
||||
import code.transactionrequests.TransactionRequests._
|
||||
import net.liftweb.json.JValue
|
||||
|
||||
@ -58,15 +58,30 @@ case class TransactionRequestDetailsSandBoxTanJSON(
|
||||
) extends TransactionRequestDetailsJSON
|
||||
|
||||
case class TransactionRequestDetailsSEPAJSON(
|
||||
value : AmountOfMoneyJSON,
|
||||
IBAN: String,
|
||||
description : String
|
||||
) extends TransactionRequestDetailsJSON
|
||||
value: AmountOfMoneyJSON,
|
||||
iban: String,
|
||||
description: String
|
||||
) extends TransactionRequestDetailsJSON
|
||||
|
||||
case class TransactionRequestDetailsSEPAResponseJSON(
|
||||
iban: String,
|
||||
to: TransactionRequestAccountJSON,
|
||||
value: AmountOfMoneyJSON,
|
||||
description: String
|
||||
) extends TransactionRequestDetailsJSON
|
||||
|
||||
case class TransactionRequestDetailsFreeFormJSON(
|
||||
value : AmountOfMoneyJSON
|
||||
) extends TransactionRequestDetailsJSON
|
||||
|
||||
case class TransactionRequestDetailsFreeFormResponseJSON(
|
||||
to: TransactionRequestAccountJSON,
|
||||
value: AmountOfMoneyJSON,
|
||||
description: String
|
||||
) extends TransactionRequestDetailsJSON
|
||||
|
||||
|
||||
|
||||
case class TransactionRequestWithChargeJSON210(
|
||||
id: String,
|
||||
`type`: String,
|
||||
@ -135,12 +150,35 @@ object JSONFactory210{
|
||||
}
|
||||
|
||||
def getTransactionRequestDetailsSEPAFromJson(details: TransactionRequestDetailsSEPAJSON) : TransactionRequestDetailsSEPA = {
|
||||
val toAccIban = Iban (
|
||||
iban = details.iban
|
||||
)
|
||||
val amount = AmountOfMoney (
|
||||
currency = details.value.currency,
|
||||
amount = details.value.amount
|
||||
)
|
||||
|
||||
TransactionRequestDetailsSEPA (
|
||||
iban = details.iban,
|
||||
value = amount,
|
||||
description = details.description
|
||||
)
|
||||
}
|
||||
|
||||
def getTransactionRequestDetailsAddedTobankSEPAJSONFromJson(details: TransactionRequestDetailsSEPAResponseJSON) : TransactionRequestDetailsSEPAResponse = {
|
||||
val toAcc = TransactionRequestAccount (
|
||||
bank_id = details.to.bank_id,
|
||||
account_id = details.to.account_id
|
||||
)
|
||||
val toAccIban = Iban (
|
||||
iban = details.iban
|
||||
)
|
||||
val amount = AmountOfMoney (
|
||||
currency = details.value.currency,
|
||||
amount = details.value.amount
|
||||
)
|
||||
TransactionRequestDetailsSEPAResponse (
|
||||
iban = details.iban,
|
||||
to=toAcc,
|
||||
value = amount,
|
||||
description = details.description
|
||||
)
|
||||
@ -157,6 +195,23 @@ object JSONFactory210{
|
||||
)
|
||||
}
|
||||
|
||||
def getTransactionRequestDetailsFreeFormAddedTobankJson(details: TransactionRequestDetailsFreeFormResponseJSON) : TransactionRequestDetailsFreeFormResponse = {
|
||||
val toAcc = TransactionRequestAccount (
|
||||
bank_id = details.to.bank_id,
|
||||
account_id = details.to.account_id
|
||||
)
|
||||
val amount = AmountOfMoney (
|
||||
currency = details.value.currency,
|
||||
amount = details.value.amount
|
||||
)
|
||||
TransactionRequestDetailsFreeFormResponse (
|
||||
to=toAcc,
|
||||
value = amount,
|
||||
description = details.description
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/** Creates v2.1.0 representation of a TransactionType
|
||||
*
|
||||
* @param tr An internal TransactionRequest instance
|
||||
|
||||
@ -5,7 +5,7 @@ import java.util.Date
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.util.ErrorMessages
|
||||
import code.api.v2_1_0.{TransactionRequestDetailsFreeFormJSON, TransactionRequestDetailsSEPAJSON, TransactionRequestDetailsSandBoxTanJSON}
|
||||
import code.api.v2_1_0.{TransactionRequestDetailsFreeFormJSON, TransactionRequestDetailsSEPAResponseJSON, TransactionRequestDetailsSandBoxTanJSON}
|
||||
import code.fx.fx
|
||||
import code.management.ImporterAPI.ImporterTransaction
|
||||
import code.model.{Transaction, User, _}
|
||||
@ -266,7 +266,6 @@ trait Connector {
|
||||
|
||||
//set challenge to null
|
||||
result = Full(result.get.copy(challenge = null))
|
||||
|
||||
//save transaction_id if we have one
|
||||
createdTransactionId match {
|
||||
case Full(ti) => {
|
||||
@ -395,7 +394,9 @@ trait Connector {
|
||||
case "SANDBOX_TAN" => Connector.connector.vend.makePaymentv200(initiator, BankAccountUID(fromAccount.bankId, fromAccount.accountId),
|
||||
BankAccountUID(toAccount.get.bankId, toAccount.get.accountId), BigDecimal(details.value.amount), details.asInstanceOf[TransactionRequestDetailsSandBoxTan].description)
|
||||
case "SEPA" => Connector.connector.vend.makePaymentv200(initiator, BankAccountUID(fromAccount.bankId, fromAccount.accountId),
|
||||
BankAccountUID(toAccount.get.bankId, toAccount.get.accountId), BigDecimal(details.value.amount), details.asInstanceOf[TransactionRequestDetailsSandBoxTan].description)
|
||||
BankAccountUID(toAccount.get.bankId, toAccount.get.accountId), BigDecimal(details.value.amount), details.asInstanceOf[TransactionRequestDetailsSEPAResponse].description)
|
||||
case "FREE_FORM" => Connector.connector.vend.makePaymentv200(initiator, BankAccountUID(fromAccount.bankId, fromAccount.accountId),
|
||||
BankAccountUID(toAccount.get.bankId, toAccount.get.accountId), BigDecimal(details.value.amount), "")
|
||||
}
|
||||
|
||||
//set challenge to null
|
||||
|
||||
@ -112,6 +112,12 @@ object BankId {
|
||||
def unapply(id : String) = Some(BankId(id))
|
||||
}
|
||||
|
||||
case class CounterpartyMetadataIban(val value : String) {
|
||||
override def toString = value
|
||||
}
|
||||
object CounterpartyMetadataIban {
|
||||
def unapply(id : String) = Some(CounterpartyMetadataIban(id))
|
||||
}
|
||||
|
||||
case class CustomerId(val value : String) {
|
||||
override def toString = value
|
||||
@ -658,4 +664,8 @@ class Transaction(
|
||||
case class AmountOfMoney (
|
||||
val currency: String,
|
||||
val amount: String
|
||||
)
|
||||
|
||||
case class Iban(
|
||||
val iban: String
|
||||
)
|
||||
@ -67,14 +67,28 @@ object TransactionRequests extends SimpleInjector {
|
||||
val description : String
|
||||
) extends TransactionRequestDetails
|
||||
|
||||
case class TransactionRequestDetailsSEPA (
|
||||
val value : AmountOfMoney,
|
||||
val description : String
|
||||
) extends TransactionRequestDetails
|
||||
case class TransactionRequestDetailsSEPA(
|
||||
val iban: String,
|
||||
val value: AmountOfMoney,
|
||||
val description: String
|
||||
) extends TransactionRequestDetails
|
||||
case class TransactionRequestDetailsSEPAResponse(
|
||||
val iban: String,
|
||||
val to: TransactionRequestAccount,
|
||||
val value: AmountOfMoney,
|
||||
val description: String
|
||||
) extends TransactionRequestDetails
|
||||
|
||||
case class TransactionRequestDetailsFreeForm(
|
||||
val value: AmountOfMoney
|
||||
) extends TransactionRequestDetails
|
||||
|
||||
case class TransactionRequestDetailsFreeFormResponse(
|
||||
val to: TransactionRequestAccount,
|
||||
val value: AmountOfMoney,
|
||||
val description: String
|
||||
) extends TransactionRequestDetails
|
||||
|
||||
case class TransactionRequestDetailsFreeForm (
|
||||
val value : AmountOfMoney
|
||||
) extends TransactionRequestDetails
|
||||
|
||||
val transactionRequestProvider = new Inject(buildOne _) {}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import net.liftweb.common.Box
|
||||
import net.liftweb.mapper.MetaMapper
|
||||
import net.liftweb.util.Helpers._
|
||||
import code.entitlement.{Entitlement, MappedEntitlement}
|
||||
import code.metadata.counterparties.MappedCounterpartyMetadata
|
||||
import code.transaction.MappedTransaction
|
||||
|
||||
import scala.util.Random
|
||||
@ -26,6 +27,14 @@ trait LocalMappedConnectorTestSetup extends TestConnectorSetupWithStandardPermis
|
||||
.national_identifier(randomString(5)).saveMe
|
||||
}
|
||||
|
||||
override protected def createCounterpartyMetadata(BankId:String,AccountId:String,iBan:String):CounterpartyMetadata = {
|
||||
MappedCounterpartyMetadata.create.
|
||||
thisAccountBankId(BankId).
|
||||
thisAccountId(AccountId).
|
||||
accountNumber(iBan).
|
||||
saveMe
|
||||
}
|
||||
|
||||
// TODO: Should return an option or box so can test if the insert succeeded
|
||||
// or if it failed due to unique exception etc. However, we'll need to modify / lift callers so they can handle an Option
|
||||
// override protected def createBank(id : String) : Option[Bank] = {
|
||||
|
||||
@ -2,7 +2,8 @@ package code.api
|
||||
|
||||
import java.util.{Calendar, Date}
|
||||
|
||||
import code.bankconnectors.{OBPLimit, OBPOffset, Connector}
|
||||
import code.bankconnectors.{Connector, OBPLimit, OBPOffset}
|
||||
import code.metadata.counterparties.MappedCounterpartyMetadata
|
||||
import code.model._
|
||||
import net.liftweb.util.Helpers._
|
||||
|
||||
@ -13,6 +14,8 @@ trait TestConnectorSetup {
|
||||
protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount
|
||||
protected def createTransaction(account : BankAccount, startDate : Date, finishDate : Date)
|
||||
|
||||
//TODO: Here I use the createCounterpartyMetadata.accountNumber to replace the Iban. I will fix it when new version is comming.
|
||||
protected def createCounterpartyMetadata(BankId:String,AccountId:String,iBan:String):CounterpartyMetadata
|
||||
|
||||
final protected def createAccountAndOwnerView(accountOwner: Option[User], bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {
|
||||
val account = createAccount(bankId, accountId, currency)
|
||||
|
||||
1284
src/test/scala/code/api/v2_1_0/TransactionRequestsFreeformTest.scala
Normal file
1284
src/test/scala/code/api/v2_1_0/TransactionRequestsFreeformTest.scala
Normal file
File diff suppressed because it is too large
Load Diff
1383
src/test/scala/code/api/v2_1_0/TransactionRequestsSepaTest.scala
Normal file
1383
src/test/scala/code/api/v2_1_0/TransactionRequestsSepaTest.scala
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user