Reevit

SDKs

Python SDK

Python SDK for Reevit API with async support

Python SDK

PyPI version GitHub

The official Python SDK for the Reevit payment orchestration platform.

Installation

pip install reevit

Quick Start

from reevit import Reevit

client = Reevit(api_key="pfk_live_xxx")

# Create a payment
payment = client.payments.create_intent({
    "amount": 5000,  # 50.00 GHS
    "currency": "GHS",
    "method": "momo",
    "country": "GH",
    "customer_id": "cust_123",
    "metadata": {
        "order_id": "12345"
    }
})

print(f"Payment created: {payment['id']}")

Configuration

Environment Variables

import os
from reevit import Reevit

client = Reevit(
    api_key=os.environ["REEVIT_API_KEY"],
    org_id=os.environ["REEVIT_ORG_ID"],
    base_url=os.environ.get("REEVIT_BASE_URL", "https://api.reevit.io")
)

Payments

Create Payment Intent

payment = client.payments.create_intent({
    "amount": 10000,
    "currency": "GHS",
    "method": "momo",
    "country": "GH",
    "customer_id": "cust_123",
    "metadata": {
        "order_id": "ORD-2024-001"
    }
})

Get Payment

payment = client.payments.get("pay_abc123")
print(f"Status: {payment['status']}")

List Payments

payments = client.payments.list()
for p in payments:
    print(f"{p['id']}: {p['status']}")

Refund Payment

# Full refund
refund = client.payments.refund("pay_abc123")

# Partial refund
refund = client.payments.refund("pay_abc123", amount=2500, reason="Customer requested")

Async Support

import asyncio
from reevit import AsyncReevit

async def main():
    client = AsyncReevit(
        api_key="pfk_live_xxx",
        org_id="org_123"
    )
    
    payment = await client.payments.create_intent({
        "amount": 5000,
        "currency": "GHS",
        "method": "momo",
        "country": "GH"
    })
    
    print(f"Payment ID: {payment['id']}")

asyncio.run(main())

Webhook Verification

Reevit sends webhooks to notify your application of payment events. Always verify signatures.

Signature Format

  • Header: X-Reevit-Signature: sha256=<hex-signature>
  • Signature: HMAC-SHA256(request_body, signing_secret)

Flask Handler

import hmac
import hashlib
import os
from flask import Flask, request, jsonify

app = Flask(__name__)

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    if not signature.startswith('sha256='):
        return False
    
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    received = signature[7:]  # Remove "sha256=" prefix
    return hmac.compare_digest(received, expected)

@app.route('/webhooks/reevit', methods=['POST'])
def webhook():
    payload = request.get_data()
    signature = request.headers.get('X-Reevit-Signature', '')
    secret = os.environ.get('REEVIT_WEBHOOK_SECRET', '')
    
    if secret and not verify_signature(payload, signature, secret):
        return jsonify({'error': 'Invalid signature'}), 401
    
    event = request.get_json()
    event_type = event.get('type')
    
    if event_type == 'payment.succeeded':
        data = event.get('data', {})
        order_id = data.get('metadata', {}).get('order_id')
        # Fulfill order, send confirmation email
        print(f"Payment succeeded for order {order_id}")
    
    elif event_type == 'payment.failed':
        # Notify customer, allow retry
        pass
    
    return jsonify({'received': True})

FastAPI Handler

from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
import os

app = FastAPI()

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    if not signature.startswith('sha256='):
        return False
    
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    received = signature[7:]
    return hmac.compare_digest(received, expected)

@app.post('/webhooks/reevit')
async def webhook(request: Request):
    payload = await request.body()
    signature = request.headers.get('X-Reevit-Signature', '')
    secret = os.environ.get('REEVIT_WEBHOOK_SECRET', '')
    
    if secret and not verify_signature(payload, signature, secret):
        raise HTTPException(status_code=401, detail='Invalid signature')
    
    event = await request.json()
    event_type = event.get('type')
    
    if event_type == 'payment.succeeded':
        data = event.get('data', {})
        # Process payment
    
    return {'received': True}

Django Handler

import hmac
import hashlib
import json
import os
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    if not signature.startswith('sha256='):
        return False
    
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    received = signature[7:]
    return hmac.compare_digest(received, expected)

@csrf_exempt
@require_POST
def reevit_webhook(request):
    payload = request.body
    signature = request.headers.get('X-Reevit-Signature', '')
    secret = os.environ.get('REEVIT_WEBHOOK_SECRET', '')
    
    if secret and not verify_signature(payload, signature, secret):
        return JsonResponse({'error': 'Invalid signature'}, status=401)
    
    event = json.loads(payload)
    event_type = event.get('type')
    
    if event_type == 'payment.succeeded':
        # Handle success
        pass
    
    return JsonResponse({'received': True})

Environment Variables

export REEVIT_API_KEY=pfk_live_xxx
export REEVIT_ORG_ID=org_xxx
export REEVIT_WEBHOOK_SECRET=whsec_xxx

Supported Providers

ProviderCountriesMethods
PaystackNG, GH, ZA, KECard, Mobile Money, Bank
FlutterwaveNG, GH, KE, ZA+Card, Mobile Money, Bank
HubtelGHMobile Money
StripeGlobalCard, Apple Pay, Google Pay
MonnifyNGBank Transfer, Card
M-PesaKE, TZMobile Money