56 Commits

Author SHA1 Message Date
ameye 713e7bb5ac Merge branch 'penal_charge' of DigiFi/digifi-BankEmulator into master 2026-03-18 22:43:06 +00:00
VivianDee f9e80ee088 Merge branch 'verify_balance_check' into penal_charge 2026-03-18 14:59:30 +01:00
VivianDee 2f2eb6b89f Update digifi_swagger.json 2026-03-18 14:59:07 +01:00
VivianDee ca32bfda1c [add]: penal charge 2026-03-18 14:52:46 +01:00
vivian.d.simbrellang.com 74e5563e6a Merge branch 'verify_balance_check' of DigiFi/digifi-BankEmulator into master 2026-03-11 13:10:12 +00:00
VivianDee 473d9568d2 [fix]: Vrifyy balance 2026-03-11 14:07:15 +01:00
VivianDee ab7cd0bedf [fix]: Verify balance 2026-03-11 13:54:56 +01:00
VivianDee bb5237797d Update verify_account_balance.py 2026-03-11 11:16:23 +01:00
VivianDee b8fde2c320 Update verify_account_balance.py 2026-03-11 11:14:31 +01:00
VivianDee c92255c0c5 [add]: Balance Check 2026-03-11 11:06:26 +01:00
CHIEFSOFT\ameye 422d60addd Amount for clooection 2025-11-03 13:25:41 -05:00
CHIEFSOFT\ameye a63d20f50e Collect Status retrieved Successfully 2025-11-02 16:38:53 -05:00
CHIEFSOFT\ameye 3fb48a08b0 responseMessage 2025-11-02 16:34:54 -05:00
CHIEFSOFT\ameye 249e624ef3 fix exytra data 2025-11-02 16:23:41 -05:00
CHIEFSOFT\ameye 630174fa8c Very data fix 2025-11-02 15:58:00 -05:00
ameye f4cd8ae162 Merge branch 'sync_payload' of DigiFi/digifi-BankEmulator into master 2025-10-29 17:13:07 +00:00
Chinenye Nmoh 5794ddfa0c added bearer token authentication 2025-10-29 17:39:31 +01:00
Chinenye Nmoh 1293f28bf2 Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankEmulator into sync_payload
pulled latest master changes
2025-10-29 07:17:25 +01:00
ameye db36278ae7 Merge branch 'partial_payment' of DigiFi/digifi-BankEmulator into master 2025-10-28 19:24:45 +00:00
VivianDee b48ccacd7c [add]: Make all customers valid 2025-09-26 12:03:33 +01:00
ameye 4e52459d51 Merge branch 'partial_payment' of DigiFi/digifi-BankEmulator into master 2025-08-29 19:18:35 +00:00
VivianDee c0f1845c5d [add]: Partial loan collection 2025-08-29 12:51:28 +01:00
Chinenye Nmoh 6869b77428 Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankEmulator into sync_payload
pulled changes
2025-07-13 13:44:34 +01:00
Chinenye Nmoh 73c0377033 pull changes 2025-07-13 13:44:27 +01:00
ameye cfc40b89dc Merge branch 'health_check' of DigiFi/digifi-BankEmulator into master 2025-06-28 13:50:03 +00:00
VivianDee eb7c0f6221 [add]: health check 2025-06-27 15:58:12 +01:00
Chinenye Nmoh 02b4ba4a5a Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankEmulator into sync_payload
pulled
2025-06-26 14:01:31 +01:00
ameye d69bcd11ea Merge branch 'randomize_rac_check_values' of DigiFi/digifi-BankEmulator into master 2025-06-25 17:32:57 +00:00
VivianDee c4d7db5c59 Update rac_check.py 2025-06-25 17:31:02 +01:00
Chinenye Nmoh b468b2ad4b Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankEmulator into sync_payload
pulled
2025-06-25 13:22:11 +01:00
CHIEFSOFT\ameye d359532775 Fbn trax 2025-06-21 10:52:09 -04:00
CHIEFSOFT\ameye 2b12e1ab0b Partial simulation 2025-06-21 10:41:53 -04:00
vivian.d.simbrellang.com 23b352d9c3 Merge branch 'rac_check' of DigiFi/digifi-BankEmulator into master 2025-06-12 14:33:11 +00:00
VivianDee f665d7b8e4 Update rac_check.py 2025-06-12 15:32:00 +01:00
Chinenye Nmoh 7b1da3b095 expanded disbursement endpoint 2025-06-09 21:08:02 +01:00
ameye 855f343626 Merge branch 'sync_payload' of DigiFi/digifi-BankEmulator into master 2025-06-09 19:40:35 +00:00
Chinenye Nmoh e7279a8c65 expanded disbursement endpoint 2025-06-09 20:31:32 +01:00
CHIEFSOFT\ameye 3e4fad5418 responseCode 2025-06-05 22:50:45 -04:00
CHIEFSOFT\ameye 4b018a26e9 res 2025-06-05 22:46:46 -04:00
CHIEFSOFT\ameye dfdfa51583 res[pose code 2025-06-05 22:43:38 -04:00
CHIEFSOFT\ameye 82053f41ce Fix emulator data 2025-06-05 18:18:56 -04:00
ameye 0833d0d0f2 Merge branch 'rac_check_update' of DigiFi/digifi-BankEmulator into master 2025-06-05 14:49:16 +00:00
VivianDee b674b6e6f0 [update]: Rac check response 2025-06-05 12:47:32 +01:00
VivianDee 8c73fe48c5 Update rac_check.py 2025-06-05 11:56:52 +01:00
CHIEFSOFT\ameye 61fda080d5 remove request id 2025-06-04 19:52:41 -04:00
CHIEFSOFT\ameye 13a45eeb77 Fix data 2025-06-04 19:39:33 -04:00
ameye 900c0e0ab3 Merge branch 'sync_payload' of DigiFi/digifi-BankEmulator into master 2025-05-26 21:17:44 +00:00
Chinenye Nmoh 43c07769a8 corrected checkRac swagger endpoint 2025-05-26 22:02:39 +01:00
ameye 1fd0a5be64 Merge branch 'sync_payload' of DigiFi/digifi-BankEmulator into master 2025-05-23 12:58:18 +00:00
Chinenye Nmoh 9b91bbe091 added missing dependencies to the docker file 2025-05-23 13:09:27 +01:00
ameye 7373eb4e58 Merge branch 'sync_payload' of DigiFi/digifi-BankEmulator into master 2025-05-23 10:46:03 +00:00
Chinenye Nmoh d0d51f35c0 made changes on the api to match bank api 2025-05-23 11:20:50 +01:00
ameye 556d51f133 Merge branch 'feature' of DigiFi/digifi-BankEmulator into master 2025-05-23 01:02:30 +00:00
CHIEFSOFT\ameye 4181db05ee Sample from the bank 2025-05-14 11:29:20 -04:00
Azeez Muibi 8454722a27 added complete rac 2025-05-09 14:25:12 +01:00
Azeez Muibi 6638fcabde B
Revert "complete rac check"

This reverts commit 78a1b573d5.
2025-05-09 13:52:18 +01:00
53 changed files with 3888 additions and 852 deletions
Generated
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+1
View File
@@ -0,0 +1 @@
https://first-advance-middleware-develop.fbn-devops-dev-asenv.appserviceenvironment.net/swagger/v1/swagger.json
+1916
View File
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "==2.3.3"
flask-marshmallow = "==0.15.0"
marshmallow = "==3.19.0"
flask-cors = "==3.0.10"
gunicorn = "*"
flask-swagger-ui = "*"
python-dotenv = "*"
[dev-packages]
[requires]
python_version = "3.13"
Generated
+213
View File
@@ -0,0 +1,213 @@
{
"_meta": {
"hash": {
"sha256": "4729a28392b881795159ff885c9db5ee8ce14e84697fd7343f4999f53cfbac22"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.13"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"blinker": {
"hashes": [
"sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf",
"sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"
],
"markers": "python_version >= '3.9'",
"version": "==1.9.0"
},
"click": {
"hashes": [
"sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c",
"sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d"
],
"markers": "python_version >= '3.10'",
"version": "==8.2.0"
},
"colorama": {
"hashes": [
"sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
"sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'",
"version": "==0.4.6"
},
"flask": {
"hashes": [
"sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc",
"sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.3.3"
},
"flask-cors": {
"hashes": [
"sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438",
"sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"
],
"index": "pypi",
"version": "==3.0.10"
},
"flask-marshmallow": {
"hashes": [
"sha256:2083ae55bebb5142fff98c6bbd483a2f5dbc531a8bc1be2180ed5f75e7f3fccc",
"sha256:ce08a153f74da6ebfffd8065d1687508b0179df37fff7fc0c8f28ccfb64f1b56"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==0.15.0"
},
"flask-swagger-ui": {
"hashes": [
"sha256:5ecff6c284d7c5559f3473bd534a31fa5dfc0022502d63f4a04728c2b10596f6",
"sha256:872d038dc11a68eacab88f6f05be3c533aa300453e273775dad3e029b31e03d4"
],
"index": "pypi",
"version": "==5.21.0"
},
"gunicorn": {
"hashes": [
"sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d",
"sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==23.0.0"
},
"itsdangerous": {
"hashes": [
"sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
"sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.0"
},
"jinja2": {
"hashes": [
"sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d",
"sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.6"
},
"markupsafe": {
"hashes": [
"sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
"sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
"sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
"sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
"sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
"sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
"sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
"sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
"sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
"sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
"sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
"sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
"sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
"sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
"sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
"sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
"sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
"sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
"sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
"sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
"sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
"sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
"sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
"sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
"sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
"sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
"sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
"sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
"sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
"sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
"sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
"sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
"sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
"sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
"sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
"sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
"sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
"sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
"sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
"sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
"sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
"sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
"sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
"sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
"sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
"sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
"sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
"sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
"sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
"sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
"sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
"sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
"sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
"sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
"sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
"sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
"sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
"sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
"sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
"sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
"sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
],
"markers": "python_version >= '3.9'",
"version": "==3.0.2"
},
"marshmallow": {
"hashes": [
"sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78",
"sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==3.19.0"
},
"packaging": {
"hashes": [
"sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484",
"sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"
],
"markers": "python_version >= '3.8'",
"version": "==25.0"
},
"python-dotenv": {
"hashes": [
"sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5",
"sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d"
],
"index": "pypi",
"markers": "python_version >= '3.9'",
"version": "==1.1.0"
},
"six": {
"hashes": [
"sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
"sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.17.0"
},
"werkzeug": {
"hashes": [
"sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e",
"sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"
],
"markers": "python_version >= '3.9'",
"version": "==3.1.3"
}
},
"develop": {}
}
+1 -1
View File
@@ -45,7 +45,7 @@ This ensures that the application uses secure API keys and app IDs.
Once you have the repository cloned, you can easily set up and run the application using Docker Compose. Simply execute the following command:
```bash
docker-compose up --build
docker-compose up -d --build
```
This command will build the Docker image and start the Flask application in a container. By default, the application will be accessible at `http://localhost:6337`.
+34 -10
View File
@@ -1,37 +1,61 @@
from flask import Flask
from flask import Flask, jsonify
import os
from flask_swagger_ui import get_swaggerui_blueprint
from flask_cors import CORS
from app.config import Config
from app.api.routes import api
from app.api.routes import api, auth_bp
from app.errors import register_error_handlers
from flask_jwt_extended import JWTManager
def create_app():
""" Factory function to create a Flask app instance """
app = Flask(__name__)
# Load configuration
app.config.from_object(Config)
jwt = JWTManager(app)
CORS(app)
CORS(app)
# Swagger Doc
SWAGGER_URL = app.config.get("SWAGGER_URL")
API_URL = app.config.get("API_URL")
# Register blueprints
app.register_blueprint(api)
# Register blueprints with /api prefix for the main API routes
app.register_blueprint(api, url_prefix='/api')
# Register blueprints with /auth prefix for the authentication routes
app.register_blueprint(auth_bp, url_prefix='/api/Auth')
swagger_ui_blueprint = get_swaggerui_blueprint(SWAGGER_URL, API_URL)
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)
def jwt_error(message, code=401):
return jsonify({
"status": "error",
"message": message
}), code
@jwt.unauthorized_loader
def unauthorized_response(callback):
return jwt_error("Unauthorized access")
@jwt.expired_token_loader
def expired_token_callback(jwt_header, jwt_payload):
return jwt_error("Expired token")
@jwt.invalid_token_loader
def invalid_token_callback(error):
return jwt_error("Invalid authentication token.", 422)
@jwt.revoked_token_loader
def revoked_token_callback(jwt_header, jwt_payload):
return jwt_error("This token has been revoked. Please log in again.")
# Error Handlers
register_error_handlers(app)
return app
+1 -1
View File
@@ -1,3 +1,3 @@
from .verify_api_key import require_api_key
from .app_id_checker import require_app_id
from .cors import enforce_json
from .cors import enforce_json
+1
View File
@@ -1,4 +1,5 @@
from flask import request, jsonify
from app.utils.logger import logger
def enforce_json():
+1 -1
View File
@@ -11,7 +11,7 @@ def require_api_key(f):
@wraps(f)
def decorated_function(*args, **kwargs):
api_key = request.headers.get("X-API-KEY")
logger.info(f"Received API key: {api_key}")
if not api_key:
logger.error("Unauthorized access: Missing API key.")
+1
View File
@@ -1 +1,2 @@
from .routes import api
from .authentication import auth_bp
+24
View File
@@ -0,0 +1,24 @@
from flask import Blueprint, request, jsonify
from app.utils.logger import logger
from app.api.middlewares import enforce_json
from app.api.services.generate_token import GenerateTokenService
auth_bp = Blueprint("api/Auth", __name__)
# Enforce json
@auth_bp.before_request
def cors_middleware():
"""Middleware applied globally to all API routes in this blueprint"""
return enforce_json()
@auth_bp.route('/generate-token', methods=['POST'])
def get_token():
try:
data = request.get_json()
logger.info(f"GenerateToken request received: {data}")
response = GenerateTokenService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /GenerateToken route", exc_info=e)
return jsonify({"message": "Unhandled server error"}), 500
+115 -53
View File
@@ -1,8 +1,8 @@
from flask import Flask, Blueprint, request, jsonify, send_from_directory
import sys
import os
from app.api.services import (
RACCheckService,
CompleteRACcheckService,
DisbursementService,
CollectLoanService,
TransactionVerifyService,
@@ -11,9 +11,14 @@ from app.api.services import (
TokenValidationService,
LienCheckService,
NewTransactionCheckService,
CompleteRACcheckService,
VerifyAccountBalanceService
)
from app.utils.logger import logger
from app.api.middlewares import require_api_key, require_app_id, enforce_json
from app.api.middlewares import enforce_json
from flask_jwt_extended import (jwt_required)
api = Blueprint("api", __name__)
@@ -40,70 +45,102 @@ def serve_paths(filename):
return send_from_directory(swagger_dir, filename)
# RACCheck Endpoint
@api.route('/RACCheck', methods=['POST'])
@require_api_key
@require_app_id
@api.route('/rac-check', methods=['POST'])
@jwt_required()
def rac_check():
data = request.get_json()
# logger.info(f"RACCheck request received: {data}")
response = RACCheckService.process_request(data)
return response
logger.info("RACCheck request received")
try:
logger.info("RACCheck inside try request received")
data = request.get_json()
response = RACCheckService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /RACCheck route")
return jsonify({"message": "Unhandled server error"}), 500
# VerifyAccountBalance Endpoint
@api.route('/VerifyAccountBalance', methods=['POST'])
@jwt_required()
def verify_account_balance():
logger.info("VerifyAccountBalance request received")
try:
logger.info("VerifyAccountBalance inside try request received")
data = request.get_json()
response = VerifyAccountBalanceService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /VerifyAccountBalance route")
return jsonify({"message": "Unhandled server error"}), 500
# CompleteRACcheck Endpoint
@api.route('/CompleteRACcheck', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def complete_rac_check():
data = request.get_json()
# logger.info(f"CompleteRACcheck request received: {data}")
response = CompleteRACcheckService.process_request(data)
return response
try:
data = request.get_json()
response = CompleteRACcheckService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /CompleteRACcheck route")
return jsonify({"message": "Unhandled server error"}), 500
# Disbursement Endpoint
@api.route('/Disbursement', methods=['POST'])
@require_api_key
@require_app_id
@api.route('/DisburseLoan', methods=['POST'])
@jwt_required()
def disbursement():
data = request.get_json()
# logger.info(f"Disbursement request received: {data}")
response = DisbursementService.process_request(data)
return response
try:
data = request.get_json()
# logger.info(f"Disbursement request received: {data}")
response = DisbursementService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /Disbursement route")
return jsonify({"message": "Unhandled server error"}), 500
# CollectLoan Endpoint
@api.route('/CollectLoan', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def collect_loan():
data = request.get_json()
# logger.info(f"CollectLoan request received: {data}")
response = CollectLoanService.process_request(data)
return response
try:
data = request.get_json()
# logger.info(f"CollectLoan request received: {data}")
response = CollectLoanService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /CollectLoan route")
return jsonify({"message": "Unhandled server error"}), 500
# TransactionVerify Endpoint
@api.route('/TransactionVerify', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def transaction_verify():
data = request.get_json()
# logger.info(f"TransactionVerify request received: {data}")
response = TransactionVerifyService.process_request(data)
return response
try:
data = request.get_json()
# logger.info(f"TransactionVerify request received: {data}")
response = TransactionVerifyService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /TransactionVerify route")
return jsonify({"message": "Unhandled server error"}), 500
# PenalCharge Endpoint
@api.route('/PenalCharge', methods=['POST'])
@require_api_key
@require_app_id
# CollectPenalCharge Endpoint
@api.route('/CollectPenalCharge', methods=['POST'])
@jwt_required()
def penal_charge():
data = request.get_json()
# logger.info(f"PenalCharge request received: {data}")
response = PenalChargeService.process_request(data)
return response
try:
data = request.get_json()
response = PenalChargeService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /CollectPenalCharge route")
return jsonify({"message": "Unhandled server error"}), 500
# RevokeEnableConsent Endpoint
@api.route('/RevokeEnableConsent', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def revoke_enable_consent():
data = request.get_json()
# logger.info(f"RevokeEnableConsent request received: {data}")
@@ -112,8 +149,7 @@ def revoke_enable_consent():
# TokenValidation Endpoint
@api.route('/TokenValidation', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def token_validation():
data = request.get_json()
# logger.info(f"TokenValidation request received: {data}")
@@ -122,8 +158,7 @@ def token_validation():
# LienCheck Endpoint
@api.route('/LienCheck', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def lien_check():
data = request.get_json()
# logger.info(f"LienCheck request received: {data}")
@@ -132,15 +167,42 @@ def lien_check():
# NewTransactionCheck Endpoint
@api.route('/NewTransactionCheck', methods=['POST'])
@require_api_key
@require_app_id
@jwt_required()
def new_transaction_check():
data = request.get_json()
# logger.info(f"NewTransactionCheck request received: {data}")
response = NewTransactionCheckService.process_request(data)
return response
# Health Check Endpoint
@api.route('/health', methods=['GET'])
@api.route('/system-health-check', methods=['GET'])
@jwt_required()
def health_check():
return {"status": "ok"} , 200
"""Basic system health check"""
try:
checks = {
"python_version": sys.version_info >= (3, 6),
"disk_space": os.statvfs('/').f_bavail * os.statvfs('/').f_frsize > 500 * 1024 * 1024,
"system_operational": True
}
if all(checks.values()):
return jsonify({
"status": "Active",
"responseCode": "00",
"responseMessage": "Successful"
}), 200
else:
return jsonify({
"status": "Degraded",
"responseCode": "01",
"responseMessage": "System check failed"
}), 200
except Exception as e:
return jsonify({
"status": "Error",
"responseCode": "99",
"responseMessage": f"Health check failed: {str(e)}"
}), 500
+31 -12
View File
@@ -1,16 +1,35 @@
from marshmallow import Schema, fields
# Collect Loan Schema
class CollectLoanSchema(Schema):
transactionId = fields.Str(required=True)
fbnTransactionId = fields.Str(required=True)
debtId = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
productId = fields.Str(required=True)
collectAmount = fields.Float(required=True)
penalCharge = fields.Float(required=False) # Optional
collectionMethod = fields.Int(required=True)
channel = fields.Str(allow_none=True)
transactionId = fields.Str(allow_none=True)
fbnTransactionId = fields.Str(allow_none=True)
debtId = fields.Str(allow_none=True)
accountId = fields.Str(allow_none=True)
customerId = fields.Str(allow_none=True)
productId = fields.Str(allow_none=True)
collectAmount = fields.Float(required=True)
penalCharge = fields.Float(required=True)
collectionMethod = fields.Str(allow_none=True)
lienAmount = fields.Float(required=True)
countryId = fields.Str(allow_none=True)
comment = fields.Str(allow_none=True)
class CollectLoanResponseSchema(Schema):
transactionId = fields.Str(allow_none=True)
fbnTransactionId = fields.Str(allow_none=True)
debtId = fields.Str(allow_none=True)
customerId = fields.Str(allow_none=True)
accountId = fields.Str(allow_none=True)
productId = fields.Str(allow_none=True)
amountCollected = fields.Float(required=True)
interestCollected = fields.Float(required=True)
penalChargeCollected = fields.Float(required=True)
lienAmount = fields.Float(required=True)
countryId = fields.Str(required=True)
comment = fields.Str(required=False) # Optional
countryId = fields.Str(allow_none=True)
comment = fields.Str(allow_none=True)
responseCode = fields.Str(allow_none=True)
responseMessage = fields.Str(allow_none=True)
responseDescr = fields.Str(allow_none=True)
fullDescription = fields.Str(allow_none=True)
+1
View File
@@ -3,6 +3,7 @@ from marshmallow import Schema, fields, validate
# CompleteRACcheck Request Schema
class CompleteRACcheckSchema(Schema):
transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms")
fbnTransactionId = fields.Str(required=True, description="Unique identifier of transaction in FBN system")
customerId = fields.Str(required=True, description="Unique identifier of a user")
accountId = fields.Str(required=True, description="Specific identifier of a user's account")
RAC_Array = fields.Dict(required=True, description="Risk Acceptance Criteria array")
+36 -10
View File
@@ -1,17 +1,43 @@
from marshmallow import Schema, fields
# Disbursement Schema
class DisbursementSchema(Schema):
requestId = fields.Str(required=True)
debtId = fields.Str(required=True)
transactionId = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
productId = fields.Str(required=True)
transactionId = fields.Str(required=False, allow_none=True)
fbnTransactionId = fields.Str(required=False, allow_none=True)
debtId = fields.Str(required=False, allow_none=True)
customerId = fields.Str(required=False, allow_none=True)
accountId = fields.Str(required=False, allow_none=True)
productId = fields.Str(required=False, allow_none=True)
provideAmount = fields.Float(required=True)
collectAmountInterest = fields.Float(required=False) # Optional
collectAmountInterest = fields.Float(required=True)
collectAmountMgtFee = fields.Float(required=True)
collectAmountInsurance = fields.Float(required=True)
collectAmountVAT = fields.Float(required=True)
countryId = fields.Str(required=True)
comment = fields.Str(required=False) # Optional
countryId = fields.Str(required=False, allow_none=True)
comment = fields.Str(required=False, allow_none=True)
class DisburseLoanResponseSchema(Schema):
transactionId = fields.Str(allow_none=True)
fbnTransactionId = fields.Str(allow_none=True)
debtId = fields.Str(allow_none=True)
customerId = fields.Str(allow_none=True)
accountId = fields.Str(allow_none=True)
productId = fields.Str(allow_none=True)
provideAmount = fields.Float(required=True)
collectAmountInterest = fields.Float(required=True)
collectAmountMgtFee = fields.Float(required=True)
collectAmountInsurance = fields.Float(required=True)
collectAmountVAT = fields.Float(required=True)
countryId = fields.Str(allow_none=True)
responseCode = fields.Str(allow_none=True)
responseMessage = fields.Str(allow_none=True)
disburseResult = fields.Str(allow_none=True)
disburseDate = fields.Str(allow_none=True)
disburseVerify = fields.Str(allow_none=True)
disburseDescription = fields.Str(allow_none=True)
verifyResult = fields.Str(allow_none=True)
verifyDescription = fields.Str(allow_none=True)
+18
View File
@@ -0,0 +1,18 @@
from marshmallow import Schema, fields
class GenerateTokenRequestSchema(Schema):
username = fields.Str(required=True)
password = fields.Str(required=True)
grant_type = fields.Str(required=True)
class GenerateTokenResponseSchema(Schema):
access_token = fields.Str(required=True)
token_type = fields.Str(required=True)
expires_in = fields.Int(required=True)
userName = fields.Str(required=False, allow_none=True)
ipaddress = fields.Str(required=False, allow_none=True)
errorMessage = fields.Str(required=False, allow_none=True)
issued = fields.DateTime(required=False, allow_none=True)
expires = fields.DateTime(required=False, allow_none=True)
+18 -6
View File
@@ -1,14 +1,26 @@
from marshmallow import Schema, fields
# Penal Charge Schema
# This file contains the schema for penal charge operations
class PenalChargeSchema(Schema):
channel = fields.Str(required=True)
transactionId = fields.Str(required=True)
fbnTransactionId = fields.Str(required=True)
debtId = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
penalCharge = fields.Decimal(required=True)
lienAmount = fields.Decimal(required=True)
penalCharge = fields.Int(required=True)
customerId = fields.Str(required=True)
lienAmount = fields.Int(required=True)
comment = fields.Str(required=True)
countryId = fields.Str(required=True)
comment = fields.Str(required=False)
#represents the response schema for penal charge
class CollectPenalFeeResponseSchema(Schema):
customerId = fields.Str(allow_none=True)
transactionId = fields.Str(allow_none=True)
amountCollected = fields.Float(required=True)
lienAmount = fields.Int(allow_none=True)
accountId = fields.Str(allow_none=True)
responseCode = fields.Str(allow_none=True)
responseMessage = fields.Str(allow_none=True)
+46 -12
View File
@@ -1,17 +1,43 @@
from marshmallow import Schema, fields
from marshmallow import Schema, fields
from datetime import date
class RACItemSchema(Schema):
salaryAccount = fields.Bool(required=True)
bvn = fields.Str(required=True)
crc = fields.Bool(required=True)
crms = fields.Bool(required=True)
accountStatus = fields.Str(required=True)
lien = fields.Bool(required=True)
noBouncedCheck = fields.Bool(required=True)
existingLoan = fields.Bool(required=True)
whitelist = fields.Bool(required=True)
noPastDueSalaryLoan = fields.Bool(required=True)
noPastDueOtherLoans = fields.Bool(required=True)
PROCESS_DATE = fields.Date(required=True, default=date.today)
CIF_ID = fields.Str(required=True)
CUSTOMER_id = fields.Str(required=True)
SALACCT_1 = fields.Str(required=True)
ALERT_PHONE = fields.Str(required=True)
AVERAGE_SALARY = fields.Decimal(required=True, as_string=True)
LOAN_OUSTANDING_BAL = fields.Decimal(required=True, as_string=True)
EMI = fields.Decimal(required=True, as_string=True)
ELIG_AMT = fields.Decimal(required=True, as_string=True)
rule1_45day_sal = fields.Bool(required=True)
rule2_2m_sal = fields.Bool(required=True)
rule3_no_bounced_check = fields.Bool(required=True)
rule4_current_loan_payments = fields.Bool(required=True)
rule5_no_past_due_fadv_loan = fields.Bool(required=True)
rule6_no_past_due_other_loan = fields.Bool(required=True)
rule7_consistent_salary_amount = fields.Bool(required=True)
rule8_whitelisted = fields.Bool(required=True)
rule9_regular_account = fields.Bool(required=True)
rule10_bvn_validation = fields.Bool(required=True)
rule11_CRC_no_delinquency = fields.Bool(required=True)
rule12_CRMS_no_delinquency = fields.Bool(required=True)
rule13_BVN_ignore = fields.Bool(required=True)
rule14_no_lien = fields.Bool(required=True)
rule15_null_ignore = fields.Bool(required=True)
OVERALL_ELIG = fields.Bool(required=True)
SALARYPAYMENT_1 = fields.Decimal(required=True, as_string=True)
SALARYPAYMENT_2 = fields.Decimal(required=True, as_string=True)
SALARYPAYMENT_3 = fields.Decimal(required=True, as_string=True)
SALARYPAYMENT_4 = fields.Decimal(required=True, as_string=True)
SALARYPAYMENT_5 = fields.Decimal(required=True, as_string=True)
SALARYPAYMENT_6 = fields.Decimal(required=True, as_string=True)
# RAC Check Schema
@@ -20,4 +46,12 @@ class RACCheckSchema(Schema):
fbnTransactionId = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
RAC_Array = fields.List(fields.Nested(RACItemSchema), required=True)
channel = fields.Str(required=True)
countryCode = fields.Str(required=True)
class RACCheckResponseSchema(Schema):
transactionId = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
racResponse = fields.Nested(RACItemSchema, required=True)
+42 -8
View File
@@ -1,12 +1,46 @@
from marshmallow import Schema, fields
class TransactionVerifySchemaNotGood(Schema):
channel = fields.Str(allow_none=True)
accountId = fields.Str(allow_none=True)
customerId = fields.Str(allow_none=True)
transactionId = fields.Str(allow_none=True)
transactionType = fields.Str(allow_none=True)
countryId = fields.Str(allow_none=True)
requestId = fields.Str(allow_none=True)
# Transaction Verify Schema
class TransactionVerifySchema(Schema):
counter = fields.Str(required=True)
transactionId = fields.Str(required=True)
requestID = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
countryId = fields.Str(required=True) # Static value “01”
transactionType = fields.Str(required=True)
customerId = fields.Str(allow_none=True)
accountId = fields.Str(allow_none=True)
transactionId = fields.Str(allow_none=True)
transactionType = fields.Str(allow_none=True)
fbnTransactionId = fields.Str(allow_none=True)
countryId = fields.Str(allow_none=True)
requestId = fields.Str(allow_none=True)
class TransactionVerifyResponseSchema(Schema):
responseCode = fields.Str(allow_none=True)
responseDescr = fields.Str(allow_none=True)
responseMessage = fields.Str(allow_none=True)
customerId = fields.Str(allow_none=True)
accountId = fields.Str(allow_none=True)
providedAmount = fields.Float(required=True)
collectedAmount = fields.Float(required=True)
transactionId = fields.Str(allow_none=True)
transactionType = fields.Str(allow_none=True)
# '''
# verify_data = {
# "customerId": loan_data.get('customerId'),
# "accountId": loan_data.get('accountId'),
# "transactionId": loan_data.get('transactionId'),
# "transactionType": "provide",
# "fbnTransactionId": loan_data.get('transactionId'),
# "countryId": "NG",
# "requestId": loan_data.get('transactionId')
# }
# '''
+10
View File
@@ -0,0 +1,10 @@
from marshmallow import Schema, fields
from marshmallow import Schema, fields
from datetime import date
class VerifyAccountBalanceSchema(Schema):
accountId = fields.Str(required=True)
amount = fields.Str(required=True)
requestId = fields.Str(required=True)
+3 -1
View File
@@ -1,5 +1,4 @@
from app.api.services.rac_check import RACCheckService
from app.api.services.complete_rac_check_service import CompleteRACcheckService
from app.api.services.disbursement import DisbursementService
from app.api.services.collect_loan import CollectLoanService
from app.api.services.transaction_verify import TransactionVerifyService
@@ -8,3 +7,6 @@ from app.api.services.revoke_enable_consent import RevokeEnableConsentService
from app.api.services.token_validation import TokenValidationService
from app.api.services.lien_check import LienCheckService
from app.api.services.new_transaction_check import NewTransactionCheckService
from app.api.services.complete_rac_check_service import CompleteRACcheckService
from app.api.services.generate_token import GenerateTokenService
from app.api.services.verify_account_balance import VerifyAccountBalanceService
+75 -33
View File
@@ -1,21 +1,23 @@
import random
from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.collect_loan import CollectLoanSchema
from app.api.schemas.collect_loan import CollectLoanSchema, CollectLoanResponseSchema
from app.config import Config
"""
Process the CollectLoan request.
Args:
data (dict): The request data.
Returns:
tuple: JSON response and status code.
"""
class CollectLoanService:
@staticmethod
def process_request(data):
"""
Process the CollectLoan request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
logger.info("Processing CollectLoan request")
@@ -23,37 +25,77 @@ class CollectLoanService:
schema = CollectLoanSchema()
validated_data = schema.load(data)
# Simulated processing logic
response_data = {
"transactionId": "T002",
"debtId": "273194670",
"customerId": "CN621868",
"accountId": "2017821799",
"productId": "101",
"collectAmount": 60000.00,
"penalCharge": 0,
"lienAmount": 20000,
"countryId": "01",
"comment": "Testing CollectionLoanRequest",
"resultCode": "00",
"resultDescription": "Loan Collection Successful"
}
amountForCollection = validated_data.get("collectAmount")
productId = validated_data.get("productId")
customerId = validated_data.get("customerId")
amountCollected = amountForCollection
responseDescr= "Loan Collection Successful EMULATOR"
fullDescription= "Loan collection completed successfully EMULATOR"
responseMessage= "Loan collection completed successfully EMULATOR"
interestCollected = amountForCollection * 0.03
lienAmount = validated_data.get("lienAmount", 0)
isValid = not (
int(customerId[-1]) in [2, 7, 9]
)
if Config.MIN_AMOUNT_FOR_COLLECTION <= amountForCollection <= Config.MAX_AMOUNT_FOR_COLLECTION:
# amountCollected = amountForCollection if lienAmount >= amountForCollection else 0
responseDescr = "Partial Loan Collection Successful EMULATOR"
fullDescription = "Partial Loan collection completed successfully EMULATOR"
responseMessage = "Partial Loan collection completed successfully EMULATOR"
# return ResponseHelper.success(
# data=response_data,
# message="Loan collection completed successfully"
# )
return response_data
response_data = {
"transactionId": validated_data.get("transactionId"),
"fbnTransactionId": validated_data.get("fbnTransactionId"),
"debtId": validated_data.get("debtId"),
"customerId": validated_data.get("customerId"),
"accountId": validated_data.get("accountId"),
"productId": validated_data.get("productId"),
"amountCollected": amountCollected,
"interestCollected": interestCollected,
"penalChargeCollected": 0,
"lienAmount": lienAmount if amountCollected == 0 else 0,
"countryId": validated_data.get("countryId"),
"comment": validated_data.get("comment", "Testing CollectionLoanRequest EMULATOR"),
"responseCode": "00",
"responseDescr": responseDescr,
"fullDescription": fullDescription,
"responseMessage": responseMessage
}
else:
response_data = {
"transactionId": validated_data.get("transactionId"),
"fbnTransactionId": validated_data.get("fbnTransactionId"),
"debtId": validated_data.get("debtId"),
"customerId": validated_data.get("customerId"),
"accountId": validated_data.get("accountId"),
"productId": validated_data.get("productId"),
"amountCollected": amountCollected,
"interestCollected": interestCollected,
"penalChargeCollected": 0,
"amountCollected": amountCollected,
"countryId": validated_data.get("countryId"),
"comment": validated_data.get("comment", "Testing CollectionLoanRequest EMULATOR"),
"responseCode": "00",
"responseDescr": responseDescr,
"fullDescription": fullDescription,
"responseMessage": responseMessage
}
# Validate and serialize the response data
response_schema = CollectLoanResponseSchema()
result = response_schema.dump(response_data)
return jsonify(result), 200
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception"
"message": "Validation exception",
"errors": err.messages
}) , 422
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return jsonify({
@@ -17,8 +17,6 @@ class CompleteRACcheckService:
dict: A standardized response.
"""
try:
logger.info("Processing CompleteRACcheck request")
# Validate input data using CompleteRACcheckSchema
schema = CompleteRACcheckSchema()
validated_data = schema.load(data) # Raises ValidationError if invalid
+33 -27
View File
@@ -1,8 +1,8 @@
from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.disbursement import DisbursementSchema
from app.api.schemas.disbursement import DisbursementSchema, DisburseLoanResponseSchema
import datetime
class DisbursementService:
@staticmethod
@@ -14,7 +14,7 @@ class DisbursementService:
data (dict): The request data.
Returns:
dict: A standardized response.
tuple: JSON response and HTTP status code.
"""
try:
logger.info("Processing Disbursement request")
@@ -23,40 +23,46 @@ class DisbursementService:
schema = DisbursementSchema()
validated_data = schema.load(data) # Raises ValidationError if invalid
# Simulated processing logic
# For demo purposes, we simulate a response using the validated data
response_data = {
"transactionId": "T001",
"TransactionId": "Tr201712RK9232P115",
"debtId": "273194670",
"customerId": "CN621868",
"accountId": "2017821799",
"productId": "101",
"provideAmount": 100000.0,
"collectAmountInterest": 5000,
"collectAmountMgtFee": 1000,
"collectAmountInsurance": 1000,
"collectAmountVAT": 75,
"countryId": "01",
"resultCode": "00",
"resultDescription": "Loan Request Completed Successfully!"
"transactionId": validated_data.get("transactionId"),
"fbnTransactionId": validated_data.get("fbnTransactionId"), # Example or generated value
"debtId": validated_data.get("debtId"),
"customerId": validated_data.get("customerId"),
"accountId": validated_data.get("accountId"),
"productId": validated_data.get("productId"),
"provideAmount": validated_data.get("provideAmount"),
"collectAmountInterest": validated_data.get("collectAmountInterest"),
"collectAmountMgtFee": validated_data.get("collectAmountMgtFee"),
"collectAmountInsurance": validated_data.get("collectAmountInsurance"),
"collectAmountVAT": validated_data.get("collectAmountVAT"),
"countryId": validated_data.get("countryId"),
"responseCode": "00", # success code example
"responseMessage": "Loan Request Completed Successfully!",
"disburseVerify": datetime.datetime.now().isoformat(),
"verifyResult": "00",
"verifyDescription": "Collect Status retrieved successfully.",
"disburseDate": datetime.datetime.now().isoformat(),
"disburseResult": "00",
"disburseDescription": "Loan Request Completed Successfully!",
}
# Serialize response
response_schema = DisburseLoanResponseSchema()
result = response_schema.dump(response_data)
# return ResponseHelper.success(
# data=response_data,
# message="Disbursement completed successfully"
# )
return response_data
return jsonify(result), 200
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception"
}) , 422
"message": "Validation exception",
"errors": err.messages
}), 422
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return jsonify({
"message": "Internal Server Error"
}) , 500
}), 500
+89
View File
@@ -0,0 +1,89 @@
import datetime
from datetime import timedelta
from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.generate_token import GenerateTokenRequestSchema, GenerateTokenResponseSchema
from app.config import Config
from flask_jwt_extended import (
create_access_token,
)
class GenerateTokenService:
USERNAME = Config.BANK_CALL_BASIC_AUTH_USERNAME
PASSWORD = Config.BANK_CALL_BASIC_AUTH_PASSWORD
TYPE = Config.BANK_GRANT_TYPE
@staticmethod
def process_request(data):
"""
Process the GenerateToken request.
Args:
data (dict): The request JSON payload.
Returns:
tuple: (JSON response, status code)
"""
try:
logger.info("Processing GenerateToken request")
# Step 1: Validate input using schema
schema = GenerateTokenRequestSchema()
validated_data = schema.load(data)
logger.info(f"Validated data: {validated_data}")
username = validated_data.get("username")
password = validated_data.get("password")
grant_type = validated_data.get("grant_type")
if password != GenerateTokenService.PASSWORD or username != GenerateTokenService.USERNAME or grant_type != GenerateTokenService.TYPE:
return {
"message": "Invalid credentials",
"status": 401
}
expires_in = 1800
identity = username
# Step 2: Generate JWT token
access_token = create_access_token(identity=identity, expires_delta=timedelta(seconds=expires_in))
# Step 3: Get client IP address
ipaddress = request.remote_addr or "127.0.0.1"
# Step 4: Build response timestamps
issued_time = datetime.datetime.utcnow()
expires_time = issued_time + datetime.timedelta(seconds=expires_in)
# Step 5: Construct response payload
response_data = {
"access_token": access_token,
"token_type": "bearer",
"expires_in": expires_in,
"userName": username,
"ipaddress": ipaddress,
"errorMessage": "",
"issued": issued_time,
"expires": expires_time
}
# Serialize with response schema
response_schema = GenerateTokenResponseSchema()
response_json = response_schema.dump(response_data)
return jsonify(response_json), 200
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception",
"errors": err.messages
}), 422
except Exception as e:
logger.error(f"An error occurred while generating token: {str(e)}", exc_info=True)
return jsonify({
"message": "Internal Server Error"
}), 500
+27 -17
View File
@@ -2,7 +2,10 @@ from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.penal_charge import PenalChargeSchema
from app.api.schemas.penal_charge import (
PenalChargeSchema,
CollectPenalFeeResponseSchema,
)
class PenalChargeService:
@@ -22,30 +25,37 @@ class PenalChargeService:
# Validate input data using PenalChargeSchema
schema = PenalChargeSchema()
validated_data = schema.load(data) # Raises ValidationError if invalid
validated_data = schema.load(data)
customerId = validated_data["customerId"]
transactionId = validated_data["transactionId"]
penalCharge = validated_data["penalCharge"]
accountId = validated_data["accountId"]
lienAmount = validated_data["lienAmount"]
# Simulated processing logic
response_data = {
"resultCode": "00",
"resultDescription": "Penal charge debited successfully"
"responseCode": "00",
"responseMessage": "Penal Collection Successful",
"customerId": customerId,
"transactionId": transactionId,
"amountCollected": penalCharge,
"lienAmount": lienAmount,
"accountId": accountId,
}
# Optionally validate/serialize response using schema
response_schema = CollectPenalFeeResponseSchema()
result = response_schema.dump(response_data)
# return ResponseHelper.success(
# data=response_data,
# message="Penal charge applied successfully"
# )
return response_data
return result
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception"
}) , 422
return (
jsonify({"message": "Validation exception", "errors": err.messages}),
422,
)
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return jsonify({
"message": "Internal Server Error"
}) , 500
return jsonify({"message": "Internal Server Error"}), 500
+80 -29
View File
@@ -2,7 +2,9 @@ from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.rac_check import RACCheckSchema
from app.api.schemas.rac_check import RACCheckSchema, RACCheckResponseSchema
from datetime import datetime
from decimal import Decimal
class RACCheckService:
@staticmethod
@@ -14,50 +16,99 @@ class RACCheckService:
data (dict): The request data.
Returns:
dict: A standardized response.
tuple: JSON response and status code.
"""
try:
logger.info("Processing RACCheck request")
# Validate input data using RACCheckSchema
# Validate input data
schema = RACCheckSchema()
validated_data = schema.load(data) # Raises ValidationError if invalid
validated_data = schema.load(data)
# Simulated processing logic
response_data = {
"resultCode": "00",
"RACResponse": {
"SalaryAccount": "1",
"BVN": "1",
"BVNAttachedToAccount": "1",
"CRMS": "1",
"CRC": "1",
"AccountStatus": "1",
"Lien": "1",
"NoBouncedCheck": "1",
"Whitelist": "1",
"NoPastDueSalaryLoan": "1",
"NoPastDueOtherLoan": "1"
},
"resultDescription": "RAC Check Successful"
customer_id = validated_data["customerId"]
is_valid = True
try:
salary_count = int(str(customer_id)[-1]) + 1
if salary_count < 1 or salary_count > 6:
salary_count = 3
except ValueError:
salary_count = 3
salary_payments = {}
total_salary = 0
for i in range(1, salary_count + 1):
salary = (((salary_count + i) * 7919) % 200000 + 10000) * 5
salary_payments[f"salarypaymenT_{i}"] = salary
total_salary += salary
average_salary = total_salary // salary_count if salary_count > 0 else 0
rac_response = {
"procesS_DATE": datetime.strptime("2025-06-05", "%Y-%m-%d").date(),
"ciF_ID": "416405737",
"customeR_id": customer_id,
"salaccT_1": "4142904114",
"alerT_PHONE": "2348039301606",
"averagE_SALARY": average_salary,
"loaN_OUSTANDING_BAL": 0,
"emi": 1000,
"eliG_AMT": 25000,
"rule1_45day_sal": is_valid,
"rule2_2m_sal": is_valid,
"rule3_no_bounced_check": is_valid,
"rule4_current_loan_payments": True if is_valid is False else is_valid,
"rule5_no_past_due_fadv_loan": is_valid,
"rule6_no_past_due_other_loan": is_valid,
"rule7_consistent_salary_amount": is_valid,
"rule8_whitelisted": True if is_valid is False else is_valid,
"rule9_regular_account": True if is_valid is False else is_valid,
"rule10_bvn_validation": is_valid,
"rule11_CRC_no_delinquency": is_valid,
"rule12_CRMS_no_delinquency": True if is_valid is False else is_valid,
"rule13_BVN_ignore": is_valid,
"rule14_no_lien": is_valid,
"rule15_null_ignore": True if is_valid is False else is_valid,
"overalL_ELIG": is_valid
# "salarypaymenT_1": 180000,
# "salarypaymenT_2": 50000,
# "salarypaymenT_3": 70000,
# "salarypaymenT_4": 0,
# "salarypaymenT_5": 0,
# "salarypaymenT_6": 0
}
rac_response.update(salary_payments)
# return ResponseHelper.success(
# data=response_data,
# message="RAC check completed successfully"
# )
return response_data
full_response = {
"transactionId": validated_data["transactionId"],
"customerId": validated_data["customerId"],
"accountId": validated_data["accountId"],
"racResponse": rac_response
}
# response_schema = RACCheckResponseSchema()
result = {
"responseCode": "00",
"responseMessage": "Operation Successful",
"data": full_response
}
return jsonify(result), 200
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception"
}) , 422
"message": "Validation exception",
"errors": err.messages
}), 422
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return jsonify({
"message": "Internal Server Error"
}) , 500
}), 500
+19 -16
View File
@@ -2,7 +2,10 @@ from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.transaction_verify import TransactionVerifySchema
from app.api.schemas.transaction_verify import (
TransactionVerifySchema,
TransactionVerifyResponseSchema
)
class TransactionVerifyService:
@@ -26,32 +29,32 @@ class TransactionVerifyService:
# Simulated processing logic
response_data = {
"type": "TransactionCheckResponse",
"nativeId": "FBN20191031104405CN621868",
"customerId": "CN621868",
"accountId": "2017821799",
"responseCode": "00",
"responseDescr": "Success",
"responseMessage": "Verification Status retrieved Successfully.",
"customerId": validated_data.get("customerId"),
"accountId": validated_data.get("accountId"),
"providedAmount": 0.0,
"collectedAmount": 7.50,
"resultCode": "00",
"resultDescription": "Collect Status retrieved successfully."
"transactionId": validated_data.get("transactionId"),
"transactionType": validated_data.get("transactionType")
}
# Validate and serialize response with TransactionVerifyResponseSchema
response_schema = TransactionVerifyResponseSchema()
serialized_response = response_schema.dump(response_data)
# return ResponseHelper.success(
# data=response_data,
# message="Transaction verification completed successfully"
# )
return response_data
return jsonify(serialized_response), 200
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception"
}) , 422
"message": "Validation exception",
"errors": err.messages
}), 422
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return jsonify({
"message": "Internal Server Error"
}) , 500
}), 500
@@ -0,0 +1,50 @@
from app.api.schemas.verify_account_balance import VerifyAccountBalanceSchema
from flask import request, jsonify
from marshmallow import ValidationError
from app.utils.logger import logger
from app.api.helpers.response_helper import ResponseHelper
class VerifyAccountBalanceService:
@staticmethod
def process_request(data):
"""
Process the RACCheck request.
Args:
data (dict): The request data.
Returns:
tuple: JSON response and status code.
"""
try:
logger.info("Processing VerifyBalance request")
# Validate input data
schema = VerifyAccountBalanceSchema()
validated_data = schema.load(data)
account_id = validated_data["accountId"]
request_id = validated_data["requestId"]
amount = validated_data["amount"]
result = {
"responseCode": "00",
"responseMessage": "Operation Successful",
"isSufficient": True
}
return jsonify(result), 200
except ValidationError as err:
logger.error(f"Validation Error: {err.messages}")
return jsonify({
"message": "Validation exception",
"errors": err.messages
}), 422
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return jsonify({
"message": "Internal Server Error"
}), 500
+15 -3
View File
@@ -1,17 +1,29 @@
import os
from re import M
from dotenv import load_dotenv
from datetime import timedelta
class Config:
"""Base configuration for Flask app"""
SWAGGER_URL = os.getenv("SWAGGER_URL", "/documentation")
API_URL = os.getenv("API_URL", "/swagger.json")
load_dotenv()
SWAGGER_URL = os.getenv("SWAGGER_URL")
API_URL = '/api/swagger.json'
DEBUG = True
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "753fc155-6a63-4314-bd97-ae91d61dbafe")
JWT_ACCESS_TOKEN_EXPIRES = timedelta(seconds=int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES", 1800)))
VALID_APP_ID = os.getenv("VALID_APP_ID", "app1")
VALID_API_KEY = os.getenv("VALID_API_KEY", "test-api-key-12345")
MIN_AMOUNT_FOR_COLLECTION = int(os.getenv("MIN_AMOUNT_FOR_COLLECTION", 10000))
MAX_AMOUNT_FOR_COLLECTION = int(os.getenv("MAX_AMOUNT_FOR_COLLECTION", 25000))
BANK_CALL_BASIC_AUTH_USERNAME = os.environ.get("BANK_CALL_BASIC_AUTH_USERNAME", "simbrella")
BANK_CALL_BASIC_AUTH_PASSWORD = os.environ.get("BANK_CALL_BASIC_AUTH_PASSWORD", "G7$k9@pL2!qR")
BANK_GRANT_TYPE = os.getenv("BANK_GRANT_TYPE", "password")
# SQLALCHEMY_DATABASE_URI =os.environ.get("DATABASE_URL", "database_url")
# SQLALCHEMY_TRACK_MODIFICATIONS = False
# SECRET_KEY = os.environ.get("SECRET_KEY", "your_secret_key")
DEBUG = True
def configure():
load_dotenv()
+74 -39
View File
@@ -16,6 +16,9 @@
"servers": [
{
"url": "http://localhost:6337"
},
{
"url": "http://localhost:5000"
},
{
"url": "http://10.10.11.17:6337"
@@ -25,6 +28,15 @@
}
],
"tags": [
{
"name": "Auth",
"description": "Get access token for verification",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
},
{
"name": "RACCheck",
"description": "Risk Acceptance Criteria Request",
@@ -33,6 +45,14 @@
"url": "https://www.simbrellang.net"
}
},
{
"name": "VerifyAccountBalance",
"description": "Verify Account Balance Request",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
},
{
"name": "CompleteRACcheck",
"description": "Complete Risk Acceptance Criteria Request",
@@ -107,45 +127,66 @@
}
],
"paths": {
"/RACCheck": {
"$ref": "./paths/RACCheck.json"
"/api/Auth/generate-token": {
"$ref": "swagger/paths/GenerateToken.json"
},
"/CompleteRACcheck": {
"$ref": "./paths/CompleteRACcheck.json"
"/api/system-health-check": {
"$ref": "swagger/paths/HealthCheck.json"
},
"/Disbursement": {
"$ref": "./paths/Disbursement.json"
"/api/rac-check": {
"$ref": "swagger/paths/RACCheck.json"
},
"/CollectLoan": {
"$ref": "./paths/CollectLoan.json"
"/api/VerifyAccountBalance": {
"$ref": "swagger/paths/VerifyAccountBalance.json"
},
"/TransactionVerify": {
"$ref": "./paths/TransactionVerify.json"
"/api/CompleteRACcheck": {
"$ref": "swagger/paths/CompleteRACcheck.json"
},
"/PenalCharge": {
"$ref": "./paths/PenalCharge.json"
"/api/DisburseLoan": {
"$ref": "swagger/paths/Disbursement.json"
},
"/RevokeEnableConsent": {
"$ref": "./paths/RevokeEnableConsent.json"
"/api/CollectLoan": {
"$ref": "swagger/paths/CollectLoan.json"
},
"/TokenValidation": {
"$ref": "./paths/TokenValidation.json"
"/api/TransactionVerify": {
"$ref": "swagger/paths/TransactionVerify.json"
},
"/LienCheck": {
"$ref": "./paths/LienCheck.json"
"/api/CollectPenalCharge": {
"$ref": "swagger/paths/PenalCharge.json"
},
"/NewTransactionCheck": {
"$ref": "./paths/NewTransactionCheck.json"
"/api/RevokeEnableConsent": {
"$ref": "swagger/paths/RevokeEnableConsent.json"
},
"/api/TokenValidation": {
"$ref": "swagger/paths/TokenValidation.json"
},
"/api/LienCheck": {
"$ref": "swagger/paths/LienCheck.json"
},
"/api/NewTransactionCheck": {
"$ref": "swagger/paths/NewTransactionCheck.json"
}
},
"components": {
"schemas": {
"GenerateTokenRequest": {
"$ref": "./schemas/GenerateTokenRequest.json"
},
"GenerateTokenResponse": {
"$ref": "./schemas/GenerateTokenResponse.json"
},
"RACCheckRequest": {
"$ref": "./schemas/RACCheckRequest.json"
},
"RACCheckResponse": {
"$ref": "./schemas/RACCheckResponse.json"
},
"VerifyAccountBalanceRequest": {
"$ref": "./schemas/VerifyAccountBalanceRequest.json"
},
"VerifyAccountBalanceResponse": {
"$ref": "./schemas/VerifyAccountBalanceResponse.json"
},
"CompleteRACcheckRequest": {
"$ref": "./schemas/CompleteRACcheckRequest.json"
},
@@ -211,24 +252,18 @@
}
},
"securitySchemes": {
"api_key": {
"type": "apiKey",
"name": "x-api-key",
"in": "header"
},
"app_id": {
"type": "apiKey",
"name": "App-Id",
"in": "header"
}
}
"BearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
"description": "Standard Authorization header using the Bearer scheme. Example: 'Bearer {token}'"
}
}
},
"security": [
{
"api_key": []
},
{
"app_id": []
}
]
"security": [
{
"BearerAuth": []
}
]
}
+2 -6
View File
@@ -50,11 +50,7 @@
"500": {
"description": "Internal server error"
}
},
"security": [
{
"basic_auth": []
}
]
}
}
}
+56
View File
@@ -0,0 +1,56 @@
{
"post": {
"tags": [
"GenerateToken"
],
"summary": "Generate Access Token Request",
"description": "Generate Access Token Request",
"operationId": "GenerateToken",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../schemas/GenerateTokenRequest.json"
}
},
"application/xml": {
"schema": {
"$ref": "../schemas/GenerateTokenRequest.json"
}
},
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "../schemas/GenerateTokenRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "GenerateToken Successful",
"content": {
"application/json": {
"schema": {
"$ref": "../schemas/GenerateTokenResponse.json"
}
},
"application/xml": {
"schema": {
"$ref": "../schemas/GenerateTokenResponse.json"
}
}
}
},
"400": {
"description": "Invalid request"
},
"422": {
"description": "Validation exception"
},
"500": {
"description": "Internal server error"
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"get": {
"tags": ["System"],
"summary": "System Health Check",
"description": "Returns the current health status of the system",
"responses": {
"200": {
"description": "Successful operation",
"content": {
"application/json": {
"schema": {
"$ref": "../schemas/HealthCheckResponse.json"
}
}
}
}
}
}
}
@@ -0,0 +1,56 @@
{
"post": {
"tags": [
"VerifyAccountBalance"
],
"summary": "Risk Acceptance Criteria Check",
"description": "Check if a customer passes the Risk Acceptance Criteria defined by the bank",
"operationId": "verifyAccountBalance",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../schemas/VerifyAccountBalanceRequest.json"
}
},
"application/xml": {
"schema": {
"$ref": "../schemas/VerifyAccountBalanceRequest.json"
}
},
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "../schemas/VerifyAccountBalanceRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "Verify Account Balance Successful",
"content": {
"application/json": {
"schema": {
"$ref": "../schemas/VerifyAccountBalanceResponse.json"
}
},
"application/xml": {
"schema": {
"$ref": "../schemas/VerifyAccountBalanceResponse.json"
}
}
}
},
"400": {
"description": "Invalid request"
},
"422": {
"description": "Validation exception"
},
"500": {
"description": "Internal server error"
}
}
}
}
+65 -68
View File
@@ -1,70 +1,67 @@
{
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T002"
},
"fbnTransactionId": {
"type": "string",
"example": "FBN20231123"
},
"debtId": {
"type": "string",
"example": "273194670"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"productId": {
"type": "string",
"example": "101"
},
"collectAmount": {
"type": "number",
"format": "double",
"example": 80000.0
},
"penalCharge": {
"type": "number",
"format": "double",
"example": 0.0
},
"collectionMethod": {
"type": "integer",
"example": 1
},
"lienAmount": {
"type": "number",
"format": "double",
"example": 80000.0
},
"countryId": {
"type": "string",
"example": "01"
},
"comment": {
"type": "string",
"example": "Testing CollectionLoanRequest"
}
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T002"
},
"required": [
"transactionId",
"fbnTransactionId",
"debtId",
"customerId",
"accountId",
"productId",
"collectAmount",
"penalCharge",
"collectionMethod",
"lienAmount",
"countryId",
"comment"
]
}
"fbnTransactionId": {
"type": "string",
"example": "FBN20231123"
},
"debtId": {
"type": "string",
"example": "273194670"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"productId": {
"type": "string",
"example": "101"
},
"collectAmount": {
"type": "number",
"format": "double",
"example": 80000.0
},
"penalCharge": {
"type": "number",
"format": "double",
"example": 0.0
},
"collectionMethod": {
"type": "string",
"example": "string"
},
"lienAmount": {
"type": "number",
"format": "double",
"example": 80000.0
},
"countryId": {
"type": "string",
"example": "01"
},
"comment": {
"type": "string",
"example": "Testing CollectionLoanRequest"
},
"channel": {
"type": "string",
"example": "string"
}
},
"required": [
"collectAmount",
"penalCharge",
"lienAmount"
],
"additionalProperties": false
}
+67 -68
View File
@@ -1,70 +1,69 @@
{
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T002"
},
"debtId": {
"type": "string",
"example": "273194670"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"productId": {
"type": "string",
"example": "101"
},
"collectAmount": {
"type": "number",
"format": "double",
"example": 60000.0
},
"penalCharge": {
"type": "number",
"format": "double",
"example": 0.0
},
"lienAmount": {
"type": "number",
"format": "double",
"example": 20000.0
},
"countryId": {
"type": "string",
"example": "01"
},
"comment": {
"type": "string",
"example": "Testing CollectionLoanRequest"
},
"resultCode": {
"type": "string",
"example": "00"
},
"resultDescription": {
"type": "string",
"example": "Loan Collection Successful"
}
"type": "object",
"properties": {
"responseCode": {
"type": "string",
"nullable": true,
"example": "00"
},
"required": [
"transactionId",
"debtId",
"customerId",
"accountId",
"productId",
"collectAmount",
"penalCharge",
"lienAmount",
"countryId",
"comment",
"resultCode",
"resultDescription"
]
}
"responseDescr": {
"type": "string",
"nullable": true,
"example": "Success"
},
"fullDescription": {
"type": "string",
"nullable": true,
"example": "Loan Collection Successful"
},
"transactionId": {
"type": "string",
"nullable": true,
"example": "T002"
},
"debtId": {
"type": "string",
"nullable": true,
"example": "273194670"
},
"customerId": {
"type": "string",
"nullable": true,
"example": "CN621868"
},
"accountId": {
"type": "string",
"nullable": true,
"example": "2017821799"
},
"productId": {
"type": "string",
"nullable": true,
"example": "101"
},
"amountCollected": {
"type": "number",
"format": "double",
"example": 60000.0
},
"countryId": {
"type": "string",
"nullable": true,
"example": "01"
},
"comment": {
"type": "string",
"nullable": true,
"example": "Testing CollectionLoanRequest"
},
"responseMessage": {
"type": "string",
"nullable": true,
"example": "Loan processed successfully"
}
},
"required": [
"amountCollected"
],
"additionalProperties": false
}
+76 -75
View File
@@ -1,77 +1,78 @@
{
"type": "object",
"properties": {
"requestId": {
"type": "string",
"example": "7876786"
},
"transactionId": {
"type": "string",
"example": "T001"
},
"debtId": {
"type": "string",
"example": "273194670"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"productId": {
"type": "string",
"example": "101"
},
"provideAmount": {
"type": "number",
"format": "double",
"example": 100000.0
},
"collectAmountInterest": {
"type": "number",
"format": "double",
"example": 5000.0
},
"collectAmountMgtFee": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountInsurance": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountVAT": {
"type": "number",
"format": "double",
"example": 75.0
},
"countryId": {
"type": "string",
"example": "01"
},
"comment": {
"type": "string",
"example": "Testing LoanRequest"
}
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T001",
"nullable": true
},
"required": [
"requestId",
"transactionId",
"debtId",
"customerId",
"accountId",
"productId",
"provideAmount",
"collectAmountInterest",
"collectAmountMgtFee",
"collectAmountInsurance",
"collectAmountVAT",
"countryId",
"comment"
]
}
"fbnTransactionId": {
"type": "string",
"example": "Tr201712RK9232P115",
"nullable": true
},
"debtId": {
"type": "string",
"example": "273194670",
"nullable": true
},
"customerId": {
"type": "string",
"example": "CN621868",
"nullable": true
},
"accountId": {
"type": "string",
"example": "2017821799",
"nullable": true
},
"productId": {
"type": "string",
"example": "101",
"nullable": true
},
"provideAmount": {
"type": "number",
"format": "double",
"example": 100000.0
},
"collectAmountInterest": {
"type": "number",
"format": "double",
"example": 5000.0
},
"collectAmountMgtFee": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountInsurance": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountVAT": {
"type": "number",
"format": "double",
"example": 75.0
},
"countryId": {
"type": "string",
"example": "01",
"nullable": true
},
"comment": {
"type": "string",
"example": "Testing LoanRequest",
"nullable": true
}
},
"required": [
"provideAmount",
"collectAmountInterest",
"collectAmountMgtFee",
"collectAmountInsurance",
"collectAmountVAT"
],
"additionalProperties": false
}
+112 -80
View File
@@ -1,82 +1,114 @@
{
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T001"
},
"TransactionId": {
"type": "string",
"example": "Tr201712RK9232P115"
},
"debtId": {
"type": "string",
"example": "273194670"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"productId": {
"type": "string",
"example": "101"
},
"provideAmount": {
"type": "number",
"format": "double",
"example": 100000.0
},
"collectAmountInterest": {
"type": "number",
"format": "double",
"example": 5000.0
},
"collectAmountMgtFee": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountInsurance": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountVAT": {
"type": "number",
"format": "double",
"example": 75.0
},
"countryId": {
"type": "string",
"example": "01"
},
"resultCode": {
"type": "string",
"example": "00"
},
"resultDescription": {
"type": "string",
"example": "Loan Request Completed Successfully!"
}
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T001",
"nullable": true
},
"required": [
"transactionId",
"TransactionId",
"debtId",
"customerId",
"accountId",
"productId",
"provideAmount",
"collectAmountInterest",
"collectAmountMgtFee",
"collectAmountInsurance",
"collectAmountVAT",
"countryId",
"resultCode",
"resultDescription"
]
}
"fbnTransactionId": {
"type": "string",
"example": "Tr201712RK9232P115",
"nullable": true
},
"debtId": {
"type": "string",
"example": "273194670",
"nullable": true
},
"customerId": {
"type": "string",
"example": "CN621868",
"nullable": true
},
"accountId": {
"type": "string",
"example": "2017821799",
"nullable": true
},
"productId": {
"type": "string",
"example": "101",
"nullable": true
},
"provideAmount": {
"type": "number",
"format": "double",
"example": 100000.0
},
"collectAmountInterest": {
"type": "number",
"format": "double",
"example": 5000.0
},
"collectAmountMgtFee": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountInsurance": {
"type": "number",
"format": "double",
"example": 1000.0
},
"collectAmountVAT": {
"type": "number",
"format": "double",
"example": 75.0
},
"countryId": {
"type": "string",
"example": "01",
"nullable": true
},
"responseCode": {
"type": "string",
"example": "00",
"nullable": true
},
"responseMessage": {
"type": "string",
"example": "Loan Request Completed Successfully!",
"nullable": true
},
"disburseDate": {
"type": "string",
"format": "date-time",
"example": "2023-10-01T12:00:00Z",
"nullable": true
},
"disburseResult": {
"type": "string",
"example": "00",
"nullable": true
},
"disburseDescription": {
"type": "string",
"example": "Loan Request Completed Successfully!",
"nullable": true
},
"disburseVerify": {
"type": "string",
"format": "date-time",
"example": "2023-10-01T12:00:00Z",
"nullable": true
},
"verifyResult": {
"type": "string",
"example": "00",
"nullable": true
},
"verifyDescription": {
"type": "string",
"example": "Collect Status retrieved successfully.",
"nullable": true
}
},
"required": [
"provideAmount",
"collectAmountInterest",
"collectAmountMgtFee",
"collectAmountInsurance",
"collectAmountVAT"
]
}
@@ -0,0 +1,21 @@
{
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"grant_type":{
"type":"string"
}
},
"required": [
"username",
"password",
"grant_type"
]
}
@@ -0,0 +1,41 @@
{
"type": "object",
"properties": {
"access_token": {
"type": "string",
"format": "eyjhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwic3ViIjoiYWRtaW4ifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
},
"token_type": {
"type": "string",
"format": "bearer"
},
"expires_in": {
"type": "integer",
"format": "1800"
},
"userName": {
"type": "string",
"format": "sinbrella"
},
"ipaddress": {
"type": "string",
"format": "127.0.0.1"
},
"errorMessage":{
"type":"string"
},
"issued": {
"type": "string",
"format":"date-time"
},
"expires": {
"type": "string",
"format": "date-time"
}
},
"xml": {
"name": "##default"
}
}
@@ -0,0 +1,17 @@
{
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "Active"
},
"responseCode": {
"type": "string",
"example": "00"
},
"responseMessage": {
"type": "string",
"example": "Successful"
}
}
}
@@ -0,0 +1,17 @@
{
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "Active"
},
"responseCode": {
"type": "string",
"example": "00"
},
"responseMessage": {
"type": "string",
"example": "Successful"
}
}
}
+57 -39
View File
@@ -1,41 +1,59 @@
{
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T004"
},
"fbnTransactionId": {
"type": "string",
"example": "Tr201712RK9232P115"
},
"debtId": {
"type": "string",
"example": "273194670"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"penalCharge": {
"type": "number",
"example": 1.2
},
"lienAmount": {
"type": "number",
"example": 101.2
},
"countryId": {
"type": "string",
"example": "01"
},
"comment": {
"type": "string",
"example": "Testing PenalChargeRequest"
}
"type": "object",
"properties": {
"channel": {
"type": "string",
"nullable": true
},
"transactionId": {
"type": "string",
"nullable": true,
"example": "T004"
},
"fbnTransactionId": {
"type": "string",
"nullable": true,
"example": "Tr201712RK9232P115"
},
"debtId": {
"type": "string",
"nullable": true,
"example": "273194670"
},
"customerId": {
"type": "string",
"nullable": true,
"example": "CN621868"
},
"accountId": {
"type": "string",
"nullable": true,
"example": "2017821799"
},
"penalCharge": {
"type": "number",
"format": "double",
"example": 1.2
},
"lienAmount": {
"type": "number",
"format": "double",
"example": 101.2
},
"countryId": {
"type": "string",
"nullable": true,
"example": "01"
},
"comment": {
"type": "string",
"nullable": true,
"example": "Testing PenalChargeRequest"
}
}
},
"required": [
"penalCharge",
"lienAmount"
],
"additionalProperties": false
}
+40 -10
View File
@@ -1,13 +1,43 @@
{
"type": "object",
"properties": {
"resultCode": {
"type": "string",
"example": "00"
},
"resultDescription": {
"type": "string",
"example": "Penal charge debited successfully"
}
"type": "object",
"properties": {
"customerId": {
"type": "string",
"nullable": true,
"example": "CN621868"
},
"transactionId": {
"type": "string",
"nullable": true,
"example": "T004"
},
"amountCollected": {
"type": "number",
"format": "double",
"example": 101.2
},
"lienAmount": {
"type": "integer",
"example": 1000
},
"accountId": {
"type": "string",
"nullable": true,
"example": "2017821799"
},
"responseCode": {
"type": "string",
"nullable": true,
"example": "00"
},
"responseMessage": {
"type": "string",
"nullable": true,
"example": "Penal charge debited successfully"
}
},
"required": [
"amountCollected"
],
"additionalProperties": false
}
+37 -88
View File
@@ -1,91 +1,40 @@
{
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T001"
},
"fbnTransactionId": {
"type": "string",
"example": "Tr201712RK9232P115"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"RAC_Array": {
"type": "array",
"items": {
"type": "object",
"properties": {
"salaryAccount": {
"type": "boolean",
"example": true
},
"bvn": {
"type": "string",
"example": "12345678901"
},
"crc": {
"type": "boolean",
"example": false
},
"crms": {
"type": "boolean",
"example": true
},
"accountStatus": {
"type": "string",
"example": "active"
},
"lien": {
"type": "boolean",
"example": false
},
"noBouncedCheck": {
"type": "boolean",
"example": true
},
"existingLoan": {
"type": "boolean",
"example": false
},
"whitelist": {
"type": "boolean",
"example": true
},
"noPastDueSalaryLoan": {
"type": "boolean",
"example": true
},
"noPastDueOtherLoans": {
"type": "boolean",
"example": false
}
}
},
"example": [
{
"salaryAccount": true,
"bvn": "12345678901",
"crc": false,
"crms": true,
"accountStatus": "active",
"lien": false,
"noBouncedCheck": true,
"existingLoan": false,
"whitelist": true,
"noPastDueSalaryLoan": true,
"noPastDueOtherLoans": false
}
]
}
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T001"
},
"xml": {
"name": "RACCheckRequest"
"fbnTransactionId": {
"type": "string",
"example": "Tr201712RK9232P115"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"channel": {
"type": "string",
"example": "USSD"
},
"countryCode": {
"type": "string",
"example": "NG"
}
}
},
"required": [
"transactionId",
"fbnTransactionId",
"customerId",
"accountId",
"channel",
"countryCode"
],
"xml": {
"name": "RACCheckRequest"
}
}
+91 -62
View File
@@ -1,65 +1,94 @@
{
"type": "object",
"properties": {
"resultCode": {
"type": "string",
"example": "00"
},
"RACResponse": {
"type": "object",
"properties": {
"Salary account": {
"type": "string",
"example": "1"
},
"BVN": {
"type": "string",
"example": "1"
},
"BVNAttachedtoAccount": {
"type": "string",
"example": "1"
},
"CRMS": {
"type": "string",
"example": "1"
},
"CRC": {
"type": "string",
"example": "1"
},
"AccountStatus": {
"type": "string",
"example": "1"
},
"Lien": {
"type": "string",
"example": "1"
},
"NoBouncedCheck": {
"type": "string",
"example": "1"
},
"Whitelist": {
"type": "string",
"example": "1"
},
"NoPastDueSalaryLoan": {
"type": "string",
"example": "1"
},
"NoPastDueOtherLoan": {
"type": "string",
"example": "1"
}
}
},
"resultDescription": {
"type": "string",
"example": "RAC Check Successful"
}
"type": "object",
"properties": {
"transactionId": {
"type": "string",
"example": "T001"
},
"xml": {
"name": "RACCheckResponse"
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"racResponse": {
"type": "object",
"properties": {
"PROCESS_DATE": {
"type": "string",
"format": "date",
"example": "2025-06-05"
},
"CIF_ID": {
"type": "string",
"example": "123456789"
},
"CUSTOMER_id": {
"type": "string",
"example": "987654321"
},
"SALACCT_1": {
"type": "string",
"example": "34567831"
},
"ALERT_PHONE": {
"type": "string",
"example": "2348031234567"
},
"AVERAGE_SALARY": {
"type": "number",
"format": "decimal",
"example": 50000
},
"LOAN_OUSTANDING_BAL": {
"type": "number",
"format": "decimal",
"example": 0
},
"EMI": {
"type": "number",
"format": "decimal",
"example": 10000
},
"ELIG_AMT": {
"type": "number",
"format": "decimal",
"example": 25000
},
"rule1-45day-sal": { "type": "boolean", "example": true },
"rule2-2m-sal": { "type": "boolean", "example": true },
"rule3-no-bounced-check": { "type": "boolean", "example": true },
"rule4-current-loan-payments": { "type": "boolean", "example": true },
"rule5-no-past-due-fadv-loan": { "type": "boolean", "example": true },
"rule6--no-past-due-other-loan": { "type": "boolean", "example": true },
"rule7-consistent-salary-amount": { "type": "boolean", "example": true },
"rule8-whitelisted": { "type": "boolean", "example": true },
"rule9-regular-account": { "type": "boolean", "example": true },
"rule10-bvn-validation": { "type": "boolean", "example": true },
"rule11-CRC-no-delinquency": { "type": "boolean", "example": true },
"rule12-CRMS-no-delinquency": { "type": "boolean", "example": true },
"rule13-BVN-ignore": { "type": "boolean", "example": true },
"rule14-no-lien": { "type": "boolean", "example": true },
"rule15-null-ignore": { "type": "boolean", "example": true },
"OVERALL_ELIG": { "type": "boolean", "example": true },
"SALARYPAYMENT_1": { "type": "number", "format": "decimal", "example": 50000 },
"SALARYPAYMENT_2": { "type": "number", "format": "decimal", "example": 50000 },
"SALARYPAYMENT_3": { "type": "number", "format": "decimal", "example": 50000 },
"SALARYPAYMENT_4": { "type": "number", "format": "decimal", "example": 50000 },
"SALARYPAYMENT_5": { "type": "number", "format": "decimal", "example": 50000 },
"SALARYPAYMENT_6": { "type": "number", "format": "decimal", "example": 50000 }
}
}
}
},
"required": [
"transactionId",
"customerId",
"accountId",
"racResponse"
],
"xml": {
"name": "RACCheckResponse"
}
}
@@ -1,33 +1,34 @@
{
"type": "object",
"properties": {
"counter": {
"type": "string",
"example": "2"
},
"transactionId": {
"type": "string",
"example": "T002"
},
"requestID": {
"type": "string",
"example": "R02802"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"countryId": {
"type": "string",
"example": "01"
},
"transactionType": {
"type": "string",
"example": "Disbursement"
}
"type": "object",
"properties": {
"channel": {
"type": "string",
"example": "MOBILE"
},
"transactionId": {
"type": "string",
"example": "T002"
},
"requestId": {
"type": "string",
"example": "R02802"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"countryId": {
"type": "string",
"example": "01"
},
"transactionType": {
"type": "string",
"example": "Disbursement"
}
}
},
"additionalProperties": false
}
@@ -1,37 +1,48 @@
{
"type": "object",
"properties": {
"$type": {
"type": "string",
"example": "TransactionCheckResponse"
},
"nativeId": {
"type": "string",
"example": "FBN20191031104405CN621868"
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"providedAmount": {
"type": "number",
"example": 0.0
},
"collectedAmount": {
"type": "number",
"example": 7.50
},
"resultCode": {
"type": "string",
"example": "00"
},
"resultDescription": {
"type": "string",
"example": "Collect Status retrieved successfully."
}
"type": "object",
"properties": {
"responseCode": {
"type": "string",
"example": "00"
},
"responseDescr": {
"type": "string",
"example": "Collect Status retrieved successfully."
},
"fullDescription": {
"type": "string",
"example": "Disbursement was verified and collection completed."
},
"customerId": {
"type": "string",
"example": "CN621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
},
"providedAmount": {
"type": "number",
"format": "double",
"example": 0.0
},
"collectedAmount": {
"type": "number",
"format": "double",
"example": 7.50
},
"transactionId": {
"type": "string",
"example": "T002"
},
"transactionType": {
"type": "string",
"example": "Disbursement"
}
}
},
"required": [
"providedAmount",
"collectedAmount"
],
"additionalProperties": false
}
@@ -0,0 +1,25 @@
{
"type": "object",
"properties": {
"amount": {
"type": "string",
"example": "200"
},
"requestId": {
"type": "string",
"example": "RQ621868"
},
"accountId": {
"type": "string",
"example": "2017821799"
}
},
"required": [
"accountId",
"requestId",
"amount"
],
"xml": {
"name": "VerifyAccountBalanceRequest"
}
}
@@ -0,0 +1,15 @@
{
"type": "object",
"properties": {
"isSufficient": {
"type": "string",
"example": "true"
}
},
"required": [
"isSufficient"
],
"xml": {
"name": "VerifyAccountBalanceResponse"
}
}
+3 -3
View File
@@ -5,11 +5,11 @@ marshmallow==3.19.0
Flask-Cors==3.0.10
gunicorn
flask-swagger-ui
python-dotenv
flask-jwt-extended==4.7.1
# Logging (Python Standard Library, for reference)
# Logging (Python Standard Library, for reference)