Skip to main content

Python SDK for Bank of Maldives Connect API with synchronous and asynchronous support

Project description

BML Connect Python SDK

PyPI version Python Support License: MIT

ViewCount GitHub forks GitHub stars PyPI - Downloads contributions welcome GitHub issues

Python SDK for Bank of Maldives Connect API with synchronous and asynchronous support.
Compatible with all Python frameworks including Django, Flask, FastAPI, and Sanic.

Features

  • ๐Ÿ”„ Sync/Async Support: Choose your preferred programming style
  • ๐ŸŽฏ Full API Coverage: Create, retrieve, cancel transactions; webhook signature verification
  • ๐Ÿ“ Type Annotations: Full type hint support for better development experience
  • ๐Ÿ›ก๏ธ Error Handling: Comprehensive error hierarchy for easy debugging
  • ๐Ÿš€ Framework Agnostic: Works with any Python web framework
  • ๐Ÿ”’ Context Manager Support: Automatic resource cleanup with with/async with
  • ๐Ÿ“„ MIT Licensed: Open source and free to use

Installation

pip install bml-connect-python

Quick Start

Synchronous Usage

from bml_connect import BMLConnect, Environment

# Use as a context manager for automatic cleanup
with BMLConnect(
    api_key="your_api_key",
    app_id="your_app_id",
    environment=Environment.SANDBOX
) as client:
    transaction = client.transactions.create_transaction({
        "amount": 1500,  # 15.00 MVR
        "currency": "MVR",
        "provider": "alipay",
        "redirectUrl": "https://yourstore.com/success",
        "localId": "order_123",
        "customerReference": "Customer #456"
    })
    print(f"Transaction ID: {transaction.transaction_id}")
    print(f"Payment URL: {transaction.url}")

Asynchronous Usage

import asyncio
from bml_connect import BMLConnect, Environment

async def main():
    async with BMLConnect(
        api_key="your_api_key",
        app_id="your_app_id",
        environment=Environment.SANDBOX,
        async_mode=True
    ) as client:
        transaction = await client.transactions.create_transaction({
            "amount": 2000,
            "currency": "MVR",
            "provider": "wechat",
            "redirectUrl": "https://yourstore.com/success"
        })
        print(f"Transaction ID: {transaction.transaction_id}")

asyncio.run(main())

Framework Integration Examples

Flask Integration

from flask import Flask, request, jsonify
from bml_connect import BMLConnect

app = Flask(__name__)
client = BMLConnect(api_key="your_api_key", app_id="your_app_id")

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_json()
    signature = payload.get('signature')

    if client.verify_webhook_signature(payload, signature):
        # Process webhook
        return jsonify({"status": "success"}), 200
    else:
        return jsonify({"error": "Invalid signature"}), 403

FastAPI Integration

from fastapi import FastAPI, Request, HTTPException
from bml_connect import BMLConnect

app = FastAPI()
client = BMLConnect(api_key="your_api_key", app_id="your_app_id")

@app.post("/webhook")
async def handle_webhook(request: Request):
    payload = await request.json()
    signature = payload.get("signature")

    if client.verify_webhook_signature(payload, signature):
        return {"status": "success"}
    else:
        raise HTTPException(403, "Invalid signature")

Sanic Integration

from sanic import Sanic, response
from bml_connect import BMLConnect

app = Sanic("BMLWebhook")
client = BMLConnect(api_key="your_api_key", app_id="your_app_id")

@app.post('/webhook')
async def webhook(request):
    payload = request.json
    signature = payload.get('signature')

    if client.verify_webhook_signature(payload, signature):
        return response.json({"status": "success"})
    else:
        return response.json({"error": "Invalid signature"}, status=403)

API Reference

BMLConnect(api_key, app_id, environment, async_mode, timeout)

Main entry point for the SDK.

Parameter Type Default Description
api_key str required Your API key from the BML merchant portal
app_id str required Your application ID from the BML merchant portal
environment Environment or str PRODUCTION Environment.SANDBOX or Environment.PRODUCTION
async_mode bool False Set True to use async methods
timeout int 30 Request timeout in seconds

Transaction Methods

Method Sync Async Description
create_transaction(data) โœ… โœ… Create a new payment transaction
get_transaction(id) โœ… โœ… Retrieve a transaction by ID
cancel_transaction(id) โœ… โœ… Cancel a transaction by ID
list_transactions(...) โœ… โœ… List transactions with optional filters

list_transactions Parameters

client.transactions.list_transactions(
    page=1,
    per_page=20,
    state="CONFIRMED",       # Filter by TransactionState value
    provider="alipay",       # Filter by provider
    start_date="2026-01-01", # Filter from date
    end_date="2026-02-01",   # Filter to date
)

Core Classes

  • BMLConnect: Main entry point for the SDK
  • Transaction: Typed transaction object returned by all transaction methods
  • QRCode: QR code details attached to a transaction
  • PaginatedResponse: Wraps paginated transaction list results
  • Environment: SANDBOX or PRODUCTION
  • SignMethod: SHA1 (default) or MD5
  • TransactionState: CREATED, QR_CODE_GENERATED, CONFIRMED, CANCELLED, FAILED, EXPIRED, REFUND_REQUESTED, REFUNDED

Exception Hierarchy

BMLConnectError
โ”œโ”€โ”€ AuthenticationError   (401)
โ”œโ”€โ”€ ValidationError       (400)
โ”œโ”€โ”€ NotFoundError         (404)
โ”œโ”€โ”€ ServerError           (5xx)
โ””โ”€โ”€ RateLimitError        (429)

Signature Utilities

from bml_connect import SignatureUtils

# Generate a signature manually
signature = SignatureUtils.generate_signature(data, api_key, method)

# Verify a signature with constant-time comparison
is_valid = SignatureUtils.verify_signature(data, signature, api_key, method)

Advanced Usage

Transaction Management

with BMLConnect(api_key="your_api_key", app_id="your_app_id") as client:
    # Create
    transaction = client.transactions.create_transaction({
        "amount": 5000,
        "currency": "MVR",
        "provider": "alipay",
        "redirectUrl": "https://yourstore.com/success",
        "localId": "order_456"
    })

    # Retrieve
    details = client.transactions.get_transaction(transaction.transaction_id)
    print(f"State: {details.state}")

    # Cancel
    cancelled = client.transactions.cancel_transaction(transaction.transaction_id)

    # List with filters
    results = client.transactions.list_transactions(
        page=1,
        per_page=10,
        state="CONFIRMED"
    )
    for t in results.items:
        print(t.transaction_id, t.amount, t.state)

Webhook Handling

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    payload = request.get_json()

    if not client.verify_webhook_signature(payload, payload.get('signature')):
        return {"error": "Invalid signature"}, 403

    state = payload.get('state')
    if state == 'CONFIRMED':
        pass  # fulfil the order
    elif state == 'REFUND_REQUESTED':
        pass  # initiate refund flow
    elif state == 'REFUNDED':
        pass  # mark order as refunded

    return {"status": "success"}

Custom Timeout

# For slow network environments or large payloads
client = BMLConnect(
    api_key="your_api_key",
    app_id="your_app_id",
    timeout=60
)

Requirements

  • Python 3.9+
  • requests
  • aiohttp

Development

Setup

git clone https://github.com/quillfires/bml-connect-python.git
cd bml-connect-python
pip install -e .[dev]

Running Tests

pytest

Code Quality

black .
flake8 .
mypy .

Project Structure

bml-connect-python/
โ”œโ”€โ”€ src/bml_connect/          # Source code
โ”œโ”€โ”€ tests/                    # Test files
โ”œโ”€โ”€ examples/                 # Usage examples
โ”œโ”€โ”€ pyproject.toml           # Build configuration
โ”œโ”€โ”€ requirements.txt         # Runtime dependencies
โ”œโ”€โ”€ requirements-dev.txt     # Development dependencies
โ””โ”€โ”€ README.md               # This file

Contributing

Contributions are welcome. Please see CONTRIBUTING.md for details.

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

License

MIT License โ€” see LICENSE for details.

Support

Changelog

See CHANGELOG.md for a full history of changes.

Security

If you discover a security issue, please email fayaz.quill@gmail.com instead of opening a public issue.


Made with โค๏ธ for the Maldivian developer community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bml_connect_python-1.2.0.tar.gz (13.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bml_connect_python-1.2.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file bml_connect_python-1.2.0.tar.gz.

File metadata

  • Download URL: bml_connect_python-1.2.0.tar.gz
  • Upload date:
  • Size: 13.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bml_connect_python-1.2.0.tar.gz
Algorithm Hash digest
SHA256 cae3f35930535d7cab0dba8d438957de7ec23578ec1c87b651f66329dbaf818f
MD5 1c0af5d6ec8eb4806651506a5fc8daea
BLAKE2b-256 cfc8d3b75191de78c3fb53b7ce294cda817033478b93ab8c6c81f5f2431c6b28

See more details on using hashes here.

Provenance

The following attestation bundles were made for bml_connect_python-1.2.0.tar.gz:

Publisher: release.yml on quillfires/bml-connect-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bml_connect_python-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for bml_connect_python-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c1e6d2dc3a6aca3f61df6fa4de377ccb7a61755ae7087167121c83b07af5fde3
MD5 bb72a268b04c23e7f43a4577d613a34d
BLAKE2b-256 e45aec20e26322d077668cef842e2428f407ee676f01c57f8fe50610c46a20ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for bml_connect_python-1.2.0-py3-none-any.whl:

Publisher: release.yml on quillfires/bml-connect-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page