Intégration

Webhooks

Recevez et traitez les événements de paiement sur votre serveur via le proxy ash-gate.

Gestion des Webhooks

ash-gate agit comme un routeur de webhooks. Vos aggrégateurs envoient tous les événements à une seule URL (ash-gate), qui les route automatiquement vers le bon projet.


1. Configurer l'URL de Webhook

Sur votre tableau de bord FedaPay (ou autre aggrégateur), vous devez configurer l'URL de notification. Vous avez deux options :

A. URL Spécifique par Projet (Recommandé)

Chaque projet peut utiliser son propre secret de signature FedaPay défini dans ses paramètres AshGate.

https://app.ashgateway.com/fedapay/webhook/:projectId

Remplacez :projectId par l'ID ou le Slug de votre projet AshGate.

B. URL Globale (Standard)

Utilise le secret de webhook global défini par l'administrateur d'AshGate.

https://app.ashgateway.com/fedapay/webhook

!IMPORTANT L'option A est recommandée car elle permet d'utiliser le secret de webhook (whsec_...) unique à VOTRE compte FedaPay, garantissant une vérification de signature sécurisée et isolée.


2. Comment ash-gate route les événements

Aggrégateur envoie un événement POST /fedapay/webhooks
        │
        ▼
ash-gate lit : event.metadata.ash_project_id
        │
        ▼
Lookup du projet correspondant en base
        │
        ├──► Vérification de la signature HMAC-SHA256
        │
        ▼
Si webhookUrl configuré dans le projet :
   → Forward de l'événement vers VOTRE serveur
Sinon :
   → Traitement interne (renouvellement d'abonnement, etc.)

3. Configurer votre URL de Callback (optionnel)

Si vous voulez recevoir les événements aussi sur votre propre backend :

# Via la CLI
wallet project update mon-app --webhook-url https://mon-serveur.com/webhooks/fedapay

# Ou directement dans le dashboard ash-gate

4. Recevoir et vérifier les webhooks (NestJS)

import { Controller, Post, Headers, Body, BadRequestException } from '@nestjs/common';
import * as crypto from 'crypto';

@Controller('webhooks')
export class WebhookController {
  @Post('fedapay')
  handleFedaCloudWebhook(
    @Headers('x-feda-signature') signature: string,
    @Headers('x-feda-project-id') projectId: string,
    @Body() payload: any,
  ) {
    // 1. Vérifier la signature avec votre Secret Key
    const expectedSig = crypto
      .createHmac('sha256', process.env.FEDA_PROJECT_SECRET)
      .update(JSON.stringify(payload))
      .digest('hex');

    if (signature !== expectedSig) {
      throw new BadRequestException('Signature invalide');
    }

    // 2. Traiter l'événement
    const { event, transaction } = payload;

    switch (event) {
      case 'transaction.approved':
        // Activer l'abonnement, débloquer l'accès...
        console.log(`Paiement reçu : ${transaction.amount} ${transaction.currency}`);
        break;
      case 'transaction.canceled':
        console.log(`Transaction annulée : ${transaction.id}`);
        break;
    }

    return { received: true };
  }
}

5. Recevoir et vérifier les webhooks (Express / Node.js)

const express = require('express');
const crypto = require('crypto');
const app = express();

app.post('/webhooks/fedapay', express.json(), (req, res) => {
  const signature = req.headers['x-feda-signature'];
  const expected = crypto
    .createHmac('sha256', process.env.FEDA_PROJECT_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (signature !== expected) {
    return res.status(400).json({ error: 'Signature invalide' });
  }

  const { event, transaction } = req.body;
  console.log(`Événement reçu : ${event}`, transaction);

  res.json({ received: true });
});

Événements supportés

ÉvénementDescription
transaction.approvedLe paiement a été validé par l'opérateur mobile
transaction.declinedLe paiement a été refusé
transaction.canceledL'utilisateur a annulé
transaction.pendingEn attente de confirmation

Suivant : Plans & Abonnements ->