Strapi v4: Implémentation d’un système d’abonnement payant avec Wave et Orange Money via Paytech.

Introduction

Dans un monde de plus en plus numérique, les entreprises en ligne sont confrontées à la nécessité d’intégrer des systèmes de paiement sûrs et efficaces dans leurs plateformes. Ces systèmes sont essentiels pour offrir une expérience de transaction optimale aux clients et pour soutenir la croissance des entreprises. Cependant, naviguer parmi les nombreuses options de paiement disponibles peut être complexe, chaque solution ayant ses propres caractéristiques.
Dans cet article, nous nous concentrons sur l’intégration de systèmes de paiement comme Wave et Orange Money avec Strapi, un CMS headless reconnu pour sa flexibilité et sa puissance. Notre objectif est de vous guider à travers les étapes clés de cette intégration, en abordant les défis courants auxquels vous pourriez être confrontés et en vous fournissant des conseils pratiques pour une mise en œuvre efficace.
En suivant ce guide, nous mettrons en lumière les stratégies clés pour structurer un système d’abonnement qui non seulement répond aux attentes des utilisateurs mais assure également la sécurité et la fluidité des transactions.

Prérequis

  • Avant de commencer, assurez-vous d’avoir installé Node.js et yarn. Vous pouvez installer Strapi globalement avec la commande suivante :
yarn create strapi-app my-project --ts --quickstart
  • Création d’un compte PayTech.sn
  • Pour exposer votre serveur local sur Internet et tester votre API, utilisez ngrok. Téléchargez ngrok depuis le site de ngrok, puis lancez-le avec ngrok http 1337 pour rendre le port 1337 de votre serveur accessible publiquement.
  • Pour commencer à utiliser la fonction addMonths de date-fns dans votre projet Node.js, installez d’abord la bibliothèque en exécutant la commande suivante dans votre terminal:
npm install date-fns 

Cette fonction vous aidera à manipuler et ajouter des mois à des dates spécifiques dans votre application.

use case

Imaginons que nous développions une plateforme avec Strapi pour gérer des abonnements à des services ou des contenus premium. Notre objectif est de permettre aux utilisateurs de s’abonner à différents plans, chaque plan offrant un accès spécifique à du contenu ou à des services. Pour cela, nous devons intégrer un système de paiement, comme Wave, pour gérer les transactions de manière sécurisée.

Lors de la souscription à un plan, l’utilisateur doit pouvoir choisir parmi les options disponibles. Si l’utilisateur sélectionne un plan, une vérification de l’éligibilité à ce plan est réalisée pour s’assurer qu’il n’a pas déjà un abonnement actif ou en cours qui entrerait en conflit. Si tout est conforme, l’utilisateur procède au paiement via Wave ou Orange Money.

En outre, lors de la réponse au paiement par le système Wave ou Orange Money, Strapi traitera cette réponse pour activer ou mettre à jour l’abonnement de l’utilisateur en fonction du résultat du paiement. Cette gestion des réponses assure que chaque abonnement est correctement suivi et mis à jour, garantissant ainsi une gestion efficace des droits d’accès des utilisateurs.

En intégrant ces fonctionnalités, nous assurons non seulement la facilité d’inscription et de gestion des abonnements pour l’utilisateur, mais aussi l’intégrité et la sécurité des transactions et des données sur la plateforme.

Scénario :

1. L’utilisateur accède à la plateforme et explore les différents plans d’abonnement disponibles.

2. L’utilisateur choisit un plan d’abonnement parmi les options proposées.

3. Le système Strapi vérifie l’éligibilité de l’utilisateur au plan sélectionné en s’assurant qu’il n’a pas déjà un abonnement actif ou en cours qui entrerait en conflit.

4. Si l’utilisateur est éligible, il procède au paiement via le système de paiement intégré (Wave, Orange Money) grâce à Paytech.

5. Le système de paiement (Wave, Orange Money) via Paytech traite la transaction et envoie une réponse au système Strapi.

6. Strapi traite la réponse du paiement pour activer ou mettre à jour l’abonnement de l’utilisateur en fonction du résultat de la transaction.

7. L’utilisateur reçoit une confirmation de son abonnement et peut désormais accéder au contenu ou aux services spécifiques inclus dans son plan.

Création des content-types

Pour mettre en place un système d’abonnement efficace dans Strapi, nous commençons par créer deux types de contenu essentiels : Plan et Subscription.

Plan

Ce content-type permet de définir les différents abonnements que les utilisateurs peuvent choisir. Chaque Plan comprendra des informations spécifiques qui définissent l’offre. Ce modèle comprend les champs ci dessus:

  • name, Type : string
  • description, Type: text
  • price, Type: decimal
  • duration, Type : integer
  • status, Type : enumeration valeurs FREEMIUM, et PREMIUM (optionnel).
  • type, Type: Client, Fournisseur
yarn strapi generate content-type

$ strapi generate content-type
? Content type display name Plan
? Content type singular name plan
? Content type plural name plans
? Please choose the model type Collection Type
? Use draft and publish? No
? Do you want to add attributes? Yes
? Name of attribute name
? What type of attribute string
? Do you want to add another attribute? Yes
? Name of attribute description
? What type of attribute text
? Do you want to add another attribute? Yes
? Name of attribute price
? What type of attribute decimal
? Do you want to add another attribute? Yes
? Name of attribute duration
? What type of attribute integer
? Do you want to add another attribute? Yes
? Name of attribute type
? What type of attribute enumeration
? Add values separated by a comma Client,Fournisseur
? Do you want to add another attribute? Yes
? Name of attribute status
? What type of attribute enumeration
? Add values separated by a comma FREEMIUM,PREMIUM
? Do you want to add another attribute? No
? Where do you want to add this model? Add model to new API
? Name of the new API? plan
? Bootstrap API related files? Yes
✔  ++ /api/plan/content-types/plan/schema.json
✔  +- /api/plan/content-types/plan/schema.json
✔  ++ /api/plan/controllers/plan.ts
✔  ++ /api/plan/services/plan.ts
✔  ++ /api/plan/routes/plan.ts
✨  Done in 203.10s.

Subscription

Ce content-type est utilisé pour gérer les abonnements actifs des utilisateurs. Il stocke les détails de chaque abonnement. Ce modèle comprend les champs ci dessus :

  • status, Type: Enumeration valeurs SUCCESS, WAITING, CANCEL.
  • dateStart,Type : Date.
  • dateEnd, Type: Date.
  • user (Relation): Établissez une relation manyToOne avec le content type user pour lier chaque souscription à un utilisateur spécifique.
  • current, Type: Boolean
yarn strapi generate content-type

$ strapi generate content-type
? Content type display name: Subscription
? Content type singular name: subscription
? Content type plural name: subscriptions
? Please choose the model type Collection Type
? Use draft and publish: No
? Do you want to add attributes? Yes
? Name of attribute: status
? What type of attribute: enumeration
? Add values separated by a comma: SUCCESS,WAITING,CANCEL
? Do you want to add another attribute? Yes
? Name of attribute: dateStart
? What type of attribute: date
? Do you want to add another attribute? Yes
? Name of attribute: dateEnd
? What type of attribute: date
? Do you want to add another attribute? Yes
? Name of attribute: current
? What type of attribute: boolean
? Do you want to add another attribute? No
? Where do you want to add this model? Add model to new API
? Name of the new API? subscription
? Bootstrap API related files? Yes
✔  ++ /api/subscription/content-types/subscription/schema.json
✔  +- /api/subscription/content-types/subscription/schema.json
✔  ++ /api/subscription/controllers/subscription.ts
✔  ++ /api/subscription/services/subscription.ts
✔  ++ /api/subscription/routes/subscription.ts
✨  Done in 26448.29s.

Maintenant, ajoutons manuellement la relation au niveau du type de contenu Subscription.

Ajoutons la relation entre user et subscription

Configurer les permissions

  1. Allez dans la section “Settings” > “Roles”.
  2. Sélectionnez le rôle “Public”.
  3. Assurez-vous que dans la section Plan, les permissions updatecreatefindfindOne est correctement sélectionnée.

Creation des roles Client et Fournisseur

  1. Naviguez vers le menu “Settings” situé dans la barre latérale inférieure.
  2. Cliquez sur “Users & Permissions plugin”, puis sur “Roles”.
  3. Ajouter un Nouveau Rôle:
    • Cliquez sur le bouton “Add new role” en haut à droite.
    • Entrez le nom du rôle, par exemple Client, Fournisseur.
    • Ajoutez une description pour décrire les responsabilités ou les limites du rôle.
  4. Choisissez le rôle Client et assurez-vous que les permissions pour les content-types “Plan”, incluant “update“, “create“, “find“, et “findOne“, ainsi que pour “Subscription” avec les permissions “payment” et “paymentResponse“, sont correctement configurées.
  5. Faites de meme pour le role Fournisseur.

Remplissage des données

Dans cette section, nous allons procéder à la création d’un enregistrement dans notre entité Plan pour un client afin de préparer nos tests pour les étapes à venir.

Creation d’un fournisseur

Nous allons maintenant procéder à la création d’un fournisseur dans notre système, ce qui nous permettra de remplir et de gérer les données nécessaires pour nos plans et abonnements.

Ajouter une colonne nommé: ref, type: uid

Création d’un compte Paytech

  • Avant de pouvoir intégrer Paytech dans votre projet Strapi, vous devez créer un compte sur la plateforme Paytech et récupérer vos clés API. Voici les étapes à suivre:
    • Visitez le site de Paytech: Allez sur le site officiel de Paytech (PayTech.sn ) pour commencer le processus d’inscription. Vous devrez fournir des informations telles que votre nom, adresse e-mail, numéro de téléphone etc… .
    • Validation de compte: Une fois votre compte créé, Paytech peut exiger une vérification de votre identité ou de votre entreprise pour activer votre compte. Suivez les instructions pour compléter ce processus.
    • Accédez au tableau de bord Paytech: Une fois votre compte validé et activé, connectez-vous au tableau de bord Paytech. Ce tableau de bord est l’interface centrale où vous pourrez gérer vos transactions, configurer vos paramètres de paiement, et accéder à vos clés API.
    • Récupération des clés API: Dans le tableau de bord, recherchez la section généralement intitulée “Parametres > API & APN” . Dans cette section, vous trouverez vos clés API, composées d’une clé publique (API_KEY) et d’une clé secrète (API_SECRET). Ces clés seront utilisées pour authentifier les requêtes entre votre application Strapi et Paytech.
    • Sécurité des clés API: Assurez-vous de garder vos clés API en sécurité et de ne pas les exposer publiquement dans votre code ou sur des répertoires accessibles. Utilisez des variables d’environnement pour stocker ces clés dans votre application Strapi.
    • Configuration des URLs de redirection: Paytech nécessite des URLs de redirection pour les réponses de paiement, comme success_url, cancel_url, et ipn_url (Instant Payment Notification). Configurez ces URLs dans votre compte Paytech pour qu’elles correspondent aux endpoints de votre application Strapi où vous souhaitez recevoir les notifications de paiement.
    • En suivant ces étapes, vous aurez préparé le terrain pour intégrer Paytech avec votre application Strapi, permettant des transactions sécurisées et efficaces pour les utilisateurs de votre plateforme.

En suivant ces étapes, vous aurez préparé le terrain pour intégrer Paytech avec votre application Strapi, permettant des transactions sécurisées et efficaces pour les utilisateurs de votre plateforme.

Configuration des variables d’environnement dans le ficher .env

Dans votre fichier .env, ajoutez les lignes suivantes pour définir les variables nécessaires pour les configurations de paiement. Utiliser ngrok pour les tests en local.

PAYMENT_API_KEY=VotreCléAPIPayTech
PAYMENT_API_SECRET=VotreSecretAPIPayTech
PAYMENT_SUCCESS_URL=https://<subdomain>.ngrok.io/subscription/success
PAYMENT_CANCEL_URL=https://<subdomain>.ngrok.io/subscription/cancel
PAYMENT_IPN_URL=https://<subdomain>.ngrok.io/subscription/payment-response

Remplacez les valeurs de clé et de secret par celles fournies par PayTech. Après avoir entré les variables, sauvegardez les modifications.

Utilisation des Variables dans config/payment.ts

Pour configurer les paramètres de paiement dans votre application Strapi, créez un fichier nommé payment.ts dans le dossier config/. Ce fichier contiendra les déclarations de vos variables de configuration liées au paiement. Voici comment vous pouvez définir chaque variable dans ce fichier :

export default ({ env }) => ({
    apiKey: env('PAYMENT_API_KEY'),
    apiSecret: env('PAYMENT_API_SECRET'),
    successUrl: env('PAYMENT_SUCCESS_URL'),
    cancelUrl: env('PAYMENT_CANCEL_URL'),
    ipnUrl: env('PAYMENT_IPN_URL'),
});

Création du Service de Paiement

  • Ouvrez votre terminal: Accédez au répertoire racine de votre projet Strapi.
  • Exécutez la commande de génération de service:
yarn strapi generate service

$ strapi generate service
? Service name: payment
? Where do you want to add this service? Add service to an existing API
? Which API is this for? subscription
✔  ++ /api/subscription/services/payment.ts
✨  Done in 20.10s.

ajouter ce code suivant dans le fichier payment.ts

/**
 * paymentStatus service
 */
import { factories } from '@strapi/strapi';
import fetch from 'node-fetch';
import { addMonths } from 'date-fns';

export default factories.createCoreService('api::subscription.subscription', ({ strapi }) => ({

  // Correction: Fonction pour générer une référence aléatoire
  generateRandomRef(length) {
    let result = '';
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    const charactersLength = characters.length;
    for (let i = 0; i < length; i++) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
  },

  async canSubscribe(userId, planId) {

    const plan = await strapi.entityService.findOne('api::plan.plan', planId);
    const now = new Date();
    // Récupère les abonnements actives de l'utilisateur pour ce plan
    const subscriptions = await strapi.entityService.findMany('api::subscription.subscription', {
      filters: { user: userId, current: true, status: 'SUCCESS', },
    });
    // Vérifie si un abonnement actif existe
    if (subscriptions.length > 0) {
      console.log(subscriptions);
      const subscription = subscriptions[0];

      // Vérifie si l'abonnement actuel est toujours valide
      if (new Date(subscription.dateEnd) >= now) {
        // La abonnement n'est pas terminée, donc on lance une exception
        throw new Error('L\'bonnement n\'est pas terminée.');

      }
    }

    // Aucun abonnement active ou tous les abonnements actifs sont expirés
    return true;
  },

  async setCurrentSubscriptionToFalse() {
    // Sélectionne tous les abonnements actuels
    const subscriptions = await strapi.entityService.findMany('api::subscription.subscription', {
      filters: {
        current: true,
      },
    });

    // Prépare une liste des IDs des abonnements à mettre à jour
    const listIdSubscription = subscriptions.map(subscription => subscription.id);

    // Met à jour les abonnements si nécessaire
    if (listIdSubscription.length > 0) {
      await Promise.all(listIdSubscription.map(async (subscriptionId) => {
        await strapi.entityService.update('api::subscription.subscription', subscriptionId, {
          data: {
            current: false,
          },
        });
      }));
    }
  },

  async createSubscription(userId, planId) {
    try {
      await this.setCurrentSubscriptionToFalse();
      const plan = await strapi.entityService.findOne('api::plan.plan', planId);
      const now = new Date();
      const dateEnd = addMonths(now, plan.duration); // Utilise plan.duration pour déterminer la date de fin


      const STATUS: SubscriptionStatus = "WAITING"; // Utilisez une logique conditionnelle ici si nécessaire
      type SubscriptionStatus = "CANCEL" | "WAITING" | "SUCCESS";
      // Créer un nouvel abonnement
      const newSubscription = {
        status: STATUS, // Assumant que "SUCCESS" est une valeur valide pour ton modèle
        dateStart: now,
        dateEnd: dateEnd,
        user: userId,
        plan: planId,
        current: true,
        ref: this.generateRandomRef(10),
      };
      // Crée l'abonnement et le retourne
      const createdSubscription = await strapi.entityService.create('api::subscription.subscription', { data: newSubscription });

      const populatedSubscription = await strapi.entityService.findOne('api::subscription.subscription', createdSubscription.id, {
        populate: { plan: true },
      });

      return populatedSubscription;

    } catch (error) {
      // Gère les erreurs, par exemple un abonnement qui ne peut pas être créée
      throw new Error('Impossible de créer la abonnement : ' + error.message);
    }
  },

  async payment(subscription, user) {

    const plan = subscription.plan;

    console.log(subscription);
    const userType = subscription.plan.type;
    console.log('usertype', userType);
    console.log('user type', user.role.name);
    if (userType !== user.role.name) {
      return { result: false, message: "User type is not equal to type plan" }
    }

    let role = userType === 'Fournisseur' ? '-fournisseur' : '-client';

    // Configuration des URLs en fonction du type d'utilisateur
    const successUrl = strapi.config.get('payment.successUrl') + role;
    const cancelUrl = strapi.config.get('payment.cancelUrl') + role;
    //Url de l'Ipn
    const ipnUrl = strapi.config.get('payment.ipnUrl');


    let paymentRequestUrl = "https://paytech.sn/api/payment/request-payment";
    let params = {
      item_name: plan.name,
      item_price: plan.price.toString(),
      currency: "XOF",
      ref_command: subscription.ref, // Utilise directement 'ref' de la souscription
      command_name: plan.description,
      env: "test",
      ipn_url: ipnUrl,
      success_url: successUrl,
      cancel_url: cancelUrl,
    };

    let headers = {
      Accept: "application/json",
      'Content-Type': "application/json",
      API_KEY: strapi.config.get('payment.apiKey'),
      API_SECRET: strapi.config.get('payment.apiSecret'),
    };

    try {
      const response = await fetch(paymentRequestUrl, {
        method: 'POST',
        body: JSON.stringify(params),
        headers: headers
      });
      const jsonResponse = await response.json();

      return jsonResponse; // Retourne le résultat du paiement
    } catch (error) {
      console.error("Erreur lors du paiement:", error);
      throw new Error('Le paiement a échoué : ' + error.message);
    }
  },
 
  async updateSubscriptionStatus(ref_command, isSuccess) {
    try {
      // Trouver l'abonnement basée sur ref_command
      const subscription = await strapi.entityService.findMany('api::subscription.subscription', {
        filters: { ref: ref_command },
      });

      if (subscription.length === 0) {
        throw new Error('Abonnement non trouvée.');
      }

      // Mettre à jour le statut de l'abonnement en fonction du succès du paiement
      // Ajuste ici pour utiliser les valeurs d'enum correctes
      let status: any = isSuccess ? 'SUCCESS' : 'CANCEL';

      await strapi.entityService.update('api::subscription.subscription', subscription[0].id, {
        data: { status },
      });

      return { message: 'Le statut de l\'abonnement a été mis à jour avec succès.' };
    } catch (error) {
      throw new Error('Erreur lors de la mise à jour du statut de l\'abonnement : ' + error.message);
    }
  },

  async paymentResponse({ type_event, ref_command, api_key_sha256, api_secret_sha256 }) {
    const SHA256Encrypt = (password) => {
      const crypto = require('crypto');
      const sha256 = crypto.createHash('sha256');
      sha256.update(password);
      return sha256.digest('hex');
    };

    const my_api_key = strapi.config.get('payment.apiKey');
    const my_api_secret = strapi.config.get('payment.apiSecret');


    console.log('api_key_sha256', SHA256Encrypt(my_api_key));
    console.log('api_secret_sha256', SHA256Encrypt(my_api_secret));

    // Vérification de l'authenticité de la requête
    if (SHA256Encrypt(my_api_secret) === api_secret_sha256 && SHA256Encrypt(my_api_key) === api_key_sha256) {
      // Détermine si le paiement a été un succès ou un échec
      const isSuccess = type_event === 'sale_complete';

      // Met à jour le statut de la souscription avec la fonction existante
      return await this.updateSubscriptionStatus(ref_command, isSuccess);
    } else {
      // L'authentification a échoué
      throw new Error('Authentification échouée');
    }
  },

}));

Explication du code

1. Génération de Référence Aléatoire

La fonction generateRandomRef crée une chaîne aléatoire de longueur spécifiée. Elle est utilisée pour générer des références uniques pour chaque souscription, ce qui est essentiel pour identifier de manière unique chaque transaction ou abonnement.

2. Vérification de la Possibilité de s’abonner

La méthode canSubscribe s’assure qu’un utilisateur peut s’abonner à un plan. Elle vérifie d’abord s’il existe des abonnements actifs et réussies pour l’utilisateur. Si un abonnement actif est trouvée et qu’elle n’est pas encore expiré, une erreur est générée pour éviter les abonnements redondants.

3. Désactivation des Souscriptions Actuelles

setCurrentSubscriptionToFalse est appelée pour désactiver tous les abonnements actuels de l’utilisateur. Ceci est crucial avant d’activer un nouvel abonnement pour éviter les conflits ou les doublons dans les statuts des abonnements.

4. Création d’une Souscription

La méthode createSubscription crée un nouvel abonnement en utilisant les informations du plan et de l’utilisateur. Elle détermine la date de fin basée sur la durée du plan et initialise l’ abonnement avec un statut dépendant du type de plan.

5. Initiation du Paiement

payment gère le processus d’initiation de paiement. Elle prépare et envoie les détails de la transaction à PayTech et gère la réponse. Si le type d’utilisateur ne correspond pas au type de plan, elle renvoie une erreur, garantissant que seuls les utilisateurs éligibles procèdent au paiement.

6. Mise à Jour du Statut de Souscription

updateSubscriptionStatus est appelée pour mettre à jour le statut de l’abonnement en fonction du résultat du paiement. Elle cherche la souscription par sa référence et met à jour son statut en SUCCESS ou CANCEL selon le résultat du paiement.

7. Réponse au Paiement

La méthode paymentResponse traite la réponse de PayTech suite à un paiement. Elle vérifie l’authenticité de la réponse à l’aide de SHA256 et, si la vérification réussit, elle met à jour le statut de la souscription selon que le paiement a été un succès ou un échec.

Implémentation dans le Contrôleur

Voici comment ces appels de service sont intégrés dans le contrôleur Strapi:

// Importation des dépendances nécessaires
import { factories } from '@strapi/strapi';

export default factories.createCoreController('api::subscription.subscription', ({ strapi }) => ({
    async payment(ctx) {
        const user = ctx.state.user;
        const { body } = ctx.request;

        if (!user) {
            return ctx.badRequest('Aucun utilisateur connecté.');
        }
        const planId = body.planId;

        if (!planId) {
            return ctx.badRequest('Le planId est requis.');
        }

        try {
            // Vérifier si l'utilisateur peut souscrire à un nouveau plan
            const canSubscribe = await strapi.service('api::subscription.subscription').canSubscribe(user.id, planId);
            if (!canSubscribe) {
                return ctx.internalServerError('La souscription n\'est pas terminée.');
            }

            // Créer la souscription si l'utilisateur est éligible
            const subscription = await strapi.service('api::subscription.subscription').createSubscription(user.id, planId);
            
            // Initier le paiement et renvoyer le résultat
            const paymentResult = await strapi.service('api::subscription.subscription').payment(subscription, user);
            return paymentResult;
        } catch (error) {
            console.error("Erreur lors de l'initiation du processus de paiement:", error);
            return ctx.internalServerError('Erreur lors du traitement du paiement.');
        }
    },

    async paymentResponse(ctx) {
        try {
            // Gérer la réponse au paiement
            const response = await strapi.service('api::subscription.subscription').paymentResponse(ctx.request.body);
            return response;
        } catch (error) {
            ctx.send({ message: error.message }, 403);
        }
    },
}));

Configurez les permissions : Acceder aux roles Client et Fournisseur, trouvez l’entité Subscription et activez les cases pour les actions payment et paymentResponse

Explication de l’Intégration des Services dans le Contrôleur

  1. Appel du Service canSubscribe:
    • Objectif: Vérifier si l’utilisateur est éligible pour s’abonner à un nouveau plan.
    • Dans le contrôleur: Avant de créer une souscription ou d’initier un paiement, le contrôleur appelle canSubscribe pour s’assurer qu’aucune souscription active et valide n’empêche l’utilisateur de souscrire à nouveau.
  2. Création de la Souscription avec createSubscription:
    • Objectif: Enregistrer une nouvelle souscription dans la base de données si l’utilisateur est éligible.
    • Dans le contrôleur: Si canSubscribe retourne true, le contrôleur procède à la création de la souscription en utilisant createSubscription. Cette méthode configure la nouvelle souscription avec les informations nécessaires et la sauvegarde.
  3. Initiation du Paiement avec payment:
    • Objectif: Gérer la transaction de paiement via PayTech.
    • Dans le contrôleur: Une fois la souscription créée, le contrôleur utilise la méthode payment pour initier le processus de paiement, en passant les détails nécessaires à PayTech et en traitant la réponse.
  4. Gestion des Réponses de Paiement avec paymentResponse:
    • Objectif: Traiter les réponses après les tentatives de paiement.
    • Dans le contrôleur: Le contrôleur utilise paymentResponse pour gérer et analyser la réponse de PayTech, mettant à jour le statut de la souscription en fonction du succès ou de l’échec du paiement.

Configuration des Routes

  • ouvrez le dossier \api\subscription\routes\ et créer un fichier que vous allez nommer subscription-custom, ajoutez-y le code ci-dessous :
export default {
    routes: [
        {
            path: '/subscription/payment',
            handler: 'subscription.payment',
            method: 'POST',
            config: {
            },
        },
        {
            path: '/subscription/payment-response',
            handler: 'subscription.paymentResponse',
            method: 'POST',
            config: {
            },
        }
    ],
};

Tester avec Postman

Tester l’Endpoint /api/subscription/payment

1. Configurer la Requête POST dans Postman

  1. Lancez Postman et cliquez sur New > Request pour créer une nouvelle requête.
  2. Nommez la requête, par exemple, “Payment Request”.
  3. Entrez l’URL de votre endpoint dans le champ d’adresse. Utilisez une URL comme https://<subdomain>.ngrok.io/api/subscription/payment si vous utilisez ngrok, ou http://localhost:1337/api/subscription/payment si vous testez en local.
  4. Sélectionnez la méthode POST qui se trouve juste à côté de la barre d’adresse pour configurer le type de la requête.

Étape 1: Obtenir le Token JWT

D’abord, vous devez vous connecter à votre API Strapi pour obtenir un jeton JWT. Ceci peut être réalisé en utilisant une commande cURL. Assurez-vous de fournir la bonne URL ainsi que les identifiants corrects. Voici une commande ajustée qui utilise une URL de localhost appropriée et un exemple de données d’utilisateur. Vous pouvez créer cet utilisateur dans l’espace administrateur de Strapi sous Content Manager > User :

curl -X POST http://localhost:1337/api/auth/local \
-H "Content-Type: application/json" \
-d '{
  "identifier": "[email protected]",
  "password": "Password"
}'

Cette commande vous retournera un jeton JWT dans la réponse si les identifiants sont corrects. La réponse ressemblera généralement à ceci :

{
  "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJidWQiOiI1ZWFmMjQ4Njg3NDIzNTAwMTM2ODJlYzQiLCJpYXQiOjE1ODk2MjQwNjIsImV4cCI6MTU5MjIxNjA2Mn0.w5G1cR8cHPHCSOc-J9x7H9loXfRghsJZQZ2F4ohwNcs",
  "user": {
    "id": 1,
    "username": "JohnDoe",
    "email": "[email protected]"
  }
}

Étape 2: Ajouter le Token JWT à la Requête

Pour utiliser le token JWT dans une requête, procédez comme suit :

  1. Sélectionnez l’onglet “Authorization” dans la fenêtre de configuration de la requête Postman.
  2. Choisissez “Bearer Token” dans le menu déroulant du type d’authentification.
  3. Collez le token JWT dans le champ “Token”.

Étape 3: Ajouter le Body de la Requête

  • Allez à l’onglet “Body” situé juste en dessous de la barre d’URL.
  • Assurez-vous que l’option raw est sélectionnée.
  • Changez le format à JSON (application/json) en utilisant le menu déroulant à droite de l’option raw.
  • Entrez les détails de votre requête dans la zone de texte qui devient disponible après avoir sélectionné raw. Par exemple:
{
  "planId": 1
}

Étape 4: Envoyer la Requête

Après avoir cliqué sur “Send”, examinez la réponse obtenue. Si tout est correct, elle devrait inclure les détails de la transaction. Voici un exemple de ce à quoi la réponse pourrait ressembler :

{
  "success": 1,
  "token": "valeur_de_token",
  "redirect_url": "https://paytech.sn/payment/checkout/valeur_de_token",
  "redirectUrl": "https://paytech.sn/payment/checkout/valeur_de_token"
}

Tester l’Endpoint /api/subscription/payment-response

Avant de passer aux tests manuels avec Postman, il est important de comprendre le rôle de l’endpoint /api/subscription/payment-response dans votre système de paiement. Cet endpoint est spécifiquement conçu pour être appelé par PayTech, qui fournira le résultat des tentatives de paiement effectuées par les utilisateurs.

Rôle de l’Endpoint de Réponse au Paiement

Lorsqu’un utilisateur effectue un paiement via PayTech, cette plateforme traite la transaction et, à son issue, appelle cet endpoint pour communiquer le résultat du paiement à votre application Strapi. L’endpoint reçoit des informations telles que le statut de la transaction, le montant payé, et d’autres détails pertinents. Ces données sont essentielles pour que votre système puisse mettre à jour le statut de l’abonnement de l’utilisateur en fonction de l’issue du paiement.

Importance de Tester Manuellement

Tester manuellement cet endpoint avec Postman est une étape cruciale pour s’assurer que votre application traite correctement les données envoyées par PayTech. Ce processus de test vous permet de vérifier que :

  • Votre contrôleur reçoit correctement les données de PayTech.
  • Les réponses et les mises à jour d’état de l’abonnement sont effectuées comme prévu.

Cela garantit que lorsque PayTech envoie réellement les données de paiement en production, votre application répond correctement et met à jour les états des abonnements sans erreur.

1. Configurer la Requête POST dans Postman

Dans le code que vous avez utilisé, j’ai inclus des instructions console.log pour afficher les hachages SHA-256 de la clé API et du secret API. Ces valeurs hachées sont essentielles pour tester votre API de manière sécurisée. Voici comment vous pouvez les utiliser pour configurer votre requête Postman :

  • Créez une nouvelle requête en répétant les étapes ci-dessus. Vous pouvez utiliser le même token que celui obtenu précédemment.
  • Nommez la requête, par exemple, “Payment Response”.
  • Sélectionnez “POST” comme méthode de requête.
  • Dans le champ URL, entrez https://ngrok-free.app/api/subscription/payment-response.
  • Consultez votre console : Lorsque votre serveur démarre et que les fonctions de paiement sont exécutées, regardez dans la console pour trouver les valeurs hachées affichées par les console.log.
  • Copiez les valeurs hachées : Sélectionnez et copiez les valeurs de api_key_sha256 et api_secret_sha256 directement depuis la console.
  • Pour le token, récupérez la valeur "valeur_de_token" qui est retournée par l’API lors de la transaction de paiement ci-dessus.
  • Naviguez vers l’onglet ‘Body’ sous la barre d’adresse dans Postman.
  • Choisissez l’option raw et assurez-vous que le format est réglé sur JSON.
  • Saisissez les données nécessaires pour simuler une réponse de paiement. Par exemple:
{
  "type_event": "sale_complete",
  "client_phone": "+221 suivie du numero de telephone",
  "payment_method": "Wave",
  "item_name": "Test",
  "item_price": "100",
  "currency": "XOF",
  "ref_command": "mhZLyCWW0W",
  "command_name": "Achat Produit Test",
  "env": "test",
  "custom_field": "",
  "token": "valeur_de_token",
  "api_key_sha256": "valeur_copiée_de_la_console",
  "api_secret_sha256": "valeur_copiée_de_la_console"
}
  • Cliquez sur Send.
  • Vérifiez la réponse dans Postman. Vous devriez voir le détail de la transaction ou une réponse correspondante à l’opération demandée.

Conclusion

En résumé, intégrer et tester un système de paiement avec Strapi et PayTech nécessite une compréhension claire de la manière dont les requêtes sont envoyées et des réponses sont gérées. En suivant les étapes décrites, vous avez pu configurer votre système pour initier des transactions de paiement, recevoir et traiter des réponses sécurisées, et vérifier les opérations en utilisant des valeurs hachées pour maintenir la sécurité des données.

Grâce à ces pratiques, vous pouvez assurer une expérience de paiement fluide et sécurisée pour vos utilisateurs, tout en maintenant une structure solide et fiable pour votre application Strapi. Continuez à explorer et à améliorer vos intégrations pour tirer le meilleur parti de vos systèmes de paiement et de gestion de contenu.

Développeuse web full-stack * Plus de publications

Développeuse Fullstack passionnée par le code, je suis diplômée en Programmation/Développement informatique de Sup’Info. Maîtrisant des langages comme PHP, JAVA et C++, je m’adapte facilement à différents environnements techniques. Mon parcours m'a permis de travailler sur une variété de projets, allant du développement Web et mobile à la création d'API et d'applications monétiques pour TPE. J'ai également une bonne connaissance de frameworks tels que Laravel, Tailwind CSS, Spring Boot et React Native.

Contributeurs

0 0 votes
Évaluation de l'article
guest
0 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires

Ingénierie informatique (SSII)

Applize crée des logiciels métiers pour accompagner les entreprises dans la transition vers le zéro papier.


Avez-vous un projet en tête ? Discutons-en.