ITSkillsCenter
Business Digital

Intégrer Mobile Money à Hasura via Actions et Event Triggers — tutoriel 2026

13 دقائق للقراءة

📍 Article principal : Hasura DDN + PostgreSQL pour PME. Ce tutoriel intègre Mobile Money à un backend Hasura via les Actions et Event Triggers, transformant chaque facture en demande de paiement Wave/Orange Money/MTN MoMo automatique.

L’intégration Mobile Money dans une application moderne dépasse le simple webhook. Quand un utilisateur valide son panier, il faut générer une demande de paiement chez l’agrégateur, retourner l’URL ou le QR code au frontend, attendre la confirmation, marquer la commande comme payée, déclencher la livraison, notifier le client. Hasura propose deux mécanismes complémentaires : les Actions qui exposent une mutation custom appelant un service HTTP externe (création de demande de paiement), et les Event Triggers qui réagissent aux changements de la base (commande passée en payée → déclencher la livraison). Ce tutoriel met en place les deux côté Hasura, avec un exemple complet basé sur Paydunya pour couvrir Wave, Orange Money et MTN MoMo.

Prérequis

Étape 1 — Comprendre Actions vs Event Triggers

La distinction entre Actions et Event Triggers conditionne l’architecture du backend. Une Action ajoute une mutation ou query custom au schéma GraphQL exposé par Hasura : le frontend appelle createPaymentRequest(orderId), Hasura délègue le traitement à un endpoint HTTP fourni par l’équipe, retourne le résultat au frontend. C’est synchrone — l’appelant attend la réponse. Idéal pour : créer une demande de paiement chez Paydunya, valider une carte CB, calculer une marge complexe, appeler un service ML qui retourne une recommandation.

Un Event Trigger réagit asynchrone à un changement dans la base — INSERT, UPDATE, DELETE sur une table donnée. Quand l’événement survient, Hasura appelle un webhook avec le payload de l’événement et garantit la livraison via retry exponentiel. Idéal pour : envoyer un SMS de confirmation après création d’une commande, déclencher une livraison après passage en statut paid, synchroniser une donnée vers un système externe, alimenter un outil d’analytique.

Un workflow Mobile Money complet utilise généralement les deux mécanismes en cascade. Action createPaymentRequest appelée par le frontend → endpoint custom qui crée la demande chez Paydunya → retour de l’URL au frontend → client paie en Wave → webhook Paydunya reçu par un endpoint Hasura → mise à jour de la base via mutation directe → Event Trigger sur la mise à jour order.status = paid → endpoint custom qui notifie l’équipe logistique. Chaque maillon est testable indépendamment et résilient aux pannes.

Étape 2 — Définir l’Action createPaymentRequest

Dans la console Hasura, aller dans Actions → Create. Donner un nom (createPaymentRequest), définir le type (mutation) et le schéma GraphQL avec arguments et type de retour :

type Mutation {
  createPaymentRequest(
    orderId: uuid!
    amountXof: Int!
  ): PaymentRequestResult
}

type PaymentRequestResult {
  paymentToken: String!
  paymentUrl: String!
  qrCodeUrl: String!
  expiresAt: timestamptz!
}

Configurer le handler URL pointant vers le service Node.js qui implémentera la logique : https://api.masociete.sn/actions/createPaymentRequest. Activer la transmission des headers Hasura (notamment X-Hasura-User-Id pour valider que l’orderId appartient bien à l’utilisateur connecté). Sauvegarder l’Action.

Étape 3 — Implémenter le handler côté Node.js

Créer un petit service Node.js avec Express ou Fastify qui reçoit l’appel Hasura, valide les paramètres et l’autorisation, appelle Paydunya, et retourne le résultat. Le code minimal couvre une centaine de lignes.

app.post("/actions/createPaymentRequest", async (req, res) => {
  const { orderId, amountXof } = req.body.input;
  const userId = req.headers["x-hasura-user-id"];
  // Valider que orderId appartient à userId via Hasura admin
  const order = await hasuraQuery(
    `query { orders_by_pk(id:"${orderId}") { customer_id } }`
  );
  if (order.customer_id !== userId) {
    return res.status(403).json({message:"forbidden"});
  }
  // Créer la demande Paydunya
  const pd = await axios.post(
    "https://app.paydunya.com/api/v1/checkout-invoice/create",
    { invoice: { total_amount: amountXof, description: `Order ${orderId}` },
      store: { name: "MaSociete" },
      custom_data: { order_id: orderId } },
    { headers: paydunyaHeaders });
  res.json({
    paymentToken: pd.data.token,
    paymentUrl: pd.data.response_text,
    qrCodeUrl: `https://app.paydunya.com/qr/${pd.data.token}`,
    expiresAt: new Date(Date.now()+3600000).toISOString(),
  });
});

Cette structure est la blueprint à suivre pour toute Action Hasura : validation des paramètres, vérification de l’autorisation utilisateur, appel au service externe avec gestion d’erreur, retour au format attendu par Hasura. Le frontend appelle cette mutation comme n’importe quelle autre, sans savoir qu’un service externe est sollicité — la composition GraphQL est totalement transparente.

Étape 4 — Recevoir le webhook Paydunya

Quand le client paie effectivement, Paydunya appelle l’URL callback_url renseignée à la création de la demande. Cet endpoint vérifie la signature SHA-512, retrouve la commande concernée via le custom_data, et met à jour le statut en base.

app.post("/webhook/paydunya", async (req, res) => {
  const sig = req.headers["paydunya-hash"];
  const expected = sha512(PAYDUNYA_MASTER_KEY);
  if (sig !== expected) return res.status(401).end();
  const { status, custom_data, token } = req.body;
  if (status !== "completed") return res.status(200).end();
  await hasuraQuery(
    `mutation { update_orders_by_pk(
      pk_columns:{id:"${custom_data.order_id}"},
      _set:{status:"paid",payment_token:"${token}",paid_at:"now()"}
    ){id} }`,
    { useAdminSecret: true });
  res.status(200).end();
});

L’utilisation de l’admin secret pour la mutation se justifie car le webhook n’a pas de session utilisateur — c’est un appel système-à-système autorisé par la signature Paydunya. Cette mise à jour déclenche immédiatement un Event Trigger sur la table orders, qui orchestrera la suite du workflow.

Étape 5 — Définir l’Event Trigger sur paiement confirmé

Dans la console Hasura, aller dans Events → Create. Configurer : nom order_paid, table orders, opération UPDATE, colonne déclencheuse status. Le webhook URL pointe vers le service custom /events/order_paid. Activer le retry avec 3 tentatives et délai exponentiel de 60 secondes.

L’endpoint custom traite uniquement les transitions vers paid en filtrant le payload Hasura :

app.post("/events/order_paid", async (req, res) => {
  const { event } = req.body;
  if (event.op !== "UPDATE") return res.status(200).end();
  if (event.data.new.status !== "paid" || event.data.old.status === "paid") {
    return res.status(200).end();
  }
  const order = event.data.new;
  await sendSmsToCustomer(order);
  await scheduleDelivery(order);
  await notifyAccounting(order);
  res.status(200).end();
});

Le filtre old.status === "paid" évite les déclenchements multiples si le statut est mis à jour plusieurs fois. La règle d’or de l’idempotence reste essentielle : chaque side-effect (SMS, notification) doit être protégé par un identifiant unique stocké en base pour éviter les doublons en cas de retry.

Étape 6 — Idempotence et résilience

Hasura garantit la livraison at-least-once des Event Triggers — un événement peut être livré plusieurs fois en cas de timeout ou erreur 5xx. Pour absorber cette contrainte, chaque handler doit être idempotent. Stocker un identifiant unique par événement traité dans une table processed_events, vérifier l’absence avant traitement, marquer comme traité après succès. Ce pattern simple élimine définitivement les doublons SMS, doubles débits comptables, doubles notifications.

Pour les workflows critiques avec plusieurs étapes (paiement → livraison → comptabilité), considérer un broker de messages comme NATS JetStream ou Redpanda en aval de Hasura — chaque Event Trigger publie sur un stream, plusieurs consommateurs indépendants traitent en parallèle. Voir le comparatif streaming events pour le choix entre NATS, Redpanda et RabbitMQ. Cette architecture découplée résiste aux pics de charge et facilite l’ajout de nouveaux consommateurs sans modifier Hasura.

Sécurité des handlers Action et webhook

Les handlers d’Actions et de webhooks Mobile Money manipulent des données sensibles et déclenchent des effets de bord financiers. Quatre mesures de sécurité s’imposent. Premièrement, valider l’origine de chaque appel : les Actions Hasura envoient un header secret partagé qui authentifie l’appel, tout autre source doit être rejetée. Deuxièmement, valider l’origine du webhook Paydunya via la signature SHA-512 systématiquement, jamais de bypass même en développement. Troisièmement, journaliser chaque appel avec le payload complet (sans données sensibles comme tokens) pour faciliter le débogage et l’audit. Quatrièmement, restreindre l’accès au handler par firewall ou IP allowlist quand c’est possible — Paydunya publie ses ranges IP dans sa documentation.

Pour les PME qui hébergent leurs handlers sur Coolify ou Hetzner, prévoir aussi le scaling horizontal. Un seul instance Node peut tomber pendant un déploiement ou un crash, et perdre temporairement la capacité à recevoir les webhooks. Hasura retry automatiquement les Event Triggers en cas d’échec, mais Paydunya peut ne pas retenter indéfiniment un webhook : déployer plusieurs instances du handler derrière un load-balancer protège contre cette classe d’incidents et garantit la livraison de tous les paiements même en cas d’indisponibilité ponctuelle.

Tableau de bord paiement et réconciliation

Compléter l’intégration par un tableau de bord interne qui visualise en temps réel les paiements reçus, les paiements en attente, les paiements échoués. Une simple page React ou Vue qui consomme l’API GraphQL Hasura, avec subscription temps réel sur les changements de statut, donne aux équipes commerciales et comptables une vision complète sans passer par les portails Paydunya. La réconciliation bancaire devient ainsi continue : le tableau de bord compare automatiquement les paiements Hasura avec les virements bancaires reçus de Paydunya et signale les écarts.

Pour aller plus loin, exporter automatiquement un rapport hebdomadaire au format PDF ou CSV destiné à la comptabilité. Le rapport contient : total des paiements par opérateur, commissions Paydunya prélevées, écarts éventuels, paiements en attente de plus de 24 heures à investiguer. Cette automatisation supprime des heures de travail manuel chaque semaine et fiabilise la comptabilité. Le coût en développement reste contenu — quelques centaines de lignes de code Node ou Python pour un service qui paie son investissement en moins d’un mois.

Erreurs fréquentes

ErreurCauseSolution
Action retournant des données privéesPas de validation X-Hasura-User-Id côté handlerToujours valider que les ressources accédées appartiennent à l’utilisateur
Webhook reçu en doublePas d’idempotency keyStocker token Paydunya en clé unique, ignorer si déjà traité
Event Trigger qui boucleHandler qui modifie la table à l’origine de l’événementFiltrer sur changement effectif de statut, éviter les boucles
Performance dégradée par latence ActionService handler trop lentOptimiser le handler, utiliser un cache, ou basculer en Event Trigger asynchrone

Adaptation au contexte ouest-africain

Pour les PME ouest-africaines, l’intégration Mobile Money via Hasura ouvre une expérience client moderne : paiement en deux clics depuis l’application, confirmation immédiate, livraison déclenchée automatiquement. Cette fluidité différencie radicalement face aux solutions traditionnelles où le client doit ressaisir manuellement les références. Pour les opérateurs hors UEMOA (Cameroun, Gabon, Nigeria), passer par un agrégateur multi-pays comme Flutterwave qui couvre 30+ opérateurs Mobile Money africains avec une API unique. Le coût s’additionne (1,5 à 2,5 %) mais la simplicité de gestion compense largement pour les PME en expansion régionale.

Tester en bac à sable Paydunya

Paydunya fournit un environnement sandbox complet avec des clés API distinctes des clés production. Tester systématiquement chaque scénario en bac à sable avant la bascule live : paiement réussi, paiement échoué, timeout, double webhook (idempotence), commande introuvable, signature invalide. Le simulateur Paydunya accessible depuis le dashboard permet de déclencher manuellement chaque type de webhook pour valider tous les chemins d’erreur. Cette discipline préventive évite les surprises en production et donne à l’équipe la confiance de pousser des évolutions rapides.

Mettre en place une suite de tests automatisés qui rejoue ces scénarios à chaque déploiement. La CI Coolify peut démarrer une instance Hasura éphémère, exécuter les Actions et Event Triggers contre des mocks Paydunya, et valider que le système se comporte correctement face à chaque cas. Le coût en temps de CI reste sous deux minutes pour une couverture complète des scénarios paiement — investissement minime pour une assurance qualité majeure sur un workflow critique.

Gérer les remboursements et avoirs

Tout commerce doit prévoir le retour de marchandise et le remboursement client. L’API Paydunya supporte les disbursements (paiements sortants) qui permettent de rembourser un client sur son numéro Mobile Money d’origine. Implémenter une Action refundOrder qui prend l’orderId, valide les autorisations (seul un commercial ou admin peut rembourser), récupère le montant et le numéro client, appelle l’API disbursement Paydunya, marque la commande en refunded dans Hasura. La traçabilité complète se construit ainsi avec à chaque étape la trace dans la base et dans les journaux Paydunya.

Pour les remboursements partiels (article retourné mais commande globale conservée), créer un avoir Hasura qui modélise la dette de la PME envers le client, soit immédiatement remboursé en Mobile Money, soit déduit de la prochaine commande selon la préférence du client. Cette flexibilité différencie commercialement la PME et fidélise les clients qui apprécient le service après-vente irréprochable. Le coût technique reste minime — quelques tables et Actions supplémentaires — pour un retour business significatif.

Couverture multi-opérateurs avancée

Une PME peut vouloir donner le choix de l’opérateur au client final pour optimiser les commissions ou éviter qu’un opérateur en panne ne bloque les ventes. Implémenter une Action listAvailablePaymentMethods qui retourne la liste dynamique des opérateurs disponibles selon le pays détecté du client (XOF Sénégal → Wave + Orange Money + Free Money, XOF Côte d’Ivoire → Wave + Orange Money + MTN MoMo). Le frontend affiche les options dans l’ordre de préférence configurable par la PME, le client choisit, l’Action createPaymentRequest reçoit le mode choisi en paramètre.

Cette flexibilité technique se traduit directement en taux de conversion : un client qui n’a pas Wave peut payer en Orange Money sur le même panier sans repasser commande. Pour les commerces transfrontaliers, l’Action peut aussi gérer le change automatique XOF/XAF/EUR selon la devise demandée par le client, avec frais et taux affichés transparemment.

Pour aller plus loin

🔝 Retour à l’article principal : Hasura DDN + PostgreSQL pour PME. Tutoriels précédents : déployer Hasura sur Coolify, permissions row-level. Pour comprendre l’intégration Mobile Money côté Dolibarr, voir le module Mobile Money Dolibarr. Pour découpler les workflows événementiels, voir le comparatif streaming events.

Documentation Hasura Actions : hasura.io/docs/2.0/actions, Event Triggers : hasura.io/docs/2.0/event-triggers, API Paydunya : paydunya.com/developers. Cette combinaison Actions + Event Triggers transforme Hasura en orchestrateur de workflows événementiels : une PME ouest-africaine peut bâtir une plateforme moderne intégrant paiement, logistique, notifications et comptabilité en quelques semaines au lieu de plusieurs mois en stack traditionnelle. La rentabilité de cette approche se mesure directement dans la vitesse de mise sur le marché et dans la qualité de l’expérience utilisateur finale.

Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité