31 Commits

Author SHA1 Message Date
VivianDee 33ee8a286b [fix]: request schems 2025-07-30 05:24:02 +01:00
VivianDee 038c5323b0 [add]: eco endpoints and dummy responses 2025-07-30 05:16:47 +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
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
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
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
76 changed files with 4332 additions and 836 deletions
Vendored
BIN
View File
Binary file not shown.
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": {}
}
+6 -3
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`.
@@ -55,7 +55,8 @@ This command will build the Docker image and start the Flask application in a co
You can check if the Flask application is running by accessing the `/health` endpoint. To perform a health check, run the following command:
```bash
curl http://localhost:6337/health
curl http://localhost:6337/api/health
curl http://localhost:6337/eco/health
```
If the application is running properly, you should receive a response similar to this:
@@ -71,7 +72,9 @@ If the application is running properly, you should receive a response similar to
You can check the Swagger Doc by accessing the `/documentation` endpoint. Run the following command:
```bash
curl http://localhost:6337/documentation
curl http://localhost:6337/api/documentation
curl http://localhost:6337/eco/documentation
```
+29 -11
View File
@@ -1,10 +1,18 @@
from re import S
from flask import Flask
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.eco.routes import eco
from app.errors import register_error_handlers
from flask_jwt_extended import (
JWTManager,
jwt_required,
create_access_token,
get_jwt_identity,
)
def create_app():
""" Factory function to create a Flask app instance """
@@ -13,25 +21,35 @@ def create_app():
# Load configuration
app.config.from_object(Config)
CORS(app)
CORS(app)
JWTManager(app)
CORS(app, supports_credentials=True)
# 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")
app.register_blueprint(eco, url_prefix="/eco")
# Swagger UI Blueprint
api_docs = "/api" + SWAGGER_URL
api_url = "/api" + API_URL
swagger_ui_api = get_swaggerui_blueprint(api_docs, api_url)
swagger_ui_api.name = 'swagger_ui_api' # Rename blueprint
app.register_blueprint(swagger_ui_api, url_prefix=api_docs)
# Second UI (ECO)
eco_docs = "/eco" + SWAGGER_URL
eco_api = "/eco" + API_URL
swagger_ui_eco = get_swaggerui_blueprint(eco_docs, eco_api)
swagger_ui_eco.name = 'swagger_ui_eco' # Rename blueprint
app.register_blueprint(swagger_ui_eco, url_prefix=eco_docs)
swagger_ui_blueprint = get_swaggerui_blueprint(SWAGGER_URL, API_URL)
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)
# Error Handlers
register_error_handlers(app)
return app
+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.")
+82 -31
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,11 +11,13 @@ from app.api.services import (
TokenValidationService,
LienCheckService,
NewTransactionCheckService,
CompleteRACcheckService
)
from app.utils.logger import logger
from app.api.middlewares import require_api_key, require_app_id, enforce_json
api = Blueprint("api", __name__)
@@ -40,65 +42,87 @@ def serve_paths(filename):
return send_from_directory(swagger_dir, filename)
# RACCheck Endpoint
@api.route('/RACCheck', methods=['POST'])
@api.route('/rac-check', methods=['POST'])
@require_api_key
@require_app_id
def rac_check():
data = request.get_json()
# logger.info(f"RACCheck request received: {data}")
response = RACCheckService.process_request(data)
return response
try:
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
# CompleteRACcheck Endpoint
@api.route('/CompleteRACcheck', methods=['POST'])
@require_api_key
@require_app_id
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'])
@api.route('/DisburseLoan', methods=['POST'])
@require_api_key
@require_app_id
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
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
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'])
@api.route('/CollectPenalFee', methods=['POST'])
@require_api_key
@require_app_id
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()
# logger.info(f"PenalCharge request received: {data}")
response = PenalChargeService.process_request(data)
return response
except Exception as e:
logger.exception("Unhandled exception in /PenalCharge route")
return jsonify({"message": "Unhandled server error"}), 500
# RevokeEnableConsent Endpoint
@api.route('/RevokeEnableConsent', methods=['POST'])
@@ -140,7 +164,34 @@ def new_transaction_check():
response = NewTransactionCheckService.process_request(data)
return response
# Health Check Endpoint
@api.route('/health', methods=['GET'])
@api.route('/system-health-check', methods=['GET'])
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
+27 -13
View File
@@ -1,16 +1,30 @@
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)
lienAmount = fields.Float(required=True)
countryId = fields.Str(required=True)
comment = fields.Str(required=False) # Optional
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):
responseCode = fields.Str(allow_none=True)
responseDescr = fields.Str(allow_none=True)
fullDescription = fields.Str(allow_none=True)
transactionId = 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)
countryId = fields.Str(allow_none=True)
comment = fields.Str(allow_none=True)
responseMessage = 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)
disburseMessage = 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)
+22 -11
View File
@@ -1,14 +1,25 @@
from marshmallow import Schema, fields
# Penal Charge Schema
# This file contains the schema for penal charge operations
class PenalChargeSchema(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)
penalCharge = fields.Decimal(required=True)
lienAmount = fields.Decimal(required=True)
countryId = fields.Str(required=True)
comment = fields.Str(required=False)
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)
penalCharge = fields.Float(required=True)
customerId = fields.Str(allow_none=True)
lienAmount = fields.Float(required=True)
comment = fields.Str(allow_none=True)
countryId = fields.Str(allow_none=True)
#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)
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)
+22 -9
View File
@@ -1,12 +1,25 @@
from marshmallow import Schema, fields
# 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)
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)
class TransactionVerifyResponseSchema(Schema):
responseCode = fields.Str(allow_none=True)
responseDescr = fields.Str(allow_none=True)
fullDescription = 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)
disburseVerify = fields.Str(allow_none=True)
verifyDescription = fields.Str(allow_none=True)
verifyResult = fields.Str(allow_none=True)
+1 -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,4 @@ 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
+59 -30
View File
@@ -2,20 +2,20 @@ 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
"""
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 +23,66 @@ class CollectLoanService:
schema = CollectLoanSchema()
validated_data = schema.load(data)
amountForCollection = validated_data.get("collectAmount")
amountCollected = amountForCollection
responseDescr= "Loan Collection Successful EMULATOR"
fullDescription= "Loan collection completed successfully EMULATOR"
responseMessage= "Loan collection completed successfully EMULATOR"
if amountForCollection in [5555.0, 6666.0, 7777.0, 8888.0 , 9999.0, 22222.0] :
amountCollected = amountForCollection * 0.85
responseDescr = "Partial Loan Collection Successful EMULATOR"
fullDescription = "Partial Loan collection completed successfully EMULATOR"
responseMessage = "Partial Loan collection completed successfully EMULATOR"
# 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"
"transactionId": validated_data.get("transactionId"),
"debtId": validated_data.get("debtId"),
"customerId": validated_data.get("customerId"),
"accountId": validated_data.get("accountId"),
"productId": validated_data.get("productId"),
"amountCollected": amountCollected,
"countryId": validated_data.get("countryId"),
"comment": validated_data.get("comment", "Testing CollectionLoanRequest EMULATOR"),
"responseCode": "00",
"responseDescr": responseDescr,
"fullDescription": fullDescription,
"responseMessage": responseMessage
}
# # Simulated processing logic
# response_data = {
# "transactionId": validated_data.get("transactionId", "T002"),
# "debtId": validated_data.get("debtId", "273194670"),
# "customerId": validated_data.get("customerId", "CN621868"),
# "accountId": validated_data.get("accountId", "2017821799"),
# "productId": validated_data.get("productId", "101"),
# "amountCollected": validated_data.get("collectAmount", 60000.00),
# "countryId": validated_data.get("countryId", "01"),
# "comment": validated_data.get("comment", "Testing CollectionLoanRequest"),
# "responseCode": "00",
# "responseDescr": "Loan Collection Successful",
# "fullDescription": "Loan collection completed successfully",
# "responseMessage": "Loan collection completed successfully"
# }
#
# return ResponseHelper.success(
# data=response_data,
# message="Loan collection completed successfully"
# )
return response_data
# 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
+30 -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,43 @@ 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!",
"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
+16 -13
View File
@@ -2,7 +2,7 @@ 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 +22,33 @@ class PenalChargeService:
# Validate input data using PenalChargeSchema
schema = PenalChargeSchema()
validated_data = schema.load(data) # Raises ValidationError if invalid
validated_data = schema.load(data)
# Simulated processing logic
response_data = {
"resultCode": "00",
"resultDescription": "Penal charge debited successfully"
"customerId": validated_data.get("customerId"),
"transactionId": validated_data.get("transactionId"),
"amountCollected": validated_data.get("penalCharge", 0.0),
"accountId": validated_data.get("accountId"),
"responseCode": "00",
"responseMessage": "Penal charge debited successfully"
}
# 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
"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
+82 -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,101 @@ 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 = not (
int(customer_id[-1]) in [2, 7, 9]
)
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
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
+23 -16
View File
@@ -2,7 +2,11 @@ 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
)
import datetime
class TransactionVerifyService:
@@ -26,32 +30,35 @@ class TransactionVerifyService:
# Simulated processing logic
response_data = {
"type": "TransactionCheckResponse",
"nativeId": "FBN20191031104405CN621868",
"customerId": "CN621868",
"accountId": "2017821799",
"responseCode": "00",
"responseDescr": "Success",
"fullDescription": "Collect 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"),
"disburseVerify": datetime.datetime.now().isoformat(),
"verifyResult": "00",
"verifyDescription": "Collect Status retrieved successfully.",
}
# 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
+19 -3
View File
@@ -1,10 +1,12 @@
import os
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 = os.getenv("API_URL")
DEBUG = True
VALID_APP_ID = os.getenv("VALID_APP_ID", "app1")
@@ -14,4 +16,18 @@ class Config:
# SQLALCHEMY_TRACK_MODIFICATIONS = False
# SECRET_KEY = os.environ.get("SECRET_KEY", "your_secret_key")
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "secret-key")
JWT_ACCESS_TOKEN_EXPIRES = os.getenv("JWT_ACCESS_TOKEN_EXPIRES", timedelta(hours=1))
JWT_REFRESH_TOKEN_EXPIRES = os.getenv(
"JWT_REFRESH_TOKEN_EXPIRES", timedelta(days=30)
)
BASIC_AUTH_USERNAME = os.environ.get("BASIC_AUTH_USERNAME", "user")
BASIC_AUTH_PASSWORD = os.environ.get("BASIC_AUTH_PASSWORD", "password")
DEBUG = True
def configure():
load_dotenv()
settings = Config()
+1
View File
@@ -0,0 +1 @@
from .transaction_type import TransactionType
+7
View File
@@ -0,0 +1,7 @@
from enum import Enum
class InstallmentStatus(str, Enum):
PENDING = 'PENDING'
PAID = 'PAID'
OVERDUE = 'OVERDUE'
PARTIALLY_PAID = 'PARTIALLY_PAID'
+8
View File
@@ -0,0 +1,8 @@
from enum import Enum
class LoanStatus(str, Enum):
PENDING = 'PENDING'
ACTIVE = 'ACTIVE'
PAID = 'PAID'
DEFAULTED = 'DEFAULTED'
CLOSED = 'CLOSED'
+7
View File
@@ -0,0 +1,7 @@
from enum import Enum
class TransactionType(str, Enum):
DEBT_CLOSURE_NOTIFICATION = "debt_closure_notification"
DISBURSEMENT = "disbursement"
SEND_SMS = "send_sms"
COLLECT_LOAN = "collect_loan"
+112
View File
@@ -0,0 +1,112 @@
from flask import jsonify
from typing import Optional, Union, Dict, List, Any
class ResponseHelper:
"""
A helper class for building standardized JSON responses using resultCode and resultDescription.
"""
@staticmethod
def build_response(
result_code: str,
result_description: str,
data: Optional[Union[Dict, List, str]] = None
) -> Dict[str, Any]:
response = {
"resultCode": result_code,
"resultDescription": result_description
}
if isinstance(data, dict):
response.update(data)
return jsonify(response)
@staticmethod
def success(
result_description: str = "Successful",
result_code: str = "00",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def error(
result_description: str = "An error occurred",
result_code: str = "01",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def created(
result_description: str = "Resource created successfully",
result_code: str = "00",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def updated(
result_description: str = "Resource updated successfully",
result_code: str = "00",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def internal_server_error(
result_description: str = "Internal Server Error",
result_code: str = "500",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def unauthorized(
result_description: str = "Unauthorized",
result_code: str = "401",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def forbidden(
result_description: str = "Forbidden",
result_code: str = "403",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def not_found(
result_description: str = "Resource not found",
result_code: str = "404",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def unprocessable_entity(
result_description: str = "Unprocessable entity",
result_code: str = "422",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def method_not_allowed(
result_description: str = "Method Not Allowed",
result_code: str = "405",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
@staticmethod
def bad_request(
result_description: str = "Bad Request",
result_code: str = "400",
data: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
return ResponseHelper.build_response(result_code, result_description, data)
+1
View File
@@ -0,0 +1 @@
from .routes import eco
+87
View File
@@ -0,0 +1,87 @@
from flask import Blueprint, request, jsonify, send_from_directory
from app.eco.services import (
AuthorizationService,
DisbursementService,
CollectLoanService,
DebtClosureNotificationService,
SendSMSService
)
from app.utils.logger import logger
from flask_jwt_extended import jwt_required
import os
eco = Blueprint("eco", __name__)
# Swagger JSON file
@eco.route("/swagger.json", methods=["GET"])
def swagger_json():
swagger_dir = os.path.join("swagger")
return send_from_directory(swagger_dir, "eco_digifi_swagger.json")
@eco.route("/swagger/<path:filename>")
def serve_paths(filename):
swagger_dir = os.path.join("swagger")
return send_from_directory(swagger_dir, filename)
# Disbursement (Simbrella -> EcoBank)
@eco.route("/Disbursement", methods=["POST"])
@jwt_required()
def disbursement():
data = request.get_json()
response = DisbursementService.process_request(data)
return response
# CollectLoan (Simbrella -> EcoBank)
@eco.route("/CollectLoan", methods=["POST"])
@jwt_required()
def collect_loan():
data = request.get_json()
response = CollectLoanService.process_request(data)
return response
# Debt Closure Notification (Simbrella -> EcoBank)
@eco.route("/DebtClosureNotification", methods=["POST"])
@jwt_required()
def debt_closure():
data = request.get_json()
response = DebtClosureNotificationService.process_request(data)
return response
# Send SMS (Simbrella -> EcoBank)
@eco.route("/SendSMS", methods=["POST"])
@jwt_required()
def send_sms():
data = request.get_json()
response = SendSMSService.process_request(data)
return response
# Health Check
@eco.route("/health", methods=["GET"])
def health_check():
return jsonify({"status": "ok"}), 200
# Authorize endpoint
@eco.route("/Authorize", methods=["POST"])
def authorize():
data = request.get_json()
response = AuthorizationService.process_request(data)
return response
# Authorize refresh endpoint
@eco.route("/AuthorizeRefresh", methods=["POST"])
@jwt_required(refresh=True)
def refresh():
response = AuthorizationService.process_refresh_request()
return response
+5
View File
@@ -0,0 +1,5 @@
from .authorization import AuthorizeRequestSchema
from .disbursement import DisbursementSchema
from .debt_closure_notification import DebtClosureNotificationSchema
from .send_sms import SendSmsSchema
from .collect_loan import CollectLoanSchema
+6
View File
@@ -0,0 +1,6 @@
from marshmallow import Schema, fields
class AuthorizeRequestSchema(Schema):
username = fields.Str(required=True)
password = fields.Str(required=True)
+13
View File
@@ -0,0 +1,13 @@
from marshmallow import Schema, fields, EXCLUDE
class CollectLoanSchema(Schema):
requestId = fields.Str(required=True)
affiliateCode = fields.Str(required=True)
debtId = fields.Int(required=True)
principal = fields.Decimal(required=True)
interest = fields.Decimal(required=True)
penalty = fields.Decimal(required=True)
collectAmount = fields.Decimal(required=True)
class Meta:
unknown = EXCLUDE
@@ -0,0 +1,11 @@
from marshmallow import Schema, fields, EXCLUDE
class DebtClosureNotificationSchema(Schema):
requestId = fields.Str(required=True)
affiliateCode = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
debtId = fields.Int(required=True)
class Meta:
unknown = EXCLUDE
+15
View File
@@ -0,0 +1,15 @@
from marshmallow import Schema, fields, EXCLUDE
class DisbursementSchema(Schema):
requestId = fields.Str(required=True)
affiliateCode = fields.Str(required=True)
debtId = fields.Int(required=True)
productId = fields.Str(required=True)
customerId = fields.Str(required=True)
accountId = fields.Str(required=True)
provideAmount = fields.Decimal(required=True)
collectAmount = fields.Decimal(required=True)
interestRate = fields.Decimal(required=True)
class Meta:
unknown = EXCLUDE
+10
View File
@@ -0,0 +1,10 @@
from marshmallow import Schema, fields, EXCLUDE
class SendSmsSchema(Schema):
requestId = fields.Str(required=True)
phoneNums = fields.List(fields.Str(), required=True)
affiliateCode = fields.Str(required=True)
message = fields.Str(required=True)
class Meta:
unknown = EXCLUDE
+5
View File
@@ -0,0 +1,5 @@
from .authorization import AuthorizationService
from .disbursement import DisbursementService
from .debt_closure_notification import DebtClosureNotificationService
from .send_sms import SendSMSService
from .collect_loan import CollectLoanService
+102
View File
@@ -0,0 +1,102 @@
from flask import request, jsonify
from marshmallow import ValidationError
from app.eco.services.base_service import BaseService
from app.utils.logger import logger
from app.eco.schemas.authorization import AuthorizeRequestSchema
from app.eco.helpers.response_helper import ResponseHelper
from flask_jwt_extended import (
JWTManager,
jwt_required,
create_access_token,
create_refresh_token,
get_jwt_identity,
)
from app.config import Config
USERNAME = Config.BASIC_AUTH_USERNAME
PASSWORD = Config.BASIC_AUTH_PASSWORD
class AuthorizationService(BaseService):
@staticmethod
def process_request(data):
"""
Process the Authorization request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
logger.info("Processing Authorization request")
if not data:
return ResponseHelper.bad_request(result_description="Missing JSON in request")
# Validate input data using the Authorization schema
schema = AuthorizeRequestSchema()
validated_data = schema.load(data) # Raises ValidationError if invalid
if (
validated_data["username"] != USERNAME
or validated_data["password"] != PASSWORD
):
return ResponseHelper.unauthorized(result_description="Invalid credentials")
access_token = create_access_token(identity=validated_data["username"])
refresh_token = create_refresh_token(identity=validated_data["username"])
# Simulated processing logic
response_data = {
"access_token": access_token,
"refresh_token": refresh_token,
}
return ResponseHelper.success(
data={"data": response_data}, result_description="Authorization processed successfully"
)
except ValidationError as e:
logger.error(f"Validation error: {e}")
return ResponseHelper.bad_request(result_description=f"Validation error: {e}")
except Exception as e:
logger.error(f"Error processing Authorization request: {e}")
return ResponseHelper.internal_server_error(
result_description=f"Error processing Authorization request: {e}"
)
@staticmethod
def process_refresh_request():
"""
Process the RefreshToken request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
logger.info("Processing RefreshToken request")
identity = get_jwt_identity()
access_token = create_access_token(identity=identity)
# Simulated processing logic
response_data = {
"access_token": access_token,
}
return ResponseHelper.success(
data={"data": response_data}, result_description="RefreshToken processed successfully"
)
except Exception as e:
logger.error(f"Error processing RefreshToken request: {e}")
return ResponseHelper.internal_server_error(
result_description=f"Error processing RefreshToken request: {e}"
)
+32
View File
@@ -0,0 +1,32 @@
from app.eco.enums import TransactionType
from flask import jsonify
from marshmallow import ValidationError
import logging
logger = logging.getLogger(__name__)
class BaseService:
TRANSACTION_TYPE = None
@classmethod
def validate_data(cls, data, schema):
"""
Validate input data based on the provided schema.
"""
logger.info(f"Processing {cls.TRANSACTION_TYPE} request")
return schema.load(data)
# @classmethod
# def log_session(cls, validated_data):
# """
# Create a new session.
# """
# channel = "USSD" if validated_data.get("channel") is None else validated_data.get("channel")
# return Session.create_session(
# session_id = validated_data.get("transactionId"),
# customer_id = validated_data.get('customerId', None),
# account_id = validated_data.get("accountId", None),
# type = cls.TRANSACTION_TYPE,
# channel = channel,
# )
+33
View File
@@ -0,0 +1,33 @@
from app.eco.enums.transaction_type import TransactionType
from app.eco.services.base_service import BaseService
from app.eco.schemas.collect_loan import CollectLoanSchema
from marshmallow import ValidationError
from app.eco.helpers.response_helper import ResponseHelper
class CollectLoanService(BaseService):
TRANSACTION_TYPE = TransactionType.COLLECT_LOAN
@staticmethod
def process_request(data):
"""
Process the loan collection request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
validated_data = CollectLoanService.validate_data(data, CollectLoanSchema())
response_data = {
"transactionId": "01135062",
"amountCollected": 900.0,
}
return ResponseHelper.success(data=response_data)
except ValidationError as err:
return ResponseHelper.unprocessable_entity(result_description="Validation exception")
except Exception as e:
return ResponseHelper.internal_server_error()
@@ -0,0 +1,27 @@
from app.eco.enums.transaction_type import TransactionType
from app.eco.services.base_service import BaseService
from app.eco.schemas.debt_closure_notification import DebtClosureNotificationSchema
from marshmallow import ValidationError
from app.eco.helpers.response_helper import ResponseHelper
class DebtClosureNotificationService(BaseService):
TRANSACTION_TYPE = TransactionType.DEBT_CLOSURE_NOTIFICATION
@staticmethod
def process_request(data):
"""
Process the debt closure notification request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
validated_data = DebtClosureNotificationService.validate_data(data, DebtClosureNotificationSchema())
return ResponseHelper.success()
except ValidationError as err:
return ResponseHelper.unprocessable_entity(result_description="Validation exception")
except Exception as e:
return ResponseHelper.internal_server_error()
+32
View File
@@ -0,0 +1,32 @@
from app.eco.enums.transaction_type import TransactionType
from app.eco.services.base_service import BaseService
from app.eco.schemas.disbursement import DisbursementSchema
from marshmallow import ValidationError
from app.eco.helpers.response_helper import ResponseHelper
class DisbursementService(BaseService):
TRANSACTION_TYPE = TransactionType.DISBURSEMENT
@staticmethod
def process_request(data):
"""
Process the disbursement request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
validated_data = DisbursementService.validate_data(data, DisbursementSchema())
response_data = {
"transactionId": "SIM01135042",
}
return ResponseHelper.success(data=response_data)
except ValidationError as err:
return ResponseHelper.unprocessable_entity(result_description="Validation exception")
except Exception as e:
return ResponseHelper.internal_server_error()
+31
View File
@@ -0,0 +1,31 @@
from app.eco.enums.transaction_type import TransactionType
from app.eco.services.base_service import BaseService
from app.eco.schemas.send_sms import SendSmsSchema
from marshmallow import ValidationError
from app.eco.helpers.response_helper import ResponseHelper
class SendSMSService(BaseService):
TRANSACTION_TYPE = TransactionType.SEND_SMS
@staticmethod
def process_request(data):
"""
Process the SMS sending request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
validated_data = SendSMSService.validate_data(data, SendSmsSchema())
response_data = {
"undelivered": []
}
return ResponseHelper.success(data=response_data)
except ValidationError as err:
return ResponseHelper.unprocessable_entity(result_description="Validation exception")
except Exception as e:
return ResponseHelper.internal_server_error()
+53 -41
View File
@@ -16,6 +16,9 @@
"servers": [
{
"url": "http://localhost:6337"
},
{
"url": "http://localhost:5000"
},
{
"url": "http://10.10.11.17:6337"
@@ -107,101 +110,110 @@
}
],
"paths": {
"/RACCheck": {
"$ref": "../swagger/paths/RACCheck.json"
"/api/system-health-check": {
"$ref": "swagger/paths/HealthCheck.json"
},
"/CompleteRACcheck": {
"$ref": "../swagger/paths/CompleteRACcheck.json"
"/api/rac-check": {
"$ref": "swagger/paths/RACCheck.json"
},
"/Disbursement": {
"$ref": "../swagger/paths/Disbursement.json"
"/api/CompleteRACcheck": {
"$ref": "swagger/paths/CompleteRACcheck.json"
},
"/CollectLoan": {
"$ref": "../swagger/paths/CollectLoan.json"
"/api/DisburseLoan": {
"$ref": "swagger/paths/Disbursement.json"
},
"/TransactionVerify": {
"$ref": "../swagger/paths/TransactionVerify.json"
"/api/CollectLoan": {
"$ref": "swagger/paths/CollectLoan.json"
},
"/PenalCharge": {
"$ref": "../swagger/paths/PenalCharge.json"
"/api/TransactionVerify": {
"$ref": "swagger/paths/TransactionVerify.json"
},
"/RevokeEnableConsent": {
"$ref": "../swagger/paths/RevokeEnableConsent.json"
"/api/CollectPenalFee": {
"$ref": "swagger/paths/PenalCharge.json"
},
"/TokenValidation": {
"$ref": "../swagger/paths/TokenValidation.json"
"/api/RevokeEnableConsent": {
"$ref": "swagger/paths/RevokeEnableConsent.json"
},
"/LienCheck": {
"$ref": "../swagger/paths/LienCheck.json"
"/api/TokenValidation": {
"$ref": "swagger/paths/TokenValidation.json"
},
"/NewTransactionCheck": {
"$ref": "../swagger/paths/NewTransactionCheck.json"
"/api/LienCheck": {
"$ref": "swagger/paths/LienCheck.json"
},
"/api/NewTransactionCheck": {
"$ref": "swagger/paths/NewTransactionCheck.json"
}
},
"components": {
"schemas": {
"RACCheckRequest": {
"$ref": "../swagger/schemas/RACCheckRequest.json"
"$ref": "./schemas/RACCheckRequest.json"
},
"RACCheckResponse": {
"$ref": "../swagger/schemas/RACCheckResponse.json"
"$ref": "./schemas/RACCheckResponse.json"
},
"CompleteRACcheckRequest": {
"$ref": "../swagger/schemas/CompleteRACcheckRequest.json"
"$ref": "./schemas/CompleteRACcheckRequest.json"
},
"CompleteRACcheckResponse": {
"$ref": "../swagger/schemas/CompleteRACcheckResponse.json"
"$ref": "./schemas/CompleteRACcheckResponse.json"
},
"CustomerConsentRequest": {
"$ref": "./schemas/CustomerConsentRequest.json"
},
"CustomerConsentResponse": {
"$ref": "./schemas/CustomerConsentResponse.json"
},
"DisbursementRequest": {
"$ref": "../swagger/schemas/DisbursementRequest.json"
"$ref": "./schemas/DisbursementRequest.json"
},
"DisbursementResponse": {
"$ref": "../swagger/schemas/DisbursementResponse.json"
"$ref": "./schemas/DisbursementResponse.json"
},
"CollectLoanRequest": {
"$ref": "../swagger/schemas/CollectLoanRequest.json"
"$ref": "./schemas/CollectLoanRequest.json"
},
"CollectLoanResponse": {
"$ref": "../swagger/schemas/CollectLoanResponse.json"
"$ref": "./schemas/CollectLoanResponse.json"
},
"TransactionVerifyRequest": {
"$ref": "../swagger/schemas/TransactionVerifyRequest.json"
"$ref": "./schemas/TransactionVerifyRequest.json"
},
"TransactionVerifyResponse": {
"$ref": "../swagger/schemas/TransactionVerifyResponse.json"
"$ref": "./schemas/TransactionVerifyResponse.json"
},
"PenalChargeRequest": {
"$ref": "../swagger/schemas/PenalChargeRequest.json"
"$ref": "./schemas/PenalChargeRequest.json"
},
"PenalChargeResponse": {
"$ref": "../swagger/schemas/PenalChargeResponse.json"
"$ref": "./schemas/PenalChargeResponse.json"
},
"RevokeEnableConsentRequest": {
"$ref": "../swagger/schemas/RevokeEnableConsentRequest.json"
"$ref": "./schemas/RevokeEnableConsentRequest.json"
},
"RevokeEnableConsentResponse": {
"$ref": "../swagger/schemas/RevokeEnableConsentResponse.json"
"$ref": "./schemas/RevokeEnableConsentResponse.json"
},
"TokenValidationRequest": {
"$ref": "../swagger/schemas/TokenValidationRequest.json"
"$ref": "./schemas/TokenValidationRequest.json"
},
"TokenValidationResponse": {
"$ref": "../swagger/schemas/TokenValidationResponse.json"
"$ref": "./schemas/TokenValidationResponse.json"
},
"NewTransactionCheckRequest": {
"$ref": "../swagger/schemas/NewTransactionCheckRequest.json"
"$ref": "./schemas/NewTransactionCheckRequest.json"
},
"NewTransactionCheckResponse": {
"$ref": "../swagger/schemas/NewTransactionCheckResponse.json"
"$ref": "./schemas/NewTransactionCheckResponse.json"
},
"LienCheckRequest": {
"$ref": "../swagger/schemas/LienCheckRequest.json"
"$ref": "./schemas/LienCheckRequest.json"
},
"LienCheckResponse": {
"$ref": "../swagger/schemas/LienCheckResponse.json"
"$ref": "./schemas/LienCheckResponse.json"
},
"ApiResponse": {
"$ref": "../swagger/schemas/ApiResponse.json"
"$ref": "./schemas/ApiResponse.json"
}
},
"securitySchemes": {
+128
View File
@@ -0,0 +1,128 @@
{
"openapi": "3.0.3",
"info": {
"title": "bank Emulator Swagger Simbrella EcoBank - OpenAPI 3.0",
"description": "This is a Simbrella EcoBank bank Backend Server Emulator with the OpenAPI 3.0 specification. \n\n\nSome useful links:\n- [Web Simulated Demo Page](https://digifi-salaryloan.chiefsoft.net/)\n- [Web Management Support Portal](https://digifi-office.chiefsoft.net/auth/login)",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"email": "support@chiefsoft.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0.11"
},
"servers": [
{
"url": "http://localhost:6337"
},
{
"url": "http://localhost:5000"
},
{
"url": "http://10.10.11.17:6337"
},
{
"url": "https://bank-emulator.dev.simbrellang.net"
}
],
"tags": [
{
"name": "Authentication",
"description": "EcoBank Authentication Token Request",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
},
{
"name": "Disbursement",
"description": "Loan Disbursement Request to EcoBank",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
},
{
"name": "CollectLoan",
"description": "Collect Loan Repayment from EcoBank Customer",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
},
{
"name": "DebtClosureNotification",
"description": "Notify EcoBank of Loan Closure",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
},
{
"name": "SendSMS",
"description": "Send SMS to EcoBank Customers",
"externalDocs": {
"description": "Find out more",
"url": "https://www.simbrellang.net"
}
}
],
"paths": {
"/eco/Authorize": {
"$ref": "swagger/paths/eco/Authentication.json"
},
"/eco/Disbursement": {
"$ref": "swagger/paths/eco/Disbursement.json"
},
"/eco/CollectLoan": {
"$ref": "swagger/paths/eco/CollectLoan.json"
},
"/eco/DebtClosureNotification": {
"$ref": "swagger/paths/eco/DebtClosureNotification.json"
},
"/eco/SendSMS": {
"$ref": "swagger/paths/eco/SendSMS.json"
}
},
"components": {
"schemas": {
"AuthenticationRequest": {
"$ref": "swagger/schemas/eco/AuthenticationRequest.json"
},
"AuthenticationResponse": {
"$ref": "swagger/schemas/eco/AuthenticationResponse.json"
},
"DebtClosureNotificationRequest": {
"$ref": "swagger/schemas/eco/DebtClosureNotificationRequest.json"
},
"DebtClosureNotificationResponse": {
"$ref": "swagger/schemas/eco/DebtClosureNotificationResponse.json"
},
"SendSMSRequest": {
"$ref": "swagger/schemas/eco/SendSMSRequest.json"
},
"SendSMSResponse": {
"$ref": "swagger/schemas/eco/SendSMSResponse.json"
}
},
"securitySchemes": {
"basicAuth": {
"type": "http",
"scheme": "basic"
},
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"security": [
{
"basicAuth": [],
"bearerAuth": []
}
]
}
+2 -6
View File
@@ -50,11 +50,7 @@
"500": {
"description": "Internal server error"
}
},
"security": [
{
"basic_auth": []
}
]
}
}
}
+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"
}
}
}
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
{
"post": {
"tags": ["Authentication"],
"summary": "EcoBank Authentication",
"description": "Get bearer token from EcoBank",
"operationId": "authenticate",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/AuthenticationRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "Authentication Successful",
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/AuthenticationResponse.json"
}
}
}
},
"400": { "description": "Invalid request" },
"500": { "description": "Internal server error" }
}
}
}
+33
View File
@@ -0,0 +1,33 @@
{
"post": {
"tags": ["CollectLoan"],
"summary": "Collect Loan Repayment",
"description": "Collect repayment amount from EcoBank customer",
"operationId": "collectLoan",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/CollectLoanRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "Loan Collection Successful",
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/CollectLoanResponse.json"
}
}
}
},
"400": { "description": "Invalid request" },
"422": { "description": "Validation exception" },
"500": { "description": "Internal server error" }
}
}
}
@@ -0,0 +1,33 @@
{
"post": {
"tags": ["DebtClosureNotification"],
"summary": "Debt Closure Notification",
"description": "Notify EcoBank that debt has been fully repaid",
"operationId": "notifyDebtClosure",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/DebtClosureNotificationRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "Debt Closure Acknowledged",
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/DebtClosureNotificationResponse.json"
}
}
}
},
"400": { "description": "Invalid request" },
"422": { "description": "Validation exception" },
"500": { "description": "Internal server error" }
}
}
}
+33
View File
@@ -0,0 +1,33 @@
{
"post": {
"tags": ["Disbursement"],
"summary": "Loan Disbursement",
"description": "Disburse loan to EcoBank customer account",
"operationId": "disburseLoan",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/DisbursementRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "Disbursement Successful",
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/DisbursementResponse.json"
}
}
}
},
"400": { "description": "Invalid request" },
"422": { "description": "Validation exception" },
"500": { "description": "Internal server error" }
}
}
}
+33
View File
@@ -0,0 +1,33 @@
{
"post": {
"tags": ["SendSMS"],
"summary": "Send SMS Notification",
"description": "Send a message to one or more EcoBank customers",
"operationId": "sendSms",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/SendSMSRequest.json"
}
}
}
},
"responses": {
"200": {
"description": "SMS Sent Successfully",
"content": {
"application/json": {
"schema": {
"$ref": "../../schemas/eco/SendSMSResponse.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
}
+96 -80
View File
@@ -1,82 +1,98 @@
{
"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
}
},
"required": [
"provideAmount",
"collectAmountInterest",
"collectAmountMgtFee",
"collectAmountInsurance",
"collectAmountVAT"
]
}
@@ -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
}
+35 -11
View File
@@ -1,13 +1,37 @@
{
"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
},
"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,62 @@
{
"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"
},
"disburseVerify":{
"type": "string",
"format": "date-time",
"example": "2023-10-01T12:00:00Z",
"nullable": true
},
"verifyResult": {
"type": "string",
"example": "Success"
},
"verifyDescription": {
"type": "string",
"example": "Disbursement was verified and collection completed."
}
}
},
"required": [
"providedAmount",
"collectedAmount"
],
"additionalProperties": false
}
@@ -0,0 +1,14 @@
{
"type": "object",
"required": ["username", "password"],
"properties": {
"username": {
"type": "string",
"example": "user"
},
"password": {
"type": "string",
"example": "password"
}
}
}
@@ -0,0 +1,16 @@
{
"type": "object",
"properties": {
"resultCode": {
"type": "string"
},
"resultDescription": {
"type": "string",
"example": "Authentication successful"
},
"token": {
"type": "string",
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
}
@@ -0,0 +1,13 @@
{
"type": "object",
"required": ["requestId", "affiliateCode", "debtId", "principal", "interest", "penalty", "collectAmount"],
"properties": {
"requestId": { "type": "string", "example": "req-12345" },
"affiliateCode": { "type": "string", "example": "aff-67890" },
"debtId": { "type": "integer", "example": 123456 },
"principal": { "type": "number", "example": 1000.00 },
"interest": { "type": "number", "example": 100.00 },
"penalty": { "type": "number", "example": 50.00 },
"collectAmount": { "type": "number", "example": 1150.00 }
}
}
@@ -0,0 +1,9 @@
{
"type": "object",
"properties": {
"transactionId": { "type": "string", "example": "txn-12345" },
"amountCollected": { "type": "number", "example": 1150.00 },
"resultCode": { "type": "integer", "example": 0 },
"resultDescription": { "type": "string", "example": "Collection successful" }
}
}
@@ -0,0 +1,11 @@
{
"type": "object",
"required": ["requestId", "affiliateCode", "customerId", "accountId", "debtId"],
"properties": {
"requestId": { "type": "string", "example": "req-12345" },
"affiliateCode": { "type": "string", "example": "aff-67890" },
"customerId": { "type": "string", "example": "cust-54321" },
"accountId": { "type": "string", "example": "acc-98765" },
"debtId": { "type": "integer", "example": 123456 }
}
}
@@ -0,0 +1,7 @@
{
"type": "object",
"properties": {
"resultCode": { "type": "integer", "example": 0 },
"resultDescription": { "type": "string", "example": "Debt closure notification sent successfully" }
}
}
@@ -0,0 +1,15 @@
{
"type": "object",
"required": ["requestId", "affiliateCode", "debtId", "productId", "customerId", "accountId", "provideAmount", "collectAmount", "interestRate"],
"properties": {
"requestId": { "type": "string", "example": "req-12345" },
"affiliateCode": { "type": "string", "example": "aff-67890" },
"debtId": { "type": "integer", "example": 123456 },
"productId": { "type": "string", "example": "prod-78901" },
"customerId": { "type": "string", "example": "cust-54321" },
"accountId": { "type": "string", "example": "acc-98765" },
"provideAmount": { "type": "number", "example": 1000.00 },
"collectAmount": { "type": "number", "example": 1150.00 },
"interestRate": { "type": "number", "example": 5.0 }
}
}
@@ -0,0 +1,8 @@
{
"type": "object",
"properties": {
"transactionId": { "type": "string", "example": "txn-12345" },
"resultCode": { "type": "integer", "example": 0 },
"resultDescription": { "type": "string", "example": "Disbursement successful" }
}
}
@@ -0,0 +1,13 @@
{
"type": "object",
"required": ["requestId", "phoneNums", "affiliateCode", "message"],
"properties": {
"requestId": { "type": "string", "example": "req-12345" },
"phoneNums": {
"type": "array",
"items": { "type": "string", "example": "+1234567890" }
},
"affiliateCode": { "type": "string", "example": "aff-67890" },
"message": { "type": "string", "example": "Your verification code is 123456" }
}
}
@@ -0,0 +1,11 @@
{
"type": "object",
"properties": {
"undelivered": {
"type": "array",
"items": { "type": "string", "example": "+1234567890" }
},
"resultCode": { "type": "integer", "example": 0 },
"resultDescription": { "type": "string", "example": "SMS sent successfully" }
}
}
+4 -4
View File
@@ -5,11 +5,11 @@ marshmallow==3.19.0
Flask-Cors==3.0.10
gunicorn
flask-swagger-ui
python-dotenv
flask-jwt-extended
flask-apispec
# Logging (Python Standard Library, for reference)
# Logging (Python Standard Library, for reference)