Java Guide
In this project, you will required to have Java JDK, Maven and Lombok.
Click here to go to the repository. You can access all the app code and reuse it for your application.
Configuration for PKIX(SSLHandshake)
Go to Brick and click on the lock beside URL bar. Click on the Certificate -> Details then click on Copy to File.. and finally export the certificate as DER file and store it to your Java JDK Folder (e.g. C:\Program Files\Java\jdk-15.0.1\lib\security) with filename bricksandbox. Next, open your CMD and run as administrator, then run this command,
NOTE
Your file path may differ from the command below, you will need to change it to your own file path.
keytool - import -alias bricksandbox -keystore "C:\Program Files\Java\jdk-15.0.1\lib\security\cacerts" -file "C:\Program Files\Java\jdk-15.0.1\lib\security\bricksandbox.cer"
when you are prompt for password, by default it will be: changeit
when you are prompt for yes/no, type: yes
Steps to executing this program
In your terminal, you will have to go to the root folder of this project and type in the following:
mvn clean install //This will install, build, and execute the necessary packages or dependencies
once you finish the downloads and build all the necessary packages, in the terminal type the following:
java -jar target/money-save.war //this will execute the springframework builds.
Then in the terminal you will see that the moneysaveApplication is running, you can open your browser and go to:
http://localhost:8085/
Then if everything is successful, you will land on this page.


Required dependencies in pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--All repositories will be access from this-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--Configuration of project identifiers -->
<groupId>com.brick.app</groupId>
<artifactId>money-save</artifactId>
<version>1.0.0</version>
<name>money-save</name>
<description>money-save app for mock client</description>
<!--minimal/used java version-->
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<!-- dependency for spring boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- dependency for spring boot tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--for deployment uncomment this-->
<!--<scope>provided</scope>-->
<!--for deployment comment this-->
<scope>compile</scope>
</dependency>
<!-- dependency for spring boot data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- dependency for lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<!--<scope>provided</scope>-->
<!--<optional>true</optional>-->
</dependency>
<!-- dependency for thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<!-- dependency for codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.6</version>
</dependency>
<!-- dependency for http client -->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<!-- dependency for http components -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<!--H2 Database-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.9</version>
</dependency>
<!-- dependency spring boot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- build to target for compilations -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>money-save</finalName>
</build>
<packaging>war</packaging>
</project>
Main java function
package com.onebrick.app.restclient;
//package to use SpringApplication
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
//Application class for main function
@SpringBootApplication
public class MoneySaveApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
//spring boot to execute MoneySaveApplication
SpringApplication.run(MoneySaveApplication.class, args);
}
//access the builds in .war package
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MoneySaveApplication.class);
}
}
Repository folder
AuthRepository.java
This class will perform authentication with ClientID and ClientSecret from users to retrieve (JWT) public-access-token
package com.onebrick.app.restclient.repositories;
//package to read json type
import com.fasterxml.jackson.databind.JsonNode;
//package for mapping object node
import com.fasterxml.jackson.databind.ObjectMapper;
//package for object node
import com.fasterxml.jackson.databind.node.ObjectNode;
//package for encoding and decoding with base64
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;
//package to access HTTP client
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
//function to get public access token from clientID and clientSecret
//classes at service level
@Service
public class AuthRepository {
private static final String BASE_URL = "http://sandbox.onebrick.io/";
//private static final String BASE_URL = "http://localhost:8080/";
//change the value of XXXXX to your own ClientID
private static final String CLIENT_ID = "XXXXX";
//change the value of XXXXX to your own ClientSecret
private static final String CLIENT_SECRET = "XXXXX";
private static final ObjectMapper MAPPER = new ObjectMapper();
//function to get the publicToken()
public JsonNode getPublicToken() throws Exception {
//JsonNode to store the json data retrieved
JsonNode result = MAPPER.createObjectNode();
try {
//client to acces sandbox
var client = HttpClientBuilder.create().build();
//request to perform GET method
var request = new HttpGet(BASE_URL + "/v1/auth/token");
//authentication header
var authHeader = CLIENT_ID + ":" + CLIENT_SECRET;
//encoded authentication
var encHeader = Base64.encodeBase64(authHeader.getBytes(StandardCharsets.ISO_8859_1));
authHeader ="Basic " + new String(encHeader);
request.setHeader("Authorization", authHeader);
//execute Get Request
var response = client.execute(request);
var node = MAPPER.readValue(response.getEntity().getContent(), ObjectNode.class);
//if condition to store the data
if(node.has("data")) {
result = node.get("data");
}
} catch (Exception e) {
throw new Exception(e);
}
return result;//return json data with public access token from Brick API
}
}
Example of the return value from AuthRepository class will be like this JSON data.
{
"status": 200,
"message": "OK",
"data": {
"access_token": "public-sandbox-b70bcf83-87a1-4f2c-8f2a-16d48021413a"
}
}
UserAccessMappingRepository.java
This class will store the mapped value of user access data. It will retrieve from UserAccessMapping class.
package com.onebrick.app.restclient.repositories;
//import entities class from local path
import com.onebrick.app.restclient.entities.UserAccessMapping;
//package to use data JPA repository
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
//interface using data JPA to access data from UserAccessMapping class in entities folder
//persistence layer
@Repository
public interface UserAccessMappingRepository extends JpaRepository<UserAccessMapping, Integer> {
//save the userAccessMapping in JPA repository
UserAccessMapping findBySessionId(String sessionId);
}
Entities folder
UserAccessMapping.java
This class will set the value for user access variables, and will store value into H2 Database. This class will be called in repositories/UserAccessMappingRepository.java and controller/HomeController.java
package com.onebrick.app.restclient.entities;
//package from lombok get and set function
import lombok.Getter;
import lombok.Setter;
//package for persistence to be stored in jpa
import javax.persistence.*;
@Entity
//set table name
@Table(name = "user_access_mapping")
//get and set for variables
@Getter
@Setter
public class UserAccessMapping {
//id column in table h2
@Id
@GeneratedValue
private int id;
//set column user_access_token in table h2
@Column(name = "user_access_token")
//variable to get and set user_access_token
private String userAccessToken;
//set column session_id in table h2
@Column(name = "session_id")
//variable to get and set sessionId
private String sessionId;
//set column is_jenius in table h2
@Column(name = "is_jenius")
//variable to get and set isJenius
private boolean isJenius;
//lob annotation to keep in binary format
@Lob
//set column transactions in table h2
@Column(name = "transactions", length = 100000)
//variable to get and set transaction
private String transactions;
//lob annotation to keep in binary format
@Lob
//set column accounts in table h2
@Column(name = "accounts", length = 100000)
//variable to get and set accounts
private String accounts;
}
Model Folder
Transaction.java
This class is to store transaction details from a user's account. This class will be called in controller/HomeController.java.
package com.onebrick.app.restclient.models;
//package to read json data to get each specific value
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
//package from lombok get and set function
import lombok.Getter;
import lombok.Setter;
//package to get time
import java.sql.Timestamp;
//set get and set function
@Getter
@Setter
//condition to ignore JSON properties that are not identified
@JsonIgnoreProperties(ignoreUnknown = true)
public class Transaction {
//unique id for each rows of data
@JsonProperty("id")
private long id;
//store the value for account_id
@JsonProperty("account_id")
private String accountId;
//store the value for category_id
@JsonProperty("category_id")
private long categoryId;
//store the value for subcategory_id
@JsonProperty("subcategory_id")
private long subcategoryId;
//store the value for merchant_id
@JsonProperty("merchant_id")
private long merchantId;
//store the value for location_country_id
@JsonProperty("location_country_id")
private long countryId;
//store the value for location_city_id
@JsonProperty("location_city_id")
private long cityId;
//store the value for outlet_outlet_id
@JsonProperty("outlet_outlet_id")
private long outletId;
//store the value for amount
@JsonProperty("amount")
private Double amount;
//store the value for date and set with property yyyy-mm-dd
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
@JsonProperty("date")
private Timestamp date;
//store the value for description
@JsonProperty("description")
private String description;
//store the value for status
@JsonProperty("status")
private String status;
//store the value for direction
@JsonProperty("direction")
private String direction;
}
This is the sample of Transaction in JSON format
{
"status": 200,
"message": "OK",
"data": [
{
"id": 9744,
"account_id": "jwYhjuy4tQZx8sZj3oBrg9fSqvzsR41F==",
"category_id": 24,
"subcategory_id": 141,
"merchant_id": 8,
"location_country_id": 0,
"location_city_id": 0,
"outlet_outlet_id": 0,
"amount": 600000.0,
"date": "2020-06-29",
"description": "ATM-MP SA CWD XMD S1AW1MJK /7774759936/ATM-RCOASIAAFRK 4616993200225278 RCOASIAAFRK",
"status": "CONFIRMED",
"direction": "out"
},
{
"id": 9743,
"account_id": "jwYhjuy4tQZx8sZj3oBrg9fSqvzsR41F==",
"category_id": 22,
"subcategory_id": 129,
"merchant_id": 0,
"location_country_id": 0,
"location_city_id": 0,
"outlet_outlet_id": 0,
"amount": 1000.0,
"date": "2020-06-29",
"description": "CA/SA UBP DR/CR-ATM UBP60116073701FFFFFF085755130021 50000 S1AW1MJK /7774759939/ATM-RCOASIAAFRK P085755130021",
"status": "CONFIRMED",
"direction": "out"
}
]
}
Controller Folder
HomeController.java
Classes to store Balance, User Access, Account Details from user's Financial Institution account.
//Balance class to store account's balance details
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
class Balance {
private String currency;
private double availableBalance;
private double currentBalance;
private Timestamp timestamp;
}
//userAccess class to store the accessToken and its transactions
@Data
@NoArgsConstructor
class UserAccess {
private String accessToken;
private String transactions;
//private String accounts;
}
//UserAccountDetail class to store the account's details
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
class UserAccountDetail {
private String accountId;
private String accountHolder;
private String accountNumber;
private BalanceDetail balances;
//set default value if there is no account details
UserAccountDetail() {
accountHolder = "John Doe";
accountNumber = "987-0675-789";
accountId = "qwerty//++--==";
balances = new BalanceDetail(100987.0, 100987.0);
}
}
//store balance detail value only the current and available balance
@Data
@NoArgsConstructor
@AllArgsConstructor
class BalanceDetail {
private double available;
private double current;
}
getMockTransaction(string) function is to get the transaction and store it into mapper.
//function to store the transaction list
private List<Transaction> getMockTransaction(String userToken) throws Exception {
//create new object mapper
var mapper = new ObjectMapper();
//startdate to find the transaction starting date
var startDate = setStartDate(new Date());
//enddate for the end of date range of the transaction
var endDate = parseDate(new Date());
//link to access the transaction using Brick API
var url = BASE_URL + "v1/transaction/list?from=" + startDate +"&to=" + endDate;
var client = HttpClientBuilder.create().build();
var request = new HttpGet(url);
//request header for the http
request.setHeader("Authorization", "Bearer " + userToken);
var response = client.execute(request);
var node = mapper.readValue(response.getEntity().getContent(), ObjectNode.class);
return mapper.convertValue(node.get("data"), new TypeReference<ArrayList<Transaction>>(){}); //return the value of transaction into mapper
}
getMockBalance(string) function is to get the balance and store it into mapper.
private Balance getMockBalance(String userToken) throws Exception {
//create new object mapper
var mapper = new ObjectMapper();
//link to the account balance
var url = BASE_URL + "v1/account/balance";
var client = HttpClientBuilder.create().build();
var request = new HttpGet(url);
//request header for the http
request.setHeader("Authorization", "Bearer " + userToken);
var response = client.execute(request);
var node = mapper.readValue(response.getEntity().getContent(), ObjectNode.class);
return mapper.convertValue(node.get("data"), Balance.class);//return the value of balance into mapper
}
getMockUserDetail(string) function is to get the user account details and store it into mapper.
private UserAccountDetail getMockUserDetail(String userToken) throws Exception {
//create new object mapper
var mapper = new ObjectMapper();
//link to the account list
var url = BASE_URL + "v1/account/list";
var client = HttpClientBuilder.create().build();
var request = new HttpGet(url);
//request header for the http
request.setHeader("Authorization", "Bearer " + userToken);
var response = client.execute(request);
var node = mapper.readValue(response.getEntity().getContent(), ObjectNode.class);
UserAccountDetail[] accounts = mapper.convertValue(node.get("data"), UserAccountDetail[].class);
//condition when there is no account in the list
if(accounts.length == 0) {
return new UserAccountDetail();
//condition when account list exist
} else {
return accounts[0];
}
}
parseDate(date) function to set the date for transaction date range.
private String parseDate(Date date) {
var df = new SimpleDateFormat("yyyy-MM-dd");
return df.format(date);
}
private String setStartDate(Date date) {
var cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.MONTH, -1);
return parseDate(cal.getTime());
}
Controller class that calls repository and entities classes, all POST and GET request to Brick API happens in HomeController class.
@Autowired
//create AuthRepository object
private AuthRepository authRepository;
@Autowired
//create UserAccessMappingRepository object
private UserAccessMappingRepository userAccessMappingRepository;
//create ObjectMapper object
private ObjectMapper mapper;
//base url of Brick API
private static final String BASE_URL = "http://sandbox.onebrick.io/";
//private static final String BASE_URL = "http://localhost:8080/";
//private static final String REDIRECT = "https://demo.onebrick.io/result";
//redirect page to result file in local directory
private static final String REDIRECT = "http://localhost:8085/result";
//check server
@RequestMapping(value = "/ping", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody ResponseEntity<String> ping() {
return ResponseEntity.ok("Server is up and running");
}
//First function to get the index page when project is executed
@RequestMapping("/")
public String index(Model model) throws Exception {
//token to store public_access_token
var token = authRepository.getPublicToken();
//add to model
model.addAttribute("server", BASE_URL + "v1/index");
model.addAttribute("token", token.get("access_token").textValue());
model.addAttribute("redirect", REDIRECT);
return "start";
}
//function called when brick API request for POST method
@RequestMapping(value = "/result", method = RequestMethod.POST, consumes = "application/json")
public ResponseEntity<String> postResult(@RequestBody UserAccess userAccess) throws Exception {
//create a random alhpanumeric string
String randomString = RandomStringUtils.randomAlphanumeric(20);
var newMapping = new UserAccessMapping();
//mapping the value of session id from random
newMapping.setSessionId(randomString);
//map the user_access_token when received from successfull login of bank account
newMapping.setUserAccessToken(userAccess.getAccessToken());
if(userAccess.getTransactions() != null) {
newMapping.setJenius(true);
newMapping.setTransactions(userAccess.getTransactions());
}
userAccessMappingRepository.save(newMapping);
var url = REDIRECT + "?sessionId=" + randomString;
return new ResponseEntity<>(url, HttpStatus.OK);
}
//function called when brick API request for GET method
@RequestMapping(value = "/result", method = RequestMethod.GET)
public String result(@RequestParam String sessionId, Model model) throws Exception {
//call the classes to store the values
List<Transaction> transactions;
Balance balance;
UserAccountDetail detail;
//get the session id
var session = userAccessMappingRepository.findBySessionId(sessionId);
var token = authRepository.getPublicToken();
//condition to check for Jenius bank account method
if(session.isJenius()) {
transactions = scaffoldJeniusTransactions(session.getTransactions());
detail = new UserAccountDetail(); //scaffoldJeniusAccounts(session.getAccounts()).get(0);
//set Balance and currency from data retrieve with jenius account
balance = new Balance();
balance.setAvailableBalance(detail.getBalances().getAvailable());
balance.setCurrentBalance(detail.getBalances().getCurrent());
balance.setCurrency("IDR");
balance.setTimestamp(Timestamp.from(Instant.now()));
} else {
//set Balance and currency from data retrieve with non-jenius account
transactions = getMockTransaction(session.getUserAccessToken());
balance = getMockBalance(session.getUserAccessToken());
detail = getMockUserDetail(session.getUserAccessToken());
}
//add value into model
detail.setAccountHolder(WordUtils.capitalizeFully(detail.getAccountHolder()));
model.addAttribute("items", transactions);
model.addAttribute("balance", balance);
model.addAttribute("detail", detail);
model.addAttribute("server", BASE_URL + "v1/index");
model.addAttribute("token", token.get("access_token").textValue());
model.addAttribute("redirect", REDIRECT);
return "result"; //map the model
}
application.properties
//server port for starting the application
server.port=8085
//database server
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
//username and password for H2 Database
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
HTML pages
Start.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Money Save</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="icon" type="image/png" th:href="@{/images/favicon.png}"/>
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/main.css}"/>
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/bootstrap.min.css}"/>
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/permission.css}"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="javascripts/bootstrap.min.js"></script>
<script src="javascripts/popup.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
</head>
<body>
<div class="center">
<div class="content-box">
<div></div>
<div class="brick-logo"><img src="images/money-save-logo.png"class="img-fluid"></div>
<h2 class="header">Money Save App</h2>
<p>
Welcome to Brick's PFM application. Please think of Money Save as your own application UI when using this demo.
</p>
<!--<a class="btn btn-warning" type='button' href="#"
onclick="@{${server} + 'v1/launch?redirect_url=http://localhost:8085/user-access/retrieve&token=' + ${token}}">
Connect Your Bank<a/>-->
<p></p>
<a href="#" class="btn btn-warning" type="button" th:data-server="${server}" th:data-token="${token}" th:data-url="${redirect}"
th:onclick="openLink(this.getAttribute('data-server'), this.getAttribute('data-token'), this.getAttribute('data-url'))">Add a bank account</a>
</div>
<footer class="py-5">
<div class="container">
<p class="m-0 text-center">This application is for demonstrative purposes only. We do not store your data at any
time.</p>
</div>
</footer>
</div>
</body>
</html>
Result.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Money Save App</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="icon" type="image/png" th:href="@{/images/favicon.png}" />
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/main.css}" />
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/bootstrap.min.css}" />
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/permission.css}" />
<link rel="stylesheet" media="screen" th:href="@{/stylesheets/result.css}" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="javascripts/bootstrap.min.js"></script>
<script src="javascripts/popup.js"></script>
<script src="javascripts/sorttable.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
</head>
<body>
<div id="root">
<div>
<section id="navbar-margin" style="padding: 0;">
<div id="background-header" class="container-fluid">
<div class="container">
<div class="row">
<div id="logo" class="col-lg-3" style="padding-top:100px">
<img src="/images/money-save-logo.png" class="img-fluid">
</div>
<div id="info" class="col-lg-9">
<div class="row">
<div class="col-lg-6 hello-box">
<h3>Hello!</h3>
<!-- <h3>[[${detail.accountHolder}]]</h3> -->
</div>
<div class="col-lg-6 bank-box">
<h3>[[${detail.accountNumber}]]</h3>
<h4><span th:text="${#calendars.format(#calendars.createNow(), 'dd MMM yyyy')}"></span>
<!--<span class="account-details">
<span>
<span
class="account-details-separator">/</span><span>10000000</span></span><span><span
class="account-details-separator">/</span><span>01-21-31</span></span></span>-->
</h4>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div>
<div class="row">
<div id="sidebar" class="col-lg-3">
<div class="linked-accounts">
<p style="text-align:center">You have <span>1</span> account <br> linked to Money Save.</p>
<h6 class="list-group-title text-center">Add bank account</h6>
<div class="text-center">
<a href="#" id="connect-bank" class="btn btn-piggy-small text-center" type="button" th:data-server="${server}" th:data-token="${token}" th:data-url="${redirect}"
th:onclick="openLink(this.getAttribute('data-server'), this.getAttribute('data-token'), this.getAttribute('data-url'))">Connect Your Bank</a>
<!-- <button type="button" id="connect-bank" class="btn btn-piggy-small text-center">Connect your bank</button> -->
</div>
</div>
</div>
<div class="col-lg-9">
<div class="card mt-4">
<div class="row">
<div class="col col-lg-6">
<h5>Balance</h5>
</div>
<div class="col col-lg-6 text-right last-update">
<p>Updated <span class="timer"></span></p>
</div>
</div>
<div>
<div>
<div id="balance" class="row double-col">
<div class="col col-lg-6 text-center">
<span class="positive-val">[[${balance.currency}]] [[${#numbers.formatDecimal(detail.balances.available, 0, 'COMMA', 0, 'POINT')}]]</span>Available Balance
</div>
<div class="col col-lg-6 text-center">
<span class="positive-val">[[${balance.currency}]] [[${#numbers.formatDecimal(detail.balances.current, 0, 'COMMA', 0, 'POINT')}]]</span>Current Balance
</div>
</div>
</div>
</div>
</div>
<div class="card mt-4">
<div class="row">
<div class="col col-lg-6">
<h5>Transactions</h5>
</div>
<div class="col col-lg-6 text-right last-update">
<p>Updated <span class="timer"></span></p>
</div>
</div>
<div>
<div>
<div id="transactions" class="row">
<table class="table table-hover table-responsive sortable" style="font-size: 13px;">
<thead>
<tr>
<th>Time</th>
<th>Description</th>
<th>Status</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<th:block th:each="item : ${items}">
<tr>
<td th:text="${#dates.format(item.date, 'dd-MM-yyyy')}"></td>
<td th:text="${item.description}"></td>
<td th:text="${item.status}"></td>
<td th:text="${'IDR ' + #numbers.formatDecimal(item.amount, 0, 'COMMA', 0, 'POINT')}"></td>
</tr>
</th:block>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
<script type="text/javascript">
var el = '.timer';
var start = Math.round(new Date().getTime() / 1000);
var cDisplay = $(el);
var format = function (t) {
var hours = Math.floor(t / 3600),
minutes = Math.floor(t / 60 % 60),
seconds = Math.floor(t % 60),
arr = [];
if (hours > 0) {
arr.push(hours == 1 ? '1 hr ago' : hours + 'hrs ago');
}
if (minutes > 0 || hours > 0) {
arr.push(minutes > 1 ? minutes + ' mins ago' : minutes + ' min ago');
}
if (seconds > 0 || minutes > 0 || hours > 0) {
arr.push(seconds > 1 ? seconds + ' secs ago' : seconds + ' sec ago');
}
cDisplay.html(arr.join(' '));
};
setInterval(function () {
format(new Date().getTime() / 1000 - start);
}, 1000);
</script>
</body>
</html>
Updated 6 months ago