Skip to content

Commit

Permalink
reorganization of mojaloop and mpesa.
Browse files Browse the repository at this point in the history
  • Loading branch information
Abhishek-Wagh committed Nov 15, 2023
1 parent 7205e82 commit 8be04c7
Show file tree
Hide file tree
Showing 21 changed files with 391 additions and 1,098 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ async def get_payment_backend_from_fa(self, fa: str):
return None

async def make_disbursements(self, disburse_request: DisburseRequest):
# TODO:
payee_fa_list = []
try:
payee_fa_list = await self.id_translate_service.translate(
Expand All @@ -53,7 +52,7 @@ async def make_disbursements(self, disburse_request: DisburseRequest):
except Exception:
# TODO: handle the failures
pass

# TODO : we want to make backend name configurable if true then all this or of false then None
for i, disbursement in enumerate(disburse_request.disbursements):
try:
backend_name = await self.get_payment_backend_from_fa(
Expand Down
373 changes: 0 additions & 373 deletions gpb-mojaloop-sdk-payment-backend/LICENSE

This file was deleted.

6 changes: 0 additions & 6 deletions gpb-mojaloop-sdk-payment-backend/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# G2P Payments Bridge: Mojaloop SDK Scheme Adapter Payment Backend.
[![Pre-commit Status](https://github.com/OpenG2P/g2p-payments-bridge/actions/workflows/pre-commit.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-payments-bridge/actions/workflows/pre-commit.yml?query=branch%3Adevelop)
[![Build Status](https://github.com/OpenG2P/g2p-payments-bridge/actions/workflows/test.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-payments-bridge/actions/workflows/test.yml?query=branch%3Adevelop)
[![codecov](https://codecov.io/gh/OpenG2P/g2p-payments-bridge/branch/develop/graph/badge.svg)](https://codecov.io/gh/OpenG2P/g2p-payments-bridge)
[![openapi](https://img.shields.io/badge/open--API-swagger-brightgreen)](https://validator.swagger.io/?url=https://raw.githubusercontent.com/OpenG2P/g2p-payments-bridge/develop/api-docs/generated/openapi.json)
![PyPI](https://img.shields.io/pypi/v/gpb-mojaloop-sdk-payment-backend?label=pypi%20package)
![PyPI - Downloads](https://img.shields.io/pypi/dm/gpb-mojaloop-sdk-payment-backend)

Mojaloop SDK Scheme Adapter backend for G2P Payments Bridge.
186 changes: 186 additions & 0 deletions gpb-mojaloop-sdk-payment-backend/payment_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#!/usr/bin/env python3
# ruff: noqa: E402

import asyncio
import logging
from contextlib import asynccontextmanager
from datetime import datetime
from typing import List

import httpx
from fastapi import FastAPI
from g2p_payments_bridge_core.models.disburse import (
SingleDisburseStatusEnum,
)
from g2p_payments_bridge_core.models.msg_header import MsgStatusEnum
from g2p_payments_bridge_core.models.orm.payment_list import PaymentListItem
from openg2p_fastapi_common.config import Settings as BaseSettings
from openg2p_fastapi_common.context import dbengine
from openg2p_fastapi_common.service import BaseService
from pydantic import BaseModel
from pydantic_settings import SettingsConfigDict
from sqlalchemy import and_, select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker


class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="gpb_mojaloop_sdk_", env_file=".env", extra="allow"
)
openapi_title: str = "GPB Mojaloop SDK Adapter Payment Backend"
openapi_description: str = """
Payment Backend for Mojaloop SDK Adapter of G2P Payments Bridge.
***********************************
Further details goes here
***********************************
"""
openapi_version: str = "0.1.0"

payment_backend_name: str = "mojaloop"
db_dbname: str = "gpbdb"

api_timeout: int = 10
transfers_url: str = ""
payer_id_type: str = ""
payer_id_value: str = ""
payee_id_type: str = ""
transfer_note: str = "GPB benefit transfer"


_config = Settings.get_config()
_logger = logging.getLogger("openg2p_fastapi_common.app")


class ReferenceIdStatus(BaseModel):
txn_id: str
ref_id: str
status: MsgStatusEnum


class MojaloopSdkPaymentBackendService(BaseService):
def __init__(self, name="", **kwargs):
super().__init__(name if name else _config.payment_backend_name, **kwargs)

def post_init(self):
asyncio.create_task(self.disburse_loop())

async def disburse_loop(self):
while True:
db_response = []
async_session_maker = async_sessionmaker(dbengine.get())
async with async_session_maker() as session:
stmt = select(PaymentListItem)
if (
_config.dsbmt_loop_filter_backend_name
and _config.dsbmt_loop_filter_status
):
stmt = stmt.where(
and_(
PaymentListItem.backend_name
== _config.payment_backend_name,
PaymentListItem.status.in_(
[
MsgStatusEnum[status]
for status in _config.dsbmt_loop_filter_status
]
),
)
)
elif _config.dsbmt_loop_filter_backend_name:
stmt = stmt.where(
PaymentListItem.backend_name == _config.payment_backend_name
)
elif _config.dsbmt_loop_filter_status:
stmt = stmt.where(
PaymentListItem.status.in_(
[
MsgStatusEnum[status]
for status in _config.dsbmt_loop_filter_status
]
)
)
stmt = stmt.order_by(PaymentListItem.id.asc())
result = await session.execute(stmt)

db_response = list(result.scalars())
if db_response:
_logger.info("GPB Mojaloop - processing payment from payment list.")
await self.disburse(db_response, session)
else:
_logger.info(
"GPB Mojaloop - no records found in payment list table."
)

await asyncio.sleep(_config.dsbmt_loop_interval_secs)

async def disburse(self, payments: List[PaymentListItem], session: AsyncSession):
for payment in payments:
data = {
"homeTransactionId": payment.request_id,
"from": {
"idType": _config.payer_id_type,
"idValue": _config.payer_id_value,
},
"to": {
"idType": _config.payee_id_type,
"idValue": await self.get_payee_id_value_from_payee_fa(
payment.to_fa
),
},
"currency": payment.currency,
"amount": float(payment.amount),
"note": _config.transfer_note,
"transactionType": "TRANSFER",
"amountType": "SEND",
}
try:
response = httpx.post(
_config.transfers_url,
json=data,
timeout=_config.api_timeout,
)
_logger.info(
"Mojaloop SDK Payment Transfer response: %s", response.content
)
response.raise_for_status()

# TODO: Do Status check rather than hardcoding
payment.updated_at = datetime.utcnow()
payment.status = MsgStatusEnum.succ
except Exception:
_logger.exception("Mojaloop Payment Failed with unknown reason")
payment.updated_at = datetime.utcnow()
payment.status = MsgStatusEnum.rjct
payment.error_code = SingleDisburseStatusEnum.rjct_payment_failed
payment.error_msg = "Mojaloop Payment Failed with unknown reason"

await session.commit()

async def get_payee_id_value_from_payee_fa(self, fa: str) -> str:
return fa[fa.find(":") + 1 : fa.rfind("@")]


from gpb_translate_id_fa.app import Initializer as TranslateIdInitializer
from openg2p_common_g2pconnect_id_mapper.app import (
Initializer as G2pConnectMapperInitializer,
)
from openg2p_fastapi_common.app import Initializer


class PaymentBackendInitializer(Initializer):
def initialize(self, **kwargs):
MojaloopSdkPaymentBackendService()

@asynccontextmanager
async def fastapi_app_lifespan(self, app: FastAPI):
self.payment_backend.post_init()
yield
await dbengine.get().dispose()


if __name__ == "__main__":
main_init = PaymentBackendInitializer()
G2pConnectMapperInitializer()
TranslateIdInitializer()
main_init.main()
27 changes: 0 additions & 27 deletions gpb-mojaloop-sdk-payment-backend/pyproject.toml

This file was deleted.

Empty file.

This file was deleted.

This file was deleted.

Empty file.

This file was deleted.

Empty file.
Loading

0 comments on commit 8be04c7

Please sign in to comment.