Add-on Gestion de Licences

Un système de gestion de clés de licence multi-fournisseurs pour Larapen avec vérification API, suivi des activations par domaine/machine, gestion des fonctionnalités et intégration de webhooks.

Multi-fournisseurs

Clés manuelles, codes d’achat Envato et sources webhook externes : tout dans un seul système.

Suivi des activations

Suivez les activations par domaine, identifiant machine ou IP. Appliquez des limites par clé (ex. 3 domaines max).

Drapeaux de fonctionnalités

Définissez des ensembles de fonctionnalités par produit (modules, limites, niveaux) retournés dans chaque réponse de vérification.

API REST

Points de terminaison de vérification, activation et désactivation pour l’intégration client.

Cas d’utilisation

Application SaaS

Votre produit SaaS utilise des clés de licence auto-hébergées pour contrôler les niveaux d’abonnement.

  • Chaque plan correspond à un Produit avec différentes fonctionnalités : {"max_users": 5} (Starter), {"max_users": 50, "api_access": true} (Pro).
  • L’application appelle GET /api/licenses/verify au démarrage pour vérifier la validité et lire l’objet features.
  • Pas besoin d’activation par domaine : juste la vérification.

Application de bureau

Une application de bureau est licenciée par machine.

  • Au lancement, l’application appelle POST /api/licenses/activate avec un machine_id.
  • L’application appelle périodiquement GET /api/licenses/verify pour vérifier la validité.
  • Lorsque l’utilisateur décommissionne une machine, il appelle POST /api/licenses/deactivate pour libérer l’emplacement.

Plugin / Thème WordPress

Un plugin WordPress premium valide sa licence sur le site du client.

  • L’administrateur entre la clé dans les paramètres WP. Le plugin appelle POST /api/licenses/activate avec domain = site_url().
  • La vérification s’exécute quotidiennement via WP-Cron en utilisant GET /api/licenses/verify.
  • Si la limite d’activation est atteinte, le client doit désactiver un ancien domaine avant d’en activer un nouveau.

Niveaux d’accès API

Vous vendez un accès API avec différentes limites de débit par plan.

  • Les produits définissent des fonctionnalités : {"rate_limit": 100, "endpoints": ["read"]} (Basic), {"rate_limit": 10000, "endpoints": ["read","write","admin"]} (Enterprise).
  • Votre passerelle API appelle GET /api/licenses/verify et lit les features pour appliquer les limites.

Produits Envato (CodeCanyon)

Vous vendez un produit sur CodeCanyon et souhaitez une vérification automatique des licences.

  • Configurez le fournisseur Envato avec votre jeton API et votre nom d’utilisateur auteur.
  • Les clients entrent leur code d’achat Envato. Le système le vérifie directement auprès de l’API Envato.
  • Pas besoin de création manuelle de clé : le fournisseur gère tout.

Bibliothèque / Plugin JavaScript

Vous vendez un composant d’éditeur JS premium. Chaque client reçoit une clé de licence valide pour N domaines.

  • Au chargement de la page, la bibliothèque appelle POST /api/licenses/activate avec la clé et le domaine actuel.
  • Le serveur vérifie la clé, l’active sur le domaine (comptabilisé dans la limite) et retourne les drapeaux de fonctionnalités via GET /api/licenses/verify (ex. "toolbar_presets": true, "ai_integration": false).

Prérequis

  • Larapen CMS v1.0.0 ou ultérieur
  • PHP 8.3+
  • MySQL 8.0+
  • Une installation Larapen active avec le système d’add-ons activé

Installation

Étape 1 : Placer l’add-on

Copiez ou créez un lien symbolique du dossier licenses dans le répertoire « extensions/addons » de votre Larapen :

Ou, si vous développez en dehors du projet, créez un lien symbolique :

Étape 2 : Activer l’add-on

Allez dans Admin → Add-ons → Add-ons installés et activez Gestion de Licences. Alternativement, insérez une ligne dans la table addons :

Étape 3 : Exécuter les migrations

Cela crée 5 tables : licenses_products, licenses_keys, licenses_activations, licenses_webhook_logs, et licenses_key_user (pivot). Cela ajoute également supported_until à licenses_keys et license_product_id à shop_products (si l’add-on Shop est installé).

Étape 4 : Définir les permissions

L’add-on enregistre 14 permissions (voir Permissions). Assignez-les aux rôles administrateur via Admin → Utilisateurs → Rôles & Permissions.

Étape 5 : Configurer

Naviguez vers Admin → Licences → Paramètres et définissez votre clé API, les préférences de format de clé et les identifiants fournisseur. Voir Configuration.

Configuration

Tous les paramètres peuvent être configurés de deux manières :

  1. Panneau d’administration : Licences → Paramètres (stockés dans la table settings, groupe licenses)
  2. Variables d’environnement : dans .env (utilisées comme valeurs par défaut ; les paramètres admin les remplacent)
Paramètre Description Défaut
api_key Clé API requise pour tous les points de terminaison côté client. Envoyée via l’en-tête X-Api-Key ou le paramètre de requête api_key. (vide)
default_key_format Format par défaut pour les clés générées automatiquement : uuid, alphanumeric, prefixed ou hmac_signed. alphanumeric
key_prefix Chaîne de préfixe pour le format de clé prefixed (ex. LIC). LIC
default_max_activations Limite d’activation par défaut lors de la création de nouvelles clés. 1
hmac_key Clé secrète pour le format de clé signé HMAC et la vérification de signature webhook. (vide, utilise APP_KEY par défaut)
api_rate_limit Nombre maximum de requêtes API par minute par client. 3
api_daily_rate_limit Nombre maximum de requêtes API par jour par client. 50

Paramètres spécifiques aux fournisseurs

Paramètre Fournisseur Description
envato_api_token Envato Jeton personnel depuis build.envato.com
envato_author_username Envato Votre nom d’utilisateur auteur Envato
webhook_secret Webhook Secret partagé pour la vérification de signature HMAC-SHA256

Variables d’environnement

Admin : Tableau de bord

Le tableau de bord (Licences → Tableau de bord) fournit un aperçu en temps réel :

  • Cartes de statistiques : Total des clés, clés actives, total des produits, activations actives
  • Répartition par statut : Nombre de clés suspendues, expirées et révoquées
  • Clés récentes : Les 10 dernières clés créées avec affichage masqué et badges de statut
  • Webhooks récents : Les 5 derniers événements webhook avec fournisseur et statut

Admin : Produits

Les produits représentent le logiciel ou service faisant l’objet d’une licence. Chaque clé de licence appartient à un produit.

Créer un produit

Naviguez vers Licences → Produits → Ajouter un produit.

Champ Requis Description
name Oui Nom du produit (traduisible)
slug Non Identifiant compatible URL. Généré automatiquement à partir du nom si vide.
description Non Description du produit (traduisible, max 2000 caractères)
sku Non Référence article. Doit être unique.
version Non Version actuelle du produit (ex. 2.1.0)
is_active Interrupteur. Les produits inactifs sont masqués des listes de sélection.
features Non Paires clé-valeur définissant ce que ce produit débloque. Voir Drapeaux de fonctionnalités.

Admin : Clés de licence

Créer une clé

Naviguez vers Licences → Clés de licence → Ajouter une clé.

Champ Requis Description
product Oui Le produit auquel cette clé appartient
key Non Chaîne de clé de licence. Laissez vide pour générer automatiquement.
key_format Non Format pour la génération automatique (voir Formats de clé)
license_type Oui Standard, Étendue, Essai ou À vie
status Oui Active, Suspendue, Expirée ou Révoquée
expires_at Non Date d’expiration. Laissez vide pour les clés sans expiration.
supported_until Non Date de fin de support. Distincte de l’expiration de licence : suit la fin de la période de support du client (ex. fenêtre de support de 6 mois Envato).
max_activations Oui Nombre de domaines/machines sur lesquels cette clé peut être activée simultanément
provider Oui Source de la licence : manual, envato ou webhook
assigned_user Non Lier optionnellement à un compte utilisateur
notes Non Notes internes (non exposées via l’API)
Astuce : La chaîne de clé ne peut pas être modifiée après la création. Choisissez votre format avec soin ou laissez le système la générer automatiquement.

Opérations en masse

Génération en masse

Naviguez vers Clés de licence → Génération en masse pour créer jusqu’à 1 000 clés en une fois. Sélectionnez le produit, le format, le type de licence, le nombre maximum d’activations et la date d’expiration optionnelle.

Suppression en masse

Sur la page de liste des clés, sélectionnez plusieurs clés avec les cases à cocher et cliquez sur Supprimer la sélection.

Export CSV

Cliquez sur Exporter en CSV sur la page de liste des clés. Permet le filtrage par produit et statut avant l’export.

Actions de cycle de vie

Action Effet
Suspendre Définit le statut à suspended. La clé échoue à la vérification mais peut être réactivée ultérieurement. Les activations existantes restent mais ne sont pas fonctionnelles.
Révoquer Définit le statut à revoked et désactive toutes les activations actives. Cela est irréversible en pratique.
Réactiver Redéfinit le statut à active. La clé redevient valide (si non expirée).

Admin : Activations

Consultez toutes les activations d’une clé spécifique en cliquant sur Activations sur la page de détail de la clé, ou en naviguant vers /admin/licenses/keys/{id}/activations.

Chaque enregistrement d’activation affiche :

  • Domaine (si fourni) — avec un badge Local pour les domaines locaux/de développement
  • Identifiant machine (si fourni)
  • Adresse IP
  • Agent utilisateur
  • Date d’activation
  • Statut Actif/Désactivé

Les administrateurs peuvent manuellement désactiver toute activation active pour libérer un emplacement pour le client.

Lorsque « Enregistrer les activations de domaines locaux » est activé dans les paramètres de contournement des domaines locaux, les activations locales apparaissent dans la liste mais ne comptent pas dans la limite max_activations de la clé. Un bouton Supprimer les activations locales permet de supprimer en masse tous les enregistrements d’activation locale pour une clé. La page d’index des clés de licence fournit un filtre pour afficher uniquement les clés avec des activations locales.

Admin : Drapeaux de fonctionnalités

Chaque produit peut définir un ensemble de drapeaux de fonctionnalités clé-valeur sur le formulaire de création/modification. Ceux-ci sont stockés en JSON et retournés dans chaque réponse de l’API /verify.

Comment ça fonctionne

  1. Modifiez un produit et faites défiler jusqu’à la section Fonctionnalités.
  2. Cliquez sur Ajouter une fonctionnalité pour ajouter des lignes clé-valeur.
  3. Définissez la clé de fonctionnalité (ex. api_access) et la valeur (ex. true).
  4. Enregistrez. Les fonctionnalités sont retournées sous forme d’objet JSON dans les réponses API.

Exemples d’ensembles de fonctionnalités

Admin : Paramètres

La page de paramètres (Licences → Paramètres) est organisée en sections :

  • Configuration API : clé API et limite de débit
  • Génération de clés : format par défaut, préfixe, nombre maximum d’activations, clé HMAC
  • Contournement des domaines locaux : activer/désactiver le contournement, interrupteur d’enregistrement des activations locales et motifs de domaines
  • Fournisseur Envato : activer/désactiver, jeton API et nom d’utilisateur auteur
  • Fournisseur Webhook : secret webhook et affichage de l’URL

La barre latérale affiche tous les points de terminaison API disponibles et les badges de statut de configuration des fournisseurs.

Admin : Journaux de webhooks

Tous les événements webhook entrants sont journalisés avec leur fournisseur, type d’événement, données brutes, données de réponse, statut (Succès / Échec / Ignoré) et messages d’erreur éventuels. Naviguez vers Licences → Journaux de webhooks pour consulter. Filtrez par fournisseur ou statut.

Mise à jour

Étape 1 : Remplacer les fichiers

Remplacez le répertoire de l’add-on par la nouvelle version (ou faites un pull de la dernière version si vous utilisez un lien symbolique vers un dépôt Git).

Étape 2 : Exécuter les migrations

Les nouvelles migrations sont automatiquement détectées. L’add-on utilise des migrations horodatées qui ne s’exécutent qu’une seule fois.

Étape 3 : Vider les caches

Étape 4 : Vérifier

Visitez Licences → Tableau de bord pour confirmer que tout se charge correctement. Vérifiez la page Paramètres pour découvrir les nouvelles options de configuration introduites par la mise à jour.

Sauvegarde préalable : Sauvegardez toujours votre base de données avant d’exécuter des migrations sur un système en production.

Page d’enregistrement de licence

Une page publique où les clients enregistrent leur code d’achat (Envato ou manuel) et l’activent sur leur domaine. Disponible à /{locale}/licenses/register (ou /licenses/register sans préfixe de langue).

URL & Routes

MéthodeURLNom de routeDescription
GET /{locale}/licenses/register front.licenses.register.localized Afficher le formulaire d’enregistrement
POST /{locale}/licenses/register front.licenses.register.localized Traiter l’enregistrement
GET /licenses/register front.licenses.register Variante non localisée

Flux d’enregistrement

  1. Le client visite /licenses/register et remplit sa clé de licence / code d’achat et son domaine.
  2. Le système recherche la clé dans la base de données locale.
  3. Si elle n’est pas trouvée localement, il essaie le fournisseur Envato : vérifie le code d’achat via l’API Envato. Si valide, un enregistrement LicenseKey est automatiquement créé avec provider = envato.
  4. Si l’utilisateur est authentifié, la LicenseKey est liée à son compte utilisateur (user_id).
  5. Le système appelle LicenseActivationService::activate() avec le domaine fourni.
  6. En cas de succès, le client voit un message de confirmation. En cas d’échec (clé invalide, expirée, activations maximum atteintes), une erreur est affichée.

Champs du formulaire

ChampValidationDescription
license_key Requis, chaîne, max 255 La clé de licence ou le code d’achat Envato
domain Requis, chaîne, max 255 Le domaine où le logiciel est installé (sans http/https)

Vues de thème

Chaque thème fournit sa propre version stylisée du formulaire d’enregistrement à :

Thèmes : default, creative, elegant, minimalist, olive, technology.

Astuce : La page d’enregistrement est liée depuis le menu de navigation front-end via l’entrée front_menu dans addon.json. Le libellé « Enregistrer une licence » apparaît dans le menu d’en-tête.

Portail client (Mes licences)

Les clients authentifiés peuvent consulter toutes leurs licences liées et gérer les activations de domaines. Nécessite la connexion utilisateur (utilise le middleware auth).

URL & Routes

MéthodeURLNom de routeDescription
GET /{locale}/licenses/list front.licenses.my.localized Lister toutes les licences de l’utilisateur
GET /{locale}/licenses/list/{id} front.licenses.my.show.localized Voir les détails de la licence & activations
POST /{locale}/licenses/list/{id}/deactivate front.licenses.my.deactivate.localized Désactiver un domaine

Des variantes non localisées (sans {locale}) sont également disponibles.

Page Mes licences

Affiche une liste/tableau de toutes les licences appartenant à l’utilisateur connecté, montrant :

  • Nom du produit : produit de licence lié
  • Clé de licence : masquée par défaut (ex. XXXX-XXXX-XXXX-ab12), avec un bouton de copie
  • Badge de statut : Active (vert), Expirée (ambre), Suspendue (rouge), Révoquée (sombre)
  • Type de licence : Standard, Étendue, Essai, À vie
  • Activations : nombre / max (ex. « 2 / 3 »)
  • Date d’expiration : ou « Jamais » pour les licences à vie
  • Lien Voir les détails

Page de détail de la licence

Affiche les informations complètes pour une licence unique :

  • Informations sur la clé : clé complète (masquée avec bouton de révélation via JavaScript natif), statut, type, dates d’émission/expiration
  • Domaines actifs tableau : domaine, adresse IP, date d’activation et un bouton Désactiver pour chacun
  • Historique des activations : toutes les activations (actives + désactivées) avec horodatages

Désactivation

Les clients peuvent auto-désactiver les domaines qu’ils n’utilisent plus. La désactivation :

  1. Vérifie que la licence appartient à l’utilisateur authentifié
  2. Appelle LicenseActivationService::deactivateByDomain()
  3. Libère un emplacement d’activation pour utilisation sur un autre domaine
  4. Redirige avec un message de succès

Vues de thème

Menu utilisateur : Le lien « Mes licences » apparaît dans le menu déroulant du compte utilisateur (configuré via user_menu dans addon.json, icône : bi-key).

Génération automatique via la boutique

Lorsque l’add-on Shop est actif et qu’un produit de la boutique est lié à un produit de licence, les clés de licence sont automatiquement générées lorsqu’une commande est payée.

Configuration

  1. Exécutez la migration : La migration 2026_03_07_100001_add_license_product_id_to_shop_products_table.php ajoute une colonne license_product_id à shop_products.
  2. Liez les produits de la boutique aux produits de licence : Dans le formulaire d’administration du produit de la boutique, définissez le license_product_id pour le lier à un produit de licence créé sous Licences → Produits.

Flux de génération automatique

  1. Un client effectue un achat via la boutique.
  2. Le payment_status de la commande est mis à jour à PAID (via markAsPaid() ou le webhook de la passerelle de paiement).
  3. Le ShopOrderObserver détecte le changement de statut de paiement.
  4. Pour chaque article de commande où le produit de la boutique a un license_product_id :
    • Une LicenseKey est créée par quantité d’article (ex. qté 2 → 2 clés)
    • Le fournisseur est défini à shop
    • Le statut est défini à active
    • provider_reference est défini à shop_order:{order_number} (empêche la génération en double)
    • La clé hérite du format par défaut des paramètres
  5. Un e-mail LicenseKeyIssuedNotification est envoyé au client avec :
    • Salutation avec le nom du client
    • Toutes les clés de licence générées
    • Un bouton « Enregistrer une licence » pointant vers /licenses/register
    • Instructions sur la manière d’activer

Prévention des doublons

L’observateur vérifie l’existence de clés avec le même provider_reference avant de générer. Si des clés pour shop_order:ORD-12345 existent déjà, l’observateur ignore la génération. Cela empêche les doublons si le statut de paiement est mis à jour plusieurs fois.

Modifications de la base de données

TableColonneTypeDescription
shop_products license_product_id BIGINT UNSIGNED NULL FK vers licenses_products.id (ON DELETE SET NULL)
Prérequis : L’add-on Shop doit être installé et actif. L’observateur n’est enregistré que lorsque Addons\Shop\Models\Order existe.
Remarque : L’observateur se déclenche uniquement sur l’événement Eloquent updated (pas created). Une commande créée directement avec payment_status = PAID ne déclenchera pas la génération automatique : le statut doit passer d’un état non payé à PAID via une mise à jour.

Dépannage

L’API renvoie 503 : « License API is not configured »

Vous n’avez pas défini de clé API. Allez dans Licences → Paramètres et définissez le champ Clé API, ou définissez LICENSES_API_KEY dans .env.

L’API renvoie 401 : « Invalid API key »

L’en-tête X-Api-Key ou le paramètre api_key ne correspond pas à la clé configurée. Vérifiez les espaces en début/fin ou les problèmes d’encodage.

L’activation échoue avec « Maximum activations reached »

La clé a atteint sa limite max_activations. Options :

  • Désactivez un domaine inutilisé via POST /deactivate ou depuis le panneau d’administration
  • Augmentez max_activations sur la clé dans le panneau d’administration

La vérification Envato échoue

Vérifiez que :

  • Le jeton API Envato a les permissions View Your Envato Account Username et Verify Purchases
  • Le Nom d’utilisateur auteur correspond exactement à votre profil Envato (sensible à la casse)
  • Le code d’achat est valide et appartient à l’un de vos articles

Les événements webhook sont journalisés comme « Échec »

Causes courantes :

  • Signature invalide : L’en-tête X-Webhook-Signature ne correspond pas. Assurez-vous que les deux côtés utilisent le même secret et calculent HMAC-SHA256 sur le corps brut de la requête.
  • Produit manquant : Le slug product dans les données ne correspond à aucun produit actif. Créez d’abord le produit.
  • Événement invalide : Le champ event doit être l’un de : license.created, license.updated, license.revoked, license.expired.

La page d’enregistrement renvoie « Clé de licence invalide »

La clé n’a pas été trouvée localement et la vérification Envato a également échoué. Vérifiez :

  • Le jeton API Envato et le nom d’utilisateur auteur sont correctement configurés dans Licences → Paramètres
  • Le code d’achat est valide et appartient à l’un de vos articles Envato
  • Si vous utilisez des clés manuelles, assurez-vous que la clé existe dans Licences → Clés de licence

Le domaine local n’est pas conttourné

Vérifiez que :

  • Le contournement des domaines locaux est activé dans Licences → Paramètres (ou LICENSES_LOCAL_DOMAIN_BYPASS=true dans .env)
  • Le domaine correspond à l’un des motifs configurés (les motifs utilisent la syntaxe fnmatch())
  • Le domaine n’inclut pas le protocole : utilisez localhost et non http://localhost

L’achat en boutique ne génère pas de clés de licence

Vérifiez que :

  • Le produit de la boutique a un license_product_id défini (lié à un produit de licence)
  • Le payment_status de la commande est changé en PAID
  • La migration 2026_03_07_100001_add_license_product_id_to_shop_products_table a été exécutée
  • Vérifiez la colonne provider_reference : si des clés avec shop_order:{order_number} existent déjà, l’observateur ignore la génération

La vérification côté client affiche « Licence invalide »

Vérifiez que :

  • LICENSE_API_BASE_URL pointe vers le bon serveur (ex. https://larapen.com/api/licenses)
  • LICENSE_API_KEY correspond au LICENSES_API_KEY sur le serveur
  • Le code d’achat est valide et n’a pas été révoqué
  • Le serveur est joignable depuis le client (pas de problèmes de pare-feu/DNS)

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Besoin d'aide ? Créez un ticket de support

Créer un Ticket