Skip to main content

Django Tamara Payment Gateway

PyPI Version Django Python License

A professional Django package for integrating Tamara - the leading Buy Now Pay Later (BNPL) payment solution in the Middle East. Supports Saudi Arabia, UAE, Kuwait, Bahrain, Qatar, and Oman.

Features

  • ✅ Full Tamara Online Checkout flow
  • ✅ Payment Types lookup
  • ✅ Create Checkout Sessions
  • ✅ Authorise / Capture / Cancel / Refund orders
  • ✅ Webhook management (register, list, update, delete)
  • ✅ Sandbox & Production environments
  • ✅ Multi-currency support (SAR, AED, KWD, BHD, QAR, OMR)
  • ✅ Multi-country support (SA, AE, KW, BH, QA, OM)
  • ✅ In-store checkout support
  • ✅ Requests HTTP client (no raw cURL)
  • ✅ Configurable URL prefix & middleware
  • ✅ Transaction logging model
  • ✅ Django 4.2, 5.0 & 5.1 compatible
  • ✅ Python 3.9+

Requirements

Django Python Package Version
4.2.x 3.9+ ^2.0
5.0.x 3.10+ ^2.0
5.1.x 3.10+ ^2.0
5.2.x 3.10+ ^2.0
6.0.x 3.12+ ^2.0

Installation

pip install aghfatehi-django-tamara

Configuration

1. Add to INSTALLED_APPS

# settings.py
INSTALLED_APPS = [
    ...
    'tamara',
]

2. Environment / Settings Variables

# settings.py

# ─── Tamara Payment Gateway Settings ──────────────────────────────

TAMARA_SANDBOX_MODE = True
# bool | Sandbox mode (testing) when True, Production mode when False

TAMARA_API_TOKEN = "your-api-token-here"
# string | Your Tamara API token from Tamara dashboard

TAMARA_COUNTRY_CODE = "SA"
# string (2 chars) | Country code
# SA = Saudi Arabia | AE = UAE | KW = Kuwait | BH = Bahrain | QA = Qatar | OM = Oman

TAMARA_CURRENCY = "SAR"
# string (3 chars) | Currency code
# SAR = Saudi Riyal | AED = UAE Dirham | KWD = Kuwaiti Dinar | BHD = Bahraini Dinar | QAR = Qatari Riyal | OMR = Omani Riyal

TAMARA_INSTALMENTS = 3
# int | Number of instalments (3, 4, or 6)

TAMARA_PAYMENT_TYPE = "PAY_BY_INSTALMENTS"
# string | Payment type - "PAY_BY_INSTALMENTS" or "PAY_NEXT_MONTH" or "SINGLE_PAYMENT"

TAMARA_LOCALE = "en_US"
# string | Locale - "en_US" or "ar_SA"

TAMARA_ROUTE_PREFIX = "tamara"
# string | URL prefix for all Tamara routes

3. Include URLs

# urls.py
from django.urls import include, path

urlpatterns = [
    ...
    path('tamara/', include('tamara.urls')),
]

4. Run Migrations

python manage.py migrate tamara

Usage

Quick Start - Frontend Checkout

from tamara.client import client

# Get available payment types
types = client.get_payment_types('SA', 'SAR', 500)

# Create a checkout session
response = client.create_checkout({
    'total_amount': {'amount': 500, 'currency': 'SAR'},
    'order_reference_id': 'ORD-' + str(int(__import__('time').time())),
    'order_number': 'INV-2024-001',
    'consumer': {
        'email': 'customer@example.com',
        'first_name': 'Ahmed',
        'last_name': 'Ali',
        'phone_number': '500000000',
    },
    'country_code': 'SA',
    'merchant_url': {
        'success': 'https://example.com/tamara/callback',
        'failure': 'https://example.com/tamara/failure',
        'cancel': 'https://example.com/tamara/cancel',
        'notification': 'https://example.com/tamara/webhook',
    },
})

# Redirect customer to Tamara checkout
if 'checkout_url' in response:
    # return redirect(response['checkout_url'])
    print(f"Redirect to: {response['checkout_url']}")

Using Routes

The package registers these routes under the configured prefix (/tamara by default):

Method URI Name Description
GET /tamara/payment/types tamara:payment_types Get eligible payment types
POST /tamara/pay tamara:pay Initiate checkout
ANY /tamara/callback tamara:callback Payment callback
GET /tamara/cancel tamara:cancel Cancel handler
GET /tamara/failure tamara:failure Failure handler
POST /tamara/webhook tamara:webhook Webhook receiver
POST /tamara/authorise tamara:authorise Authorise order

API Methods

from tamara.client import client

# Payment Types
types = client.get_payment_types('SA', 'SAR', 500, '500000000')

# Checkout
checkout = client.create_checkout(data)

# Order Management
order = client.get_order('order-id-here')
order = client.get_order_by_reference_id('ref-id-here')

# Authorise / Capture / Cancel / Refund
authorised = client.authorise_order('order-id')
captured = client.capture_order('order-id', {'amount': 500})
cancelled = client.cancel_order('order-id', {'reason': 'out_of_stock'})
refunded = client.refund_order('order-id', 500, 'SAR', 'Refund comment')

# Webhook Management
webhook = client.webhook_register(
    'https://example.com/webhook',
    ['order_approved', 'order_declined', 'order_authorised', 'order_captured', 'order_refunded'],
)
webhook_list = client.webhook_list()
webhook_detail = client.webhook_get('webhook-id')
client.webhook_delete('webhook-id')
client.webhook_update('webhook-id', 'https://example.com/webhook', ['order_approved'])

Handling Webhooks

The webhook endpoint logs all incoming events. Extend the view or listen to the log to implement your business logic:

# views.py (custom webhook handler)
import json
import logging
from django.http import JsonResponse
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt

logger = logging.getLogger(__name__)

@method_decorator(csrf_exempt, name='dispatch')
class CustomWebhookView(View):
    def post(self, request):
        payload = json.loads(request.body)
        event = payload.get('event_type')
        order_id = payload.get('order_id')
        status = payload.get('status')

        if event == 'order_approved':
            # Mark order as approved
            pass
        elif event == 'order_captured':
            # Fulfill the order
            pass
        elif event == 'order_refunded':
            # Process refund
            pass

        return JsonResponse({'success': True})

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Lint
ruff check src/ tests/

Changelog

See CHANGELOG for recent changes.

Security

If you discover security issues, please email fathi.a.n2002@gmail.com instead of using the issue tracker.

License

This package is open-sourced software licensed under the MIT license.

Support

Countries & Currencies

Country Code Currency Code
Saudi Arabia SA Riyal SAR
UAE AE Dirham AED
Kuwait KW Dinar KWD
Bahrain BH Dinar BHD
Qatar QA Riyal QAR
Oman OM Riyal OMR

Metadata

Release files for aghfatehi-django-tamara 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aghfatehi-django-tamara 2.0.1
File Size Uploaded Provenance Actions
aghfatehi_django_tamara-2.0.1.tar.gz 11.6 kB Without provenance Details for aghfatehi_django_tamara-2.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for aghfatehi-django-tamara 2.0.1
File Interpreter ABI Platform Actions
aghfatehi_django_tamara-2.0.1-py3-none-any.whl Python 3 none any Details for aghfatehi_django_tamara-2.0.1-py3-none-any.whl

Total release size: 24.2 kB

Release files / aghfatehi_django_tamara-2.0.1.tar.gz

Download URL aghfatehi_django_tamara-2.0.1.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
a4394d2520b876607cfcddd6a2b2fa7460c560d81cb922c6a9b69116a6a57eb9
BLAKE2b-256 checksum
How to use checksums
e82d26bfaaf3e914ea1361f2c9c717a05936daec3ddafc053388faf7f20fd7f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / aghfatehi_django_tamara-2.0.1-py3-none-any.whl

Download URL aghfatehi_django_tamara-2.0.1-py3-none-any.whl
Size 12.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
18d79e01d44a0914cea64ceed12e43665c9687b7e7d482e3ff8ffd2ca70ba243
BLAKE2b-256 checksum
How to use checksums
79edb19435119203c593a2c81bb3be666eb22f1e8888af1511245b7907f55771
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Security for aghfatehi-django-tamara 2.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page