# Exemple d’adaptateur de licence Merchant-owned

Cet exemple Python 3.10+ implémente le pont HTTP externe de Launch avec la persistance des événements/nonce SQLite et un worker de récupération. Il ne génère **pas** de licences, ne valide pas les fonctionnalités protégées et ne remplace pas votre système de licence.

Implémentez un module Python avec ces hooks :

```python
def apply_snapshot(snapshot):
    # Call your licensing system with snapshot["event_id"] as its durable
    # idempotency key. Apply desired_state and the absolute purchased dates.
    # Return only after confirming the original operation was applied.
    # Raise ValueError for a result requiring manual review.
    ...

def delivery(snapshot):
    # Read an existing result owned by this purchase; do not issue here.
    return {"type": "instructions", "value": "Your own delivery instructions", "expires_at": None}
```

Remplacez le `...` par une intégration réelle avant de configurer un backend. Si aucun module backend n’est configuré, les hooks inclus déclenchent `NotImplementedError` ; les événements passent en révision manuelle et il n’est jamais indiqué qu’une autorisation a été délivrée. Le worker d’exemple peut réessayer un hook après un crash ou une erreur incertaine, donc votre backend de licence doit dédupliquer/récupérer avec le même ID d’événement.

Configurez l’adaptateur en utilisant des variables d’environnement, en gardant la clé hors du contrôle de version et de l’historique du shell :

- `CUSTOM_LICENSING_KEY` : encodage standard Base64 des octets aléatoires 32–128, correspondant à Launch.
- `CUSTOM_LICENSING_KEY_ID` : `key-1`, ou votre identifiant de clé configuré.
- `CUSTOM_LICENSING_CONNECTION_REF` : référence de connexion correspondante.
- `CUSTOM_LICENSING_ENVIRONMENT` : `sandbox` ou `live`.
- `CUSTOM_LICENSING_DATABASE` : un chemin SQLite privé et modifiable en dehors de votre checkout ; conservez-le entre les redémarrages.
- `CUSTOM_LICENSING_BACKEND` : module importable implémentant les hooks ci-dessus.
- `CUSTOM_LICENSING_PORT` : port d’écoute local, par défaut `18883`.

Exécutez `python server.py`. Pour des tests en sandbox local, configurez `http://127.0.0.1:18883` dans Launch et activez explicitement son exception HTTP de loopback. Pour un usage en production, utilisez la terminaison HTTPS, la supervision des processus, les sauvegardes de base de données protégées et la vérification SDK/runtime de votre backend. Ne publiez que les types d’achat/livraison que votre backend prend réellement en charge ; adaptez `capabilities` en conséquence.

Après avoir résolu un problème de backend, `python server.py --retry-event ORIGINAL_EVENT_UUID` remet localement en file d'attente la même charge utile stockée. Dans la page de tâche d'autorisation de Launch, réessayez également cet événement original. Ne changez pas les IDs et n'ajoutez pas de temps à nouveau pour récupérer une réponse.

L'exemple est un point de départ, pas une qualification pour la production. Sa durée de bail de travailleur est de 60 secondes ; limitez les appels de hook à un délai plus court ou renouvelez le bail. Ajoutez la surveillance, les procédures de rotation, des contrôles commerciaux/schema plus stricts et les contrôles opérationnels de votre déploiement avant d'accepter des achats en direct. Le [guide d'intégration](/fr/launch-documents/external-licensing/) et [OpenAPI](/fr/assets/launch/external-licensing-openapi.json) définissent le protocole. N'utilisez jamais une réponse d’état Launch comme permission pour exécuter du code protégé.
