├── .DS_Store ├── .github ├── FUNDING.yml └── workflows │ └── gradle.yml ├── .gitignore ├── LICENSE ├── README.md ├── core-banking-service ├── .gitignore ├── Dockerfile ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ ├── CoreBankingServiceApplication.java │ │ │ │ ├── controller │ │ │ │ ├── AccountController.java │ │ │ │ ├── TransactionController.java │ │ │ │ └── UserController.java │ │ │ │ ├── exception │ │ │ │ ├── EntityNotFoundException.java │ │ │ │ ├── ErrorResponse.java │ │ │ │ ├── GlobalErrorCode.java │ │ │ │ ├── GlobalExceptionHandler.java │ │ │ │ ├── InsufficientFundsException.java │ │ │ │ └── SimpleBankingGlobalException.java │ │ │ │ ├── model │ │ │ │ ├── AccountStatus.java │ │ │ │ ├── AccountType.java │ │ │ │ ├── TransactionType.java │ │ │ │ ├── dto │ │ │ │ │ ├── BankAccount.java │ │ │ │ │ ├── Transaction.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UtilityAccount.java │ │ │ │ │ ├── request │ │ │ │ │ │ ├── FundTransferRequest.java │ │ │ │ │ │ └── UtilityPaymentRequest.java │ │ │ │ │ └── response │ │ │ │ │ │ ├── FundTransferResponse.java │ │ │ │ │ │ └── UtilityPaymentResponse.java │ │ │ │ ├── entity │ │ │ │ │ ├── BankAccountEntity.java │ │ │ │ │ ├── TransactionEntity.java │ │ │ │ │ ├── UserEntity.java │ │ │ │ │ └── UtilityAccountEntity.java │ │ │ │ └── mapper │ │ │ │ │ ├── BankAccountMapper.java │ │ │ │ │ ├── BaseMapper.java │ │ │ │ │ ├── UserMapper.java │ │ │ │ │ └── UtilityAccountMapper.java │ │ │ │ ├── repository │ │ │ │ ├── BankAccountRepository.java │ │ │ │ ├── TransactionRepository.java │ │ │ │ ├── UserRepository.java │ │ │ │ └── UtilityAccountRepository.java │ │ │ │ └── service │ │ │ │ ├── AccountService.java │ │ │ │ ├── TransactionService.java │ │ │ │ └── UserService.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap-dev.yml │ │ │ ├── bootstrap-docker.yml │ │ │ ├── bootstrap.yml │ │ │ ├── db │ │ │ └── migration │ │ │ │ ├── V1.0.20210427174638__create_base_table_structure.sql │ │ │ │ ├── V1.0.20210427174721__temp_data.sql │ │ │ │ └── V1.0.20210429210839__create_transaction_table.sql │ │ │ ├── messages.properties │ │ │ └── messages_fr.properties │ └── test │ │ ├── java │ │ └── com │ │ │ └── javatodev │ │ │ └── finance │ │ │ └── CoreBankingServiceApplicationTests.java │ │ └── resources │ │ └── application.yml └── wait-for-it.sh ├── docker-compose ├── docker-compose-support-apps.yml ├── docker-compose.yml ├── keycloak │ ├── Dockerfile │ └── realm-export.json └── mysql │ ├── Dockerfile │ └── privileges.sql ├── draw_io ├── centralized_configuration.drawio └── centralized_configuration.jpg ├── internet-banking-api-gateway ├── .gitignore ├── Dockerfile ├── api_test.http ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ ├── InternetBankingApiGatewayApplication.java │ │ │ │ └── configuration │ │ │ │ ├── GatewayConfiguration.java │ │ │ │ └── security │ │ │ │ └── SecurityConfiguration.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap-dev.yml │ │ │ ├── bootstrap-docker.yml │ │ │ └── bootstrap.yml │ └── test │ │ └── java │ │ └── com │ │ └── javatodev │ │ └── finance │ │ └── InternetBankingApiGatewayApplicationTests.java └── wait-for-it.sh ├── internet-banking-config-server ├── .gitignore ├── Dockerfile ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ └── InternetBankingConfigServerApplication.java │ │ └── resources │ │ │ └── application.yml │ └── test │ │ └── java │ │ └── com │ │ └── javatodev │ │ └── finance │ │ └── InternetBankingConfigServerApplicationTests.java └── wait-for-it.sh ├── internet-banking-fund-transfer-service ├── .gitignore ├── Dockerfile ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ ├── InternetBankingFundTransferServiceApplication.java │ │ │ │ ├── configuration │ │ │ │ ├── CustomFeignClientConfiguration.java │ │ │ │ ├── audit │ │ │ │ │ ├── AuditConfig.java │ │ │ │ │ └── AuditorAwareConfig.java │ │ │ │ └── filter │ │ │ │ │ ├── ApiRequestContext.java │ │ │ │ │ ├── ApiRequestContextHolder.java │ │ │ │ │ └── AppAuthUserFilter.java │ │ │ │ ├── controller │ │ │ │ └── FundTransferController.java │ │ │ │ ├── exception │ │ │ │ ├── ErrorResponse.java │ │ │ │ ├── GlobalExceptionHandler.java │ │ │ │ └── SimpleBankingGlobalException.java │ │ │ │ ├── model │ │ │ │ ├── TransactionStatus.java │ │ │ │ ├── dto │ │ │ │ │ ├── AuditAware.java │ │ │ │ │ ├── FundTransfer.java │ │ │ │ │ ├── request │ │ │ │ │ │ ├── FundTransferRequest.java │ │ │ │ │ │ └── UtilityPaymentRequest.java │ │ │ │ │ └── response │ │ │ │ │ │ ├── AccountResponse.java │ │ │ │ │ │ ├── FundTransferResponse.java │ │ │ │ │ │ └── UtilityPaymentResponse.java │ │ │ │ ├── entity │ │ │ │ │ └── FundTransferEntity.java │ │ │ │ ├── mapper │ │ │ │ │ ├── BaseMapper.java │ │ │ │ │ └── FundTransferMapper.java │ │ │ │ └── repository │ │ │ │ │ └── FundTransferRepository.java │ │ │ │ └── service │ │ │ │ ├── FundTransferService.java │ │ │ │ └── rest │ │ │ │ └── client │ │ │ │ └── BankingCoreFeignClient.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap-dev.yml │ │ │ ├── bootstrap-docker.yml │ │ │ └── bootstrap.yml │ └── test │ │ ├── java │ │ └── com │ │ │ └── javatodev │ │ │ └── finance │ │ │ └── InternetBankingFundTransferServiceApplicationTests.java │ │ └── resources │ │ └── application.yml └── wait-for-it.sh ├── internet-banking-service-registry ├── .gitignore ├── Dockerfile ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ └── InternetBankingServiceRegistryApplication.java │ │ └── resources │ │ │ └── application.yml │ └── test │ │ └── java │ │ └── com │ │ └── javatodev │ │ └── finance │ │ └── InternetBankingServiceRegistryApplicationTests.java └── wait-for-it.sh ├── internet-banking-user-service ├── .gitignore ├── Dockerfile ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ ├── InternetBankingUserServiceApplication.java │ │ │ │ ├── configuration │ │ │ │ ├── audit │ │ │ │ │ ├── AuditConfig.java │ │ │ │ │ └── AuditorAwareConfig.java │ │ │ │ ├── feign │ │ │ │ │ ├── CustomFeignClientConfiguration.java │ │ │ │ │ └── CustomFeignErrorDecoder.java │ │ │ │ ├── filter │ │ │ │ │ ├── ApiRequestContext.java │ │ │ │ │ ├── ApiRequestContextHolder.java │ │ │ │ │ └── AppAuthUserFilter.java │ │ │ │ └── keycloak │ │ │ │ │ ├── KeycloakManager.java │ │ │ │ │ └── KeycloakProperties.java │ │ │ │ ├── controller │ │ │ │ └── UserController.java │ │ │ │ ├── exception │ │ │ │ ├── EntityNotFoundException.java │ │ │ │ ├── ErrorResponse.java │ │ │ │ ├── GlobalErrorCode.java │ │ │ │ ├── GlobalExceptionHandler.java │ │ │ │ ├── InvalidBankingUserException.java │ │ │ │ ├── InvalidEmailException.java │ │ │ │ ├── SimpleBankingGlobalException.java │ │ │ │ └── UserAlreadyRegisteredException.java │ │ │ │ ├── model │ │ │ │ ├── dto │ │ │ │ │ ├── AuditAware.java │ │ │ │ │ ├── Status.java │ │ │ │ │ ├── User.java │ │ │ │ │ └── UserUpdateRequest.java │ │ │ │ ├── entity │ │ │ │ │ └── UserEntity.java │ │ │ │ ├── mapper │ │ │ │ │ ├── BaseMapper.java │ │ │ │ │ └── UserMapper.java │ │ │ │ ├── repository │ │ │ │ │ └── UserRepository.java │ │ │ │ └── rest │ │ │ │ │ └── response │ │ │ │ │ ├── AccountResponse.java │ │ │ │ │ └── UserResponse.java │ │ │ │ └── service │ │ │ │ ├── KeycloakUserService.java │ │ │ │ ├── UserService.java │ │ │ │ └── rest │ │ │ │ └── BankingCoreRestClient.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap-dev.yml │ │ │ ├── bootstrap-docker.yml │ │ │ └── bootstrap.yml │ └── test │ │ ├── java │ │ └── com │ │ │ └── javatodev │ │ │ └── finance │ │ │ └── InternetBankingUserServiceApplicationTests.java │ │ └── resources │ │ └── application.yml └── wait-for-it.sh ├── internet-banking-utility-payment-service ├── .gitignore ├── Dockerfile ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── javatodev │ │ │ │ └── finance │ │ │ │ ├── InternetBankingUtilityPaymentServiceApplication.java │ │ │ │ ├── configuration │ │ │ │ ├── CustomFeignClientConfiguration.java │ │ │ │ ├── audit │ │ │ │ │ ├── AuditConfig.java │ │ │ │ │ └── AuditorAwareConfig.java │ │ │ │ └── filter │ │ │ │ │ ├── ApiRequestContext.java │ │ │ │ │ ├── ApiRequestContextHolder.java │ │ │ │ │ └── AppAuthUserFilter.java │ │ │ │ ├── controller │ │ │ │ └── UtilityPaymentController.java │ │ │ │ ├── exception │ │ │ │ ├── ErrorResponse.java │ │ │ │ ├── GlobalExceptionHandler.java │ │ │ │ └── SimpleBankingGlobalException.java │ │ │ │ ├── model │ │ │ │ ├── TransactionStatus.java │ │ │ │ ├── dto │ │ │ │ │ ├── AuditAware.java │ │ │ │ │ └── UtilityPayment.java │ │ │ │ ├── entity │ │ │ │ │ └── UtilityPaymentEntity.java │ │ │ │ ├── mapper │ │ │ │ │ ├── BaseMapper.java │ │ │ │ │ └── UtilityPaymentMapper.java │ │ │ │ └── rest │ │ │ │ │ ├── request │ │ │ │ │ └── UtilityPaymentRequest.java │ │ │ │ │ └── response │ │ │ │ │ ├── AccountResponse.java │ │ │ │ │ └── UtilityPaymentResponse.java │ │ │ │ ├── repository │ │ │ │ └── UtilityPaymentRepository.java │ │ │ │ └── service │ │ │ │ ├── UtilityPaymentService.java │ │ │ │ └── rest │ │ │ │ └── BankingCoreRestClient.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap-dev.yml │ │ │ ├── bootstrap-docker.yml │ │ │ └── bootstrap.yml │ └── test │ │ ├── java │ │ └── com │ │ │ └── javatodev │ │ │ └── finance │ │ │ └── InternetBankingUtilityPaymentServiceApplicationTests.java │ │ └── resources │ │ └── application.yml └── wait-for-it.sh └── postman_collection ├── BANKING_CORE_MICROSERVICES_PROJECT.postman_environment.json └── JAVA_TO_DEV_MICROSERVICES.postman_collection.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/.DS_Store -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: javatodev # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: CI For Concept Microservice 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: { dir: [ 14 | 'core-banking-service', 15 | 'internet-banking-config-server', 16 | 'internet-banking-fund-transfer-service', 17 | 'internet-banking-user-service', 18 | 'internet-banking-utility-payment-service', 19 | 'internet-banking-service-registry', 20 | 'internet-banking-api-gateway' 21 | ] } 22 | permissions: 23 | contents: read 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | - name: Set up JDK 21 28 | uses: actions/setup-java@v4 29 | with: 30 | java-version: '21' 31 | distribution: 'temurin' 32 | 33 | - name: Setup Gradle 34 | uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 35 | 36 | - name: Build 37 | run: ./gradlew build -x test 38 | working-directory: ${{ matrix.dir }} 39 | 40 | - uses: actions/upload-artifact@v4 41 | with: 42 | name: ${{ matrix.dir }}-artifacts 43 | path: | 44 | ${{ matrix.dir }}/build/libs/${{ matrix.dir }}*SNAPSHOT.jar 45 | ${{ matrix.dir }}/Dockerfile 46 | ${{ matrix.dir }}/wait-for-it.sh 47 | retention-days: 1 48 | overwrite: true 49 | 50 | docker_publish: 51 | runs-on: ubuntu-latest 52 | strategy: 53 | matrix: { dir: [ 54 | 'core-banking-service', 55 | 'internet-banking-config-server', 56 | 'internet-banking-fund-transfer-service', 57 | 'internet-banking-user-service', 58 | 'internet-banking-utility-payment-service', 59 | 'internet-banking-service-registry', 60 | 'internet-banking-api-gateway' 61 | ] } 62 | permissions: 63 | contents: read 64 | packages: write 65 | needs: build 66 | 67 | steps: 68 | - name: Download latest build artifact 69 | uses: actions/download-artifact@v4 70 | with: 71 | name: ${{ matrix.dir }}-artifacts 72 | - name: Move artifacts to the correct directory 73 | shell: bash 74 | run: | 75 | ls -lrt 76 | mkdir -p ${{ matrix.dir }}-downloaded-artifacts 77 | mv build ${{ matrix.dir }}-downloaded-artifacts 78 | mv Dockerfile ${{ matrix.dir }}-downloaded-artifacts 79 | mv wait-for-it.sh ${{ matrix.dir }}-downloaded-artifacts 80 | 81 | - name: Validate moved artifacts 82 | run: ls -lrt 83 | working-directory: ${{ matrix.dir }}-downloaded-artifacts 84 | 85 | - name: Build Docker images 86 | run: docker build -t javatodev/${{ matrix.dir }} . 87 | working-directory: ${{ matrix.dir }}-downloaded-artifacts 88 | 89 | - name: Login to GitHub Container Registry 90 | uses: docker/login-action@v3 91 | with: 92 | username: ${{ secrets.DOCKERHUB_USERNAME }} 93 | password: ${{ secrets.DOCKERHUB_TOKEN }} 94 | 95 | - name: Push Docker image to GitHub Container Registry 96 | run: docker push javatodev/${{ matrix.dir }} 97 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 javatodev.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /core-banking-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /core-banking-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/core-banking-service-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8092 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /core-banking-service/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | id "com.gorylenko.gradle-git-properties" version "2.4.2" 6 | } 7 | 8 | gitProperties { 9 | dateFormat = "yyyy-MM-dd'T'HH:mmZ" 10 | dateFormatTimeZone = "IST" 11 | } 12 | 13 | group = 'com.javatodev.finance' 14 | version = '0.0.1-SNAPSHOT' 15 | 16 | java { 17 | sourceCompatibility = '21' 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | ext { 25 | set('springCloudVersion', "2023.0.0") 26 | } 27 | 28 | dependencies { 29 | implementation 'org.springframework.boot:spring-boot-starter-web' 30 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 31 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' 32 | 33 | //SPRING BOOT - TRACING 34 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 35 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 36 | implementation 'io.zipkin.reporter2:zipkin-reporter-brave' 37 | implementation 'io.github.openfeign:feign-micrometer' 38 | 39 | 40 | //SPRING CLOUD CONFIG 41 | implementation 'org.springframework.cloud:spring-cloud-starter-config' 42 | implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' 43 | 44 | compileOnly 'org.projectlombok:lombok' 45 | annotationProcessor 'org.projectlombok:lombok' 46 | 47 | implementation 'org.flywaydb:flyway-core:10.12.0' 48 | implementation 'org.flywaydb:flyway-mysql:10.12.0' 49 | implementation 'com.mysql:mysql-connector-j:8.4.0' 50 | 51 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 52 | testImplementation 'com.h2database:h2:2.2.224' 53 | 54 | 55 | } 56 | 57 | dependencyManagement { 58 | imports { 59 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 60 | } 61 | } 62 | 63 | test { 64 | useJUnitPlatform() 65 | } 66 | -------------------------------------------------------------------------------- /core-banking-service/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/core-banking-service/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /core-banking-service/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /core-banking-service/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /core-banking-service/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'core-banking-service' 2 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/CoreBankingServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CoreBankingServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CoreBankingServiceApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/controller/AccountController.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.controller; 2 | 3 | import com.javatodev.finance.service.AccountService; 4 | 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import lombok.RequiredArgsConstructor; 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | @Slf4j 15 | @RestController 16 | @RequestMapping(value = "/api/v1/account") 17 | @RequiredArgsConstructor 18 | public class AccountController { 19 | 20 | private final AccountService accountService; 21 | 22 | @GetMapping("/bank-account/{account_number}") 23 | public ResponseEntity getBankAccount(@PathVariable("account_number") String accountNumber) { 24 | log.info("Reading account by ID {}", accountNumber); 25 | return ResponseEntity.ok(accountService.readBankAccount(accountNumber)); 26 | } 27 | 28 | @GetMapping("/util-account/{account_name}") 29 | public ResponseEntity getUtilityAccount(@PathVariable("account_name") String providerName) { 30 | log.info("Reading utitlity account by ID {}", providerName); 31 | return ResponseEntity.ok(accountService.readUtilityAccount(providerName)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/controller/TransactionController.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.controller; 2 | 3 | import com.javatodev.finance.model.dto.request.FundTransferRequest; 4 | import com.javatodev.finance.model.dto.request.UtilityPaymentRequest; 5 | import com.javatodev.finance.service.TransactionService; 6 | 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import lombok.RequiredArgsConstructor; 14 | import lombok.extern.slf4j.Slf4j; 15 | 16 | @Slf4j 17 | @RestController 18 | @RequiredArgsConstructor 19 | @RequestMapping(value = "/api/v1/transaction") 20 | public class TransactionController { 21 | 22 | private final TransactionService transactionService; 23 | 24 | @PostMapping("/fund-transfer") 25 | public ResponseEntity fundTransfer(@RequestBody FundTransferRequest fundTransferRequest) { 26 | 27 | log.info("Fund transfer initiated in core bank from {}", fundTransferRequest.toString()); 28 | return ResponseEntity.ok(transactionService.fundTransfer(fundTransferRequest)); 29 | 30 | } 31 | 32 | @PostMapping("/util-payment") 33 | public ResponseEntity utilPayment(@RequestBody UtilityPaymentRequest utilityPaymentRequest) { 34 | 35 | log.info("Utility Payment initiated in core bank from {}", utilityPaymentRequest.toString()); 36 | return ResponseEntity.ok(transactionService.utilPayment(utilityPaymentRequest)); 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.controller; 2 | 3 | import com.javatodev.finance.service.UserService; 4 | 5 | import org.springframework.context.MessageSource; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import lombok.RequiredArgsConstructor; 14 | import lombok.extern.slf4j.Slf4j; 15 | 16 | @Slf4j 17 | @RestController 18 | @RequestMapping(value = "/api/v1/user") 19 | @RequiredArgsConstructor 20 | public class UserController { 21 | 22 | private final UserService userService; 23 | private final MessageSource messageSource; 24 | 25 | @GetMapping(value = "/{identification}") 26 | public ResponseEntity readUser(@PathVariable("identification") String identification) { 27 | return ResponseEntity.ok(userService.readUser(identification)); 28 | } 29 | 30 | @GetMapping 31 | public ResponseEntity readUsers(Pageable pageable) { 32 | return ResponseEntity.ok(userService.readUsers(pageable)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/exception/EntityNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class EntityNotFoundException extends SimpleBankingGlobalException { 4 | public EntityNotFoundException() { 5 | super("Requested entity not present in the DB.", GlobalErrorCode.ERROR_ENTITY_NOT_FOUND); 6 | } 7 | 8 | public EntityNotFoundException(String message) { 9 | super(message, GlobalErrorCode.ERROR_ENTITY_NOT_FOUND); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/exception/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | public class ErrorResponse { 11 | private String code; 12 | private String message; 13 | } 14 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/exception/GlobalErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class GlobalErrorCode { 4 | public static final String ERROR_ENTITY_NOT_FOUND = "BANKING-CORE-SERVICE-1000"; 5 | public static final String INSUFFICIENT_FUNDS = "BANKING-CORE-SERVICE-1001"; 6 | } 7 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 7 | 8 | import java.util.Locale; 9 | 10 | @ControllerAdvice 11 | public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { 12 | 13 | @ExceptionHandler(SimpleBankingGlobalException.class) 14 | protected ResponseEntity handleGlobalException(SimpleBankingGlobalException simpleBankingGlobalException, Locale locale) { 15 | return ResponseEntity 16 | .badRequest() 17 | .body(ErrorResponse.builder() 18 | .code(simpleBankingGlobalException.getCode()) 19 | .message(simpleBankingGlobalException.getMessage()) 20 | .build()); 21 | } 22 | 23 | @ExceptionHandler({Exception.class}) 24 | protected ResponseEntity handleException(Exception e, Locale locale) { 25 | return ResponseEntity 26 | .badRequest() 27 | .body("Exception occur inside API " + e); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/exception/InsufficientFundsException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class InsufficientFundsException extends SimpleBankingGlobalException { 4 | public InsufficientFundsException(String message, String code) { 5 | super(message, code); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/exception/SimpleBankingGlobalException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SimpleBankingGlobalException extends RuntimeException { 13 | 14 | private String code; 15 | private String message; 16 | 17 | public SimpleBankingGlobalException(String message) { 18 | super(message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/AccountStatus.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model; 2 | 3 | public enum AccountStatus { 4 | PENDING, ACTIVE, DORMANT, BLOCKED 5 | } 6 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/AccountType.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model; 2 | 3 | public enum AccountType { 4 | SAVINGS_ACCOUNT, FIXED_DEPOSIT, LOAN_ACCOUNT 5 | } 6 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/TransactionType.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model; 2 | 3 | public enum TransactionType { 4 | 5 | FUND_TRANSFER, UTILITY_PAYMENT 6 | 7 | } 8 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/BankAccount.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import com.javatodev.finance.model.AccountStatus; 4 | import com.javatodev.finance.model.AccountType; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import lombok.Data; 9 | 10 | @Data 11 | public class BankAccount { 12 | 13 | private Long id; 14 | private String number; 15 | private AccountType type; 16 | private AccountStatus status; 17 | private BigDecimal availableBalance; 18 | private BigDecimal actualBalance; 19 | private User user; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/Transaction.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class Transaction { 9 | 10 | private Long id; 11 | private BigDecimal amount; 12 | private BankAccount bankAccount; 13 | private String referenceNumber; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/User.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import java.util.List; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class User { 9 | 10 | private Long id; 11 | private String firstName; 12 | private String lastName; 13 | private String email; 14 | private String identificationNumber; 15 | private List bankAccounts; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/UtilityAccount.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class UtilityAccount { 7 | private Long id; 8 | private String number; 9 | private String providerName; 10 | } 11 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/request/FundTransferRequest.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.request; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class FundTransferRequest { 9 | private String fromAccount; 10 | private String toAccount; 11 | private BigDecimal amount; 12 | } 13 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/request/UtilityPaymentRequest.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.request; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class UtilityPaymentRequest { 9 | 10 | private Long providerId; 11 | private BigDecimal amount; 12 | private String referenceNumber; 13 | private String account; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/response/FundTransferResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.response; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Builder 8 | @Getter 9 | @Setter 10 | public class FundTransferResponse { 11 | 12 | private String message; 13 | private String transactionId; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/dto/response/UtilityPaymentResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.response; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | public class UtilityPaymentResponse { 11 | private String message; 12 | private String transactionId; 13 | } 14 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/entity/BankAccountEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import com.javatodev.finance.model.AccountStatus; 4 | import com.javatodev.finance.model.AccountType; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import jakarta.persistence.*; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | @Entity 15 | @Table(name = "banking_core_account") 16 | public class BankAccountEntity { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | private String number; 23 | 24 | @Enumerated(EnumType.STRING) 25 | private AccountType type; 26 | 27 | @Enumerated(EnumType.STRING) 28 | private AccountStatus status; 29 | 30 | private BigDecimal availableBalance; 31 | 32 | private BigDecimal actualBalance; 33 | 34 | @ManyToOne 35 | @JoinColumn(name = "user_id") 36 | private UserEntity user; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/entity/TransactionEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import com.javatodev.finance.model.TransactionType; 4 | 5 | import java.math.BigDecimal; 6 | 7 | import jakarta.persistence.*; 8 | import lombok.Builder; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Builder 13 | @Getter 14 | @Setter 15 | @Entity 16 | @Table(name = "banking_core_transaction") 17 | public class TransactionEntity { 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | private BigDecimal amount; 24 | 25 | @Enumerated(EnumType.STRING) 26 | private TransactionType transactionType; 27 | 28 | private String referenceNumber; 29 | 30 | private String transactionId; 31 | 32 | @OneToOne(cascade = CascadeType.ALL) 33 | @JoinColumn(name = "account_id", referencedColumnName = "id") 34 | private BankAccountEntity account; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/entity/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import java.util.List; 4 | 5 | import jakarta.persistence.*; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | @Entity 12 | @Table(name = "banking_core_user") 13 | public class UserEntity { 14 | 15 | @Id 16 | @GeneratedValue(strategy = GenerationType.IDENTITY) 17 | private Long id; 18 | 19 | private String firstName; 20 | private String lastName; 21 | private String email; 22 | private String identificationNumber; 23 | 24 | @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL) 25 | private List accounts; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/entity/UtilityAccountEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.GenerationType; 6 | import jakarta.persistence.Id; 7 | import jakarta.persistence.Table; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | 12 | @Getter 13 | @Setter 14 | @Entity 15 | @Table(name = "banking_core_utility_account") 16 | public class UtilityAccountEntity { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | private String number; 23 | 24 | private String providerName; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/mapper/BankAccountMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import com.javatodev.finance.model.dto.BankAccount; 4 | import com.javatodev.finance.model.entity.BankAccountEntity; 5 | 6 | import org.springframework.beans.BeanUtils; 7 | 8 | public class BankAccountMapper extends BaseMapper { 9 | 10 | @Override 11 | public BankAccountEntity convertToEntity(BankAccount dto, Object... args) { 12 | BankAccountEntity entity = new BankAccountEntity(); 13 | if (dto != null) { 14 | BeanUtils.copyProperties(dto, entity, "user"); 15 | } 16 | return entity; 17 | } 18 | 19 | @Override 20 | public BankAccount convertToDto(BankAccountEntity entity, Object... args) { 21 | BankAccount dto = new BankAccount(); 22 | if (entity != null) { 23 | BeanUtils.copyProperties(entity, dto, "user"); 24 | } 25 | return dto; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/mapper/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | 8 | public abstract class BaseMapper { 9 | public abstract E convertToEntity(D dto, Object... args); 10 | 11 | public abstract D convertToDto(E entity, Object... args); 12 | 13 | public Collection convertToEntity(Collection dto, Object... args) { 14 | return dto.stream().map(d -> convertToEntity(d, args)).collect(Collectors.toList()); 15 | } 16 | 17 | public Collection convertToDto(Collection entity, Object... args) { 18 | return entity.stream().map(e -> convertToDto(e, args)).collect(Collectors.toList()); 19 | } 20 | 21 | public List convertToEntityList(Collection dto, Object... args) { 22 | return convertToEntity(dto, args).stream().collect(Collectors.toList()); 23 | } 24 | 25 | public List convertToDtoList(Collection entity, Object... args) { 26 | return convertToDto(entity, args).stream().collect(Collectors.toList()); 27 | } 28 | 29 | public Set convertToEntitySet(Collection dto, Object... args) { 30 | return convertToEntity(dto, args).stream().collect(Collectors.toSet()); 31 | } 32 | 33 | public Set convertToDtoSet(Collection entity, Object... args) { 34 | return convertToDto(entity, args).stream().collect(Collectors.toSet()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import com.javatodev.finance.model.dto.User; 4 | import com.javatodev.finance.model.entity.UserEntity; 5 | 6 | import org.springframework.beans.BeanUtils; 7 | 8 | public class UserMapper extends BaseMapper { 9 | private BankAccountMapper bankAccountMapper = new BankAccountMapper(); 10 | 11 | @Override 12 | public UserEntity convertToEntity(User dto, Object... args) { 13 | UserEntity entity = new UserEntity(); 14 | if (dto != null) { 15 | BeanUtils.copyProperties(dto, entity, "accounts"); 16 | entity.setAccounts(bankAccountMapper.convertToEntityList(dto.getBankAccounts())); 17 | } 18 | return entity; 19 | } 20 | 21 | @Override 22 | public User convertToDto(UserEntity entity, Object... args) { 23 | User dto = new User(); 24 | if (entity != null) { 25 | BeanUtils.copyProperties(entity, dto, "accounts"); 26 | dto.setBankAccounts(bankAccountMapper.convertToDtoList(entity.getAccounts())); 27 | } 28 | return dto; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/model/mapper/UtilityAccountMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import com.javatodev.finance.model.dto.UtilityAccount; 4 | import com.javatodev.finance.model.entity.UtilityAccountEntity; 5 | 6 | import org.springframework.beans.BeanUtils; 7 | 8 | public class UtilityAccountMapper extends BaseMapper { 9 | @Override 10 | public UtilityAccountEntity convertToEntity(UtilityAccount dto, Object... args) { 11 | UtilityAccountEntity entity = new UtilityAccountEntity(); 12 | if (dto != null) { 13 | BeanUtils.copyProperties(dto, entity); 14 | } 15 | return entity; 16 | } 17 | 18 | @Override 19 | public UtilityAccount convertToDto(UtilityAccountEntity entity, Object... args) { 20 | UtilityAccount dto = new UtilityAccount(); 21 | if (entity != null) { 22 | BeanUtils.copyProperties(entity, dto); 23 | } 24 | return dto; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/repository/BankAccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.repository; 2 | 3 | import com.javatodev.finance.model.entity.BankAccountEntity; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.Optional; 8 | 9 | public interface BankAccountRepository extends JpaRepository { 10 | Optional findByNumber(String accountNumber); 11 | } 12 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/repository/TransactionRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.repository; 2 | 3 | import com.javatodev.finance.model.entity.TransactionEntity; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface TransactionRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.repository; 2 | 3 | import com.javatodev.finance.model.entity.UserEntity; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.Optional; 8 | 9 | public interface UserRepository extends JpaRepository { 10 | Optional findByIdentificationNumber(String identificationNumber); 11 | } 12 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/repository/UtilityAccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.repository; 2 | 3 | import com.javatodev.finance.model.entity.UtilityAccountEntity; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.Optional; 8 | 9 | public interface UtilityAccountRepository extends JpaRepository { 10 | Optional findByProviderName(String provider); 11 | } 12 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/service/AccountService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.exception.EntityNotFoundException; 4 | import com.javatodev.finance.model.dto.BankAccount; 5 | import com.javatodev.finance.model.dto.UtilityAccount; 6 | import com.javatodev.finance.model.entity.BankAccountEntity; 7 | import com.javatodev.finance.model.entity.UtilityAccountEntity; 8 | import com.javatodev.finance.model.mapper.BankAccountMapper; 9 | import com.javatodev.finance.model.mapper.UtilityAccountMapper; 10 | import com.javatodev.finance.repository.BankAccountRepository; 11 | import com.javatodev.finance.repository.UtilityAccountRepository; 12 | 13 | import org.springframework.stereotype.Service; 14 | 15 | import lombok.RequiredArgsConstructor; 16 | 17 | @Service 18 | @RequiredArgsConstructor 19 | public class AccountService { 20 | 21 | private BankAccountMapper bankAccountMapper = new BankAccountMapper(); 22 | private UtilityAccountMapper utilityAccountMapper = new UtilityAccountMapper(); 23 | 24 | private final BankAccountRepository bankAccountRepository; 25 | private final UtilityAccountRepository utilityAccountRepository; 26 | 27 | public BankAccount readBankAccount(String accountNumber) { 28 | BankAccountEntity entity = bankAccountRepository.findByNumber(accountNumber).orElseThrow(EntityNotFoundException::new); 29 | return bankAccountMapper.convertToDto(entity); 30 | } 31 | 32 | public UtilityAccount readUtilityAccount(String provider) { 33 | UtilityAccountEntity utilityAccountEntity = utilityAccountRepository.findByProviderName(provider).orElseThrow(EntityNotFoundException::new); 34 | return utilityAccountMapper.convertToDto(utilityAccountEntity); 35 | } 36 | 37 | public UtilityAccount readUtilityAccount(Long id) { 38 | return utilityAccountMapper.convertToDto(utilityAccountRepository.findById(id).orElseThrow(EntityNotFoundException::new)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/service/TransactionService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.exception.EntityNotFoundException; 4 | import com.javatodev.finance.exception.GlobalErrorCode; 5 | import com.javatodev.finance.exception.InsufficientFundsException; 6 | import com.javatodev.finance.model.TransactionType; 7 | import com.javatodev.finance.model.dto.BankAccount; 8 | import com.javatodev.finance.model.dto.UtilityAccount; 9 | import com.javatodev.finance.model.dto.request.FundTransferRequest; 10 | import com.javatodev.finance.model.dto.request.UtilityPaymentRequest; 11 | import com.javatodev.finance.model.dto.response.FundTransferResponse; 12 | import com.javatodev.finance.model.dto.response.UtilityPaymentResponse; 13 | import com.javatodev.finance.model.entity.BankAccountEntity; 14 | import com.javatodev.finance.model.entity.TransactionEntity; 15 | import com.javatodev.finance.repository.BankAccountRepository; 16 | import com.javatodev.finance.repository.TransactionRepository; 17 | 18 | import org.springframework.stereotype.Service; 19 | 20 | import java.math.BigDecimal; 21 | import java.util.UUID; 22 | 23 | import jakarta.transaction.Transactional; 24 | import lombok.RequiredArgsConstructor; 25 | 26 | @Service 27 | @Transactional 28 | @RequiredArgsConstructor 29 | public class TransactionService { 30 | 31 | private final AccountService accountService; 32 | private final BankAccountRepository bankAccountRepository; 33 | private final TransactionRepository transactionRepository; 34 | 35 | public FundTransferResponse fundTransfer(FundTransferRequest fundTransferRequest) { 36 | 37 | BankAccount fromBankAccount = accountService.readBankAccount(fundTransferRequest.getFromAccount()); 38 | BankAccount toBankAccount = accountService.readBankAccount(fundTransferRequest.getToAccount()); 39 | 40 | //validating account balances 41 | validateBalance(fromBankAccount, fundTransferRequest.getAmount()); 42 | 43 | String transactionId = internalFundTransfer(fromBankAccount, toBankAccount, fundTransferRequest.getAmount()); 44 | return FundTransferResponse.builder().message("Transaction successfully completed").transactionId(transactionId).build(); 45 | 46 | } 47 | 48 | public UtilityPaymentResponse utilPayment(UtilityPaymentRequest utilityPaymentRequest) { 49 | 50 | String transactionId = UUID.randomUUID().toString(); 51 | 52 | BankAccount fromBankAccount = accountService.readBankAccount(utilityPaymentRequest.getAccount()); 53 | 54 | //validating account balances 55 | validateBalance(fromBankAccount, utilityPaymentRequest.getAmount()); 56 | 57 | UtilityAccount utilityAccount = accountService.readUtilityAccount(utilityPaymentRequest.getProviderId()); 58 | 59 | BankAccountEntity fromAccount = bankAccountRepository.findByNumber(fromBankAccount.getNumber()).get(); 60 | 61 | //we can call third party API to process UTIL payment from payment provider from here. 62 | 63 | fromAccount.setActualBalance(fromAccount.getActualBalance().subtract(utilityPaymentRequest.getAmount())); 64 | fromAccount.setAvailableBalance(fromAccount.getActualBalance().subtract(utilityPaymentRequest.getAmount())); 65 | 66 | transactionRepository.save(TransactionEntity.builder().transactionType(TransactionType.UTILITY_PAYMENT) 67 | .account(fromAccount) 68 | .transactionId(transactionId) 69 | .referenceNumber(utilityPaymentRequest.getReferenceNumber()) 70 | .amount(utilityPaymentRequest.getAmount().negate()).build()); 71 | 72 | return UtilityPaymentResponse.builder().message("Utility payment successfully completed") 73 | .transactionId(transactionId).build(); 74 | 75 | } 76 | 77 | private void validateBalance(BankAccount bankAccount, BigDecimal amount) { 78 | if (bankAccount.getActualBalance().compareTo(BigDecimal.ZERO) < 0 || bankAccount.getActualBalance().compareTo(amount) < 0) { 79 | throw new InsufficientFundsException("Insufficient funds in the account " + bankAccount.getNumber(), GlobalErrorCode.INSUFFICIENT_FUNDS); 80 | } 81 | } 82 | 83 | public String internalFundTransfer(BankAccount fromBankAccount, BankAccount toBankAccount, BigDecimal amount) { 84 | 85 | String transactionId = UUID.randomUUID().toString(); 86 | 87 | BankAccountEntity fromBankAccountEntity = bankAccountRepository.findByNumber(fromBankAccount.getNumber()).orElseThrow(EntityNotFoundException::new); 88 | BankAccountEntity toBankAccountEntity = bankAccountRepository.findByNumber(toBankAccount.getNumber()).orElseThrow(EntityNotFoundException::new); 89 | 90 | fromBankAccountEntity.setActualBalance(fromBankAccountEntity.getActualBalance().subtract(amount)); 91 | fromBankAccountEntity.setAvailableBalance(fromBankAccountEntity.getActualBalance().subtract(amount)); 92 | bankAccountRepository.save(fromBankAccountEntity); 93 | 94 | transactionRepository.save(TransactionEntity.builder().transactionType(TransactionType.FUND_TRANSFER) 95 | .referenceNumber(toBankAccountEntity.getNumber()) 96 | .transactionId(transactionId) 97 | .account(fromBankAccountEntity).amount(amount.negate()).build()); 98 | 99 | toBankAccountEntity.setActualBalance(toBankAccountEntity.getActualBalance().add(amount)); 100 | toBankAccountEntity.setAvailableBalance(toBankAccountEntity.getActualBalance().add(amount)); 101 | bankAccountRepository.save(toBankAccountEntity); 102 | 103 | transactionRepository.save(TransactionEntity.builder().transactionType(TransactionType.FUND_TRANSFER) 104 | .referenceNumber(toBankAccountEntity.getNumber()) 105 | .transactionId(transactionId) 106 | .account(toBankAccountEntity).amount(amount).build()); 107 | 108 | return transactionId; 109 | 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /core-banking-service/src/main/java/com/javatodev/finance/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.exception.EntityNotFoundException; 4 | import com.javatodev.finance.model.dto.User; 5 | import com.javatodev.finance.model.entity.UserEntity; 6 | import com.javatodev.finance.model.mapper.UserMapper; 7 | import com.javatodev.finance.repository.UserRepository; 8 | 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.List; 13 | 14 | import lombok.RequiredArgsConstructor; 15 | 16 | @Service 17 | @RequiredArgsConstructor 18 | public class UserService { 19 | 20 | private UserMapper userMapper = new UserMapper(); 21 | 22 | private final UserRepository userRepository; 23 | 24 | public User readUser(String identification) { 25 | UserEntity userEntity = userRepository.findByIdentificationNumber(identification).orElseThrow(EntityNotFoundException::new); 26 | return userMapper.convertToDto(userEntity); 27 | } 28 | 29 | public List readUsers(Pageable pageable) { 30 | return userMapper.convertToDtoList(userRepository.findAll(pageable).getContent()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: core-banking-service 4 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/bootstrap-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://192.168.1.5:8090 5 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/bootstrap-docker.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://internet-banking-config-server:8090 5 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://localhost:8090 5 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/db/migration/V1.0.20210427174638__create_base_table_structure.sql: -------------------------------------------------------------------------------- 1 | -- banking_core_service.banking_core_user definition 2 | 3 | CREATE TABLE `banking_core_user` ( 4 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 5 | `email` varchar(255) DEFAULT NULL, 6 | `first_name` varchar(255) DEFAULT NULL, 7 | `identification_number` varchar(255) DEFAULT NULL, 8 | `last_name` varchar(255) DEFAULT NULL, 9 | PRIMARY KEY (`id`) 10 | ); 11 | 12 | -- banking_core_service.banking_core_account definition 13 | 14 | CREATE TABLE `banking_core_account` ( 15 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 16 | `actual_balance` decimal(19, 2) DEFAULT NULL, 17 | `available_balance` decimal(19, 2) DEFAULT NULL, 18 | `number` varchar(255) DEFAULT NULL, 19 | `status` varchar(255) DEFAULT NULL, 20 | `type` varchar(255) DEFAULT NULL, 21 | `user_id` bigint(20) DEFAULT NULL, 22 | PRIMARY KEY (`id`), 23 | KEY `FKt5uqy9p0v3rp3yhlgvm7ep0ij`(`user_id`), 24 | CONSTRAINT `FKt5uqy9p0v3rp3yhlgvm7ep0ij` FOREIGN KEY (`user_id`) REFERENCES `banking_core_user`(`id`) 25 | ); 26 | 27 | -- banking_core_service.banking_core_account definition 28 | 29 | CREATE TABLE `banking_core_utility_account` ( 30 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 31 | `number` varchar(255) DEFAULT NULL, 32 | `provider_name` varchar(255) DEFAULT NULL, 33 | PRIMARY KEY (`id`) 34 | ); 35 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/db/migration/V1.0.20210427174721__temp_data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO banking_core_user (id, email, first_name, identification_number, last_name) 2 | VALUES ('1', 'sam@gmail.com', 'Sam', '808829932V', 'Silva'); 3 | INSERT INTO banking_core_service.banking_core_user (id, email, first_name, identification_number, last_name) 4 | VALUES ('2', 'guru@gmail.com', 'Guru', '901830556V', 'Darmaraj'); 5 | INSERT INTO banking_core_service.banking_core_user (id, email, first_name, identification_number, last_name) 6 | VALUES ('3', 'ragu@gmail.com', 'Ragu', '348829932V', 'Sivaraj'); 7 | INSERT INTO banking_core_service.banking_core_user (id, email, first_name, identification_number, last_name) 8 | VALUES ('4', 'randor@gmail.com', 'Randor', '842829932V', 'Manoon'); 9 | 10 | INSERT INTO banking_core_account 11 | (actual_balance, available_balance, `number`, status, `type`, user_id) 12 | VALUES (100000.00, 100000.00, 100015003000, 'ACTIVE', 'SAVINGS_ACCOUNT', '1'), 13 | (100000.00, 100000.00, 100015003001, 'ACTIVE', 'SAVINGS_ACCOUNT', '1'), 14 | (100000.00, 100000.00, 100015003002, 'ACTIVE', 'SAVINGS_ACCOUNT', '2'), 15 | (12000.00, 12000.00, 100015003003, 'ACTIVE', 'SAVINGS_ACCOUNT', '2'), 16 | (12000.00, 12000.00, 100015003004, 'ACTIVE', 'SAVINGS_ACCOUNT', '2'), 17 | (12000.00, 12000.00, 100015003005, 'ACTIVE', 'SAVINGS_ACCOUNT', '3'), 18 | (290000.00, 290000.00, 100015003006, 'ACTIVE', 'SAVINGS_ACCOUNT', '3'), 19 | (290000.00, 290000.00, 100015003007, 'ACTIVE', 'SAVINGS_ACCOUNT', '3'), 20 | (290000.00, 290000.00, 100015003008, 'ACTIVE', 'SAVINGS_ACCOUNT', '3'), 21 | (365023.00, 365023.00, 100015003009, 'ACTIVE', 'SAVINGS_ACCOUNT', '3'), 22 | (365023.00, 365023.00, 100015003010, 'ACTIVE', 'SAVINGS_ACCOUNT', '4'), 23 | (365023.00, 89456.00, 100015003011, 'ACTIVE', 'SAVINGS_ACCOUNT', '4'), 24 | (89456.00, 89456.00, 100015003012, 'ACTIVE', 'SAVINGS_ACCOUNT', '4'), 25 | (889000.33, 889000.33, 100015003013, 'ACTIVE', 'SAVINGS_ACCOUNT', '4'); 26 | 27 | 28 | INSERT INTO banking_core_utility_account (`number`, provider_name) 29 | VALUES ('8203232565', 'VODAFONE'); 30 | INSERT INTO banking_core_utility_account (`number`, provider_name) 31 | VALUES ('5464546545', 'VERIZON'); 32 | INSERT INTO banking_core_utility_account (`number`, provider_name) 33 | VALUES ('6546456464', 'SINGTEL'); 34 | INSERT INTO banking_core_utility_account (`number`, provider_name) 35 | VALUES ('7889987999', 'HUTCH'); 36 | INSERT INTO banking_core_utility_account (`number`, provider_name) 37 | VALUES ('2132123132', 'AIRTEL'); 38 | INSERT INTO banking_core_utility_account (`number`, provider_name) 39 | VALUES ('61645564646', 'GIO'); 40 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/db/migration/V1.0.20210429210839__create_transaction_table.sql: -------------------------------------------------------------------------------- 1 | -- banking_core_service.banking_core_transaction definition 2 | 3 | CREATE TABLE `banking_core_transaction` ( 4 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 5 | `amount` decimal(19, 2) DEFAULT NULL, 6 | `transaction_type` varchar(30) NOT NULL, 7 | `reference_number` varchar(50) NOT NULL, 8 | `transaction_id` varchar(50) NOT NULL, 9 | `account_id` bigint(20) DEFAULT NULL, 10 | PRIMARY KEY (`id`), 11 | KEY `FKk9w2ogq595jbe8r2due7vv3xr`(`account_id`), 12 | CONSTRAINT `FKk9w2ogq595jbe8r2due7vv3xr` FOREIGN KEY (`account_id`) REFERENCES `banking_core_account`(`id`) 13 | ); 14 | -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | hello.message=Hello from API -------------------------------------------------------------------------------- /core-banking-service/src/main/resources/messages_fr.properties: -------------------------------------------------------------------------------- 1 | hello.message=Hola from API -------------------------------------------------------------------------------- /core-banking-service/src/test/java/com/javatodev/finance/CoreBankingServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CoreBankingServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core-banking-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: core-banking-service 4 | datasource: 5 | url: jdbc:h2:mem:banking_core_service 6 | username: root 7 | password: password 8 | driver-class-name: org.h2.Driver 9 | jpa: 10 | hibernate: 11 | ddl-auto: none 12 | database-platform: org.hibernate.dialect.H2Dialect 13 | 14 | flyway: 15 | enabled: false 16 | server: 17 | port: 8092 18 | 19 | eureka: 20 | client: 21 | service-url: 22 | defaultZone: http://localhost:8081/eureka 23 | 24 | info: 25 | app: 26 | name: ${spring.application.name} 27 | -------------------------------------------------------------------------------- /core-banking-service/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | WAITFORIT_cmdname=${0##*/} 5 | 6 | echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 28 | echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 29 | else 30 | echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" 31 | fi 32 | WAITFORIT_start_ts=$(date +%s) 33 | while : 34 | do 35 | if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then 36 | nc -z $WAITFORIT_HOST $WAITFORIT_PORT 37 | WAITFORIT_result=$? 38 | else 39 | (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 40 | WAITFORIT_result=$? 41 | fi 42 | if [[ $WAITFORIT_result -eq 0 ]]; then 43 | WAITFORIT_end_ts=$(date +%s) 44 | echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" 45 | break 46 | fi 47 | sleep 1 48 | done 49 | return $WAITFORIT_result 50 | } 51 | 52 | wait_for_wrapper() 53 | { 54 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 55 | if [[ $WAITFORIT_QUIET -eq 1 ]]; then 56 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 57 | else 58 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 59 | fi 60 | WAITFORIT_PID=$! 61 | trap "kill -INT -$WAITFORIT_PID" INT 62 | wait $WAITFORIT_PID 63 | WAITFORIT_RESULT=$? 64 | if [[ $WAITFORIT_RESULT -ne 0 ]]; then 65 | echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 66 | fi 67 | return $WAITFORIT_RESULT 68 | } 69 | 70 | # process arguments 71 | while [[ $# -gt 0 ]] 72 | do 73 | case "$1" in 74 | *:* ) 75 | WAITFORIT_hostport=(${1//:/ }) 76 | WAITFORIT_HOST=${WAITFORIT_hostport[0]} 77 | WAITFORIT_PORT=${WAITFORIT_hostport[1]} 78 | shift 1 79 | ;; 80 | --child) 81 | WAITFORIT_CHILD=1 82 | shift 1 83 | ;; 84 | -q | --quiet) 85 | WAITFORIT_QUIET=1 86 | shift 1 87 | ;; 88 | -s | --strict) 89 | WAITFORIT_STRICT=1 90 | shift 1 91 | ;; 92 | -h) 93 | WAITFORIT_HOST="$2" 94 | if [[ $WAITFORIT_HOST == "" ]]; then break; fi 95 | shift 2 96 | ;; 97 | --host=*) 98 | WAITFORIT_HOST="${1#*=}" 99 | shift 1 100 | ;; 101 | -p) 102 | WAITFORIT_PORT="$2" 103 | if [[ $WAITFORIT_PORT == "" ]]; then break; fi 104 | shift 2 105 | ;; 106 | --port=*) 107 | WAITFORIT_PORT="${1#*=}" 108 | shift 1 109 | ;; 110 | -t) 111 | WAITFORIT_TIMEOUT="$2" 112 | if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi 113 | shift 2 114 | ;; 115 | --timeout=*) 116 | WAITFORIT_TIMEOUT="${1#*=}" 117 | shift 1 118 | ;; 119 | --) 120 | shift 121 | WAITFORIT_CLI=("$@") 122 | break 123 | ;; 124 | --help) 125 | usage 126 | ;; 127 | *) 128 | echoerr "Unknown argument: $1" 129 | usage 130 | ;; 131 | esac 132 | done 133 | 134 | if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then 135 | echoerr "Error: you need to provide a host and port to test." 136 | usage 137 | fi 138 | 139 | WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} 140 | WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} 141 | WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} 142 | WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} 143 | 144 | # Check to see if timeout is from busybox? 145 | WAITFORIT_TIMEOUT_PATH=$(type -p timeout) 146 | WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) 147 | 148 | WAITFORIT_BUSYTIMEFLAG="" 149 | if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then 150 | WAITFORIT_ISBUSY=1 151 | # Check if busybox timeout uses -t flag 152 | # (recent Alpine versions don't support -t anymore) 153 | if timeout &>/dev/stdout | grep -q -e '-t '; then 154 | WAITFORIT_BUSYTIMEFLAG="-t" 155 | fi 156 | else 157 | WAITFORIT_ISBUSY=0 158 | fi 159 | 160 | if [[ $WAITFORIT_CHILD -gt 0 ]]; then 161 | wait_for 162 | WAITFORIT_RESULT=$? 163 | exit $WAITFORIT_RESULT 164 | else 165 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 166 | wait_for_wrapper 167 | WAITFORIT_RESULT=$? 168 | else 169 | wait_for 170 | WAITFORIT_RESULT=$? 171 | fi 172 | fi 173 | 174 | if [[ $WAITFORIT_CLI != "" ]]; then 175 | if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then 176 | echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" 177 | exit $WAITFORIT_RESULT 178 | fi 179 | exec "${WAITFORIT_CLI[@]}" 180 | else 181 | exit $WAITFORIT_RESULT 182 | fi 183 | -------------------------------------------------------------------------------- /docker-compose/docker-compose-support-apps.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | 5 | zipkin: 6 | image: openzipkin/zipkin:3 7 | ports: 8 | - 9411:9411 9 | networks: 10 | javatodev_ib_network: 11 | ipv4_address: 172.25.0.12 12 | 13 | keycloak_web: 14 | image: quay.io/keycloak/keycloak:23.0.7 15 | container_name: keycloak_web 16 | environment: 17 | KC_DB: postgres 18 | KC_DB_URL: jdbc:postgresql://keycloakdb:5432/keycloak 19 | KC_DB_USERNAME: keycloak 20 | KC_DB_PASSWORD: password 21 | KEYCLOAK_ADMIN: admin 22 | KEYCLOAK_ADMIN_PASSWORD: password 23 | command: ["start-dev", "--import-realm"] 24 | depends_on: 25 | - keycloakdb 26 | ports: 27 | - 8080:8080 28 | volumes: 29 | - ./keycloak:/opt/keycloak/data/import 30 | networks: 31 | javatodev_ib_network: 32 | ipv4_address: 172.25.0.11 33 | 34 | keycloakdb: 35 | image: postgres:15 36 | volumes: 37 | - postgres_data:/var/lib/postgresql/data 38 | environment: 39 | POSTGRES_DB: keycloak 40 | POSTGRES_USER: keycloak 41 | POSTGRES_PASSWORD: password 42 | networks: 43 | javatodev_ib_network: 44 | ipv4_address: 172.25.0.10 45 | 46 | mysql_core_db: 47 | build: mysql 48 | container_name: mysql_javatodev_app 49 | environment: 50 | MYSQL_ROOT_PASSWORD: woVERANKliGharym 51 | ports: 52 | - 3306:3306 53 | volumes: 54 | - mysqldata:/var/lib/mysql 55 | networks: 56 | javatodev_ib_network: 57 | ipv4_address: 172.25.0.9 58 | 59 | internet-banking-config-server: 60 | image: javatodev/internet-banking-config-server 61 | ports: 62 | - 8090:8090 63 | networks: 64 | javatodev_ib_network: 65 | ipv4_address: 172.25.0.8 66 | 67 | internet-banking-service-registry: 68 | image: javatodev/internet-banking-service-registry 69 | ports: 70 | - 8081:8081 71 | networks: 72 | javatodev_ib_network: 73 | ipv4_address: 172.25.0.7 74 | 75 | volumes: 76 | postgres_data: 77 | mysqldata: 78 | 79 | networks: 80 | javatodev_ib_network: 81 | driver: bridge 82 | ipam: 83 | driver: default 84 | config: 85 | - subnet: 172.25.0.0/16 86 | gateway: 172.25.0.1 -------------------------------------------------------------------------------- /docker-compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | 5 | zipkin: 6 | image: openzipkin/zipkin:3 7 | container_name: openzipkin_server 8 | ports: 9 | - 9411:9411 10 | networks: 11 | javatodev_ib_network: 12 | ipv4_address: 172.25.0.12 13 | 14 | keycloak_web: 15 | image: quay.io/keycloak/keycloak:23.0.7 16 | container_name: keycloak_web 17 | environment: 18 | KC_DB: postgres 19 | KC_DB_URL: jdbc:postgresql://keycloakdb:5432/keycloak 20 | KC_DB_USERNAME: keycloak 21 | KC_DB_PASSWORD: password 22 | KEYCLOAK_ADMIN: admin 23 | KEYCLOAK_ADMIN_PASSWORD: password 24 | command: ["start-dev", "--import-realm"] 25 | depends_on: 26 | - keycloakdb 27 | ports: 28 | - 8080:8080 29 | volumes: 30 | - ./keycloak:/opt/keycloak/data/import 31 | networks: 32 | javatodev_ib_network: 33 | ipv4_address: 172.25.0.11 34 | 35 | keycloakdb: 36 | image: postgres:15 37 | container_name: keycloak_postgre_db 38 | volumes: 39 | - postgres_data:/var/lib/postgresql/data 40 | environment: 41 | POSTGRES_DB: keycloak 42 | POSTGRES_USER: keycloak 43 | POSTGRES_PASSWORD: password 44 | networks: 45 | javatodev_ib_network: 46 | ipv4_address: 172.25.0.10 47 | 48 | mysql_core_db: 49 | build: mysql 50 | container_name: mysql_javatodev_app 51 | environment: 52 | MYSQL_ROOT_PASSWORD: woVERANKliGharym 53 | ports: 54 | - 3306:3306 55 | volumes: 56 | - mysqldata:/var/lib/mysql 57 | networks: 58 | javatodev_ib_network: 59 | ipv4_address: 172.25.0.9 60 | 61 | internet-banking-config-server: 62 | image: javatodev/internet-banking-config-server 63 | container_name: internet-banking-config-server 64 | ports: 65 | - 8090:8090 66 | networks: 67 | javatodev_ib_network: 68 | ipv4_address: 172.25.0.8 69 | 70 | internet-banking-service-registry: 71 | image: javatodev/internet-banking-service-registry 72 | container_name: internet-banking-service-registry 73 | ports: 74 | - 8081:8081 75 | networks: 76 | javatodev_ib_network: 77 | ipv4_address: 172.25.0.7 78 | 79 | internet-banking-api-gateway: 80 | image: javatodev/internet-banking-api-gateway 81 | container_name: internet-banking-api-gateway 82 | ports: 83 | - 8082:8082 84 | entrypoint: ["./wait-for-it.sh", "internet-banking-service-registry:8081", "--timeout=50", "--", "./wait-for-it.sh", "internet-banking-config-server:8090", "--timeout=50", "--", "java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 85 | networks: 86 | javatodev_ib_network: 87 | ipv4_address: 172.25.0.6 88 | 89 | internet-banking-user-service: 90 | image: javatodev/internet-banking-user-service 91 | container_name: internet-banking-user-service 92 | ports: 93 | - 8083:8083 94 | entrypoint: ["./wait-for-it.sh", "internet-banking-service-registry:8081", "--timeout=50", "--", "./wait-for-it.sh", "internet-banking-config-server:8090", "--timeout=50", "--", "./wait-for-it.sh", "mysql_core_db:3306", "--timeout=50", "--","java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 95 | networks: 96 | javatodev_ib_network: 97 | ipv4_address: 172.25.0.5 98 | 99 | internet-banking-fund-transfer-service: 100 | image: javatodev/internet-banking-fund-transfer-service 101 | container_name: internet-banking-fund-transfer-service 102 | ports: 103 | - 8084:8084 104 | entrypoint: ["./wait-for-it.sh", "internet-banking-service-registry:8081", "--timeout=50", "--", "./wait-for-it.sh", "internet-banking-config-server:8090", "--timeout=50", "--", "./wait-for-it.sh", "mysql_core_db:3306", "--timeout=50", "--","java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 105 | networks: 106 | javatodev_ib_network: 107 | ipv4_address: 172.25.0.4 108 | 109 | internet-banking-utility-payment-service: 110 | container_name: internet-banking-utility-payment-service 111 | image: javatodev/internet-banking-utility-payment-service 112 | ports: 113 | - 8085:8085 114 | entrypoint: ["./wait-for-it.sh", "internet-banking-service-registry:8081", "--timeout=50", "--", "./wait-for-it.sh", "internet-banking-config-server:8090", "--timeout=50", "--", "./wait-for-it.sh", "mysql_core_db:3306", "--timeout=50", "--","java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 115 | networks: 116 | javatodev_ib_network: 117 | ipv4_address: 172.25.0.3 118 | 119 | core-banking-service: 120 | image: javatodev/core-banking-service 121 | container_name: core-banking-service 122 | ports: 123 | - 8092:8092 124 | entrypoint: ["./wait-for-it.sh", "internet-banking-service-registry:8081", "--timeout=50", "--", "./wait-for-it.sh", "internet-banking-config-server:8090", "--timeout=50", "--", "./wait-for-it.sh", "mysql_core_db:3306", "--timeout=50", "--","java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 125 | networks: 126 | javatodev_ib_network: 127 | ipv4_address: 172.25.0.2 128 | 129 | volumes: 130 | postgres_data: 131 | mysqldata: 132 | 133 | networks: 134 | javatodev_ib_network: 135 | driver: bridge 136 | ipam: 137 | driver: default 138 | config: 139 | - subnet: 172.25.0.0/16 140 | gateway: 172.25.0.1 -------------------------------------------------------------------------------- /docker-compose/keycloak/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/keycloak/keycloak:23.0.7 2 | 3 | # Make the realm configuration available for import 4 | COPY ./realm-export.json /opt/keycloak_import/ 5 | 6 | # Import the realm and user 7 | RUN /opt/keycloak/bin/kc.sh import --optimized --file /opt/keycloak_import/realm-export.json 8 | 9 | # The Keycloak server is configured to listen on port 8080 10 | EXPOSE 8080 11 | 12 | # Import the realm on start-up 13 | CMD ["start-dev"] -------------------------------------------------------------------------------- /docker-compose/mysql/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mysql:8.4.0 2 | ENV MYSQL_ROOT_PASSWORD woVERANKliGharym 3 | COPY ./privileges.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /docker-compose/mysql/privileges.sql: -------------------------------------------------------------------------------- 1 | CREATE USER 'javatodev_development'@'%' IDENTIFIED BY 'oPItyPticIAt'; 2 | GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on *.* TO 'javatodev_development'@'%'; 3 | FLUSH PRIVILEGES; 4 | 5 | CREATE DATABASE IF NOT EXISTS banking_core_service; 6 | CREATE DATABASE IF NOT EXISTS banking_core_fund_transfer_service; 7 | CREATE DATABASE IF NOT EXISTS banking_core_user_service; 8 | CREATE DATABASE IF NOT EXISTS banking_core_utility_payment_service; -------------------------------------------------------------------------------- /draw_io/centralized_configuration.drawio: -------------------------------------------------------------------------------- 1 | 7ZjfT9swEMf/mj5SpXGTto/0FxsDCcEEbC+TSUzizclFjtMf/PU7N06TzIKCBAsPfal6X5999n18ySk9Mks2Z5Jm8SWETPRcJ9z0yLznupOhj79a2JbCyPVKIZI8LKVBLdzwJ2ZEx6gFD1neclQAQvGsLQaQpixQLY1KCeu22yOIdtSMRswSbgIqbPWOhyou1bE7qvUvjEdxFXngT8qRhFbO5iR5TENYNySy6JGZBFDlv2QzY0LnrspLOW/5zOh+Y5Kl6jUTwpPzBV9632+/Dq/pN3L78/48PhmbvaltdWAW4vmNCVLFEEFKxaJWpxKKNGR6VQet2ucCIENxgOJvptTWwKSFApRilQgzWsbUgZ49ipFyKGTAXth/dSWojJh6wc/dJxwvKoOEKbnFeZIJqviqvQ9qrky096uzin9MYt+QZLPuiorCRDrjKi4eULtmGeRcgYnSBLFiUnG8iBf0gYkr7cUhxaEHUAqSdkYr31PBI+2jNIkpNVaAaWUShVxJ+MNmIACteQqpxvnIhaiknkscZ7pYuto5ppneSrKJdGX36VMhWT/a7fxXgHWOPhlwvfRihRHyFl29I7Z5ma/Nw0wgY/OQMA+NiSmhdV2BnpHiRvFV2rsDnHRRJZgrub3X8/teZf4wy+2M+aZlbZvWFZMcz66p78R3LDn3lSVHOi05pwtkHWR52GmWB8fCeDsyr1Nk7hHZ25H5XSJzrfZhBukjj1C7YRJftBZRKJTgKb7oq55Ypy2kebxneLC5eGVH0WBs9QvrnPRZ4NotxtIbe2SIOjqGHJf6pyN5lw6C9Ns9xL4PbzYRxG4iRuSDMBIL4yUPJOSIkOMldZ3TI0eL48BpUyRjm+LIr1A3OU4+iuPwEMfpkaPF0R1/Oo7eIY6zI0eL49D/dBz9QxznR44WR3/4HzmiWX/m2o01vhWSxV8= -------------------------------------------------------------------------------- /draw_io/centralized_configuration.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/draw_io/centralized_configuration.jpg -------------------------------------------------------------------------------- /internet-banking-api-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .jpb 2 | HELP.md 3 | .gradle 4 | build/ 5 | !gradle/wrapper/gradle-wrapper.jar 6 | !**/src/main/**/build/ 7 | !**/src/test/**/build/ 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | bin/ 18 | !**/src/main/**/bin/ 19 | !**/src/test/**/bin/ 20 | 21 | ### IntelliJ IDEA ### 22 | .idea 23 | *.iws 24 | *.iml 25 | *.ipr 26 | out/ 27 | !**/src/main/**/out/ 28 | !**/src/test/**/out/ 29 | 30 | ### NetBeans ### 31 | /nbproject/private/ 32 | /nbbuild/ 33 | /dist/ 34 | /nbdist/ 35 | /.nb-gradle/ 36 | 37 | ### VS Code ### 38 | .vscode/ 39 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/internet-banking-api-gateway-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8082 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/api_test.http: -------------------------------------------------------------------------------- 1 | ### CHECK USER SERVICE INFO 2 | GET http://localhost:8082/user/actuator/info 3 | 4 | ### CHECK FUND TRANSFER INFO 5 | GET http://localhost:8082/fund-transfer/actuator/info -------------------------------------------------------------------------------- /internet-banking-api-gateway/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | id "com.gorylenko.gradle-git-properties" version "2.4.2" 6 | } 7 | 8 | gitProperties { 9 | dateFormat = "yyyy-MM-dd'T'HH:mmZ" 10 | dateFormatTimeZone = "IST" 11 | } 12 | 13 | group = 'com.javatodev.finance' 14 | version = '0.0.1-SNAPSHOT' 15 | 16 | java { 17 | sourceCompatibility = '21' 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | ext { 25 | set('springCloudVersion', "2023.0.0") 26 | } 27 | 28 | dependencies { 29 | implementation 'org.springframework.cloud:spring-cloud-starter-gateway' 30 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' 31 | 32 | //SPRING BOOT - TRACING 33 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 34 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 35 | implementation 'io.zipkin.reporter2:zipkin-reporter-brave' 36 | implementation 'io.github.openfeign:feign-micrometer' 37 | 38 | //SPRING CLOUD CONFIG 39 | implementation 'org.springframework.cloud:spring-cloud-starter-config' 40 | implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' 41 | 42 | //OAUTH2.0 CLIENT LIBRARIES 43 | implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' 44 | implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' 45 | implementation 'org.springframework.boot:spring-boot-starter-security' 46 | implementation 'org.springframework.boot:spring-boot-starter-webflux' 47 | 48 | 49 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 50 | } 51 | 52 | dependencyManagement { 53 | imports { 54 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 55 | } 56 | } 57 | 58 | test { 59 | useJUnitPlatform() 60 | } 61 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/internet-banking-api-gateway/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /internet-banking-api-gateway/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'internet-banking-api-gateway' 2 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/java/com/javatodev/finance/InternetBankingApiGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class InternetBankingApiGatewayApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(InternetBankingApiGatewayApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/java/com/javatodev/finance/configuration/GatewayConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration; 2 | 3 | import org.springframework.cloud.gateway.filter.GlobalFilter; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.security.Principal; 8 | 9 | import reactor.core.publisher.Mono; 10 | 11 | @Configuration 12 | public class GatewayConfiguration { 13 | 14 | private static final String HTTP_HEADER_AUTH_USER_ID = "X-Auth-Id"; 15 | private static final String UNAUTHORIZED_USER_NAME = "SYSTEM USER"; 16 | 17 | @Bean 18 | public GlobalFilter customGlobalFilter() { 19 | return (exchange, chain) -> exchange.getPrincipal().map(Principal::getName).defaultIfEmpty(UNAUTHORIZED_USER_NAME).map(principal -> { 20 | // adds header to proxied request 21 | exchange.getRequest().mutate() 22 | .header(HTTP_HEADER_AUTH_USER_ID, principal) 23 | .build(); 24 | return exchange; 25 | }).flatMap(chain::filter).then(Mono.fromRunnable(() -> { 26 | 27 | })); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/java/com/javatodev/finance/configuration/security/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.security; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; 7 | import org.springframework.security.config.web.server.ServerHttpSecurity; 8 | import org.springframework.security.web.server.SecurityWebFilterChain; 9 | 10 | @Configuration 11 | @EnableWebFluxSecurity 12 | public class SecurityConfiguration { 13 | 14 | @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") 15 | private String jwkUri; 16 | 17 | @Bean 18 | public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { 19 | 20 | ServerHttpSecurity httpSecurity = http 21 | .authorizeExchange(exchanges -> { 22 | 23 | //ALLOW USER REGISTRATION API ENDPOINT 24 | exchanges.pathMatchers("/user/api/v1/bank-users/register").permitAll(); 25 | 26 | //ALLOW ACTUATOR ENDPOINTS 27 | exchanges.pathMatchers("/actuator/**").permitAll() 28 | .pathMatchers("/user/actuator/**").permitAll() 29 | .pathMatchers("/fund-transfer/actuator/**").permitAll() 30 | .pathMatchers("/banking-core/actuator/**").permitAll() 31 | .pathMatchers("/utility-payment/actuator/**").permitAll() 32 | .anyExchange().authenticated(); 33 | }); 34 | 35 | httpSecurity.csrf(ServerHttpSecurity.CsrfSpec::disable); 36 | 37 | httpSecurity.oauth2ResourceServer(oAuth2ResourceServer -> oAuth2ResourceServer.jwt(jwt -> jwt.jwkSetUri(jwkUri))); 38 | 39 | return httpSecurity.build(); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: internet-banking-api-gateway 4 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/resources/bootstrap-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://192.168.1.5:8090 5 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/resources/bootstrap-docker.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://internet-banking-config-server:8090 5 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://localhost:8090 5 | -------------------------------------------------------------------------------- /internet-banking-api-gateway/src/test/java/com/javatodev/finance/InternetBankingApiGatewayApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InternetBankingApiGatewayApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-config-server/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /internet-banking-config-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/internet-banking-config-server-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8090 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /internet-banking-config-server/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | id "com.gorylenko.gradle-git-properties" version "2.4.2" 6 | } 7 | 8 | gitProperties { 9 | dateFormat = "yyyy-MM-dd'T'HH:mmZ" 10 | dateFormatTimeZone = "IST" 11 | } 12 | 13 | group = 'com.javatodev.finance' 14 | version = '0.0.1-SNAPSHOT' 15 | 16 | java { 17 | sourceCompatibility = '21' 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | ext { 25 | set('springCloudVersion', "2023.0.0") 26 | } 27 | 28 | dependencies { 29 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 30 | implementation 'org.springframework.cloud:spring-cloud-config-server' 31 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 32 | } 33 | 34 | dependencyManagement { 35 | imports { 36 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 37 | } 38 | } 39 | 40 | tasks.named('test') { 41 | useJUnitPlatform() 42 | } 43 | -------------------------------------------------------------------------------- /internet-banking-config-server/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/internet-banking-config-server/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /internet-banking-config-server/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /internet-banking-config-server/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /internet-banking-config-server/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'internet-banking-config-server' 2 | -------------------------------------------------------------------------------- /internet-banking-config-server/src/main/java/com/javatodev/finance/InternetBankingConfigServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.config.server.EnableConfigServer; 6 | 7 | @EnableConfigServer 8 | @SpringBootApplication 9 | public class InternetBankingConfigServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(InternetBankingConfigServerApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-config-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8090 3 | spring: 4 | cloud: 5 | config: 6 | server: 7 | git: 8 | uri: https://github.com/JavatoDev-com/internet-banking-microservices-configurations.git 9 | search-paths: configuration 10 | default-label: main 11 | -------------------------------------------------------------------------------- /internet-banking-config-server/src/test/java/com/javatodev/finance/InternetBankingConfigServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InternetBankingConfigServerApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/internet-banking-fund-transfer-service-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8084 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | id "com.gorylenko.gradle-git-properties" version "2.4.2" 6 | } 7 | 8 | gitProperties { 9 | dateFormat = "yyyy-MM-dd'T'HH:mmZ" 10 | dateFormatTimeZone = "IST" 11 | } 12 | 13 | group = 'com.javatodev.finance' 14 | version = '0.0.1-SNAPSHOT' 15 | 16 | java { 17 | sourceCompatibility = '21' 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | ext { 25 | set('springCloudVersion', "2023.0.0") 26 | } 27 | 28 | dependencies { 29 | implementation 'org.springframework.boot:spring-boot-starter-web' 30 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 31 | implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' 32 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' 33 | 34 | //SPRING BOOT - TRACING 35 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 36 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 37 | implementation 'io.zipkin.reporter2:zipkin-reporter-brave' 38 | implementation 'io.github.openfeign:feign-micrometer' 39 | 40 | //SPRING CLOUD CONFIG 41 | implementation 'org.springframework.cloud:spring-cloud-starter-config' 42 | implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' 43 | 44 | implementation 'com.mysql:mysql-connector-j:8.4.0' 45 | compileOnly 'org.projectlombok:lombok' 46 | annotationProcessor 'org.projectlombok:lombok' 47 | 48 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 49 | testImplementation 'com.h2database:h2:2.2.224' 50 | } 51 | 52 | dependencyManagement { 53 | imports { 54 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 55 | } 56 | } 57 | 58 | test { 59 | useJUnitPlatform() 60 | } 61 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/internet-banking-fund-transfer-service/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'internet-banking-fund-transfer-service' 2 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/InternetBankingFundTransferServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.openfeign.EnableFeignClients; 6 | 7 | @EnableFeignClients 8 | @SpringBootApplication 9 | public class InternetBankingFundTransferServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(InternetBankingFundTransferServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/configuration/CustomFeignClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import feign.Logger; 7 | 8 | @Configuration 9 | public class CustomFeignClientConfiguration { 10 | 11 | @Bean 12 | Logger.Level feignLoggerLevel() { 13 | return Logger.Level.FULL; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/configuration/audit/AuditConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.audit; 2 | 3 | import com.javatodev.finance.configuration.filter.AppAuthUserFilter; 4 | 5 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.domain.AuditorAware; 9 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 10 | 11 | @Configuration 12 | @EnableJpaAuditing 13 | public class AuditConfig { 14 | 15 | @Bean 16 | public AuditorAware myAuditorProvider() { 17 | return new AuditorAwareConfig(); 18 | } 19 | 20 | @Bean 21 | public FilterRegistrationBean authUserFilter() { 22 | FilterRegistrationBean registrationBean 23 | = new FilterRegistrationBean<>(); 24 | 25 | registrationBean.setFilter(new AppAuthUserFilter()); 26 | registrationBean.addUrlPatterns("/api/*"); 27 | 28 | return registrationBean; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/configuration/audit/AuditorAwareConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.audit; 2 | 3 | import com.javatodev.finance.configuration.filter.ApiRequestContextHolder; 4 | 5 | import org.apache.commons.lang.StringUtils; 6 | import org.springframework.data.domain.AuditorAware; 7 | 8 | import java.util.Optional; 9 | 10 | public class AuditorAwareConfig implements AuditorAware { 11 | @Override public Optional getCurrentAuditor() { 12 | if (StringUtils.isEmpty(ApiRequestContextHolder.getContext().getAuthId())) { 13 | return Optional.of("SYSTEM_USER"); 14 | } 15 | return Optional.of(ApiRequestContextHolder.getContext().getAuthId()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/configuration/filter/ApiRequestContext.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class ApiRequestContext { 9 | private String authId; 10 | } 11 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/configuration/filter/ApiRequestContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | @Slf4j 6 | public final class ApiRequestContextHolder { 7 | 8 | private ApiRequestContextHolder() { 9 | } 10 | 11 | private static final ThreadLocal contextHolder = new ThreadLocal<>(); 12 | 13 | public static void clearContext() { 14 | contextHolder.remove(); 15 | } 16 | 17 | public static ApiRequestContext getContext() { 18 | 19 | ApiRequestContext ctx = contextHolder.get(); 20 | 21 | if (ctx == null) { 22 | ctx = new ApiRequestContext(); 23 | contextHolder.set(ctx); 24 | log.debug("getContext() : new APIRequestContext created..!"); 25 | } 26 | 27 | return ctx; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/configuration/filter/AppAuthUserFilter.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.io.IOException; 6 | 7 | import jakarta.servlet.Filter; 8 | import jakarta.servlet.FilterChain; 9 | import jakarta.servlet.ServletException; 10 | import jakarta.servlet.ServletRequest; 11 | import jakarta.servlet.ServletResponse; 12 | import jakarta.servlet.http.HttpServletRequest; 13 | import lombok.extern.slf4j.Slf4j; 14 | 15 | @Slf4j 16 | public class AppAuthUserFilter implements Filter { 17 | 18 | private static final String HTTP_HEADER_AUTH_USER_ID = "X-Auth-Id"; 19 | 20 | @Override 21 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 22 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 23 | String userAuthId = httpServletRequest.getHeader(HTTP_HEADER_AUTH_USER_ID); 24 | log.info("Incoming Request From {}", userAuthId); 25 | if (!StringUtils.isEmpty(userAuthId)) { 26 | ApiRequestContextHolder.getContext().setAuthId(userAuthId); 27 | } 28 | try { 29 | chain.doFilter(request, response); 30 | }finally { 31 | ApiRequestContextHolder.clearContext(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/controller/FundTransferController.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.controller; 2 | 3 | import com.javatodev.finance.model.dto.request.FundTransferRequest; 4 | import com.javatodev.finance.service.FundTransferService; 5 | 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import lombok.RequiredArgsConstructor; 15 | import lombok.extern.slf4j.Slf4j; 16 | 17 | @Slf4j 18 | @RequiredArgsConstructor 19 | @RestController 20 | @RequestMapping("/api/v1/transfer") 21 | public class FundTransferController { 22 | 23 | private final FundTransferService fundTransferService; 24 | 25 | @PostMapping 26 | public ResponseEntity sendFundTransfer(@RequestBody FundTransferRequest fundTransferRequest) { 27 | log.info("Got fund transfer request from API {}", fundTransferRequest.toString()); 28 | return ResponseEntity.ok(fundTransferService.fundTransfer(fundTransferRequest)); 29 | } 30 | 31 | @GetMapping 32 | public ResponseEntity readFundTransfers(Pageable pageable) { 33 | log.info("Reading fund transfers from core"); 34 | return ResponseEntity.ok(fundTransferService.readAllTransfers(pageable)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/exception/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | public class ErrorResponse { 11 | private String code; 12 | private String message; 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 7 | 8 | import java.util.Locale; 9 | 10 | @ControllerAdvice 11 | public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { 12 | 13 | @ExceptionHandler(SimpleBankingGlobalException.class) 14 | protected ResponseEntity handleGlobalException(SimpleBankingGlobalException e, Locale locale) { 15 | return ResponseEntity 16 | .badRequest() 17 | .body(new ErrorResponse(e.getCode(), e.getMessage())); 18 | } 19 | 20 | @ExceptionHandler({Exception.class}) 21 | protected ResponseEntity handleException(Exception e, Locale locale) { 22 | return ResponseEntity 23 | .badRequest() 24 | .body("Exception occur inside API " + e); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/exception/SimpleBankingGlobalException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SimpleBankingGlobalException extends RuntimeException { 13 | 14 | private String code; 15 | private String message; 16 | 17 | public SimpleBankingGlobalException(String message) { 18 | super(message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/TransactionStatus.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model; 2 | 3 | public enum TransactionStatus { 4 | PENDING, PROCESSING, SUCCESS, FAILED 5 | } 6 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/AuditAware.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | import org.springframework.data.annotation.CreatedBy; 6 | import org.springframework.data.annotation.CreatedDate; 7 | import org.springframework.data.annotation.LastModifiedBy; 8 | import org.springframework.data.annotation.LastModifiedDate; 9 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 10 | 11 | import java.io.Serializable; 12 | import java.time.Instant; 13 | 14 | import jakarta.persistence.EntityListeners; 15 | import jakarta.persistence.MappedSuperclass; 16 | import jakarta.persistence.Version; 17 | import lombok.Getter; 18 | import lombok.Setter; 19 | 20 | @Getter 21 | @Setter 22 | @MappedSuperclass 23 | @EntityListeners(AuditingEntityListener.class) 24 | public class AuditAware implements Serializable { 25 | 26 | @JsonIgnore 27 | @CreatedDate 28 | private Instant createdDate; 29 | 30 | @JsonIgnore 31 | @CreatedBy 32 | private String createdBy; 33 | 34 | @JsonIgnore 35 | @LastModifiedDate 36 | private Instant modifiedDate; 37 | 38 | @JsonIgnore 39 | @LastModifiedBy 40 | private String modifiedBy; 41 | 42 | @Version 43 | private long version; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/FundTransfer.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class FundTransfer extends AuditAware { 9 | private Long id; 10 | private String transactionReference; 11 | private String status; 12 | private String fromAccount; 13 | private String toAccount; 14 | private BigDecimal amount; 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/request/FundTransferRequest.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.request; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class FundTransferRequest { 9 | private String fromAccount; 10 | private String toAccount; 11 | private BigDecimal amount; 12 | private String authID; 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/request/UtilityPaymentRequest.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.request; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class UtilityPaymentRequest { 9 | private Long providerId; 10 | private BigDecimal amount; 11 | private String referenceNumber; 12 | private String account; 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/response/AccountResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.response; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class AccountResponse { 9 | private Long number; 10 | private BigDecimal actualBalance; 11 | private Long id; 12 | private String type; 13 | private String status; 14 | private BigDecimal availableBalance; 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/response/FundTransferResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.response; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class FundTransferResponse { 7 | private String message; 8 | private String transactionId; 9 | } 10 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/dto/response/UtilityPaymentResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto.response; 2 | 3 | public class UtilityPaymentResponse { 4 | } 5 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/entity/FundTransferEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import com.javatodev.finance.model.TransactionStatus; 4 | import com.javatodev.finance.model.dto.AuditAware; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import jakarta.persistence.*; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | @Entity 15 | @Table(name = "fund_transfer") 16 | public class FundTransferEntity extends AuditAware { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | private String transactionReference; 23 | private String fromAccount; 24 | private String toAccount; 25 | private BigDecimal amount; 26 | 27 | @Enumerated(EnumType.STRING) 28 | private TransactionStatus status; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/mapper/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | 8 | public abstract class BaseMapper { 9 | public abstract E convertToEntity(D dto, Object... args); 10 | 11 | public abstract D convertToDto(E entity, Object... args); 12 | 13 | public Collection convertToEntity(Collection dto, Object... args) { 14 | return dto.stream().map(d -> convertToEntity(d, args)).collect(Collectors.toList()); 15 | } 16 | 17 | public Collection convertToDto(Collection entity, Object... args) { 18 | return entity.stream().map(e -> convertToDto(e, args)).collect(Collectors.toList()); 19 | } 20 | 21 | public List convertToEntityList(Collection dto, Object... args) { 22 | return convertToEntity(dto, args).stream().collect(Collectors.toList()); 23 | } 24 | 25 | public List convertToDtoList(Collection entity, Object... args) { 26 | return convertToDto(entity, args).stream().collect(Collectors.toList()); 27 | } 28 | 29 | public Set convertToEntitySet(Collection dto, Object... args) { 30 | return convertToEntity(dto, args).stream().collect(Collectors.toSet()); 31 | } 32 | 33 | public Set convertToDtoSet(Collection entity, Object... args) { 34 | return convertToDto(entity, args).stream().collect(Collectors.toSet()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/mapper/FundTransferMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import com.javatodev.finance.model.dto.FundTransfer; 4 | import com.javatodev.finance.model.entity.FundTransferEntity; 5 | 6 | import org.springframework.beans.BeanUtils; 7 | 8 | public class FundTransferMapper extends BaseMapper { 9 | @Override 10 | public FundTransferEntity convertToEntity(FundTransfer dto, Object... args) { 11 | FundTransferEntity entity = new FundTransferEntity(); 12 | if (dto != null) { 13 | BeanUtils.copyProperties(dto, entity); 14 | } 15 | return entity; 16 | } 17 | 18 | @Override 19 | public FundTransfer convertToDto(FundTransferEntity entity, Object... args) { 20 | FundTransfer dto = new FundTransfer(); 21 | if (entity != null) { 22 | BeanUtils.copyProperties(entity, dto); 23 | } 24 | return dto; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/model/repository/FundTransferRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.repository; 2 | 3 | import com.javatodev.finance.model.entity.FundTransferEntity; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface FundTransferRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/service/FundTransferService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.model.TransactionStatus; 4 | import com.javatodev.finance.model.dto.FundTransfer; 5 | import com.javatodev.finance.model.dto.request.FundTransferRequest; 6 | import com.javatodev.finance.model.dto.response.FundTransferResponse; 7 | import com.javatodev.finance.model.entity.FundTransferEntity; 8 | import com.javatodev.finance.model.mapper.FundTransferMapper; 9 | import com.javatodev.finance.model.repository.FundTransferRepository; 10 | import com.javatodev.finance.service.rest.client.BankingCoreFeignClient; 11 | 12 | import org.springframework.beans.BeanUtils; 13 | import org.springframework.data.domain.Pageable; 14 | import org.springframework.stereotype.Service; 15 | 16 | import java.util.List; 17 | 18 | import lombok.RequiredArgsConstructor; 19 | import lombok.extern.slf4j.Slf4j; 20 | 21 | @Slf4j 22 | @RequiredArgsConstructor 23 | @Service 24 | public class FundTransferService { 25 | 26 | private final FundTransferRepository fundTransferRepository; 27 | private final BankingCoreFeignClient bankingCoreFeignClient; 28 | 29 | private FundTransferMapper mapper = new FundTransferMapper(); 30 | 31 | public FundTransferResponse fundTransfer(FundTransferRequest request) { 32 | log.info("Sending fund transfer request {}" + request.toString()); 33 | 34 | FundTransferEntity entity = new FundTransferEntity(); 35 | BeanUtils.copyProperties(request, entity); 36 | entity.setStatus(TransactionStatus.PENDING); 37 | FundTransferEntity optFundTransfer = fundTransferRepository.save(entity); 38 | 39 | FundTransferResponse fundTransferResponse = bankingCoreFeignClient.fundTransfer(request); 40 | optFundTransfer.setTransactionReference(fundTransferResponse.getTransactionId()); 41 | optFundTransfer.setStatus(TransactionStatus.SUCCESS); 42 | fundTransferRepository.save(optFundTransfer); 43 | 44 | fundTransferResponse.setMessage("Fund Transfer Successfully Completed"); 45 | return fundTransferResponse; 46 | 47 | } 48 | 49 | public List readAllTransfers(Pageable pageable) { 50 | return mapper.convertToDtoList(fundTransferRepository.findAll(pageable).getContent()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/java/com/javatodev/finance/service/rest/client/BankingCoreFeignClient.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service.rest.client; 2 | 3 | import com.javatodev.finance.configuration.CustomFeignClientConfiguration; 4 | import com.javatodev.finance.model.dto.request.FundTransferRequest; 5 | import com.javatodev.finance.model.dto.response.AccountResponse; 6 | import com.javatodev.finance.model.dto.response.FundTransferResponse; 7 | 8 | import org.springframework.cloud.openfeign.FeignClient; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | 14 | @FeignClient(value = "core-banking-service", configuration = CustomFeignClientConfiguration.class) 15 | public interface BankingCoreFeignClient { 16 | 17 | @RequestMapping(path = "/api/v1/account/bank-account/{account_number}", method = RequestMethod.GET) 18 | AccountResponse readAccount(@PathVariable("account_number") String accountNumber); 19 | 20 | @RequestMapping(path = "/api/v1/transaction/fund-transfer", method = RequestMethod.POST) 21 | FundTransferResponse fundTransfer(@RequestBody FundTransferRequest fundTransferRequest); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: internet-banking-fund-transfer-service 4 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/resources/bootstrap-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://192.168.1.5:8090 5 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/resources/bootstrap-docker.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://internet-banking-config-server:8090 5 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://localhost:8090 5 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/test/java/com/javatodev/finance/InternetBankingFundTransferServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InternetBankingFundTransferServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-fund-transfer-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: banking_core_fund_transfer_service 4 | datasource: 5 | url: jdbc:h2:mem:banking_core_fund_transfer_service 6 | username: root 7 | password: password 8 | driver-class-name: org.h2.Driver 9 | jpa: 10 | hibernate: 11 | ddl-auto: none 12 | database-platform: org.hibernate.dialect.H2Dialect 13 | 14 | flyway: 15 | enabled: false 16 | server: 17 | port: 8092 18 | 19 | eureka: 20 | client: 21 | service-url: 22 | defaultZone: http://localhost:8081/eureka 23 | enabled: false 24 | 25 | info: 26 | app: 27 | name: ${spring.application.name} 28 | -------------------------------------------------------------------------------- /internet-banking-service-registry/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /internet-banking-service-registry/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/internet-banking-service-registry-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8081 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /internet-banking-service-registry/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | } 6 | 7 | group = 'com.javatodev.finance' 8 | version = '0.0.1-SNAPSHOT' 9 | 10 | java { 11 | sourceCompatibility = '21' 12 | } 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('springCloudVersion', "2023.0.0") 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-web' 25 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server' 26 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 27 | } 28 | 29 | dependencyManagement { 30 | imports { 31 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 32 | } 33 | } 34 | 35 | test { 36 | useJUnitPlatform() 37 | } 38 | -------------------------------------------------------------------------------- /internet-banking-service-registry/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/internet-banking-service-registry/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /internet-banking-service-registry/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /internet-banking-service-registry/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /internet-banking-service-registry/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'internet-banking-service-registry' 2 | -------------------------------------------------------------------------------- /internet-banking-service-registry/src/main/java/com/javatodev/finance/InternetBankingServiceRegistryApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @EnableEurekaServer 8 | @SpringBootApplication 9 | public class InternetBankingServiceRegistryApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(InternetBankingServiceRegistryApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-service-registry/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | 4 | eureka: 5 | client: 6 | service-url: 7 | defaultZone: http://localhost:${server.port}/eureka 8 | register-with-eureka: false 9 | fetch-registry: false 10 | instance: 11 | prefer-ip-address: true 12 | hostname: localhost 13 | -------------------------------------------------------------------------------- /internet-banking-service-registry/src/test/java/com/javatodev/finance/InternetBankingServiceRegistryApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InternetBankingServiceRegistryApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-user-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /internet-banking-user-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/internet-banking-user-service-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8083 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /internet-banking-user-service/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | id "com.gorylenko.gradle-git-properties" version "2.4.2" 6 | } 7 | 8 | gitProperties { 9 | dateFormat = "yyyy-MM-dd'T'HH:mmZ" 10 | dateFormatTimeZone = "IST" 11 | } 12 | 13 | group = 'com.javatodev.finance' 14 | version = '0.0.1-SNAPSHOT' 15 | 16 | java { 17 | sourceCompatibility = '21' 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | ext { 25 | set('springCloudVersion', "2023.0.0") 26 | } 27 | 28 | dependencies { 29 | implementation 'org.springframework.boot:spring-boot-starter-web' 30 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 31 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' 32 | 33 | //SPRING BOOT - TRACING 34 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 35 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 36 | implementation 'io.zipkin.reporter2:zipkin-reporter-brave' 37 | implementation 'io.github.openfeign:feign-micrometer' 38 | 39 | //Open feign 40 | implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' 41 | implementation 'io.github.openfeign:feign-okhttp:13.2.1' 42 | 43 | //SPRING CLOUD CONFIG 44 | implementation 'org.springframework.cloud:spring-cloud-starter-config' 45 | implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' 46 | implementation 'org.keycloak:keycloak-admin-client:24.0.4' 47 | 48 | 49 | compileOnly 'org.projectlombok:lombok' 50 | annotationProcessor 'org.projectlombok:lombok' 51 | 52 | implementation 'com.mysql:mysql-connector-j:8.4.0' 53 | 54 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 55 | testImplementation 'com.h2database:h2:2.2.224' 56 | } 57 | 58 | dependencyManagement { 59 | imports { 60 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 61 | } 62 | } 63 | 64 | test { 65 | useJUnitPlatform() 66 | } 67 | -------------------------------------------------------------------------------- /internet-banking-user-service/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/internet-banking-user-service/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /internet-banking-user-service/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /internet-banking-user-service/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /internet-banking-user-service/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'internet-banking-user-service' 2 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/InternetBankingUserServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.openfeign.EnableFeignClients; 6 | 7 | @EnableFeignClients 8 | @SpringBootApplication 9 | public class InternetBankingUserServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(InternetBankingUserServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/audit/AuditConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.audit; 2 | 3 | import com.javatodev.finance.configuration.filter.AppAuthUserFilter; 4 | 5 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.domain.AuditorAware; 9 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 10 | 11 | @Configuration 12 | @EnableJpaAuditing 13 | public class AuditConfig { 14 | 15 | @Bean 16 | public AuditorAware myAuditorProvider() { 17 | return new AuditorAwareConfig(); 18 | } 19 | 20 | @Bean 21 | public FilterRegistrationBean authUserFilter() { 22 | FilterRegistrationBean registrationBean 23 | = new FilterRegistrationBean<>(); 24 | 25 | registrationBean.setFilter(new AppAuthUserFilter()); 26 | registrationBean.addUrlPatterns("/api/*"); 27 | 28 | return registrationBean; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/audit/AuditorAwareConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.audit; 2 | 3 | import com.javatodev.finance.configuration.filter.ApiRequestContextHolder; 4 | 5 | import org.apache.commons.lang.StringUtils; 6 | import org.springframework.data.domain.AuditorAware; 7 | 8 | import java.util.Optional; 9 | 10 | public class AuditorAwareConfig implements AuditorAware { 11 | @Override public Optional getCurrentAuditor() { 12 | if (StringUtils.isEmpty(ApiRequestContextHolder.getContext().getAuthId())) { 13 | return Optional.of("SYSTEM_USER"); 14 | } 15 | return Optional.of(ApiRequestContextHolder.getContext().getAuthId()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/feign/CustomFeignClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.feign; 2 | 3 | import feign.codec.ErrorDecoder; 4 | import org.springframework.cloud.openfeign.FeignClientProperties; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class CustomFeignClientConfiguration extends FeignClientProperties.FeignClientConfiguration { 10 | 11 | @Bean 12 | public ErrorDecoder errorDecoder() { 13 | return new CustomFeignErrorDecoder(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/feign/CustomFeignErrorDecoder.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.feign; 2 | 3 | import com.fasterxml.jackson.databind.DeserializationFeature; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.javatodev.finance.exception.SimpleBankingGlobalException; 6 | import feign.Response; 7 | import feign.codec.ErrorDecoder; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.io.IOUtils; 10 | 11 | import java.io.IOException; 12 | import java.io.Reader; 13 | import java.nio.charset.StandardCharsets; 14 | 15 | @Slf4j 16 | public class CustomFeignErrorDecoder implements ErrorDecoder { 17 | @Override 18 | public Exception decode(String methodKey, Response response) { 19 | 20 | SimpleBankingGlobalException simpleBankingGlobalException = extractBankingCoreGlobalException(response); 21 | 22 | return switch (response.status()) { 23 | case 400 -> { 24 | log.error("Error in request went through feign client {} ", simpleBankingGlobalException.getMessage() + " - " + simpleBankingGlobalException.getCode()); 25 | yield simpleBankingGlobalException; 26 | } 27 | case 401 -> { 28 | log.error("Unauthorized Request Through Feign"); 29 | yield new Exception("Unauthorized Request Through Feign"); 30 | } 31 | case 404 -> { 32 | log.error("Unidentified Request Through Feign "); 33 | yield new Exception("Unidentified Request Through Feign"); 34 | } 35 | default -> { 36 | log.error("Error in request went through feign client"); 37 | yield new Exception("Common Feign Exception"); 38 | } 39 | }; 40 | 41 | } 42 | 43 | private SimpleBankingGlobalException extractBankingCoreGlobalException(Response response) { 44 | SimpleBankingGlobalException exceptionMessage = null; 45 | Reader reader = null; 46 | //capturing error message from response body. 47 | try { 48 | reader = response.body().asReader(StandardCharsets.UTF_8); 49 | String result = IOUtils.toString(reader); 50 | ObjectMapper mapper = new ObjectMapper(); 51 | mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 52 | exceptionMessage = mapper.readValue(result, 53 | SimpleBankingGlobalException.class); 54 | } catch (IOException e) { 55 | log.error("IO Exception on reading exception message feign client" + e); 56 | } finally { 57 | try { 58 | if (reader != null) { 59 | reader.close(); 60 | } 61 | } catch (IOException e) { 62 | log.error("IO Exception on reading exception message feign client" + e); 63 | } 64 | } 65 | return exceptionMessage; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/filter/ApiRequestContext.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class ApiRequestContext { 9 | private String authId; 10 | } 11 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/filter/ApiRequestContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | @Slf4j 6 | public final class ApiRequestContextHolder { 7 | 8 | private ApiRequestContextHolder() { 9 | } 10 | 11 | private static final ThreadLocal contextHolder = new ThreadLocal<>(); 12 | 13 | public static void clearContext() { 14 | contextHolder.remove(); 15 | } 16 | 17 | public static ApiRequestContext getContext() { 18 | 19 | ApiRequestContext ctx = contextHolder.get(); 20 | 21 | if (ctx == null) { 22 | ctx = new ApiRequestContext(); 23 | contextHolder.set(ctx); 24 | log.debug("getContext() : new APIRequestContext created..!"); 25 | } 26 | 27 | return ctx; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/filter/AppAuthUserFilter.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.io.IOException; 6 | 7 | import jakarta.servlet.Filter; 8 | import jakarta.servlet.FilterChain; 9 | import jakarta.servlet.ServletException; 10 | import jakarta.servlet.ServletRequest; 11 | import jakarta.servlet.ServletResponse; 12 | import jakarta.servlet.http.HttpServletRequest; 13 | import lombok.extern.slf4j.Slf4j; 14 | 15 | @Slf4j 16 | public class AppAuthUserFilter implements Filter { 17 | 18 | private static final String HTTP_HEADER_AUTH_USER_ID = "X-Auth-Id"; 19 | 20 | @Override 21 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 22 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 23 | String userAuthId = httpServletRequest.getHeader(HTTP_HEADER_AUTH_USER_ID); 24 | log.info("Incoming Request From {}", userAuthId); 25 | if (!StringUtils.isEmpty(userAuthId)) { 26 | ApiRequestContextHolder.getContext().setAuthId(userAuthId); 27 | } 28 | try { 29 | chain.doFilter(request, response); 30 | }finally { 31 | ApiRequestContextHolder.clearContext(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/keycloak/KeycloakManager.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.keycloak; 2 | 3 | import org.keycloak.admin.client.resource.RealmResource; 4 | import org.springframework.stereotype.Component; 5 | 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Component 9 | @RequiredArgsConstructor 10 | public class KeycloakManager { 11 | 12 | private final KeycloakProperties keycloakProperties; 13 | 14 | public RealmResource getKeyCloakInstanceWithRealm() { 15 | return keycloakProperties.getInstance().realm(keycloakProperties.getRealm()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/configuration/keycloak/KeycloakProperties.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.keycloak; 2 | 3 | import lombok.Getter; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.keycloak.admin.client.Keycloak; 6 | import org.keycloak.admin.client.KeycloakBuilder; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Slf4j 11 | @Component 12 | public class KeycloakProperties { 13 | @Value("${app.config.keycloak.server-url}") 14 | private String serverUrl; 15 | 16 | @Getter @Value("${app.config.keycloak.realm}") 17 | private String realm; 18 | 19 | @Value("${app.config.keycloak.clientId}") 20 | private String clientId; 21 | 22 | @Value("${app.config.keycloak.client-secret}") 23 | private String clientSecret; 24 | 25 | private static Keycloak keycloakInstance = null; 26 | 27 | public Keycloak getInstance() { 28 | 29 | if (keycloakInstance == null) { 30 | keycloakInstance = KeycloakBuilder 31 | .builder() 32 | .serverUrl(serverUrl) 33 | .realm(realm) 34 | .grantType("client_credentials") 35 | .clientId(clientId) 36 | .clientSecret(clientSecret) 37 | .build(); 38 | } 39 | return keycloakInstance; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.controller; 2 | 3 | import com.javatodev.finance.model.dto.User; 4 | import com.javatodev.finance.model.dto.UserUpdateRequest; 5 | import com.javatodev.finance.service.KeycloakUserService; 6 | import com.javatodev.finance.service.UserService; 7 | 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.List; 13 | 14 | import lombok.RequiredArgsConstructor; 15 | import lombok.extern.slf4j.Slf4j; 16 | 17 | @Slf4j 18 | @RestController 19 | @RequestMapping(value = "/api/v1/bank-users") 20 | @RequiredArgsConstructor 21 | public class UserController { 22 | 23 | private final UserService userService; 24 | 25 | @PostMapping(value = "/register") 26 | public ResponseEntity createUser(@RequestBody User request) { 27 | log.info("Creating user with {}", request.toString()); 28 | return ResponseEntity.ok(userService.createUser(request)); 29 | } 30 | 31 | @PatchMapping(value = "/update/{id}") 32 | public ResponseEntity updateUser(@PathVariable("id") Long userId, @RequestBody UserUpdateRequest userUpdateRequest) { 33 | log.info("Updating user with {}", userUpdateRequest.toString()); 34 | return ResponseEntity.ok(userService.updateUser(userId, userUpdateRequest)); 35 | } 36 | 37 | @GetMapping 38 | public ResponseEntity> readUsers(Pageable pageable) { 39 | log.info("Reading all users from API"); 40 | return ResponseEntity.ok(userService.readUsers(pageable)); 41 | } 42 | 43 | @GetMapping(value = "/{id}") 44 | public ResponseEntity readUser(@PathVariable("id") Long id) { 45 | log.info("Reading user by id {}", id); 46 | return ResponseEntity.ok(userService.readUser(id)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/EntityNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class EntityNotFoundException extends SimpleBankingGlobalException { 4 | public EntityNotFoundException() { 5 | super("Requested entity not present in the DB.", GlobalErrorCode.ERROR_ENTITY_NOT_FOUND); 6 | } 7 | 8 | public EntityNotFoundException (String message) { 9 | super(message, GlobalErrorCode.ERROR_ENTITY_NOT_FOUND); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | public class ErrorResponse { 11 | private String code; 12 | private String message; 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/GlobalErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class GlobalErrorCode { 4 | public static final String ERROR_ENTITY_NOT_FOUND = "USER-SERVICE-1000"; 5 | public static final String ERROR_EMAIL_REGISTERED = "USER-SERVICE-1001"; 6 | public static final String ERROR_INVALID_EMAIL = "USER-SERVICE-1002"; 7 | public static final String ERROR_USER_NOT_FOUND_UNDER_NIC = "USER-SERVICE-1003"; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 7 | 8 | import java.util.Locale; 9 | 10 | @ControllerAdvice 11 | public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { 12 | 13 | @ExceptionHandler(SimpleBankingGlobalException.class) 14 | protected ResponseEntity handleGlobalException (SimpleBankingGlobalException simpleBankingGlobalException, Locale locale) { 15 | return ResponseEntity 16 | .badRequest() 17 | .body(ErrorResponse.builder() 18 | .code(simpleBankingGlobalException.getCode()) 19 | .message(simpleBankingGlobalException.getMessage()) 20 | .build()); 21 | } 22 | 23 | @ExceptionHandler({Exception.class}) 24 | protected ResponseEntity handleException(Exception e, Locale locale) { 25 | return ResponseEntity 26 | .badRequest() 27 | .body("Exception occur inside API " + e); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/InvalidBankingUserException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class InvalidBankingUserException extends SimpleBankingGlobalException { 4 | public InvalidBankingUserException(String message, String code) { 5 | super(message, code); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/InvalidEmailException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class InvalidEmailException extends SimpleBankingGlobalException { 4 | public InvalidEmailException(String message, String code) { 5 | super(message, code); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/SimpleBankingGlobalException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SimpleBankingGlobalException extends RuntimeException { 13 | 14 | private String code; 15 | private String message; 16 | 17 | public SimpleBankingGlobalException(String message) { 18 | super(message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/exception/UserAlreadyRegisteredException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | public class UserAlreadyRegisteredException extends SimpleBankingGlobalException { 4 | public UserAlreadyRegisteredException(String message, String code) { 5 | super(message, code); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/dto/AuditAware.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | import org.springframework.data.annotation.CreatedBy; 6 | import org.springframework.data.annotation.CreatedDate; 7 | import org.springframework.data.annotation.LastModifiedBy; 8 | import org.springframework.data.annotation.LastModifiedDate; 9 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 10 | 11 | import java.io.Serializable; 12 | import java.time.Instant; 13 | 14 | import jakarta.persistence.EntityListeners; 15 | import jakarta.persistence.MappedSuperclass; 16 | import jakarta.persistence.Version; 17 | import lombok.Getter; 18 | import lombok.Setter; 19 | 20 | @Getter 21 | @Setter 22 | @MappedSuperclass 23 | @EntityListeners(AuditingEntityListener.class) 24 | public class AuditAware implements Serializable { 25 | 26 | @JsonIgnore 27 | @CreatedDate 28 | private Instant createdDate; 29 | 30 | @JsonIgnore 31 | @CreatedBy 32 | private String createdBy; 33 | 34 | @JsonIgnore 35 | @LastModifiedDate 36 | private Instant modifiedDate; 37 | 38 | @JsonIgnore 39 | @LastModifiedBy 40 | private String modifiedBy; 41 | 42 | @Version 43 | private long version; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/dto/Status.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | public enum Status { 4 | PENDING, APPROVED, DISABLED, BLACKLIST 5 | } 6 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/dto/User.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | @Data 7 | @EqualsAndHashCode(callSuper = false) 8 | public class User extends AuditAware { 9 | private Long id; 10 | 11 | private String email; 12 | 13 | private String identification; 14 | 15 | private String password; 16 | 17 | private String authId; 18 | 19 | private Status status; 20 | } 21 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/dto/UserUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class UserUpdateRequest { 7 | private Status status; 8 | } 9 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/entity/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import com.javatodev.finance.model.dto.AuditAware; 4 | import com.javatodev.finance.model.dto.Status; 5 | 6 | import jakarta.persistence.*; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | @Entity 13 | @Table(name = "user") 14 | public class UserEntity extends AuditAware { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | private Long id; 19 | 20 | private String authId; 21 | 22 | private String identification; 23 | 24 | @Enumerated(EnumType.STRING) 25 | private Status status; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/mapper/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | 8 | public abstract class BaseMapper { 9 | public abstract E convertToEntity(D dto, Object... args); 10 | 11 | public abstract D convertToDto(E entity, Object... args); 12 | 13 | public Collection convertToEntity(Collection dto, Object... args) { 14 | return dto.stream().map(d -> convertToEntity(d, args)).collect(Collectors.toList()); 15 | } 16 | 17 | public Collection convertToDto(Collection entity, Object... args) { 18 | return entity.stream().map(e -> convertToDto(e, args)).collect(Collectors.toList()); 19 | } 20 | 21 | public List convertToEntityList(Collection dto, Object... args) { 22 | return convertToEntity(dto, args).stream().collect(Collectors.toList()); 23 | } 24 | 25 | public List convertToDtoList(Collection entity, Object... args) { 26 | return convertToDto(entity, args).stream().collect(Collectors.toList()); 27 | } 28 | 29 | public Set convertToEntitySet(Collection dto, Object... args) { 30 | return convertToEntity(dto, args).stream().collect(Collectors.toSet()); 31 | } 32 | 33 | public Set convertToDtoSet(Collection entity, Object... args) { 34 | return convertToDto(entity, args).stream().collect(Collectors.toSet()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import com.javatodev.finance.model.dto.User; 4 | import com.javatodev.finance.model.entity.UserEntity; 5 | import org.springframework.beans.BeanUtils; 6 | 7 | public class UserMapper extends BaseMapper{ 8 | @Override 9 | public UserEntity convertToEntity(User dto, Object... args) { 10 | UserEntity userEntity = new UserEntity(); 11 | if (dto != null) { 12 | BeanUtils.copyProperties(dto, userEntity); 13 | } 14 | return userEntity; 15 | } 16 | 17 | @Override 18 | public User convertToDto(UserEntity entity, Object... args) { 19 | User user = new User(); 20 | if (entity != null) { 21 | BeanUtils.copyProperties(entity, user); 22 | } 23 | return user; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.repository; 2 | 3 | import com.javatodev.finance.model.entity.UserEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface UserRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/rest/response/AccountResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.rest.response; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.math.BigDecimal; 7 | 8 | @Getter 9 | @Setter 10 | public class AccountResponse { 11 | private String number; 12 | private BigDecimal actualBalance; 13 | private Integer id; 14 | private String type; 15 | private String status; 16 | private BigDecimal availableBalance; 17 | } 18 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/model/rest/response/UserResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.rest.response; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.List; 7 | 8 | @Getter 9 | @Setter 10 | public class UserResponse { 11 | private String firstName; 12 | private String lastName; 13 | private List bankAccounts; 14 | private String identificationNumber; 15 | private Integer id; 16 | private String email; 17 | } 18 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/service/KeycloakUserService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.configuration.keycloak.KeycloakManager; 4 | import com.javatodev.finance.exception.EntityNotFoundException; 5 | 6 | import org.keycloak.admin.client.resource.UserResource; 7 | import org.keycloak.representations.idm.UserRepresentation; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.List; 13 | 14 | import jakarta.ws.rs.core.Response; 15 | import lombok.RequiredArgsConstructor; 16 | import lombok.extern.slf4j.Slf4j; 17 | 18 | @Slf4j 19 | @Service 20 | @RequiredArgsConstructor 21 | public class KeycloakUserService { 22 | 23 | private final KeycloakManager keyCloakManager; 24 | 25 | public Integer createUser(UserRepresentation userRepresentation) { 26 | Response response = keyCloakManager.getKeyCloakInstanceWithRealm().users().create(userRepresentation); 27 | return response.getStatus(); 28 | } 29 | 30 | public void updateUser(UserRepresentation userRepresentation) { 31 | keyCloakManager.getKeyCloakInstanceWithRealm().users().get(userRepresentation.getId()).update(userRepresentation); 32 | } 33 | 34 | 35 | public List readUserByEmail(String email) { 36 | return keyCloakManager.getKeyCloakInstanceWithRealm().users().search(email); 37 | } 38 | 39 | 40 | public UserRepresentation readUser(String authId) { 41 | try { 42 | UserResource userResource = keyCloakManager.getKeyCloakInstanceWithRealm().users().get(authId); 43 | return userResource.toRepresentation(); 44 | } catch (Exception e) { 45 | log.error("User not found under given ID {}", e.toString()); 46 | throw new EntityNotFoundException("User not found under given ID"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.exception.*; 4 | import com.javatodev.finance.model.dto.Status; 5 | import com.javatodev.finance.model.dto.User; 6 | import com.javatodev.finance.model.dto.UserUpdateRequest; 7 | import com.javatodev.finance.model.entity.UserEntity; 8 | import com.javatodev.finance.model.mapper.UserMapper; 9 | import com.javatodev.finance.model.repository.UserRepository; 10 | import com.javatodev.finance.model.rest.response.UserResponse; 11 | import com.javatodev.finance.service.rest.BankingCoreRestClient; 12 | import lombok.RequiredArgsConstructor; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.keycloak.representations.idm.CredentialRepresentation; 15 | import org.keycloak.representations.idm.UserRepresentation; 16 | import org.springframework.data.domain.Page; 17 | import org.springframework.data.domain.Pageable; 18 | import org.springframework.stereotype.Service; 19 | 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | @Slf4j 24 | @Service 25 | @RequiredArgsConstructor 26 | public class UserService { 27 | private final KeycloakUserService keycloakUserService; 28 | private final UserRepository userRepository; 29 | private final BankingCoreRestClient bankingCoreRestClient; 30 | 31 | private UserMapper userMapper = new UserMapper(); 32 | 33 | public User createUser(User user) { 34 | 35 | List userRepresentations = keycloakUserService.readUserByEmail(user.getEmail()); 36 | if (!userRepresentations.isEmpty()) { 37 | throw new UserAlreadyRegisteredException("This email already registered as a user. Please check and retry.", GlobalErrorCode.ERROR_EMAIL_REGISTERED); 38 | } 39 | 40 | UserResponse userResponse = bankingCoreRestClient.readUser(user.getIdentification()); 41 | 42 | if (userResponse.getId() != null) { 43 | 44 | if (!userResponse.getEmail().equals(user.getEmail())) { 45 | throw new InvalidEmailException("Incorrect email. Please check and retry.", GlobalErrorCode.ERROR_INVALID_EMAIL); 46 | } 47 | 48 | UserRepresentation userRepresentation = new UserRepresentation(); 49 | userRepresentation.setEmail(userResponse.getEmail()); 50 | userRepresentation.setEmailVerified(false); 51 | userRepresentation.setEnabled(false); 52 | userRepresentation.setUsername(userResponse.getEmail()); 53 | userRepresentation.setFirstName(userResponse.getFirstName()); 54 | userRepresentation.setLastName(userResponse.getLastName()); 55 | 56 | CredentialRepresentation credentialRepresentation = new CredentialRepresentation(); 57 | credentialRepresentation.setValue(user.getPassword()); 58 | credentialRepresentation.setTemporary(false); 59 | userRepresentation.setCredentials(Collections.singletonList(credentialRepresentation)); 60 | 61 | Integer userCreationResponse = keycloakUserService.createUser(userRepresentation); 62 | 63 | if (userCreationResponse == 201) { 64 | log.info("User created under given username {}", user.getEmail()); 65 | 66 | List userRepresentations1 = keycloakUserService.readUserByEmail(user.getEmail()); 67 | user.setAuthId(userRepresentations1.get(0).getId()); 68 | user.setStatus(Status.PENDING); 69 | user.setIdentification(userResponse.getIdentificationNumber()); 70 | UserEntity save = userRepository.save(userMapper.convertToEntity(user)); 71 | return userMapper.convertToDto(save); 72 | } 73 | 74 | } 75 | 76 | throw new InvalidBankingUserException("We couldn't find user under given identification. Please check and retry", GlobalErrorCode.ERROR_USER_NOT_FOUND_UNDER_NIC); 77 | 78 | } 79 | 80 | public List readUsers(Pageable pageable) { 81 | Page allUsersInDb = userRepository.findAll(pageable); 82 | List users = userMapper.convertToDtoList(allUsersInDb.getContent()); 83 | users.forEach(user -> { 84 | UserRepresentation userRepresentation = keycloakUserService.readUser(user.getAuthId()); 85 | user.setId(user.getId()); 86 | user.setEmail(userRepresentation.getEmail()); 87 | user.setIdentification(user.getIdentification()); 88 | }); 89 | return users; 90 | } 91 | 92 | public User readUser(Long userId) { 93 | return userMapper.convertToDto(userRepository.findById(userId).orElseThrow(EntityNotFoundException::new)); 94 | } 95 | 96 | public User updateUser(Long id, UserUpdateRequest userUpdateRequest) { 97 | UserEntity userEntity = userRepository.findById(id).orElseThrow(EntityNotFoundException::new); 98 | 99 | if (userUpdateRequest.getStatus() == Status.APPROVED) { 100 | UserRepresentation userRepresentation = keycloakUserService.readUser(userEntity.getAuthId()); 101 | userRepresentation.setEnabled(true); 102 | userRepresentation.setEmailVerified(true); 103 | keycloakUserService.updateUser(userRepresentation); 104 | } 105 | 106 | userEntity.setStatus(userUpdateRequest.getStatus()); 107 | return userMapper.convertToDto(userRepository.save(userEntity)); 108 | } 109 | 110 | 111 | } 112 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/java/com/javatodev/finance/service/rest/BankingCoreRestClient.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service.rest; 2 | 3 | import com.javatodev.finance.model.rest.response.UserResponse; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | 9 | @FeignClient(name = "core-banking-service") 10 | public interface BankingCoreRestClient { 11 | 12 | @GetMapping("/api/v1/user/{identification}") 13 | UserResponse readUser(@PathVariable("identification") String identification); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: internet-banking-user-service 4 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/resources/bootstrap-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://192.168.1.5:8090 5 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/resources/bootstrap-docker.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://internet-banking-config-server:8090 5 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://localhost:8090 5 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/test/java/com/javatodev/finance/InternetBankingUserServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InternetBankingUserServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-user-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: internet-banking-user-service 4 | datasource: 5 | url: jdbc:h2:mem:banking_core_user_service 6 | username: root 7 | password: password 8 | driver-class-name: org.h2.Driver 9 | jpa: 10 | hibernate: 11 | ddl-auto: none 12 | database-platform: org.hibernate.dialect.H2Dialect 13 | 14 | flyway: 15 | enabled: false 16 | server: 17 | port: 8092 18 | 19 | eureka: 20 | client: 21 | service-url: 22 | defaultZone: http://localhost:8081/eureka 23 | enabled: false 24 | 25 | info: 26 | app: 27 | name: ${spring.application.name} 28 | 29 | app: 30 | config: 31 | keycloak: 32 | server-url: http://localhost:8080/auth 33 | realm: javatodev-internet-banking 34 | clientId: internet-banking-api-client 35 | client-secret: e8548d56-d743-45ef-8655-063c9cd96759 36 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21.0.2_13-jre-alpine 2 | LABEL maintainer="chinthaka@javatodev.com" 3 | VOLUME /main-app 4 | ADD build/libs/internet-banking-utility-payment-service-0.0.1-SNAPSHOT.jar app.jar 5 | EXPOSE 8085 6 | COPY wait-for-it.sh wait-for-it.sh 7 | RUN chmod +x wait-for-it.sh 8 | # Add bash for wait-for-it.sh 9 | RUN apk add --no-cache bash 10 | ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/app.jar"] 11 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.2.4' 4 | id 'io.spring.dependency-management' version '1.1.4' 5 | id "com.gorylenko.gradle-git-properties" version "2.4.2" 6 | } 7 | 8 | gitProperties { 9 | dateFormat = "yyyy-MM-dd'T'HH:mmZ" 10 | dateFormatTimeZone = "IST" 11 | } 12 | 13 | group = 'com.javatodev.finance' 14 | version = '0.0.1-SNAPSHOT' 15 | 16 | java { 17 | sourceCompatibility = '21' 18 | } 19 | 20 | configurations { 21 | compileOnly { 22 | extendsFrom annotationProcessor 23 | } 24 | } 25 | 26 | repositories { 27 | mavenCentral() 28 | } 29 | 30 | ext { 31 | set('springCloudVersion', "2023.0.0") 32 | } 33 | 34 | dependencies { 35 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 36 | implementation 'org.springframework.boot:spring-boot-starter-web' 37 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' 38 | implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' 39 | 40 | //SPRING BOOT - TRACING 41 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 42 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 43 | implementation 'io.zipkin.reporter2:zipkin-reporter-brave' 44 | implementation 'io.github.openfeign:feign-micrometer' 45 | 46 | //SPRING CLOUD CONFIG 47 | implementation 'org.springframework.cloud:spring-cloud-starter-config' 48 | implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' 49 | implementation 'com.mysql:mysql-connector-j:8.4.0' 50 | 51 | compileOnly 'org.projectlombok:lombok' 52 | annotationProcessor 'org.projectlombok:lombok' 53 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 54 | testImplementation 'com.h2database:h2:2.2.224' 55 | } 56 | 57 | dependencyManagement { 58 | imports { 59 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 60 | } 61 | } 62 | 63 | test { 64 | useJUnitPlatform() 65 | } 66 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavatoDev-com/internet-banking-concept-microservices/f5da70976da4812d4ecdf1159aa3ff6351e3c8b7/internet-banking-utility-payment-service/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2024 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | distributionBase=GRADLE_USER_HOME 18 | distributionPath=wrapper/dists 19 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 20 | networkTimeout=10000 21 | validateDistributionUrl=true 22 | zipStoreBase=GRADLE_USER_HOME 23 | zipStorePath=wrapper/dists 24 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'internet-banking-utility-payment-service' 2 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/InternetBankingUtilityPaymentServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.openfeign.EnableFeignClients; 6 | 7 | @EnableFeignClients 8 | @SpringBootApplication 9 | public class InternetBankingUtilityPaymentServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(InternetBankingUtilityPaymentServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/configuration/CustomFeignClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration; 2 | 3 | import org.springframework.cloud.openfeign.FeignClientProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | public class CustomFeignClientConfiguration extends FeignClientProperties.FeignClientConfiguration { 8 | } 9 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/configuration/audit/AuditConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.audit; 2 | 3 | import com.javatodev.finance.configuration.filter.AppAuthUserFilter; 4 | 5 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.domain.AuditorAware; 9 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 10 | 11 | @Configuration 12 | @EnableJpaAuditing 13 | public class AuditConfig { 14 | 15 | @Bean 16 | public AuditorAware myAuditorProvider() { 17 | return new AuditorAwareConfig(); 18 | } 19 | 20 | @Bean 21 | public FilterRegistrationBean authUserFilter() { 22 | FilterRegistrationBean registrationBean 23 | = new FilterRegistrationBean<>(); 24 | 25 | registrationBean.setFilter(new AppAuthUserFilter()); 26 | registrationBean.addUrlPatterns("/api/*"); 27 | 28 | return registrationBean; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/configuration/audit/AuditorAwareConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.audit; 2 | 3 | import com.javatodev.finance.configuration.filter.ApiRequestContextHolder; 4 | 5 | import org.apache.commons.lang.StringUtils; 6 | import org.springframework.data.domain.AuditorAware; 7 | 8 | import java.util.Optional; 9 | 10 | public class AuditorAwareConfig implements AuditorAware { 11 | @Override public Optional getCurrentAuditor() { 12 | if (StringUtils.isEmpty(ApiRequestContextHolder.getContext().getAuthId())) { 13 | return Optional.of("SYSTEM_USER"); 14 | } 15 | return Optional.of(ApiRequestContextHolder.getContext().getAuthId()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/configuration/filter/ApiRequestContext.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class ApiRequestContext { 9 | private String authId; 10 | } 11 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/configuration/filter/ApiRequestContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | @Slf4j 6 | public final class ApiRequestContextHolder { 7 | 8 | private ApiRequestContextHolder() { 9 | } 10 | 11 | private static final ThreadLocal contextHolder = new ThreadLocal<>(); 12 | 13 | public static void clearContext() { 14 | contextHolder.remove(); 15 | } 16 | 17 | public static ApiRequestContext getContext() { 18 | 19 | ApiRequestContext ctx = contextHolder.get(); 20 | 21 | if (ctx == null) { 22 | ctx = new ApiRequestContext(); 23 | contextHolder.set(ctx); 24 | log.debug("getContext() : new APIRequestContext created..!"); 25 | } 26 | 27 | return ctx; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/configuration/filter/AppAuthUserFilter.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.configuration.filter; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.io.IOException; 6 | 7 | import jakarta.servlet.Filter; 8 | import jakarta.servlet.FilterChain; 9 | import jakarta.servlet.ServletException; 10 | import jakarta.servlet.ServletRequest; 11 | import jakarta.servlet.ServletResponse; 12 | import jakarta.servlet.http.HttpServletRequest; 13 | import lombok.extern.slf4j.Slf4j; 14 | 15 | @Slf4j 16 | public class AppAuthUserFilter implements Filter { 17 | 18 | private static final String HTTP_HEADER_AUTH_USER_ID = "X-Auth-Id"; 19 | 20 | @Override 21 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 22 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 23 | String userAuthId = httpServletRequest.getHeader(HTTP_HEADER_AUTH_USER_ID); 24 | log.info("Incoming Request From {}", userAuthId); 25 | if (!StringUtils.isEmpty(userAuthId)) { 26 | ApiRequestContextHolder.getContext().setAuthId(userAuthId); 27 | } 28 | try { 29 | chain.doFilter(request, response); 30 | }finally { 31 | ApiRequestContextHolder.clearContext(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/controller/UtilityPaymentController.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.controller; 2 | 3 | import com.javatodev.finance.model.rest.request.UtilityPaymentRequest; 4 | import com.javatodev.finance.service.UtilityPaymentService; 5 | 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import lombok.RequiredArgsConstructor; 15 | 16 | @RestController 17 | @RequiredArgsConstructor 18 | @RequestMapping(value = "/api/v1/utility-payment") 19 | public class UtilityPaymentController { 20 | 21 | private final UtilityPaymentService utilityPaymentService; 22 | 23 | @GetMapping 24 | public ResponseEntity readPayments(Pageable pageable) { 25 | return ResponseEntity.ok(utilityPaymentService.readPayments(pageable)); 26 | } 27 | 28 | @PostMapping 29 | public ResponseEntity processPayment(@RequestBody UtilityPaymentRequest paymentRequest) { 30 | return ResponseEntity.ok(utilityPaymentService.utilPayment(paymentRequest)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/exception/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | public class ErrorResponse { 11 | private String code; 12 | private String message; 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 7 | 8 | import java.util.Locale; 9 | 10 | @ControllerAdvice 11 | public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { 12 | 13 | @ExceptionHandler(SimpleBankingGlobalException.class) 14 | protected ResponseEntity handleGlobalException(SimpleBankingGlobalException simpleBankingGlobalException, Locale locale) { 15 | return ResponseEntity 16 | .badRequest() 17 | .body(ErrorResponse.builder() 18 | .code(simpleBankingGlobalException.getCode()) 19 | .message(simpleBankingGlobalException.getMessage()) 20 | .build()); 21 | } 22 | 23 | @ExceptionHandler({Exception.class}) 24 | protected ResponseEntity handleException(Exception e, Locale locale) { 25 | return ResponseEntity 26 | .badRequest() 27 | .body("Exception occur inside API " + e); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/exception/SimpleBankingGlobalException.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.exception; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SimpleBankingGlobalException extends RuntimeException { 13 | 14 | private String code; 15 | private String message; 16 | 17 | public SimpleBankingGlobalException(String message) { 18 | super(message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/TransactionStatus.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model; 2 | 3 | public enum TransactionStatus { 4 | PENDING, PROCESSING, SUCCESS, FAILED 5 | } 6 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/dto/AuditAware.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | import org.springframework.data.annotation.CreatedBy; 6 | import org.springframework.data.annotation.CreatedDate; 7 | import org.springframework.data.annotation.LastModifiedBy; 8 | import org.springframework.data.annotation.LastModifiedDate; 9 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 10 | 11 | import java.io.Serializable; 12 | import java.time.Instant; 13 | 14 | import jakarta.persistence.EntityListeners; 15 | import jakarta.persistence.MappedSuperclass; 16 | import jakarta.persistence.Version; 17 | import lombok.Getter; 18 | import lombok.Setter; 19 | 20 | @Getter 21 | @Setter 22 | @MappedSuperclass 23 | @EntityListeners(AuditingEntityListener.class) 24 | public class AuditAware implements Serializable { 25 | 26 | @JsonIgnore 27 | @CreatedDate 28 | private Instant createdDate; 29 | 30 | @JsonIgnore 31 | @CreatedBy 32 | private String createdBy; 33 | 34 | @JsonIgnore 35 | @LastModifiedDate 36 | private Instant modifiedDate; 37 | 38 | @JsonIgnore 39 | @LastModifiedBy 40 | private String modifiedBy; 41 | 42 | @Version 43 | private long version; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/dto/UtilityPayment.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.dto; 2 | 3 | import com.javatodev.finance.model.TransactionStatus; 4 | 5 | import java.math.BigDecimal; 6 | 7 | import lombok.Data; 8 | 9 | @Data 10 | public class UtilityPayment extends AuditAware { 11 | private Long providerId; 12 | private BigDecimal amount; 13 | private String referenceNumber; 14 | private String account; 15 | private TransactionStatus status; 16 | } 17 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/entity/UtilityPaymentEntity.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.entity; 2 | 3 | import com.javatodev.finance.model.TransactionStatus; 4 | import com.javatodev.finance.model.dto.AuditAware; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import jakarta.persistence.*; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | @Entity 15 | @Table(name = "utility_payment") 16 | public class UtilityPaymentEntity extends AuditAware { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | private Long providerId; 23 | private BigDecimal amount; 24 | private String referenceNumber; 25 | private String account; 26 | private String transactionId; 27 | 28 | @Enumerated(EnumType.STRING) 29 | private TransactionStatus status; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/mapper/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | 8 | public abstract class BaseMapper { 9 | public abstract E convertToEntity(D dto, Object... args); 10 | 11 | public abstract D convertToDto(E entity, Object... args); 12 | 13 | public Collection convertToEntity(Collection dto, Object... args) { 14 | return dto.stream().map(d -> convertToEntity(d, args)).collect(Collectors.toList()); 15 | } 16 | 17 | public Collection convertToDto(Collection entity, Object... args) { 18 | return entity.stream().map(e -> convertToDto(e, args)).collect(Collectors.toList()); 19 | } 20 | 21 | public List convertToEntityList(Collection dto, Object... args) { 22 | return convertToEntity(dto, args).stream().collect(Collectors.toList()); 23 | } 24 | 25 | public List convertToDtoList(Collection entity, Object... args) { 26 | return convertToDto(entity, args).stream().collect(Collectors.toList()); 27 | } 28 | 29 | public Set convertToEntitySet(Collection dto, Object... args) { 30 | return convertToEntity(dto, args).stream().collect(Collectors.toSet()); 31 | } 32 | 33 | public Set convertToDtoSet(Collection entity, Object... args) { 34 | return convertToDto(entity, args).stream().collect(Collectors.toSet()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/mapper/UtilityPaymentMapper.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.mapper; 2 | 3 | import com.javatodev.finance.model.dto.UtilityPayment; 4 | import com.javatodev.finance.model.entity.UtilityPaymentEntity; 5 | 6 | import org.springframework.beans.BeanUtils; 7 | 8 | public class UtilityPaymentMapper extends BaseMapper { 9 | @Override 10 | public UtilityPaymentEntity convertToEntity(UtilityPayment dto, Object... args) { 11 | UtilityPaymentEntity entity = new UtilityPaymentEntity(); 12 | if (dto != null) { 13 | BeanUtils.copyProperties(dto, entity); 14 | } 15 | return entity; 16 | } 17 | 18 | @Override 19 | public UtilityPayment convertToDto(UtilityPaymentEntity entity, Object... args) { 20 | UtilityPayment dto = new UtilityPayment(); 21 | if (entity != null) { 22 | BeanUtils.copyProperties(entity, dto); 23 | } 24 | return dto; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/rest/request/UtilityPaymentRequest.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.rest.request; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class UtilityPaymentRequest { 9 | private Long providerId; 10 | private BigDecimal amount; 11 | private String referenceNumber; 12 | private String account; 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/rest/response/AccountResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.rest.response; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class AccountResponse { 9 | private Long number; 10 | private BigDecimal actualBalance; 11 | private Long id; 12 | private String type; 13 | private String status; 14 | private BigDecimal availableBalance; 15 | } 16 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/model/rest/response/UtilityPaymentResponse.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.model.rest.response; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class UtilityPaymentResponse { 9 | private String message; 10 | private String transactionId; 11 | } 12 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/repository/UtilityPaymentRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.repository; 2 | 3 | import com.javatodev.finance.model.dto.UtilityPayment; 4 | import com.javatodev.finance.model.entity.UtilityPaymentEntity; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | public interface UtilityPaymentRepository extends JpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/service/UtilityPaymentService.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service; 2 | 3 | import com.javatodev.finance.model.TransactionStatus; 4 | import com.javatodev.finance.model.dto.UtilityPayment; 5 | import com.javatodev.finance.model.entity.UtilityPaymentEntity; 6 | import com.javatodev.finance.model.mapper.UtilityPaymentMapper; 7 | import com.javatodev.finance.model.rest.request.UtilityPaymentRequest; 8 | import com.javatodev.finance.model.rest.response.UtilityPaymentResponse; 9 | import com.javatodev.finance.repository.UtilityPaymentRepository; 10 | import com.javatodev.finance.service.rest.BankingCoreRestClient; 11 | 12 | import org.springframework.beans.BeanUtils; 13 | import org.springframework.data.domain.Page; 14 | import org.springframework.data.domain.Pageable; 15 | import org.springframework.stereotype.Service; 16 | 17 | import java.util.List; 18 | 19 | import lombok.RequiredArgsConstructor; 20 | import lombok.extern.slf4j.Slf4j; 21 | 22 | @Slf4j 23 | @Service 24 | @RequiredArgsConstructor 25 | public class UtilityPaymentService { 26 | private final UtilityPaymentRepository utilityPaymentRepository; 27 | private final BankingCoreRestClient bankingCoreRestClient; 28 | 29 | private UtilityPaymentMapper utilityPaymentMapper = new UtilityPaymentMapper(); 30 | 31 | public UtilityPaymentResponse utilPayment(UtilityPaymentRequest paymentRequest) { 32 | log.info("Utility payment processing {}", paymentRequest.toString()); 33 | 34 | UtilityPaymentEntity entity = new UtilityPaymentEntity(); 35 | BeanUtils.copyProperties(paymentRequest, entity); 36 | entity.setStatus(TransactionStatus.PROCESSING); 37 | UtilityPaymentEntity optUtilPayment = utilityPaymentRepository.save(entity); 38 | 39 | UtilityPaymentResponse utilityPaymentResponse = bankingCoreRestClient.utilityPayment(paymentRequest); 40 | log.info("Transaction response {}", utilityPaymentResponse.toString()); 41 | 42 | optUtilPayment.setStatus(TransactionStatus.SUCCESS); 43 | optUtilPayment.setTransactionId(utilityPaymentResponse.getTransactionId()); 44 | utilityPaymentRepository.save(optUtilPayment); 45 | 46 | return UtilityPaymentResponse.builder().message("Utility Payment Successfully Processed").transactionId(utilityPaymentResponse.getTransactionId()).build(); 47 | } 48 | 49 | public List readPayments(Pageable pageable) { 50 | Page allUtilPayments = utilityPaymentRepository.findAll(pageable); 51 | return utilityPaymentMapper.convertToDtoList(allUtilPayments.getContent()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/java/com/javatodev/finance/service/rest/BankingCoreRestClient.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance.service.rest; 2 | 3 | import com.javatodev.finance.configuration.CustomFeignClientConfiguration; 4 | import com.javatodev.finance.model.rest.request.UtilityPaymentRequest; 5 | import com.javatodev.finance.model.rest.response.AccountResponse; 6 | import com.javatodev.finance.model.rest.response.UtilityPaymentResponse; 7 | 8 | import org.springframework.cloud.openfeign.FeignClient; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | 14 | @FeignClient(name = "core-banking-service", configuration = CustomFeignClientConfiguration.class) 15 | public interface BankingCoreRestClient { 16 | 17 | @RequestMapping(path = "/api/v1/account/bank-account/{account_number}", method = RequestMethod.GET) 18 | AccountResponse readAccount(@PathVariable("account_number") String accountNumber); 19 | 20 | @RequestMapping(path = "/api/v1/transaction/util-payment", method = RequestMethod.POST) 21 | UtilityPaymentResponse utilityPayment(@RequestBody UtilityPaymentRequest paymentRequest); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: internet-banking-utility-payment-service 4 | 5 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/resources/bootstrap-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://192.168.1.5:8090 5 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/resources/bootstrap-docker.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://internet-banking-config-server:8090 5 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | uri: http://localhost:8090 5 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/test/java/com/javatodev/finance/InternetBankingUtilityPaymentServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatodev.finance; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InternetBankingUtilityPaymentServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /internet-banking-utility-payment-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: internet-banking-utility-payment-service 4 | datasource: 5 | url: jdbc:h2:mem:internet-banking-utility-payment-service 6 | username: root 7 | password: password 8 | driver-class-name: org.h2.Driver 9 | jpa: 10 | hibernate: 11 | ddl-auto: none 12 | database-platform: org.hibernate.dialect.H2Dialect 13 | 14 | flyway: 15 | enabled: false 16 | server: 17 | port: 8092 18 | 19 | eureka: 20 | client: 21 | service-url: 22 | defaultZone: http://localhost:8081/eureka 23 | enabled: false 24 | 25 | info: 26 | app: 27 | name: ${spring.application.name} 28 | -------------------------------------------------------------------------------- /postman_collection/BANKING_CORE_MICROSERVICES_PROJECT.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1cd910ea-4a60-4aea-89ef-196405d59cbd", 3 | "name": "BANKING_CORE_MICROSERVICES_PROJECT", 4 | "values": [ 5 | { 6 | "key": "api_gateway_host", 7 | "value": "http://localhost:8082", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "keycloack_host", 12 | "value": "http://localhost:8080", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "keycloack_client_id", 17 | "value": "internet-banking-core-client", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "keycloack_client_secret", 22 | "value": "0efd3e37-258e-4488-96ae-1dfe34679c9d", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "keycloack_realm", 27 | "value": "javatodev-internet-banking", 28 | "enabled": true 29 | } 30 | ], 31 | "_postman_variable_scope": "environment", 32 | "_postman_exported_at": "2021-05-17T19:10:55.753Z", 33 | "_postman_exported_using": "Postman/8.4.0" 34 | } --------------------------------------------------------------------------------