From 025e65742a21c9770009122f902e0d72e8354b8c Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 10 Jul 2019 09:41:37 +0200 Subject: [PATCH 1/3] added tests for getAccounts, getTransactions and Balances in BerlinGroupV1.3 --- .../AccountInformationServiceAISApi.scala | 6 +- .../v1_3/JSONFactory_BERLIN_GROUP_1_3.scala | 11 +-- .../main/scala/code/api/util/APIUtil.scala | 9 +- .../AccountInformationServiceAISApiTest.scala | 86 +++++++++---------- 4 files changed, 53 insertions(+), 59 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala index 92f93acd4..e5555b934 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala @@ -691,7 +691,7 @@ where the consent was directly managed between ASPSP and PSU e.g. in a re-direct (Full(u), callContext) <- authorizedAccess(cc) _ <- passesPsd2Aisp(callContext) consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map { - i => connectorEmptyResponse(i, callContext) + unboxFullOrFail(_, callContext, s"$ConsentNotFound ($consentId)") } } yield { (createGetConsentResponseJson(consent), HttpCode.`200`(callContext)) @@ -735,7 +735,7 @@ This method returns the SCA status of a consent initiation's authorisation sub-r (_, callContext) <- authorizedAccess(cc) _ <- passesPsd2Aisp(callContext) _ <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map { - unboxFullOrFail(_, callContext, ConsentNotFound) + unboxFullOrFail(_, callContext, s"$ConsentNotFound ($consentId)") } authorisation <- Future(Authorisations.authorisationProvider.vend.getAuthorizationByAuthorizationId( authorisationId @@ -968,7 +968,7 @@ This method returns the SCA status of a consent initiation's authorisation sub-r ], "_links": { "account": { - "href": "/v1.3/accounts/3dc3d5b3-7023-4848-9853- f5400a64e80f" + "href": "/v1.3/accounts/3dc3d5b3-7023-4848-9853-f5400a64e80f" } } } diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala index d601bfde7..cfeef0e95 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala @@ -76,7 +76,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats { ) case class AccountBalancesV13( account:FromAccount, - `balances`: List[AccountBalance] = AccountBalance() :: Nil + `balances`: List[AccountBalance] ) case class TransactionsLinksV13( account: String @@ -88,18 +88,9 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats { account: LinkHrefJson , ) - case class ExchangeRateJson( - sourceCurrency: String = "EUR", - rate: String = "string", - unitCurrency: String = "string", - targetCurrency: String = "EUR", - rateDate: String = "string", - rateContract: String = "string" - ) case class CreditorAccountJson( iban: String, ) - case class TransactionJsonV13( transactionId: String, creditorName: String, diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 1eb20cd38..9d940699c 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2612,7 +2612,14 @@ Returns a string showed to the developer def getMaskedPrimaryAccountNumber(accountNumber: String): String = { val (first, second) = accountNumber.splitAt(accountNumber.size/2) - first.substring(0, first.size - 3) + "***" + "***" + second.substring(3) + if(first.length >=3 && second.length>=3) + first.substring(0, first.size - 3) + "***" + "***" + second.substring(3) + else if (first.length >=3 && second.length< 3) + first.substring(0, first.size - 3) + "***" + "***" + second + else if (first.length <3 && second.length>= 3) + first + "***" + "***" + second.substring(3) + else + first+ "***" + "***" + second } def getBicFromBankId(bankId: String)= { diff --git a/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala b/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala index 910ba7320..18feda0f9 100644 --- a/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala +++ b/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala @@ -1,7 +1,7 @@ package code.api.berlin.group.v1_3 import code.api.ErrorMessage -import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.CoreAccountsJsonV13 +import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{AccountBalancesV13, CardTransactionsJsonV13, CoreAccountsJsonV13, TransactionsJsonV13} import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi import code.api.util.APIUtil.OAuth._ import code.api.util.ErrorMessages._ @@ -35,31 +35,11 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit object getConsentAuthorisation extends Tag(nameOf(APIMethods_AccountInformationServiceAISApi.getConsentAuthorisation)) - val consentJsonForPost = - """{ - | "access": { - | "accounts": [ - | { - | "iban": "FR7612345987650123456789014", - | "bban": "BARC12345612345678", - | "pan": "5409050000000000", - | "maskedPan": "123456xxxxxx1234", - | "msisdn": "+49 170 1234567", - | "currency": "EUR" - | } - | ] - | }, - | "recurringIndicator": false, - | "validUntil": "2020-12-31", - | "frequencyPerDay": 4, - | "combinedServiceIndicator": false - |}""".stripMargin - - feature("BG v1.3 - getAccountList") { + feature(s"BG v1.3 - $getAccountList") { scenario("Not Authentication User, test failed ", BerlinGroupV1_3, getAccountList) { When("Post consent json with no empty accounts") - val requestPost = (V1_3_BG / "accounts").GET - val response = makeGetRequest(requestPost) + val requestGet = (V1_3_BG / "accounts").GET + val response = makeGetRequest(requestGet) Then("We should get a 400 ") response.code should equal(400) @@ -68,39 +48,55 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit scenario("Authentication User, test succeed", BerlinGroupV1_3, getAccountList) { When("Post consent json with no empty accounts") - val requestPost = (V1_3_BG / "accounts").GET <@ (user1) - val response = makeGetRequest(requestPost) + val requestGet = (V1_3_BG / "accounts").GET <@ (user1) + val response = makeGetRequest(requestGet) Then("We should get a 200 ") response.code should equal(200) response.body.extract[CoreAccountsJsonV13].accounts.length > 1 should be (true) - response.body.extract[CoreAccountsJsonV13].accounts.head.bban } } - feature("test the BG v1.3 consent endpoints") { - scenario("Fail call endpoint createConsent, because accounts is not empty", BerlinGroupV1_3) { + feature(s"BG v1.3 - $getBalances") { + scenario("Authentication User, test succeed", BerlinGroupV1_3, getBalances) { When("Post consent json with no empty accounts") - val requestPost = (V1_3_BG / "consents").POST <@ (user1) - val response: APIResponse = makePostRequest(requestPost, consentJsonForPost) + val testBankId = testAccountId1 + val requestGet = (V1_3_BG / "accounts" /testBankId.value/ "balances").GET <@ (user1) + val response: APIResponse = makeGetRequest(requestGet) - Then("We should get a 400 ") - response.code should equal(400) - response.body.extract[ErrorMessage] - .message should startWith(InvalidJsonContent) + Then("We should get a 200 ") + response.code should equal(200) + response.body.extract[AccountBalancesV13].`balances`.length > 0 should be (true) + response.body.extract[AccountBalancesV13].account.iban should be ("") } - - scenario("Successful call endpoint createConsent", BerlinGroupV1_3) { + } + + feature(s"BG v1.3 - $getTransactionList") { + scenario("Authentication User, test succeed", BerlinGroupV1_3, getTransactionList) { When("Post consent json with no empty accounts") - val requestPost = (V1_3_BG / "consents").POST <@ (user1) - val emptyAccountsJson = consentJsonForPost.replaceFirst("""(?s)("accounts"\s*\:\s*\[).*?(\])""", "$1 $2") - val response: APIResponse = makePostRequest(requestPost, emptyAccountsJson) + val testBankId = testAccountId1 + val requestGet = (V1_3_BG / "accounts" /testBankId.value/ "transactions").GET <@ (user1) + val response: APIResponse = makeGetRequest(requestGet) - Then("We should get a 201 ") - response.code should equal(201) - response.body \ "consentId" should not be null - response.body \ "consentStatus" should not be null - response.body \ "_links" \ "startAuthorisation" should not be null + Then("We should get a 200 ") + response.code should equal(200) + response.body.extract[TransactionsJsonV13].account.iban should be ("") + response.body.extract[TransactionsJsonV13].transactions.booked.length >0 should be (true) + response.body.extract[TransactionsJsonV13].transactions.pending.length >0 should be (true) + } + } + + feature(s"BG v1.3 - $getCardAccountTransactionList") { + scenario("Authentication User, test succeed", BerlinGroupV1_3, getCardAccountTransactionList) { + When("Post consent json with no empty accounts") + val testBankId = testAccountId1 + val requestGet = (V1_3_BG / "card-accounts" /testBankId.value/ "transactions").GET <@ (user1) + val response: APIResponse = makeGetRequest(requestGet) + + Then("We should get a 200 ") + response.code should equal(200) + response.body.extract[CardTransactionsJsonV13].cardAccount.maskedPan.length >0 should be (true) + response.body.extract[CardTransactionsJsonV13].transactions.booked.length >0 should be (true) } } } \ No newline at end of file From b21b5625a738631e9e8992d44f86b3cd4d66009e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Jul 2019 10:43:53 +0200 Subject: [PATCH 2/3] Improved function getBicFromBankId --- .../src/main/scala/code/api/util/APIUtil.scala | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 9d940699c..abc4b558e 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2621,9 +2621,23 @@ Returns a string showed to the developer else first+ "***" + "***" + second } - + + /** + * This endpoint returns BIC on an bank according to next rules: + * 1st try - Inspect bank routing + * 2nd ry - get deprecated field "swiftBic" + * @param bankId The BANK_ID specified at an endpoint's path + * @return BIC of the Bank + */ def getBicFromBankId(bankId: String)= { - Connector.connector.vend.getBankLegacy(BankId(bankId), None).map(_._1.swiftBic).getOrElse("") + Connector.connector.vend.getBankLegacy(BankId(bankId), None) match { + case Full((bank, _)) => + bank.bankRoutingScheme match { + case "BIC" => bank.bankRoutingAddress + case _ => bank.swiftBic + } + case _ => "" + } } /** From 69af3d69e982620dc0b13ee287221f66087ad9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Jul 2019 11:18:44 +0200 Subject: [PATCH 3/3] Improved endpoint Revpke Consent --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 1 + obp-api/src/main/scala/code/consent/MappedConsent.scala | 2 ++ 2 files changed, 3 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 6407b9e1b..b153ed736 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -308,6 +308,7 @@ object ErrorMessages { val ConsentAllowedScaMethods = "OBP-35009: Only SMS and EMAIL are supported as SCA methods. " val SmsServerNotResponding = "OBP-35010: SMS server is not working or SMS server can not send the message to the phone number: " val AuthorizationNotFound = "OBP-35011: Resource identification of the related Consent authorisation sub-resource not found by AUTHORIZATION_ID. " + val ConsentAlreadyRevoked = "OBP-35012: Consent is already revoked. " //Authorisations val AuthorisationNotFound = "OBP-36001: Authorisation not found. Please specify valid values for PAYMENT_ID and AUTHORISATION_ID. " diff --git a/obp-api/src/main/scala/code/consent/MappedConsent.scala b/obp-api/src/main/scala/code/consent/MappedConsent.scala index 2dfddf84e..f43cb6c15 100644 --- a/obp-api/src/main/scala/code/consent/MappedConsent.scala +++ b/obp-api/src/main/scala/code/consent/MappedConsent.scala @@ -88,6 +88,8 @@ object MappedConsentProvider extends ConsentProvider { } override def revoke(consentId: String): Box[MappedConsent] = { MappedConsent.find(By(MappedConsent.mConsentId, consentId)) match { + case Full(consent) if consent.status == ConsentStatus.REVOKED.toString => + Failure(ErrorMessages.ConsentAlreadyRevoked) case Full(consent) => tryo(consent .mStatus(ConsentStatus.REVOKED.toString)