169 lines
6.2 KiB
Python
169 lines
6.2 KiB
Python
"""
|
|
Controller for transaction check endpoints.
|
|
"""
|
|
from flask import Blueprint, request, jsonify
|
|
from flask.typing import ResponseReturnValue
|
|
from app.middleware import api_key_required
|
|
from app.models import (
|
|
TransactionCheckRequest, TransactionCheckResponse,
|
|
NewTransactionCheckRequest, NewTransactionCheckResponse,
|
|
TransactionData
|
|
)
|
|
import logging
|
|
from typing import Dict, Any
|
|
|
|
# Configure logger
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Create blueprint
|
|
transaction_bp = Blueprint('transaction', __name__)
|
|
|
|
@transaction_bp.route('/TransactionCheck', methods=['POST'])
|
|
@api_key_required
|
|
def transaction_check() -> ResponseReturnValue:
|
|
"""
|
|
Endpoint to check transaction status.
|
|
|
|
This method is used to double-check the response received from DisburseLoan
|
|
and CollectLoan Synchronous APIs. It verifies transaction results on FirstBank.
|
|
|
|
Returns:
|
|
JSON response with transaction status details
|
|
"""
|
|
try:
|
|
# Parse and validate request
|
|
data = request.get_json()
|
|
if not data:
|
|
logger.warning("Invalid JSON payload received")
|
|
return jsonify({
|
|
'resultCode': '400',
|
|
'resultDescription': 'Invalid JSON payload'
|
|
}), 400
|
|
|
|
# Validate required fields
|
|
required_fields = ['counter', 'TransactionId', 'requestID', 'customerId',
|
|
'accountId', 'countryId', 'transactionType']
|
|
missing_fields = [field for field in required_fields if field not in data]
|
|
if missing_fields:
|
|
logger.warning(f"Missing required fields: {', '.join(missing_fields)}")
|
|
return jsonify({
|
|
'resultCode': '422',
|
|
'resultDescription': f'Missing required fields: {", ".join(missing_fields)}'
|
|
}), 422
|
|
|
|
# Create request model
|
|
req = TransactionCheckRequest.from_dict(data)
|
|
|
|
# Process transaction check (this would connect to your business logic)
|
|
# For demonstration, we'll return a mock response
|
|
|
|
# Create response based on transaction type
|
|
provided_amount = 0.0
|
|
collected_amount = 0.0
|
|
|
|
if req.transactionType == "Disbursement":
|
|
provided_amount = 10000.0
|
|
elif req.transactionType == "Collection" or req.transactionType == "Penalty":
|
|
collected_amount = 7.50
|
|
|
|
# Create response
|
|
response = TransactionCheckResponse(
|
|
type_field="TransactionCheckResponse", # This will be converted to $type in JSON
|
|
nativeId=f"FBN20191031104405{req.customerId}",
|
|
customerId=req.customerId,
|
|
accountId=req.accountId,
|
|
providedAmount=provided_amount,
|
|
collectedAmount=collected_amount,
|
|
resultCode="00",
|
|
resultDescription=f"{req.transactionType} Status retrieved successfully."
|
|
)
|
|
|
|
logger.info(f"Processed transaction check for {req.transactionType}, ID {req.TransactionId}")
|
|
return jsonify(response.to_dict())
|
|
|
|
except Exception as e:
|
|
logger.exception(f"Error processing transaction check: {str(e)}")
|
|
return jsonify({
|
|
'resultCode': '500',
|
|
'resultDescription': f'Internal server error: {str(e)}'
|
|
}), 500
|
|
|
|
@transaction_bp.route('/NewTransactionCheck', methods=['POST'])
|
|
@api_key_required
|
|
def new_transaction_check() -> ResponseReturnValue:
|
|
"""
|
|
Endpoint to check status of transactions in asynchronous requests.
|
|
|
|
This method is used for checking the status of transactions when Simbrella
|
|
doesn't receive a callback notification within 5 minutes of the initial request.
|
|
|
|
Returns:
|
|
JSON response with detailed transaction status
|
|
"""
|
|
try:
|
|
# Parse and validate request
|
|
data = request.get_json()
|
|
if not data:
|
|
logger.warning("Invalid JSON payload received")
|
|
return jsonify({
|
|
'resultCode': '400',
|
|
'resultDescription': 'Invalid JSON payload'
|
|
}), 400
|
|
|
|
# Validate required fields
|
|
required_fields = ['transactionId', 'debtId', 'transactionType',
|
|
'fbnTransactionId', 'origTransactionId', 'customerId']
|
|
missing_fields = [field for field in required_fields if field not in data]
|
|
if missing_fields:
|
|
logger.warning(f"Missing required fields: {', '.join(missing_fields)}")
|
|
return jsonify({
|
|
'resultCode': '422',
|
|
'resultDescription': f'Missing required fields: {", ".join(missing_fields)}'
|
|
}), 422
|
|
|
|
# Create request model
|
|
req = NewTransactionCheckRequest.from_dict(data)
|
|
|
|
# Process new transaction check (this would connect to your business logic)
|
|
# For demonstration, we'll return a mock response
|
|
|
|
# Create transaction data based on transaction type
|
|
provided_amount = 0.0
|
|
collected_amount = 0.0
|
|
|
|
if req.transactionType == "Disbursement":
|
|
provided_amount = 1000.0
|
|
result_description = "Loan Provision is successful"
|
|
elif req.transactionType == "Collection":
|
|
collected_amount = 500.0
|
|
result_description = "Loan Collection is successful"
|
|
else: # PenalCharge
|
|
collected_amount = 50.0
|
|
result_description = "Penal Charge is successful"
|
|
|
|
# Create transaction data
|
|
transaction_data = TransactionData(
|
|
transactionId=req.origTransactionId,
|
|
providedAmount=provided_amount,
|
|
collectedAmount=collected_amount,
|
|
resultCode="00",
|
|
resultDescription=result_description
|
|
)
|
|
|
|
# Create response
|
|
response = NewTransactionCheckResponse(
|
|
transactionId=req.transactionId,
|
|
data=transaction_data.to_dict(),
|
|
resultCode="00",
|
|
resultDescription="SUCCESS"
|
|
)
|
|
|
|
logger.info(f"Processed new transaction check for {req.transactionType}, ID {req.transactionId}")
|
|
return jsonify(response.to_dict())
|
|
|
|
except Exception as e:
|
|
logger.exception(f"Error processing new transaction check: {str(e)}")
|
|
return jsonify({
|
|
'resultCode': '500',
|
|
'resultDescription': f'Internal server error: {str(e)}'
|
|
}), 500 |