DjangoPython 3.9+ · Django 4.2+ · moncashconnect

Intégrer MonCash avec Django

Intégrez les paiements MonCash dans votre application Django : vue de paiement, vue webhook exempt CSRF et vérification de signature.

Sandbox

Commencez en Sandbox

Avant d'implémenter le code ci-dessous avec votre clé live (sk_proj_…), nous recommandons de tester d'abord en mode Sandbox avec sk_test_proj_…. Le code est identique — vous ne changez que la valeur de la variable d'environnement. Lisez le Guide Sandbox avant de continuer.

Prérequis

  • Python 3.9+
  • Django 4.2+ (ou 5.x)
  • Un projet MonCashConnect avec clé secrète — créer un projet

Installation

pip install moncashconnect

Ou ajoutez moncashconnect dans votre requirements.txt. Zéro dépendance — utilise uniquement la bibliothèque standard Python.

Configuration

Ajoutez dans settings.py (ou utilisez un fichier .env avec python-decouple) :

import os

MCC_SECRET_KEY     = os.environ.get("MCC_SECRET_KEY", "")
MCC_WEBHOOK_SECRET = os.environ.get("MCC_WEBHOOK_SECRET", "")

Fichier .env (non versionné) :

MCC_SECRET_KEY=sk_proj_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MCC_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Vues de paiement

Dans payments/views.py :

from django.shortcuts import redirect
from django.http import HttpResponse, HttpResponseBadRequest
from django.conf import settings
from moncashconnect import MonCashClient, MonCashError

# Instancié une fois au niveau du module — pas de state partagé, c'est safe
client = MonCashClient(settings.MCC_SECRET_KEY)


def initiate_payment(request, order_id: str, amount: int):
    """Lance le flux de paiement MonCash pour une commande."""
    try:
        payment = client.create_payment(
            amount=amount,
            reference_id=order_id,
            return_url=request.build_absolute_uri("/payment/return/"),
        )
    except MonCashError as exc:
        return HttpResponseBadRequest(str(exc))

    return redirect(payment["paymentUrl"])


def payment_return(request):
    """Page de retour après le paiement MonCash."""
    ref = request.GET.get("ref")
    if not ref:
        return HttpResponseBadRequest("Référence manquante.")

    try:
        tx = client.get_payment_status(ref)
    except MonCashError as exc:
        return HttpResponse(str(exc), status=exc.status_code)

    # Ne faites pas confiance aux paramètres URL pour confirmer le paiement —
    # attendez le webhook payment.completed pour créditer définitivement.
    return render(request, "payments/return.html", {"tx": tx})

Vue webhook

La vue webhook doit être décorée avec @csrf_exempt. La protection est assurée par la vérification HMAC-SHA256, non par le token CSRF.

from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.http import HttpResponse
from moncashconnect import construct_event, MonCashError
from django.conf import settings
from .models import Order


@csrf_exempt
@require_POST
def moncash_webhook(request):
    raw_body  = request.body                               # bytes, AVANT tout parsing
    signature = request.META.get("HTTP_X_MCC_SIGNATURE", "")
    timestamp = request.META.get("HTTP_X_MCC_TIMESTAMP", "")

    try:
        event = construct_event(
            raw_body,
            signature,
            timestamp,
            settings.MCC_WEBHOOK_SECRET,
        )
    except MonCashError as exc:
        return HttpResponse(str(exc), status=exc.status_code)

    if event["event"] == "payment.completed":
        Order.objects.filter(
            reference=event["reference"]
        ).update(status="paid")

    elif event["event"] == "payment.failed":
        Order.objects.filter(
            reference=event["reference"]
        ).update(status="failed")

    return HttpResponse("OK")
Lisez request.body en premier — accéder à request.POST ou request.data (DRF) avant consomme le stream et invalide la signature.

URLs

Dans payments/urls.py :

from django.urls import path
from . import views

urlpatterns = [
    path("payment/return/",         views.payment_return,   name="payment-return"),
    path("webhooks/moncash/",        views.moncash_webhook,  name="moncash-webhook"),
]

Incluez dans project/urls.py :

from django.urls import path, include

urlpatterns = [
    # ...
    path("", include("payments.urls")),
]
Configurez https://votresite.com/webhooks/moncash/ comme URL webhook dans votre projet MonCashConnect. N'oubliez pas le slash final Django.

Liste de contrôle avant mise en production

MCC_SECRET_KEY et MCC_WEBHOOK_SECRET sont dans les variables d'environnement du serveur (pas dans settings.py en clair)

DEBUG = False en production

La vue webhook est décorée @csrf_exempt et @require_POST

request.body est lu AVANT tout accès à request.POST ou json.loads()

La vue webhook est idempotente (peut recevoir le même événement plusieurs fois)

La page de retour vérifie le statut via get_payment_status() — pas les paramètres GET

L'URL webhook https://votresite.com/webhooks/moncash/ est configurée dans le tableau de bord MonCashConnect