mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 13:07:02 +00:00
feature/VRP Consent acceptance
This commit is contained in:
parent
45b1557352
commit
39dd665bea
36
obp-api/src/main/scala/code/api/util/DateTimeUtil.scala
Normal file
36
obp-api/src/main/scala/code/api/util/DateTimeUtil.scala
Normal file
@ -0,0 +1,36 @@
|
||||
package code.api.util
|
||||
|
||||
import java.time.Duration
|
||||
|
||||
object DateTimeUtil {
|
||||
|
||||
/*
|
||||
Examples:
|
||||
println(formatDuration(90000)) // "1 day, 1 hour"
|
||||
println(formatDuration(86400)) // "1 day"
|
||||
println(formatDuration(172800)) // "2 days"
|
||||
println(formatDuration(7200)) // "2 hours"
|
||||
println(formatDuration(3661)) // "1 hour, 1 minute, 1 second"
|
||||
println(formatDuration(120)) // "2 minutes"
|
||||
println(formatDuration(30)) // "30 seconds"
|
||||
println(formatDuration(0)) // "less than a second"
|
||||
*/
|
||||
def formatDuration(seconds: Long): String = {
|
||||
val days = seconds / 86400
|
||||
val hours = (seconds % 86400) / 3600
|
||||
val minutes = (seconds % 3600) / 60
|
||||
val secs = seconds % 60
|
||||
|
||||
def plural(value: Long, unit: String): Option[String] =
|
||||
if (value > 0) Some(s"$value ${unit}${if (value > 1) "s" else ""}") else None
|
||||
|
||||
val parts = List(
|
||||
plural(days, "day"),
|
||||
plural(hours, "hour"),
|
||||
plural(minutes, "minute"),
|
||||
plural(secs, "second")
|
||||
).flatten // Remove None values
|
||||
|
||||
if (parts.isEmpty) "less than a second" else parts.mkString(", ")
|
||||
}
|
||||
}
|
||||
@ -28,7 +28,7 @@ package code.snippet
|
||||
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ErrorMessages.InvalidJsonFormat
|
||||
import code.api.util.{APIUtil, CustomJsonFormats}
|
||||
import code.api.util.{APIUtil, CustomJsonFormats, DateTimeUtil}
|
||||
import code.api.v5_1_0.{APIMethods510, ConsentJsonV510}
|
||||
import code.api.v5_0_0.{APIMethods500, ConsentJsonV500, ConsentRequestResponseJson}
|
||||
import code.api.v3_1_0.{APIMethods310, ConsentChallengeJsonV310, ConsumerJsonV310}
|
||||
@ -40,6 +40,7 @@ import net.liftweb.http.rest.RestHelper
|
||||
import net.liftweb.http.{GetRequest, PostRequest, RequestVar, S, SHtml}
|
||||
import net.liftweb.json
|
||||
import net.liftweb.json.Formats
|
||||
import net.liftweb.util.CssSel
|
||||
import net.liftweb.util.Helpers._
|
||||
|
||||
class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510 with APIMethods500 with APIMethods310 {
|
||||
@ -60,22 +61,23 @@ class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510
|
||||
case Full(consentRequestResponseJson) =>
|
||||
val jsonAst = consentRequestResponseJson.payload
|
||||
val currency = (jsonAst \ "to_account" \ "limit" \ "currency").extract[String]
|
||||
val ttl: Long = (jsonAst \ "time_to_live").extract[Long]
|
||||
val formText =
|
||||
s"""
|
||||
|I, ${AuthUser.currentUser.flatMap(_.user.foreign.map(_.name)).getOrElse("")}
|
||||
|, grant to transfer of funds from my account at ${(jsonAst \ "from_account" \ "bank_routing" \ "address").extract[String]}
|
||||
|, ${(jsonAst \ "from_account" \ "account_routing" \ "address").extract[String]}
|
||||
|, to ${(jsonAst \ "to_account" \ "counterparty_name").extract[String]}
|
||||
|, address ${(jsonAst \ "to_account" \ "bank_routing" \ "address").extract[String]}
|
||||
|, of $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_single_amount").extract[String]}
|
||||
| per transaction, up to $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_monthly_amount").extract[String]}
|
||||
| per month, up to ${(jsonAst \ "to_account" \ "limit" \ "max_number_of_monthly_transactions").extract[String]} transactions per month
|
||||
|, up to $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_yearly_amount").extract[String]}
|
||||
| per year, and up to ${(jsonAst \ "to_account" \ "limit" \ "max_number_of_yearly_transactions").extract[String]} transactions per year
|
||||
|, up to the total amount of $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_total_amount").extract[String]}
|
||||
| and up to a total of ${(jsonAst \ "to_account" \ "limit" \ "max_number_of_transactions").extract[String]} in total.
|
||||
|This consent will be valid from ${(jsonAst \ "valid_from").extract[String]} for ${(jsonAst \ "time_to_live").extract[String]} seconds.
|
||||
|""".stripMargin
|
||||
s"""I, ${AuthUser.currentUser.map(_.firstName.get).getOrElse("")} ${AuthUser.currentUser.map(_.lastName.get).getOrElse("")}, consent to the service provider <CONSUMER_NAME> making transfers on my behalf from my bank account number ${(jsonAst \ "from_account" \ "account_routing" \ "address").extract[String]}, to the beneficiary ${(jsonAst \ "to_account" \ "counterparty_name").extract[String]}, account number ${(jsonAst \ "to_account" \ "account_routing" \ "address").extract[String]} at bank code ${(jsonAst \ "to_account" \ "bank_routing" \ "address").extract[String]}.
|
||||
|
|
||||
|The transfers governed by this consent must respect the following rules:
|
||||
|
|
||||
| 1) The grand total amount will not exceed {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_total_amount").extract[String]})}
|
||||
| 2) Any single amount will not exceed {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_single_amount").extract[String]})}
|
||||
| 3) The maximum amount per month that can be transferred is {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_monthly_amount").extract[String]})} over {limit (${(jsonAst \ "to_account" \ "limit" \ "max_number_of_monthly_transactions").extract[String]}) transactions.
|
||||
| 4) The maximum amount per year that can be transferred is {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_yearly_amount").extract[String]})} over {limit (${(jsonAst \ "to_account" \ "limit" \ "max_number_of_yearly_transactions").extract[String]}) transactions.
|
||||
|
|
||||
|This consent will start on date {${(jsonAst \ "valid_from").extract[String]}} and be valid for ${DateTimeUtil.formatDuration(ttl)}.
|
||||
|
|
||||
|I understand that I can revoke this consent at any time.
|
||||
|""".stripMargin
|
||||
|
||||
|
||||
"#confirm-vrp-consent-request-form-title *" #> s"Please confirm or deny the following consent request:" &
|
||||
"#confirm-vrp-consent-request-form-text *" #> s"""$formText""" &
|
||||
"#from_bank_routing_scheme [value]" #> s"${(jsonAst \ "from_account" \ "bank_routing" \ "scheme").extract[String]}" &
|
||||
@ -103,6 +105,7 @@ class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510
|
||||
"#valid_from [value]" #> s"${(jsonAst \ "valid_from").extract[String]}" &
|
||||
"#email [value]" #> s"${(jsonAst \ "email").extract[String]}" &
|
||||
"#phone_number [value]" #> s"${(jsonAst \ "phone_number").extract[String]}" &
|
||||
showHideElements &
|
||||
"#confirm-vrp-consent-request-confirm-submit-button" #> SHtml.onSubmitUnit(confirmConsentRequestProcess)
|
||||
case _ =>
|
||||
"#confirm-vrp-consent-request-form-title *" #> s"Please confirm or deny the following consent request:" &
|
||||
@ -116,6 +119,25 @@ class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def showHideElements: CssSel = {
|
||||
if (ObpS.param("format").isEmpty) {
|
||||
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
|
||||
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
|
||||
} else if(ObpS.param("format").contains("1")) {
|
||||
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:none" &
|
||||
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
|
||||
} else if(ObpS.param("format").contains("2")) {
|
||||
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
|
||||
"#confirm-vrp-consent-request-form-fields [style]" #> "display:none"
|
||||
} else if(ObpS.param("format").contains("3")) {
|
||||
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
|
||||
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
|
||||
} else {
|
||||
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
|
||||
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
|
||||
}
|
||||
}
|
||||
|
||||
def confirmVrpConsent = {
|
||||
"#otp-value" #> SHtml.textElem(otpValue) &
|
||||
|
||||
@ -28,13 +28,15 @@ Berlin 13359, Germany
|
||||
-->
|
||||
|
||||
<div data-lift="surround?with=default;at=content">
|
||||
<div id="confirm-vrp-consent-request-div" style="width: 90%; margin: 0 auto;" data-lift="VrpConsentCreation.confirmVrpConsentRequest">
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<h3 id="confirm-vrp-consent-request-form-title">Please check the VRP Consent Request: </h3>
|
||||
<p id="confirm-vrp-consent-request-form-text"></p>
|
||||
<div id="confirm-vrp-consent-request" style="width: 90%; margin: 0 auto;" data-lift="VrpConsentCreation.confirmVrpConsentRequest">
|
||||
<div class="form-group">
|
||||
<h3 id="confirm-vrp-consent-request-form-title">Please check the VRP Consent Request: </h3>
|
||||
<div id="confirm-vrp-consent-request-form-text-div">
|
||||
<pre id="confirm-vrp-consent-request-form-text"></pre>
|
||||
</div>
|
||||
<div class="wrap-text">
|
||||
</div>
|
||||
<form method="post">
|
||||
<div class="wrap-text" id="confirm-vrp-consent-request-form-fields">
|
||||
<div class="form-group col-md-6">
|
||||
<h4>From Account</h4>
|
||||
<div class="form-row">
|
||||
@ -180,9 +182,18 @@ Berlin 13359, Germany
|
||||
<br>
|
||||
<script>
|
||||
// Apply the `readonly` attribute dynamically
|
||||
const elements = document.querySelectorAll('#confirm-vrp-consent-request-div input, #confirm-vrp-consent-request-div textarea');
|
||||
const elements = document.querySelectorAll('#confirm-vrp-consent-request input, #confirm-vrp-consent-request textarea');
|
||||
elements.forEach(el => el.setAttribute('readonly', 'readonly'));
|
||||
</script>
|
||||
|
||||
<style>
|
||||
pre {
|
||||
white-space: pre-wrap; /* Preserve whitespace and wrap at spaces */
|
||||
word-break: normal; /* Prevent breaking words */
|
||||
overflow-wrap: normal; /* Prevent breaking words */
|
||||
overflow-x: auto; /* Allow horizontal scrolling if necessary */
|
||||
}
|
||||
</style>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user