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.1.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.1-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: bml_connect_python-1.2.1.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.1.tar.gz
Algorithm Hash digest
SHA256 7d48ba0bb50ae1b37a0a4874b07eecb5b61d21970b45843a64f88d7b9c058c1d
MD5 207d88a9b3283d0f6aa3ac83941bdcdd
BLAKE2b-256 7a90fb52493032fd6b5d2f5513bacea4a9ff61362652e16a815d36ff0c82271a

See more details on using hashes here.

Provenance

The following attestation bundles were made for bml_connect_python-1.2.1.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.1-py3-none-any.whl.

File metadata

File hashes

Hashes for bml_connect_python-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c01e42172b0c80d2392ad83c15966ded9d78f8623c24dd971282346b3bce564c
MD5 5b303bd7070019d88c570e444c694921
BLAKE2b-256 3f7d134561e4f78f7b59ca52c9190f4599898b92ed828ecdb1bafb62caa48e40

See more details on using hashes here.

Provenance

The following attestation bundles were made for bml_connect_python-1.2.1-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