diff --git a/.copier-answers.yml b/.copier-answers.yml index f845274..0dc6e2e 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -7,10 +7,10 @@ github_ci_precommit: true github_ci_pypi_publish: true github_ci_tests: true github_ci_tests_codecov: true -module_name: g2p_payments_bridge +module_name: g2p_cash_transfer_bridge org_name: OpenG2P org_slug: OpenG2P -package_name: g2p-payments-bridge -repo_name: G2P Payments Bridge -repo_slug: g2p-payments-bridge +package_name: g2p-cash-transfer-bridge +repo_name: G2P Cash Transfer Bridge +repo_slug: g2p-cash-transfer-bridge diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index f4ea790..996f1b5 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -10,7 +10,8 @@ jobs: runs-on: ubuntu-latest env: NAMESPACE: ${{ secrets.docker_hub_organisation }} - SERVICE_NAME: g2p-payments-bridge + SERVICE_NAME: g2p-cash-transfer-bridge + PAYMENT_BACKEND_SERVICE_NAME: gctb-payment-backend steps: - uses: actions/checkout@v3 - name: Docker build and push @@ -23,14 +24,17 @@ jobs: fi IMAGE_ID=$NAMESPACE/$SERVICE_NAME + PAYMENT_BACKEND_IMAGE_ID=$NAMESPACE/$PAYMENT_BACKEND_SERVICE_NAME # Change all uppercase to lowercase IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + PAYMENT_BACKEND_IMAGE_ID=$(echo $PAYMENT_BACKEND_IMAGE_ID | tr '[A-Z]' '[a-z]') VERSION=$BRANCH_NAME if [[ $BRANCH_NAME == master || $BRANCH_NAME == main ]]; then VERSION=develop fi echo IMAGE_ID=$IMAGE_ID + echo PAYMENT_BACKEND_IMAGE_ID=$PAYMENT_BACKEND_IMAGE_ID echo VERSION=$VERSION docker build . \ @@ -38,3 +42,9 @@ jobs: --tag $IMAGE_ID:$VERSION docker push $IMAGE_ID:$VERSION + + docker build . \ + --file payment-backend.Dockerfile \ + --tag $PAYMENT_BACKEND_IMAGE_ID:$VERSION + + docker push $PAYMENT_BACKEND_IMAGE_ID:$VERSION diff --git a/.github/workflows/openapi-push.yml b/.github/workflows/openapi-push.yml index ae8b948..73b6b29 100644 --- a/.github/workflows/openapi-push.yml +++ b/.github/workflows/openapi-push.yml @@ -18,7 +18,12 @@ jobs: with: python-version: "3.10" - name: Install app - run: python -m pip install ./g2p-payments-bridge-core + run: | + python -m pip install git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-common\&subdirectory=openg2p-fastapi-common + python -m pip install git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-auth\&subdirectory=openg2p-fastapi-auth + python -m pip install git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-common-g2pconnect-id-mapper\&subdirectory=openg2p-common-g2pconnect-id-mapper + python -m pip install ./g2p-cash-transfer-bridge-core + python -m pip install ./g2p-cash-transfer-bridge-api - name: Generate openapi json run: | mkdir -p api-docs/generated diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b6c59f2..a0437a8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,31 +15,24 @@ jobs: python-version: "3.10" - name: Install build dependencies run: pip install build - - name: Build distribution g2p-payments-bridge-core - run: python -m build ./g2p-payments-bridge-core + - name: Build distribution g2p-cash-transfer-bridge-core + run: python -m build ./g2p-cash-transfer-bridge-core - name: Publish uses: pypa/gh-action-pypi-publish@release/v1 with: - packages-dir: g2p-payments-bridge-core/dist + packages-dir: g2p-cash-transfer-bridge-core/dist password: ${{ secrets.PYPI_API_TOKEN }} - - name: Build distribution gpb-translate-id-fa - run: python -m build ./gpb-translate-id-fa - - name: Publish gpb-translate-id-fa - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: gpb-translate-id-fa/dist - password: ${{ secrets.PYPI_API_TOKEN }} - - name: Build distribution gpb-simple-mpesa-payment-backend - run: python -m build ./gpb-simple-mpesa-payment-backend - - name: Publish gpb-simple-mpesa-payment-backend + - name: Build distribution g2p-cash-transfer-bridge-api + run: python -m build ./g2p-cash-transfer-bridge-api + - name: Publish uses: pypa/gh-action-pypi-publish@release/v1 with: - packages-dir: gpb-simple-mpesa-payment-backend/dist + packages-dir: g2p-cash-transfer-bridge-api/dist password: ${{ secrets.PYPI_API_TOKEN }} - - name: Build distribution gpb-mojaloop-sdk-payment-backend - run: python -m build ./gpb-mojaloop-sdk-payment-backend - - name: Publish gpb-mojaloop-sdk-payment-backend + - name: Build distribution gctb-translate-id-fa + run: python -m build ./gctb-translate-id-fa + - name: Publish gctb-translate-id-fa uses: pypa/gh-action-pypi-publish@release/v1 with: - packages-dir: gpb-mojaloop-sdk-payment-backend/dist + packages-dir: gctb-translate-id-fa/dist password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 1e43f5f..c6bedbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,10 +22,9 @@ RUN python3 -m pip install \ git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-common\&subdirectory=openg2p-fastapi-common \ git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-auth\&subdirectory=openg2p-fastapi-auth \ git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-common-g2pconnect-id-mapper\&subdirectory=openg2p-common-g2pconnect-id-mapper \ - ./src/g2p-payments-bridge-core \ - ./src/gpb-translate-id-fa \ - ./src/gpb-simple-mpesa-payment-backend \ - ./src/gpb-mojaloop-sdk-payment-backend + ./src/g2p-cash-transfer-bridge-core \ + ./src/g2p-cash-transfer-bridge-api \ + ./src/gctb-translate-id-fa CMD python3 main.py migrate; \ python3 main.py run diff --git a/README.md b/README.md index 863b626..c840f5b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# G2P Payments Bridge -[![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) +# G2P Cash Transfer Bridge +[![Pre-commit Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml?query=branch%3Adevelop) +[![Build Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml?query=branch%3Adevelop) +[![codecov](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge/branch/develop/graph/badge.svg)](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge) +[![openapi](https://img.shields.io/badge/open--API-swagger-brightgreen)](https://validator.swagger.io/?url=https://raw.githubusercontent.com/OpenG2P/g2p-cash-transfer-bridge/develop/api-docs/generated/openapi.json) Module to offer interoperability with G2P Connect for cash disbursement @@ -10,10 +10,10 @@ Module to offer interoperability with G2P Connect for cash disbursement Package | Version | Summary ----- | ------- | ------- -[g2p-payments-bridge-core](g2p-payments-bridge-core/) | 0.1.0 | G2P Payments Bridge: Core -[gpb-translate-id-fa](gpb-translate-id-fa/) | 0.1.0 | G2P Payments Bridge: Translate ID to Financial Address -[gpb-simple-mpesa-payment-backend](gpb-simple-mpesa-payment-backend/) | 0.1.0 | G2P Payments Bridge: Simple-mpesa Payment Backend. -[gpb-mojaloop-sdk-payment-backend](gpb-mojaloop-sdk-payment-backend/) | 0.1.0 | G2P Payments Bridge: Mojaloop SDK Scheme Adapter Payment Backend. +[g2p-cash-transfer-bridge-core](g2p-cash-transfer-bridge-core/) | 0.1.0 | G2P Cash Transfer Bridge: Core +[gctb-translate-id-fa](gctb-translate-id-fa/) | 0.1.0 | G2P Cash Transfer Bridge: Translate ID to Financial Address +[gctb-simple-mpesa-payment-backend](gctb-simple-mpesa-payment-backend/) | 0.1.0 | G2P Cash Transfer Bridge: Simple-mpesa Payment Backend. +[gctb-mojaloop-sdk-payment-backend](gctb-mojaloop-sdk-payment-backend/) | 0.1.0 | G2P Cash Transfer Bridge: Mojaloop SDK Scheme Adapter Payment Backend. ## Licenses diff --git a/gpb-translate-id-fa/LICENSE b/g2p-cash-transfer-bridge-api/LICENSE similarity index 100% rename from gpb-translate-id-fa/LICENSE rename to g2p-cash-transfer-bridge-api/LICENSE diff --git a/g2p-cash-transfer-bridge-api/README.md b/g2p-cash-transfer-bridge-api/README.md new file mode 100644 index 0000000..8c64586 --- /dev/null +++ b/g2p-cash-transfer-bridge-api/README.md @@ -0,0 +1,9 @@ +# G2P Cash Transfer Bridge: API +[![Pre-commit Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml?query=branch%3Adevelop) +[![Build Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml?query=branch%3Adevelop) +[![codecov](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge/branch/develop/graph/badge.svg)](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge) +[![openapi](https://img.shields.io/badge/open--API-swagger-brightgreen)](https://validator.swagger.io/?url=https://raw.githubusercontent.com/OpenG2P/g2p-cash-transfer-bridge/develop/api-docs/generated/openapi.json) +![PyPI](https://img.shields.io/pypi/v/g2p-cash-transfer-bridge-api?label=pypi%20package) +![PyPI - Downloads](https://img.shields.io/pypi/dm/g2p-cash-transfer-bridge-api) + +API module for G2P Cash Transfer Bridge, which contains API layer and multiplexer for different payment backends. This implements G2P Connect Disburse APIs. diff --git a/g2p-cash-transfer-bridge-api/pyproject.toml b/g2p-cash-transfer-bridge-api/pyproject.toml new file mode 100644 index 0000000..f70032d --- /dev/null +++ b/g2p-cash-transfer-bridge-api/pyproject.toml @@ -0,0 +1,27 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "g2p-cash-transfer-bridge-api" +version = "0.1.0" +authors = [ + { name="OpenG2P", email="info@openg2p.org" }, +] +description = "G2P Cash Transfer Bridge: API" +readme = "README.md" +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", + "Operating System :: OS Independent", +] +dependencies=[ + "g2p-cash-transfer-bridge-core", +] + +[project.urls] +Homepage = "https://openg2p.org" +Documentation = "https://docs.openg2p.org/" +Repository = "https://github.com/OpenG2P/g2p-cash-transfer-bridge" +Source = "https://github.com/OpenG2P/g2p-cash-transfer-bridge" diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/__init__.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/__init__.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/__init__.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/__init__.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/app.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/app.py similarity index 60% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/app.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/app.py index 301a75a..2b087d5 100644 --- a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/app.py +++ b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/app.py @@ -1,13 +1,10 @@ # ruff: noqa: E402 -import asyncio - from .config import Settings -from .models.orm.payment_list import PaymentListItem _config = Settings.get_config() -from openg2p_fastapi_common.app import Initializer +from g2p_cash_transfer_bridge_core.app import Initializer from .controllers.disbursement_controller import DisbursementController from .services.payment_multiplexer import PaymentMultiplexerService @@ -19,11 +16,3 @@ def initialize(self, **kwargs): # Initialize all Services, Controllers, any utils here. PaymentMultiplexerService() DisbursementController().post_init() - - def migrate_database(self, args): - super().migrate_database(args) - - async def migrate(): - await PaymentListItem.create_migrate() - - asyncio.run(migrate()) diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/config.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/config.py similarity index 61% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/config.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/config.py index 2359e8d..a266cfa 100644 --- a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/config.py +++ b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/config.py @@ -1,8 +1,7 @@ from typing import List -from openg2p_fastapi_common.config import Settings +from g2p_cash_transfer_bridge_core.config import Settings from pydantic import BaseModel, model_validator -from pydantic_settings import SettingsConfigDict class PayerFaPayeeFaMapping(BaseModel): @@ -40,23 +39,7 @@ class FaBackendMapping(BaseModel): class Settings(Settings): - model_config = SettingsConfigDict( - env_prefix="gpb_core_", env_file=".env", extra="allow" - ) - - openapi_title: str = "G2P Payments Bridge" - openapi_description: str = """ - This module implements G2P Connect Disburse APIs. - It contains API layer and multiplexer for different payment backends. - - *********************************** - Further details goes here - *********************************** - """ - openapi_version: str = "0.1.0" - db_dbname: str = "gpbdb" - - response_sender_id: str = "g2p.payments.bridge.openg2p" + response_sender_id: str = "g2p.cash.transfer.bridge.openg2p" get_backend_name_from_translate: bool = True # TODO: Convert this to ORM Model rather than config diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/controllers/__init__.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/controllers/__init__.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/controllers/__init__.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/controllers/__init__.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/controllers/disbursement_controller.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/controllers/disbursement_controller.py similarity index 91% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/controllers/disbursement_controller.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/controllers/disbursement_controller.py index 95f9ccb..4b46a66 100644 --- a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/controllers/disbursement_controller.py +++ b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/controllers/disbursement_controller.py @@ -1,10 +1,7 @@ import asyncio import uuid -from openg2p_fastapi_common.controller import BaseController - -from ..config import Settings -from ..models.disburse import ( +from g2p_cash_transfer_bridge_core.models.disburse import ( DisburseHttpRequest, DisburseHttpResponse, DisburseResponse, @@ -12,8 +9,16 @@ DisburseTxnStatusHttpResponse, SingleDisburseResponse, ) -from ..models.msg_header import MsgResponseHeader, MsgStatusEnum -from ..services.payment_multiplexer import PaymentMultiplexerService +from g2p_cash_transfer_bridge_core.models.msg_header import ( + MsgResponseHeader, + MsgStatusEnum, +) +from g2p_cash_transfer_bridge_core.services.payment_multiplexer import ( + PaymentMultiplexerService, +) +from openg2p_fastapi_common.controller import BaseController + +from ..config import Settings _config = Settings.get_config() @@ -43,7 +48,7 @@ async def disburse_sync_disburse(self, request: DisburseHttpRequest): async def process_disbursement(): disburse_txn = request.message.model_copy() - await self.payment_multiplexer.make_disbursements(disburse_txn) + await self.payment_multiplexer.disburse(disburse_txn) asyncio.create_task(process_disbursement()) diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/__init__.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/services/__init__.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/__init__.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/services/__init__.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/payment_multiplexer.py b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/services/payment_multiplexer.py similarity index 89% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/payment_multiplexer.py rename to g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/services/payment_multiplexer.py index bc2158d..4bda285 100644 --- a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/payment_multiplexer.py +++ b/g2p-cash-transfer-bridge-api/src/g2p_cash_transfer_bridge_api/services/payment_multiplexer.py @@ -2,13 +2,7 @@ import re import uuid -from openg2p_fastapi_common.errors.http_exceptions import BadRequestError -from openg2p_fastapi_common.service import BaseService - -from g2p_payments_bridge_core.models.orm.payment_list import PaymentListItem - -from ..config import Settings -from ..models.disburse import ( +from g2p_cash_transfer_bridge_core.models.disburse import ( DisburseRequest, DisburseResponse, DisburseTxnStatusRequest, @@ -17,13 +11,22 @@ SingleDisburseTxnStatusResponse, TxnStatusAttributeTypeEnum, ) -from .id_translate_service import IdTranslateService +from g2p_cash_transfer_bridge_core.models.orm.payment_list import PaymentListItem +from g2p_cash_transfer_bridge_core.services.id_translate_service import ( + IdTranslateService, +) +from g2p_cash_transfer_bridge_core.services.payment_multiplexer import ( + PaymentMultiplexerService as CorePaymentMultiplexerService, +) +from openg2p_fastapi_common.errors.http_exceptions import BadRequestError + +from ..config import Settings _config = Settings.get_config() _logger = logging.getLogger(__name__) -class PaymentMultiplexerService(BaseService): +class PaymentMultiplexerService(CorePaymentMultiplexerService): def __init__(self, **kwargs): super().__init__(**kwargs) self._id_translate_service = IdTranslateService.get_component() @@ -40,7 +43,7 @@ async def get_payment_backend_from_fa(self, fa: str): return mapping.name return None - async def make_disbursements(self, disburse_request: DisburseRequest): + async def disburse(self, disburse_request: DisburseRequest): if _config.get_backend_name_from_translate: payee_fa_list = [] try: @@ -79,7 +82,7 @@ async def disbursement_status( ref_ids = status_request.txnstatus_request.attribute_value if not isinstance(ref_ids, list): raise BadRequestError( - "GPB-PMS-350", "attribute_value is supposed to be a list." + "GCTB-PMS-350", "attribute_value is supposed to be a list." ) payment_list = await PaymentListItem.get_by_request_ids(ref_ids) return DisburseTxnStatusResponse( @@ -112,7 +115,7 @@ async def disbursement_status( txn_id = status_request.txnstatus_request.attribute_value if not isinstance(ref_ids, str): raise BadRequestError( - "GPB-PMS-350", "attribute_value is supposed to be a string." + "GCTB-PMS-350", "attribute_value is supposed to be a string." ) payment_list = await PaymentListItem.get_by_batch_id(txn_id) return DisburseTxnStatusResponse( diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/orm/__init__.py b/g2p-cash-transfer-bridge-api/tests/__init__.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/orm/__init__.py rename to g2p-cash-transfer-bridge-api/tests/__init__.py diff --git a/g2p-cash-transfer-bridge-core/LICENSE b/g2p-cash-transfer-bridge-core/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/g2p-cash-transfer-bridge-core/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/g2p-cash-transfer-bridge-core/README.md b/g2p-cash-transfer-bridge-core/README.md new file mode 100644 index 0000000..9b0ffa3 --- /dev/null +++ b/g2p-cash-transfer-bridge-core/README.md @@ -0,0 +1,9 @@ +# G2P Cash Transfer Bridge: Core +[![Pre-commit Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml?query=branch%3Adevelop) +[![Build Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml?query=branch%3Adevelop) +[![codecov](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge/branch/develop/graph/badge.svg)](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge) +[![openapi](https://img.shields.io/badge/open--API-swagger-brightgreen)](https://validator.swagger.io/?url=https://raw.githubusercontent.com/OpenG2P/g2p-cash-transfer-bridge/develop/api-docs/generated/openapi.json) +![PyPI](https://img.shields.io/pypi/v/g2p-cash-transfer-bridge-core?label=pypi%20package) +![PyPI - Downloads](https://img.shields.io/pypi/dm/g2p-cash-transfer-bridge-core) + +Core module for G2P Cash Transfer Bridge. diff --git a/g2p-payments-bridge-core/pyproject.toml b/g2p-cash-transfer-bridge-core/pyproject.toml similarity index 71% rename from g2p-payments-bridge-core/pyproject.toml rename to g2p-cash-transfer-bridge-core/pyproject.toml index 865bff1..c777b56 100644 --- a/g2p-payments-bridge-core/pyproject.toml +++ b/g2p-cash-transfer-bridge-core/pyproject.toml @@ -3,12 +3,12 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "g2p-payments-bridge-core" +name = "g2p-cash-transfer-bridge-core" version = "0.1.0" authors = [ { name="OpenG2P", email="info@openg2p.org" }, ] -description = "G2P Payments Bridge: Core" +description = "G2P Cash Transfer Bridge: Core" readme = "README.md" requires-python = ">=3.7" classifiers = [ @@ -24,5 +24,5 @@ dependencies=[ [project.urls] Homepage = "https://openg2p.org" Documentation = "https://docs.openg2p.org/" -Repository = "https://github.com/OpenG2P/g2p-payments-bridge" -Source = "https://github.com/OpenG2P/g2p-payments-bridge" +Repository = "https://github.com/OpenG2P/g2p-cash-transfer-bridge" +Source = "https://github.com/OpenG2P/g2p-cash-transfer-bridge" diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/utils/__init__.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/__init__.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/utils/__init__.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/__init__.py diff --git a/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/app.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/app.py new file mode 100644 index 0000000..ddbf089 --- /dev/null +++ b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/app.py @@ -0,0 +1,15 @@ +import asyncio + +from openg2p_fastapi_common.app import Initializer + +from .models.orm.payment_list import PaymentListItem + + +class Initializer(Initializer): + def migrate_database(self, args): + super().migrate_database(args) + + async def migrate(): + await PaymentListItem.create_migrate() + + asyncio.run(migrate()) diff --git a/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/config.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/config.py new file mode 100644 index 0000000..410af31 --- /dev/null +++ b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/config.py @@ -0,0 +1,20 @@ +from openg2p_fastapi_common.config import Settings +from pydantic_settings import SettingsConfigDict + + +class Settings(Settings): + model_config = SettingsConfigDict( + env_prefix="gctb_core_", env_file=".env", extra="allow" + ) + + openapi_title: str = "G2P Cash Transfer Bridge" + openapi_description: str = """ + This module implements G2P Connect Disburse APIs. + It contains API layer and multiplexer for different payment backends. + + *********************************** + Further details goes here + *********************************** + """ + openapi_version: str = "0.1.0" + db_dbname: str = "gctbdb" diff --git a/g2p-payments-bridge-core/tests/__init__.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/__init__.py similarity index 100% rename from g2p-payments-bridge-core/tests/__init__.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/__init__.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/disburse.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/disburse.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/disburse.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/disburse.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/msg_header.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/msg_header.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/msg_header.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/msg_header.py diff --git a/gpb-mojaloop-sdk-payment-backend/tests/__init__.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/orm/__init__.py similarity index 100% rename from gpb-mojaloop-sdk-payment-backend/tests/__init__.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/orm/__init__.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/orm/payment_list.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/orm/payment_list.py similarity index 96% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/orm/payment_list.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/orm/payment_list.py index 5d621a0..a1f0efb 100644 --- a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/models/orm/payment_list.py +++ b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/models/orm/payment_list.py @@ -7,11 +7,11 @@ from sqlalchemy.ext.asyncio import async_sessionmaker from sqlalchemy.orm import Mapped, mapped_column -from g2p_payments_bridge_core.models.disburse import ( +from g2p_cash_transfer_bridge_core.models.disburse import ( SingleDisburseRequest, SingleDisburseStatusEnum, ) -from g2p_payments_bridge_core.models.msg_header import MsgStatusEnum +from g2p_cash_transfer_bridge_core.models.msg_header import MsgStatusEnum class PaymentListItem(BaseORMModelWithTimes): diff --git a/gpb-simple-mpesa-payment-backend/tests/__init__.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/__init__.py similarity index 100% rename from gpb-simple-mpesa-payment-backend/tests/__init__.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/__init__.py diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/id_translate_service.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/id_translate_service.py similarity index 100% rename from g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/id_translate_service.py rename to g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/id_translate_service.py diff --git a/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/payment_multiplexer.py b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/payment_multiplexer.py new file mode 100644 index 0000000..bb7c035 --- /dev/null +++ b/g2p-cash-transfer-bridge-core/src/g2p_cash_transfer_bridge_core/services/payment_multiplexer.py @@ -0,0 +1,17 @@ +from openg2p_fastapi_common.service import BaseService + +from ..models.disburse import ( + DisburseRequest, + DisburseTxnStatusRequest, + DisburseTxnStatusResponse, +) + + +class PaymentMultiplexerService(BaseService): + async def disburse(self, disburse_request: DisburseRequest): + raise NotImplementedError() + + async def disbursement_status( + self, status_request: DisburseTxnStatusRequest + ) -> DisburseTxnStatusResponse: + raise NotImplementedError() diff --git a/gpb-translate-id-fa/src/gpb_translate_id_fa/__init__.py b/g2p-cash-transfer-bridge-core/tests/__init__.py similarity index 100% rename from gpb-translate-id-fa/src/gpb_translate_id_fa/__init__.py rename to g2p-cash-transfer-bridge-core/tests/__init__.py diff --git a/g2p-payments-bridge-core/LICENSE b/g2p-payments-bridge-core/LICENSE deleted file mode 100644 index a612ad9..0000000 --- a/g2p-payments-bridge-core/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/g2p-payments-bridge-core/README.md b/g2p-payments-bridge-core/README.md deleted file mode 100644 index a3be599..0000000 --- a/g2p-payments-bridge-core/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# G2P Payments Bridge: Core -[![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/g2p-payments-bridge-core?label=pypi%20package) -![PyPI - Downloads](https://img.shields.io/pypi/dm/g2p-payments-bridge-core) - -Core module for G2P Payments Bridge, which contains API layer and multiplexer for different payment backends. This implements G2P Connect Disburse APIs. diff --git a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/__init__.py b/g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/__init__.py deleted file mode 100644 index 215fed9..0000000 --- a/g2p-payments-bridge-core/src/g2p_payments_bridge_core/services/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .id_translate_service import IdTranslateService diff --git a/gctb-mojaloop-sdk-payment-backend/README.md b/gctb-mojaloop-sdk-payment-backend/README.md new file mode 100644 index 0000000..353aa6d --- /dev/null +++ b/gctb-mojaloop-sdk-payment-backend/README.md @@ -0,0 +1,3 @@ +# G2P Cash Transfer Bridge: Mojaloop SDK Scheme Adapter Payment Backend. + +Mojaloop SDK Scheme Adapter backend for G2P Cash Transfer Bridge. diff --git a/gpb-mojaloop-sdk-payment-backend/payment_backend.py b/gctb-mojaloop-sdk-payment-backend/payment_backend.py old mode 100644 new mode 100755 similarity index 78% rename from gpb-mojaloop-sdk-payment-backend/payment_backend.py rename to gctb-mojaloop-sdk-payment-backend/payment_backend.py index b1f4dd4..a613e9c --- a/gpb-mojaloop-sdk-payment-backend/payment_backend.py +++ b/gctb-mojaloop-sdk-payment-backend/payment_backend.py @@ -9,12 +9,14 @@ import httpx from fastapi import FastAPI -from g2p_payments_bridge_core.models.disburse import ( +from g2p_cash_transfer_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 g2p_payments_bridge_core.services.id_translate_service import IdTranslateService +from g2p_cash_transfer_bridge_core.models.msg_header import MsgStatusEnum +from g2p_cash_transfer_bridge_core.models.orm.payment_list import PaymentListItem +from g2p_cash_transfer_bridge_core.services.id_translate_service import ( + IdTranslateService, +) from openg2p_fastapi_common.config import Settings as BaseSettings from openg2p_fastapi_common.context import dbengine from openg2p_fastapi_common.service import BaseService @@ -26,27 +28,31 @@ class Settings(BaseSettings): model_config = SettingsConfigDict( - env_prefix="gpb_mojaloop_sdk_", env_file=".env", extra="allow" + env_prefix="gctb_mojaloop_sdk_", env_file=".env", extra="allow" ) - openapi_title: str = "GPB Mojaloop SDK Adapter Payment Backend" + openapi_title: str = "GCTB Mojaloop SDK Adapter Payment Backend" openapi_description: str = """ - Payment Backend for Mojaloop SDK Adapter of G2P Payments Bridge. + Payment Backend for Mojaloop SDK Adapter of G2P Cash Transfer Bridge. *********************************** Further details goes here *********************************** """ openapi_version: str = "0.1.0" - payment_backend_name: str = "mojaloop" - db_dbname: str = "gpbdb" + db_dbname: str = "gctbdb" + + dsbmt_loop_interval_secs: int = 10 + dsbmt_loop_filter_backend_name: bool = True + dsbmt_loop_filter_status: List[str] = ["rcvd", "fail"] + translate_id_to_fa: bool = True 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" + transfers_url: str = "https://bank1.mec.openg2p.net/api/outbound/transfers" + payer_id_type: str = "ACCOUNT_ID" + payer_id_value: str = "1212121212" + payee_id_type: str = "ACCOUNT_ID" + transfer_note: str = "GCTB benefit transfer" translate_id_to_fa: bool = True @@ -114,11 +120,13 @@ async def disburse_loop(self): db_response = list(result.scalars()) if db_response: - _logger.info("GPB Mojaloop - processing payment from payment list.") + _logger.info( + "GCTB Mojaloop - processing payment from payment list." + ) await self.disburse(db_response, session) else: _logger.info( - "GPB Mojaloop - no records found in payment list table." + "GCTB Mojaloop - no records found in payment list table." ) await asyncio.sleep(_config.dsbmt_loop_interval_secs) @@ -127,7 +135,13 @@ async def disburse(self, payments: List[PaymentListItem], session: AsyncSession) for payment in payments: payee_acc_no = "" if _config.translate_id_to_fa: - payee_acc_no = self.id_translate_service.translate(payment.to_fa) + payee_acc_no = await self.id_translate_service.translate( + [ + payment.to_fa, + ] + ) + if payee_acc_no: + payee_acc_no = payee_acc_no[0] else: payee_acc_no = payment.to_fa data = { @@ -175,16 +189,18 @@ 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 gctb_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 +from openg2p_fastapi_common.ping import PingInitializer class PaymentBackendInitializer(Initializer): def initialize(self, **kwargs): - MojaloopSdkPaymentBackendService() + super().initialize(**kwargs) + self.payment_backend = MojaloopSdkPaymentBackendService() @asynccontextmanager async def fastapi_app_lifespan(self, app: FastAPI): @@ -197,4 +213,5 @@ async def fastapi_app_lifespan(self, app: FastAPI): main_init = PaymentBackendInitializer() G2pConnectMapperInitializer() TranslateIdInitializer() + PingInitializer() main_init.main() diff --git a/gpb-translate-id-fa/tests/__init__.py b/gctb-mojaloop-sdk-payment-backend/tests/__init__.py similarity index 100% rename from gpb-translate-id-fa/tests/__init__.py rename to gctb-mojaloop-sdk-payment-backend/tests/__init__.py diff --git a/gctb-simple-mpesa-payment-backend/README.md b/gctb-simple-mpesa-payment-backend/README.md new file mode 100644 index 0000000..133208d --- /dev/null +++ b/gctb-simple-mpesa-payment-backend/README.md @@ -0,0 +1,3 @@ +# G2P Cash Transfer Bridge: Simple-mpesa Payment Backend. + +Payment Backend for Simple M-pesa of G2P Cash Transfer Bridge. diff --git a/gpb-simple-mpesa-payment-backend/payment_backend.py b/gctb-simple-mpesa-payment-backend/payment_backend.py similarity index 86% rename from gpb-simple-mpesa-payment-backend/payment_backend.py rename to gctb-simple-mpesa-payment-backend/payment_backend.py index 8636b73..4f87c1b 100755 --- a/gpb-simple-mpesa-payment-backend/payment_backend.py +++ b/gctb-simple-mpesa-payment-backend/payment_backend.py @@ -9,12 +9,14 @@ import httpx from fastapi import FastAPI -from g2p_payments_bridge_core.models.disburse import ( +from g2p_cash_transfer_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 g2p_payments_bridge_core.services.id_translate_service import IdTranslateService +from g2p_cash_transfer_bridge_core.models.msg_header import MsgStatusEnum +from g2p_cash_transfer_bridge_core.models.orm.payment_list import PaymentListItem +from g2p_cash_transfer_bridge_core.services.id_translate_service import ( + IdTranslateService, +) from openg2p_fastapi_common.config import Settings as BaseSettings from openg2p_fastapi_common.context import dbengine from openg2p_fastapi_common.service import BaseService @@ -26,11 +28,11 @@ class Settings(BaseSettings): model_config = SettingsConfigDict( - env_prefix="gpb_simple_mpesa_", env_file=".env", extra="allow" + env_prefix="gctb_simple_mpesa_", env_file=".env", extra="allow" ) - openapi_title: str = "GPB Simple Mpesa Payment Backend" + openapi_title: str = "GCTB Simple Mpesa Payment Backend" openapi_description: str = """ - Payment Backend for Simple M-pesa of G2P Payments Bridge. + Payment Backend for Simple M-pesa of G2P Cash Transfer Bridge. *********************************** Further details goes here @@ -38,7 +40,12 @@ class Settings(BaseSettings): """ openapi_version: str = "0.1.0" payment_backend_name: str = "mpesa" - db_dbname: str = "gpbdb" + db_dbname: str = "gctbdb" + + dsbmt_loop_interval_secs: int = 10 + dsbmt_loop_filter_backend_name: bool = True + dsbmt_loop_filter_status: List[str] = ["rcvd", "fail"] + translate_id_to_fa: bool = True agent_email: str = "" agent_password: str = "" @@ -46,10 +53,6 @@ class Settings(BaseSettings): payment_url: str = "" api_timeout: int = 10 customer_type: str = "subscriber" - dsbmt_loop_interval_secs: int = 10 - dsbmt_loop_filter_backend_name: bool = True - dsbmt_loop_filter_status: List[str] = ["rcvd", "fail"] - translate_id_to_fa: bool = True _config = Settings.get_config() @@ -118,12 +121,12 @@ async def disburse_loop(self): db_response = list(result.scalars()) if db_response: _logger.info( - "GPB Simple Mpesa - processing payment from payment list." + "GCTB Simple Mpesa - processing payment from payment list." ) await self.disburse(db_response, session) else: _logger.info( - "GPB Simple Mpesa - no records found in payment list table." + "GCTB Simple Mpesa - no records found in payment list table." ) await asyncio.sleep(_config.dsbmt_loop_interval_secs) @@ -155,7 +158,13 @@ async def disburse(self, payments: List[PaymentListItem], session: AsyncSession) for payment in payments: payee_acc_no = "" if _config.translate_id_to_fa: - payee_acc_no = self.id_translate_service.translate(payment.to_fa) + payee_acc_no = await self.id_translate_service.translate( + [ + payment.to_fa, + ] + ) + if payee_acc_no: + payee_acc_no = payee_acc_no[0] else: payee_acc_no = payment.to_fa headers = { @@ -192,11 +201,12 @@ async def get_account_no_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 gctb_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 +from openg2p_fastapi_common.ping import PingInitializer class PaymentBackendInitializer(Initializer): @@ -215,4 +225,5 @@ async def fastapi_app_lifespan(self, app: FastAPI): main_init = PaymentBackendInitializer() G2pConnectMapperInitializer() TranslateIdInitializer() + PingInitializer() main_init.main() diff --git a/gctb-simple-mpesa-payment-backend/tests/__init__.py b/gctb-simple-mpesa-payment-backend/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gctb-translate-id-fa/LICENSE b/gctb-translate-id-fa/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/gctb-translate-id-fa/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/gctb-translate-id-fa/README.md b/gctb-translate-id-fa/README.md new file mode 100644 index 0000000..fa72374 --- /dev/null +++ b/gctb-translate-id-fa/README.md @@ -0,0 +1,9 @@ +# G2P Cash Transfer Bridge: Translate ID to Financial Address +[![Pre-commit Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/pre-commit.yml?query=branch%3Adevelop) +[![Build Status](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml/badge.svg?branch=develop)](https://github.com/OpenG2P/g2p-cash-transfer-bridge/actions/workflows/test.yml?query=branch%3Adevelop) +[![codecov](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge/branch/develop/graph/badge.svg)](https://codecov.io/gh/OpenG2P/g2p-cash-transfer-bridge) +[![openapi](https://img.shields.io/badge/open--API-swagger-brightgreen)](https://validator.swagger.io/?url=https://raw.githubusercontent.com/OpenG2P/g2p-cash-transfer-bridge/develop/api-docs/generated/openapi.json) +![PyPI](https://img.shields.io/pypi/v/gctb-translate-id-fa?label=pypi%20package) +![PyPI - Downloads](https://img.shields.io/pypi/dm/gctb-translate-id-fa) + +Module for G2P Cash Transfer Bridge to translate ID to Financial Address using G2P Connect APIs. diff --git a/gpb-translate-id-fa/pyproject.toml b/gctb-translate-id-fa/pyproject.toml similarity index 66% rename from gpb-translate-id-fa/pyproject.toml rename to gctb-translate-id-fa/pyproject.toml index 298bf9a..951f776 100644 --- a/gpb-translate-id-fa/pyproject.toml +++ b/gctb-translate-id-fa/pyproject.toml @@ -3,12 +3,12 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "gpb-translate-id-fa" +name = "gctb-translate-id-fa" version = "0.1.0" authors = [ { name="OpenG2P", email="info@openg2p.org" }, ] -description = "G2P Payments Bridge: Translate ID to Financial Address." +description = "G2P Cash Transfer Bridge: Translate ID to Financial Address." readme = "README.md" requires-python = ">=3.7" classifiers = [ @@ -17,12 +17,12 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies=[ - "g2p-payments-bridge-core", + "g2p-cash-transfer-bridge-core", "openg2p-common-g2pconnect-id-mapper" ] [project.urls] Homepage = "https://openg2p.org" Documentation = "https://docs.openg2p.org/" -Repository = "https://github.com/OpenG2P/g2p-payments-bridge" -Source = "https://github.com/OpenG2P/g2p-payments-bridge" +Repository = "https://github.com/OpenG2P/g2p-cash-transfer-bridge" +Source = "https://github.com/OpenG2P/g2p-cash-transfer-bridge" diff --git a/gctb-translate-id-fa/src/gctb_translate_id_fa/__init__.py b/gctb-translate-id-fa/src/gctb_translate_id_fa/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gpb-translate-id-fa/src/gpb_translate_id_fa/app.py b/gctb-translate-id-fa/src/gctb_translate_id_fa/app.py similarity index 58% rename from gpb-translate-id-fa/src/gpb_translate_id_fa/app.py rename to gctb-translate-id-fa/src/gctb_translate_id_fa/app.py index 5025d4f..5b21fa3 100644 --- a/gpb-translate-id-fa/src/gpb_translate_id_fa/app.py +++ b/gctb-translate-id-fa/src/gctb_translate_id_fa/app.py @@ -1,6 +1,12 @@ +# ruff: noqa: E402 + +from .config import Settings + +_config = Settings.get_config() + from openg2p_fastapi_common.app import Initializer -from .services import G2PConnectIdTranslateService +from .services.g2p_connect_id_translate import G2PConnectIdTranslateService class Initializer(Initializer): diff --git a/gpb-translate-id-fa/src/gpb_translate_id_fa/config.py b/gctb-translate-id-fa/src/gctb_translate_id_fa/config.py similarity index 67% rename from gpb-translate-id-fa/src/gpb_translate_id_fa/config.py rename to gctb-translate-id-fa/src/gctb_translate_id_fa/config.py index e86b48f..3aaa3ae 100644 --- a/gpb-translate-id-fa/src/gpb_translate_id_fa/config.py +++ b/gctb-translate-id-fa/src/gctb_translate_id_fa/config.py @@ -5,5 +5,6 @@ class Settings(IdMapperSettings, Settings): model_config = SettingsConfigDict( - env_prefix="gpb_id_translate_", env_file=".env", extra="allow" + env_prefix="gctb_id_translate_", env_file=".env", extra="allow" ) + callback_api_common_prefix: str = "/internal/callback" diff --git a/gctb-translate-id-fa/src/gctb_translate_id_fa/services/__init__.py b/gctb-translate-id-fa/src/gctb_translate_id_fa/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gpb-translate-id-fa/src/gpb_translate_id_fa/services/g2p_connect_id_translate.py b/gctb-translate-id-fa/src/gctb_translate_id_fa/services/g2p_connect_id_translate.py similarity index 90% rename from gpb-translate-id-fa/src/gpb_translate_id_fa/services/g2p_connect_id_translate.py rename to gctb-translate-id-fa/src/gctb_translate_id_fa/services/g2p_connect_id_translate.py index 7e7ca54..185dee1 100644 --- a/gpb-translate-id-fa/src/gpb_translate_id_fa/services/g2p_connect_id_translate.py +++ b/gctb-translate-id-fa/src/gctb_translate_id_fa/services/g2p_connect_id_translate.py @@ -1,6 +1,8 @@ from typing import List -from g2p_payments_bridge_core.services import IdTranslateService +from g2p_cash_transfer_bridge_core.services.id_translate_service import ( + IdTranslateService, +) from openg2p_common_g2pconnect_id_mapper.models.common import MapperValue from openg2p_common_g2pconnect_id_mapper.service.resolve import ( MapperResolveService as IDMapperResolveService, @@ -25,7 +27,7 @@ async def translate(self, ids: List[str]) -> List[str]: ) if not res: raise BaseAppException( - "GPB-IMS-300", + "GCTB-IMS-300", "ID Mapper Resolve Id: No response received", ) if not res.refs: diff --git a/gctb-translate-id-fa/tests/__init__.py b/gctb-translate-id-fa/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gpb-mojaloop-sdk-payment-backend/README.md b/gpb-mojaloop-sdk-payment-backend/README.md deleted file mode 100644 index f4461f8..0000000 --- a/gpb-mojaloop-sdk-payment-backend/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# G2P Payments Bridge: Mojaloop SDK Scheme Adapter Payment Backend. - -Mojaloop SDK Scheme Adapter backend for G2P Payments Bridge. diff --git a/gpb-simple-mpesa-payment-backend/README.md b/gpb-simple-mpesa-payment-backend/README.md deleted file mode 100644 index 3ed96ee..0000000 --- a/gpb-simple-mpesa-payment-backend/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# G2P Payments Bridge: Simple-mpesa Payment Backend. - -Payment Backend for Simple M-pesa of G2P Payments Bridge. diff --git a/gpb-translate-id-fa/README.md b/gpb-translate-id-fa/README.md deleted file mode 100644 index 793baa6..0000000 --- a/gpb-translate-id-fa/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# G2P Payments Bridge: Translate ID to Financial Address -[![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-translate-id-fa?label=pypi%20package) -![PyPI - Downloads](https://img.shields.io/pypi/dm/gpb-translate-id-fa) - -Core module for G2P Payments Bridge, which contains API layer and multiplexer for different payment backends. diff --git a/gpb-translate-id-fa/src/gpb_translate_id_fa/services/__init__.py b/gpb-translate-id-fa/src/gpb_translate_id_fa/services/__init__.py deleted file mode 100644 index e295a38..0000000 --- a/gpb-translate-id-fa/src/gpb_translate_id_fa/services/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .g2p_connect_id_translate import G2PConnectIdTranslateService diff --git a/main.py b/main.py index b9b935f..f715f49 100755 --- a/main.py +++ b/main.py @@ -1,22 +1,14 @@ #!/usr/bin/env python3 -from g2p_payments_bridge_core.app import Initializer as CoreInitializer - -# from gpb_mojaloop_sdk_payment_backend.app import ( -# Initializer as MojaloopSdkBackendInitializer, -# ) -# from gpb_simple_mpesa_payment_backend.app import ( -# Initializer as SimpleMpesaPaymentBackendInitializer, -# ) -from gpb_translate_id_fa.app import Initializer as TranslateIdInitializer +from g2p_cash_transfer_bridge_api.app import Initializer as ApiInitializer +from gctb_translate_id_fa.app import Initializer as TranslateIdInitializer from openg2p_common_g2pconnect_id_mapper.app import ( Initializer as G2pConnectMapperInitializer, ) +from openg2p_fastapi_common.ping import PingInitializer -main_init = CoreInitializer() +main_init = ApiInitializer() G2pConnectMapperInitializer() TranslateIdInitializer() -# SimpleMpesaPaymentBackendInitializer() -# MojaloopSdkBackendInitializer() - +PingInitializer() main_init.main() diff --git a/payment-backend.Dockerfile b/payment-backend.Dockerfile new file mode 100644 index 0000000..3c47d94 --- /dev/null +++ b/payment-backend.Dockerfile @@ -0,0 +1,30 @@ +FROM bitnami/python:3.10.13-debian-11-r24 + +ARG container_user=openg2p +ARG container_user_group=openg2p +ARG container_user_uid=1001 +ARG container_user_gid=1001 + +RUN groupadd -g ${container_user_gid} ${container_user_group} \ + && useradd -mN -u ${container_user_uid} -G ${container_user_group} -s /bin/bash ${container_user} \ + && mkdir -p /app/payment_backend + +WORKDIR /app + +RUN chown -R ${container_user}:${container_user_group} /app +USER ${container_user} + +ADD --chown=${container_user}:${container_user_group} . /app/src + +RUN python3 -m venv venv \ + && . ./venv/bin/activate +RUN python3 -m pip install \ + git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-common\&subdirectory=openg2p-fastapi-common \ + git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-auth\&subdirectory=openg2p-fastapi-auth \ + git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-common-g2pconnect-id-mapper\&subdirectory=openg2p-common-g2pconnect-id-mapper \ + ./src/g2p-cash-transfer-bridge-core \ + ./src/gctb-translate-id-fa + +WORKDIR /app/payment_backend + +CMD python3 payment_backend.py run diff --git a/tox.ini b/tox.ini index 3c2471b..c6334af 100644 --- a/tox.ini +++ b/tox.ini @@ -7,17 +7,18 @@ minversion = 4.11.3 [testenv] description = run the tests with pytest commands = pytest - --cov=g2p-payments-bridge-core - --cov=gpb-simple-mpesa-payment-backend - --cov=gpb-translate-id-fa + --cov=g2p-cash-transfer-bridge-core + --cov=g2p-cash-transfer-bridge-api + --cov=gctb-translate-id-fa + --cov=gctb-simple-mpesa-payment-backend + --cov=gctb-mojaloop-sdk-payment-backend deps = git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-common\&subdirectory=openg2p-fastapi-common git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-fastapi-auth\&subdirectory=openg2p-fastapi-auth \ git+https://github.com/openg2p/openg2p-fastapi-common.git@develop\#egg=openg2p-common-g2pconnect-id-mapper\&subdirectory=openg2p-common-g2pconnect-id-mapper - ./g2p-payments-bridge-core - ./gpb-simple-mpesa-payment-backend - ./gpb-mojaloop-sdk-payment-backend - ./gpb-translate-id-fa + ./g2p-cash-transfer-bridge-core + ./g2p-cash-transfer-bridge-api + ./gctb-translate-id-fa pytest-cov [testenv:clean]