Code de licence : guide complet du développement, débogage et mise en ligne
v1.0.0
Logiciel client : développement → débogage → mise en ligne — guide complet du processus (v4)
Concerne : les développeurs qui publient un logiciel client sur PowerSoftware.net et intègrent le système de codes de licence. Ce document couvre l’ensemble du cycle de vie, de la « création du produit » à l’« achat par de vrais utilisateurs », en mettant l’accent sur la nouvelle capacité de débogage à double environnement de la v4 : avant la mise en ligne, utiliser son propre ordinateur comme machine de débogage pour parcourir tout le processus avec la véritable chaîne de paiement (environnement Waffo Test).
1. Vue d’ensemble du processus
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ① Développement│ → │ ② Débogage │ → │ ③ Mise en │ → │ ④ Exploitation│
│ │ │ │ │ ligne │ │ après sortie │
│ Créer le │ │ Enregistrer │ │ Soumettre │ │ Consulter │
│ produit │ │ machine de │ │ la revue │ │ commandes │
│ Intégrer SDK │ │ débogage │ │ approuvée │ │ délier/remb. │
│ Enregistrer │ │ chaîne réelle│ │ synchroniser │ │ Itération │
│ brouillon │ │ (env. Test) │ │ production │ │ versions │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
| Phase | Statut du produit | Où vont licences/commandes | Revenus réels ? |
|---|---|---|---|
| ① Développement | Brouillon (DRAFT) | — | Non |
| ② Débogage | Brouillon / en revue | Tables Test (codes de licence préfixés T-) |
Non (canal de paiement test) |
| ③ Mise en ligne | Publié | Tables de production | Oui |
Règle clé : débogage et production sont totalement isolés. Tout ce qui se passe sur les machines de débogage (essais, commandes, paiements, émission de codes, activation, remboursements) n’affecte que les tables test — cela n’entre ni dans le partage de revenus ni dans la réconciliation, et n’affecte aucun utilisateur réel ; les accès depuis des machines non-débogage passent toujours par la chaîne de production.
2. Phase de développement
2.1 Créer le produit
- Se connecter au Developer Center de PowerSoftware.net → publier un produit, choisir « Logiciel client » comme type de produit
- Choisir le modèle de vente Essayer avant d’acheter et renseigner les jours d’essai (recommandé 7~14 jours)
- Configurer les éditions de licence : trois niveaux par défaut
BASIC/PRO/ULTIMATE; le code, le nom, le prix et la liste des fonctionnalités sont personnalisables - Cocher « La plateforme encaisse les frais de licence » (obligatoire pour Essayer avant d’acheter)
- Téléverser le paquet logiciel et les supports de présentation
2.2 Enregistrer le brouillon (nouvelle capacité)
En bas du formulaire produit se trouvent deux boutons :
| Bouton | Comportement |
|---|---|
| Enregistrer le brouillon | Le produit est enregistré au statut DRAFT, n’entre pas dans la file de revue et peut être modifié à tout moment |
| Enregistrer et soumettre la revue | Le produit entre dans la file de revue (PENDING_RELEASE) |
Après l’enregistrement du brouillon / la soumission, la plateforme synchronise asynchroniquement le produit vers l’environnement Waffo Test (un échec déclenche seulement une alerte sans bloquer l’enregistrement) ; c’est la condition pour pouvoir passer commande en phase de débogage. Recommandation : pendant le développement, enregistrer le brouillon suffit pour commencer à déboguer, inutile de soumettre la revue.
Après l’enregistrement, noter le productUniqueCode (visible sur la page de publication, pas un secret).
2.3 Intégrer le SDK de licence (deux scénarios d’intégration)
PowerSoftware.net propose deux modes d’intégration de licence pour les logiciels clients. Choisissez selon votre situation :
| Scénario A : chaîne complète de la plateforme (Essayer avant d’acheter) | Scénario B : commandes hors plateforme | |
|---|---|---|
| Produits concernés | Logiciel client + modèle de vente Essayer avant d’acheter | Logiciel en promotion seule (encaissement autonome) ; ou logiciel serveur / client avec modèle Payer d’abord (PAY_FIRST) ou fonctions VIP à encaissement autonome |
| Qui gère le paiement | La plateforme PowerSoftware.net (Waffo, Alipay, PayPal) ; le débogage utilise l’environnement Waffo Test comme canal de paiement | Le développeur lui-même (paiement dans l’application ou autres canaux) |
| Qui émet les codes | La plateforme émet automatiquement après paiement réussi | Le logiciel appelle l’API de la plateforme pour émettre (signature HMAC) |
Secret de licence licenseApiSecret requis ? |
❌ Non | ✅ Oui (stocké côté serveur uniquement, jamais côté client) |
| Serveur requis ? | ❌ Non, purement côté client | ✅ Oui (conserve licenseApiSecret, relaie les requêtes d’émission) |
| Licence d’essai | ✅ Prise en charge (claimTrial) |
❌ Pas d’essai (l’essai ne concerne que les produits Essayer avant d’acheter) |
| Page d’achat | Fournie par la plateforme, redirection SDK en une ligne | Pas de page d’achat plateforme, le développeur gère lui-même |
Concernant la configuration des éditions : tous les types de produits (client/serveur/promotion seule) peuvent activer les codes de licence et personnaliser les éditions (BASIC/PRO/ULTIMATE, etc.). Les prix des éditions et les listes de fonctionnalités ne s’affichent sur la page d’achat que si le développeur coche « La plateforme encaisse les frais de licence » (
licensePlatformPayment) ; sinon, le développeur gère lui-même l’encaissement et la plateforme ne fournit que l’émission et la vérification des codes.
Comment choisir :
- Développeur indépendant / petite équipe sans serveur propre → Scénario A (les chapitres 4 et 5 de ce document suivent le scénario A comme ligne principale)
- Vous avez déjà des canaux de paiement (p. ex. marchand WeChat/Alipay) et souhaitez uniquement l’émission et la vérification de codes par la plateforme → Scénario B
2.3.1 Installation du SDK
Les trois langages (Node.js / Python / Java) sont sans dépendances — copiez directement le code source dans votre projet, sans aucun gestionnaire de paquets. L’algorithme du code machine est cohérent entre langages (une même machine génère le même machineCode). Dépôt SDK : github.com/mizhanchengxi/powersoftware-license-sdk
2.3.2 Scénario A : chaîne complète de la plateforme (Essayer avant d’acheter)
Prérequis : le modèle de vente du produit est Essayer avant d’acheter, les jours d’essai et les éditions de licence sont configurés, « La plateforme encaisse les frais de licence » est coché. Le secret de licence licenseApiSecret n’est PAS requis :
# Python
from ps_license_sdk import LicenseClient, machine_code
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="") # laisser api_secret vide
mc = machine_code()
// Node.js
import { LicenseClient, machineCode } from './index.js';
const client = new LicenseClient({ productUniqueCode: 'PRO-2026-001', apiSecret: "" }); // Scénario A : secret vide
const mc = machineCode();
// Java
import com.powersoftware.sdk.LicenseClient;
LicenseClient client = new LicenseClient("PRO-2026-001", ""); // Scénario A : secret vide
String mc = LicenseClient.machineCode();
Parcours complet d’intégration :
Premier lancement
│
├─ claimTrial(machineCode) ────────────→ obtenir la licence d’essai
│ ↓ retourne { licenseCode, activationToken, licenseUpgradeMode }
│ ↓ stockage persistant local
│
├─ Pendant l’essai : toutes les fonctions disponibles
│ │
│ └─ clic sur une fonction payante → verifyCached() vérification avec cache 60s → autorisation
│
└─ Essai expiré / non activé
│
├─ verifyCached() retourne invalid/expired
├─ boîte de dialogue : « achat d’une licence d’activation requis »
└─ purchaseUrl(machineCode) → redirection vers la page d’achat de la plateforme
│
↓ l’utilisateur paie sur la plateforme → la plateforme émet le code + envoi par e-mail
│
L’utilisateur revient dans le logiciel et saisit le code de licence
│
├─ activate(licenseCode, machineCode)
│ ↓ retourne { activationToken, licenseUpgradeMode }, stockage persistant local
│
└─ utilisation ultérieure → vérification verifyCached() → autorisation
À implémenter : claimTrial (obtenir l’essai au premier lancement) → verifyCached (vérification des fonctions payantes) → purchaseUrl (redirection vers la page d’achat sans licence) → activate (activation par saisie du code) → persistance locale de licenseCode + activationToken → traitement des codes d’erreur LicenseError.
Code principal (Python) :
import json
from pathlib import Path
from ps_license_sdk import LicenseClient, machine_code
# ---------- Initialisation ----------
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="")
CRED_FILE = Path.home() / ".myapp" / "license.json"
def load_cred():
if CRED_FILE.exists():
return json.loads(CRED_FILE.read_text())
return {}
def save_cred(d):
CRED_FILE.parent.mkdir(parents=True, exist_ok=True)
CRED_FILE.write_text(json.dumps(d, ensure_ascii=False))
# ---------- Premier lancement : obtenir l’essai ----------
def claim_trial():
mc = machine_code()
try:
result = client.claim_trial(mc)
save_cred({
"licenseCode": result["licenseCode"],
"activationToken": result["activationToken"],
})
print(f"Essai activé, code de licence : {result['licenseCode']}")
except Exception as e:
print(f"Échec de l’obtention de l’essai : {e}")
# ---------- Vérifier la licence (appelée au clic sur une fonction payante) ----------
def check_license(required_edition="PRO"):
cred = load_cred()
if not cred.get("licenseCode"):
return {"valid": False, "reason": "Non activé"}
mc = machine_code()
try:
result = client.verify_cached(
cred["licenseCode"], mc, cred["activationToken"]
)
if not result.get("valid"):
return {"valid": False, "reason": "Licence invalide ou expirée"}
user_edition = result.get("edition", "")
levels = {"BASIC": 0, "PRO": 1, "ULTIMATE": 2}
if levels.get(user_edition, 0) < levels.get(required_edition, 0):
return {"valid": False, "reason": f"Édition {required_edition} ou supérieure requise"}
return {"valid": True, "edition": user_edition,
"expiryTime": result.get("expiryTime"),
"trialExpiryTime": result.get("trialExpiryTime")}
except Exception as e:
return {"valid": False, "reason": str(e)}
# ---------- Activer un code de licence (après achat) ----------
def activate(license_code):
mc = machine_code()
try:
result = client.activate(license_code, mc)
save_cred({
"licenseCode": license_code,
"activationToken": result["activationToken"],
})
return True
except Exception as e:
print(f"Échec de l’activation : {e}")
return False
# ---------- Ouvrir la page d’achat ----------
def open_purchase_page():
mc = machine_code()
url = client.purchase_url(mc)
import webbrowser
webbrowser.open(url)
Exemple de blocage de fonction :
# Définir l’édition requise par fonction
FEATURE_EDITION = {
"basic_feature": "BASIC",
"plus_feature": "PRO",
"ultimate_feature": "ULTIMATE",
}
def run_feature(feature_name):
required = FEATURE_EDITION.get(feature_name, "BASIC")
if required == "BASIC":
do_basic_feature()
return
result = check_license(required)
if result["valid"]:
do_paid_feature(feature_name)
else:
print(f"Impossible d’utiliser cette fonction : {result['reason']}")
open_purchase_page()
2.3.3 Scénario B : commandes hors plateforme (encaissement autonome)
Produits concernés : logiciels en promotion seule (encaissement autonome), ou logiciels serveurs / clients avec modèle Payer d’abord (PAY_FIRST) ou fonctions VIP à encaissement autonome.
Prérequis : le produit a licenseEnabled activé ; dans le backend développeur, obtenir licenseApiSecret (stocké côté serveur uniquement, jamais exposé au client). Architecture :
Client Votre serveur Plateforme PowerSoftware.net
│ │ │
│ L’utilisateur paie │ │
│ (votre paiement) │ │
├──────────────────────→│ │
│ │ generateForSoftware( │
│ │ machineCode, edition, │
│ │ clientOrderId) │
│ │ (signature HMAC + timestamp) │
│ ├───────────────────────────────→│
│ │ ← retourne licenseCode │
│ ← retourne licenseCode│ │
│ │ │
│ activate(licenseCode, machineCode) │
├───────────────────────────────────────────────────────→│
│ ← retourne activationToken │
│ │ │
│ verifyCached(...) │ │
├───────────────────────────────────────────────────────→│
│ ← { valid, edition, expiryTime } │
Serveur (conserve le secret de licence licenseApiSecret, émet les codes) :
from ps_license_sdk import LicenseClient, machine_code
server_client = LicenseClient(
product_unique_code="PRO-2026-001",
api_secret="VOTRE_SECRET_EMISSION_FROM_DEVELOPER_CONSOLE",
)
def issue_license(user_machine_code, edition="PRO", order_id=""):
"""Après paiement de l’utilisateur, le serveur appelle la plateforme pour émettre le code"""
result = server_client.generate_for_software(
machine_code_value=user_machine_code,
edition=edition,
expiry_days=365,
client_order_id=order_id,
)
return result["licenseCode"]
Client (pas besoin de licenseApiSecret, activation et vérification) :
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="")
def activate(license_code):
mc = machine_code()
result = client.activate(license_code, mc)
save_cred({"licenseCode": license_code,
"activationToken": result["activationToken"]})
À implémenter : côté serveur generateForSoftware (émission) + upgradeForSoftware (mise à niveau/renouvellement) ; côté client activate / verifyCached + persistance locale des identifiants + traitement des codes d’erreur LicenseError.
2.3.4 Référence des méthodes du SDK
| Méthode | Scénario A | Scénario B | Signature | Description |
|---|---|---|---|---|
machine_code() |
✅ | ✅ | — | Générer le code machine (cohérent entre langages) |
claim_trial(mc) |
✅ | — | — | Obtenir la licence d’essai (produits Essayer avant d’acheter uniquement) |
activate(code, mc) |
✅ | ✅ | — | Activer le code de licence, lier à la machine |
verify(code, mc, token) |
✅ | ✅ | — | Vérifier l’état de la licence |
verify_cached(code, mc, token) |
✅ | ✅ | — | Vérification avec cache local (60s) |
deactivate(code, mc) |
✅ | ✅ | — | Délier la machine (connexion requise, scénario navigateur) |
purchase_url(mc) |
✅ | — | — | Générer l’URL de la page d’achat plateforme |
generate_for_software(mc, edition, ...) |
— | ✅ | HMAC | Émission de code dans le logiciel (serveur uniquement) |
upgrade_for_software(code, edition, ...) |
— | ✅ | HMAC | Mise à niveau/renouvellement dans le logiciel (serveur uniquement) |
Note sur les champs retournés : les réponses de succès de
activate/verify/claimTrialcontiennent touteslicenseUpgradeMode(politique de mise à niveau du produit :SAME_CODE= la clé reste inchangée ;NEW_CODE= la clé est re-liée). Le client s’en sert pour décider d’afficher ou non le champ « Lier une clé de licence » : avecSAME_CODE, la clé ne change jamais, inutile de demander une nouvelle saisie ; avecNEW_CODE, une nouvelle clé est émise lors de la mise à niveau / du renouvellement — remplacez lelicenseCodestocké localement par celui renvoyé. Par défautSAME_CODEsi absente ; les résultats deverifysont mis en cache ~60 s, un changement prend effet sous 60 s au plus. Les réponses contiennent aussitrialExpiryTime(instantané de l’expiration d’essai, chaîne ISO 8601 ;nullsi la licence ne provient pas d’un essai). Le client peut l’utiliser comme période de grâce : si l’utilisateur teste la version complète puis achète une édition inférieure, les fonctions de l’édition supérieure restent déverrouillées jusqu’àtrialExpiryTime. Les réponses contiennent aussitrialExpiryTime(instantané de l’expiration d’essai, chaîne ISO 8601 ;nullsi la licence ne provient pas d’un essai). Le client peut l’utiliser comme période de grâce : si l’utilisateur teste la version complète puis achète une édition inférieure, les fonctions de l’édition supérieure restent déverrouillées jusqu’àtrialExpiryTime. Les réponses contiennent aussitrialExpiryTime(instantané de l’expiration d’essai, chaîne ISO 8601 ;nullsi la licence ne provient pas d’un essai). Le client peut l’utiliser comme période de grâce : si l’utilisateur teste la version complète puis achète une édition inférieure, les fonctions de l’édition supérieure restent déverrouillées jusqu’àtrialExpiryTime.
Le débogage à double environnement est totalement transparent pour les deux scénarios :
- Scénario A : sur les machines de débogage,
claimTrial/ les paiements sur la page d’achat passent automatiquement par l’environnement Test (voir chapitre 4) - Scénario B : lorsqu’une machine de débogage appelle
generateForSoftware, la plateforme route également par code machine vers l’environnement Test et retourne un code préfixéT-; le code serveur ne nécessite aucune modification - Les appels SDK sont identiques pendant le débogage et après la mise en ligne — aucun paramètre d’environnement ni branche de code nécessaire ; le routage d’environnement est effectué automatiquement par le serveur de la plateforme
3. Détails de l’intégration de licence (communs aux deux scénarios)
3.1 Spécification de stockage local des identifiants
Le SDK lui-même ne gère pas la persistance — c’est au développeur de l’implémenter. Contenu stocké :
{
"licenseCode": "XXXXXXXXXXXX",
"activationToken": "YYYYYYYYYYYY",
"lastVerify": {
"valid": true,
"edition": "ULTIMATE",
"expiryTime": 1735689600000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"cachedAt": 1735689600000
}
}
Principes :
- Ne stocker que
licenseCode+activationToken+ le dernier résultat de verify - Ne pas stocker d’informations de licence complètes déchiffrables (la protection anti-rétro-ingénierie est inutile ; sert uniquement de cache)
- Le cache de 60s de
verifyCachedréside dans le processus SDK, expire après redémarrage et nécessite un nouvel appelverify
3.2 Comparaison des niveaux d’édition (edition)
Les développeurs définissent eux-mêmes les codes d’édition (p. ex. BASIC / PRO / ULTIMATE) et les configurent sur la page de publication de la plateforme. Tous les types de produits (client/serveur/promotion seule) peuvent personnaliser leurs éditions après activation des codes de licence. Le client vérifie par comparaison de niveaux :
EDITION_LEVEL = {"BASIC": 0, "PRO": 1, "ULTIMATE": 2, "TRIAL": 99}
def edition_sufficient(user_edition, required_edition):
return EDITION_LEVEL.get(user_edition, 0) >= EDITION_LEVEL.get(required_edition, 0)
Correspondance courante (référence) :
| Niveau de fonction | Code d’édition | Niveau | Fonctions typiques |
|---|---|---|---|
| Basique | BASIC |
0 | Retouche de base, conversion de formats |
| Pro | PRO |
1 | Traitement par lots, agrandissement HD |
| Ultime | ULTIMATE |
2 | Restauration IA, assistant de couverture |
Les noms et codes d’édition sont librement définis par le développeur sur la plateforme — BASIC/PRO/ULTIMATE n’est pas obligatoire. Les prix des éditions et les listes de fonctionnalités ne s’affichent sur la page d’achat que si « La plateforme encaisse les frais de licence » est coché.
3.3 Traitement des codes d’erreur (LicenseError)
Le SDK lève LicenseError avec la propriété error_code :
from ps_license_sdk import LicenseError
try:
result = client.verify_cached(...)
except LicenseError as e:
if e.error_code == "expired":
open_purchase_page()
elif e.error_code == "revoked":
show_message("La licence a été révoquée, veuillez contacter le support")
elif e.error_code == "machineLimit":
show_message("Limite de machines liées atteinte, veuillez délier l’ancien appareil dans l’espace personnel")
elif e.error_code == "NETWORK_ERROR":
show_message("Erreur réseau, veuillez vérifier la connexion et réessayer")
else:
show_message(f"Échec de la vérification : {e}")
| Code d’erreur | Signification | Traitement recommandé côté client |
|---|---|---|
codeNotFound |
Le code de licence n’existe pas | Vérifier la saisie |
revoked |
Révoqué | Inviter à contacter le support |
expired |
Expiré | Orienter vers l’achat/le renouvellement |
machineLimit |
Limite de machines liées atteinte | Orienter vers la déliaison dans l’espace personnel |
tooManyAttempts |
Limitation de débit déclenchée | Inviter à réessayer plus tard |
trialNotEnabled |
Le produit n’a pas activé l’essai | Vérifier la configuration plateforme |
trialAlreadyPurchased |
Produit déjà acheté | Signaler l’achat existant et rediriger vers la page d’achat |
trialAlreadyPurchased |
Produit déjà acheté | Signaler l’achat existant et rediriger vers la page d’achat |
trialAlreadyPurchased |
Produit déjà acheté | Signaler l’achat existant et rediriger vers la page d’achat |
NETWORK_ERROR |
Réseau/délai dépassé | Tolérance hors ligne ou invitation à réessayer |
3.4 Redirection vers la page d’achat (scénario A uniquement)
3.4.1 URL de la page d’achat
https://www.powersoftware.app/product/license/purchase?productUniqueCode={productUniqueCode}&machineCode={machineCode}
Méthode SDK :
url = client.purchase_url(mc)
Lorsqu’une machine de débogage accède à cette page, le badge « Mode débogage (environnement de test) » apparaît en haut ; le paiement passe par le canal de test (voir chapitre 4). La langue est détectée automatiquement par la page d’achat selon le navigateur de l’utilisateur (préfixe d’URL /
Accept-Language) — le SDK n’a pas à s’en occuper.
3.4.2 Sites : utiliser uniformément le site international .app, le développeur n’a pas à choisir le site d’achat
powersoftware.app (international) |
powersoftware.cn (Chine) |
|
|---|---|---|
| Moyens de paiement | Waffo (carte / Apple Pay / Google Pay, etc.) + PayPal + Alipay | Alipay uniquement |
| Pays/devise | Cloudflare détecte automatiquement par IP (CN→CNY, autres→USD) | Fixe country=CN, CNY |
| Langue | Automatique par préfixe d’URL / Accept-Language |
Fixe zh-CN |
| Positionnement | Seule entrée d’achat que le développeur doit utiliser | Site de relais pour les paiements Alipay du site international |
Le développeur n’a pas à choisir le site d’achat : purchaseUrl pointe uniformément vers le site international .app. Les utilisateurs à l’étranger effectuent directement leurs paiements Waffo / PayPal sur .app ; lorsque les utilisateurs chinois choisissent Alipay sur .app, la plateforme redirige automatiquement vers le site chinois .cn pour le paiement Alipay (l’état de connexion est synchronisé automatiquement, pas besoin de se reconnecter) et revient au parcours de licence après paiement réussi. Toute la chaîne est transparente pour l’utilisateur et le développeur.
# Correct : utiliser fixement le site international, ne pas changer de base selon la région/langue
url = client.purchase_url(mc)
# Déconseillé : détecter soi-même la région et passer une base .cn — la redirection Alipay
# est déjà gérée par la plateforme, et coder .cn en dur fait perdre les paiements Waffo / PayPal
4. Phase de débogage (double environnement, nouveau en v4)
La validation la plus fiable avant la mise en ligne : enregistrer l’ordinateur que vous utilisez au quotidien pour le développement comme « machine de débogage » et parcourir tout le processus avec la véritable chaîne de paiement.
4.1 Enregistrer le code machine
- Espace personnel → « Mes codes machine » → enregistrer le code machine de l’ordinateur de débogage
- Le code machine peut être généré avec
machine_code()du SDK (même machine, trois langages, même résultat)
- Le code machine peut être généré avec
- Noter ce code machine
4.2 Enregistrer la machine de débogage
- Developer Center → liste des produits → bouton « Machines de débogage » du produit cible
- Dans la boîte de dialogue, choisir parmi les codes machine enregistrés et ajouter au produit (note possible)
- Limite : 3 machines de débogage maximum par produit ; interrupteur (désactiver temporairement le routage) et suppression pris en charge
4.3 Ce qui se passe sur la machine de débogage
Sur une machine de débogage enregistrée et activée, toute la chaîne de ce produit bascule automatiquement vers l’environnement Waffo Test :
Machine de débogage (votre PC) Plateforme PowerSoftware.net (le serveur détermine l’environnement automatiquement)
│ │
│ claimTrial(machineCode)
├─────────────────→│ Cette machine est une machine de débogage de ce produit → chemin Test
│ │
│ ← licence d’essai (code préfixé T-, écrit dans la table de licences test)
│ │
│ purchaseUrl(machineCode)
├─────────────────→│ La page d’achat affiche le badge « Mode débogage (environnement de test) »
│ │ → paiement avec carte test Waffo (pas d’argent réel)
│ │ → commande dans la table de commandes test, la plateforme émet un code test (code T-)
│ ← la plateforme émet le code (code T-)
│ │
│ activate(code T-, machineCode)
├─────────────────→│ Le préfixe T- localise directement la table test
│ ← activationToken│
│ │
│ verifyCached(...)
├─────────────────→│ Vérification réussie
│ ← { valid, edition, expiryTime }
Points clés :
- Identification : un code de licence préfixé
T-est une licence test ; le badge « Mode débogage (environnement de test) » apparaît en haut de la page d’achat - Paiement : passe par le checkout Waffo Test avec des cartes de test (p. ex.
4576 ... 0110) ; aucun débit réel - Zéro modification de code : le client ne nécessite aucune modification — le même code se comporte de manière identique sur la machine de débogage et sur les machines des utilisateurs réels (seules les tables backend diffèrent)
4.4 Liste de débogage recommandée
- Premier lancement de la machine de débogage →
claimTrialréussi, code d’essai préfixéT-obtenu - Pendant l’essai,
verifyCachedretournevalid, les fonctions payantes sont autorisées -
purchaseUrlouvre la page d’achat, le badge « Mode débogage » apparaît - Paiement avec carte test terminé → code de licence test reçu (e-mail/page)
-
activateréussi →verifyCachedpasse - Blocage des éditions correct (un code inférieur est bloqué sur une fonction supérieure)
- Limite de liaison machine (
machineLimit) et parcours de déliaison fonctionnels - (scénario B uniquement)
generateForSoftwaresur la machine de débogage retourne un code préfixéT-, activation/vérification normales ; le même appel avec une machine non enregistrée retourne un code officiel - Sur un ordinateur non enregistré, répéter
claimTrialet confirmer que la chaîne de production est utilisée (vérification de contrôle)
4.5 Précautions de débogage
| Sujet | Description |
|---|---|
| Nettoyage des données test | Les licences/commandes test n’affectent pas la production, aucun nettoyage nécessaire ; pour réinitialiser, retirer l’appareil du panneau des machines de débogage puis le réajouter |
| Interrupteur de débogage | Pour ne pas passer temporairement par la chaîne test, désactiver l’interrupteur dans le panneau des machines de débogage — inutile de supprimer l’appareil |
| Produits en promotion seule | Les produits de type « promotion seule » ne sont pas synchronisés dans le catalogue de produits Waffo ; pas de chaîne d’achat de débogage |
| Aucun prix valide | Si le prix principal/secondaire et toutes les éditions de licence n’ont aucun prix normal, la synchronisation du produit test échoue (alerte DingTalk) — veuillez configurer au moins un prix d’édition |
5. Phase de mise en ligne
5.1 Soumettre la revue
- Une fois tous les points de la liste de débogage validés, cliquer sur « Enregistrer et soumettre la revue » dans le formulaire produit
- Le produit entre dans la file de revue (
PENDING_RELEASE)
Pour les produits enregistrés en brouillon pendant la phase de débogage, le contenu soumis correspond au dernier brouillon ; toute modification pendant la revue repasse automatiquement au statut brouillon (empêche les changements de contenu pendant la revue) — une nouvelle soumission est nécessaire.
5.2 Revue approuvée → synchronisation automatique en production
Après approbation par l’équipe d’exploitation de la plateforme :
- Le statut du produit passe à publié et listé
- La plateforme synchronise automatiquement le produit vers l’environnement de production Waffo (réécrit
waffo_product_id), crée/restaure les produits du checkout de production - La page de détail du produit et les résultats de recherche sont visibles par tous les utilisateurs
5.3 Chaîne des utilisateurs réels (production)
La chaîne des utilisateurs réels (machines non-débogage) est identique au débogage — elle est simplement entièrement située dans les tables de production :
Premier lancement → claimTrial obtenir l’essai (code de licence officiel, sans préfixe T-)
→ essai expiré → purchaseUrl vers la page d’achat (paiement réel Alipay / PayPal)
→ la plateforme émet automatiquement le code après paiement réussi + envoi par e-mail
→ activate activer → vérification verifyCached autorisation
Les utilisateurs du scénario B (encaissement autonome) ne passent pas par la page d’achat plateforme : après paiement via votre canal, votre serveur appelle
generateForSoftwarepour émettre un code de licence officiel ; la chaîne d’activation/vérification ultérieure est identique au scénario A.
5.4 Liste de vérification de mise en ligne
- Accéder à la page de détail du produit avec un ordinateur non enregistré comme machine de débogage et confirmer l’affichage normal
- La page d’achat n’affiche aucun badge « Mode débogage »
- Paiement réel de petit montant → émission du code → activation réussie
- La commande apparaît dans la liste des commandes du Developer Center (les commandes test n’y apparaissent pas)
6. Exploitation après la mise en ligne
| Action | Entrée | Description |
|---|---|---|
| Consulter les commandes | Developer Center → Mes commandes | Commandes de production uniquement ; les commandes test ne participent ni au partage de revenus ni à la réconciliation |
| Délier un utilisateur | Espace personnel de l’utilisateur / licence manuelle par le développeur | Quota de réattribution : après déliaison, aucune nouvelle déliaison possible pendant 30 jours |
| Itération de version | Modifier le produit → enregistrer le brouillon / soumettre la revue | La modification synchronise à nouveau asynchroniquement vers Waffo Test ; les nouvelles versions peuvent continuer à être validées sur la machine de débogage |
| Remboursement | Waffo Dashboard | L’acheteur ouvre un ticket, le marchand examine dans le Dashboard ; les remboursements de commandes test révoquent seulement la licence test |
| Retirer le débogage | Retirer l’appareil du panneau des machines de débogage | Une fois la version stable, il est recommandé de retirer la machine de débogage pour éviter l’utilisation accidentelle de la chaîne test |
7. Questions fréquentes (FAQ)
Q1 : Le débogage nécessite-t-il de modifier le code client ou la configuration ? Non. Le routage d’environnement est déterminé automatiquement par le serveur de la plateforme selon que le code machine figure ou non dans la liste des machines de débogage ; les appels SDK sont identiques.
Q2 : Le code de licence obtenu sur la machine de débogage peut-il servir à de vrais utilisateurs ?
Non, et ce n’est pas recommandé. Les codes T- ne sont valides que dans les tables test, et les données de débogage ne participent à aucune logique de production ; donner des codes test à de vrais utilisateurs les empêcherait d’obtenir un support après-vente via le parcours de vérification normal.
Q3 : Le débogage coûte-t-il de l’argent ? Non. Le canal de paiement test utilise des cartes de test ; aucun débit réel ; les commandes test ne participent pas au partage de revenus/règlement.
Q4 : Le débogage affecte-t-il la revue de mon produit ? Non. Les données de débogage sont totalement découplées de la revue ; le statut brouillon suffit pour déboguer, la soumission est à votre discrétion.
Q5 : Que faire si je veux déboguer sur plusieurs ordinateurs ? Jusqu’à 3 machines de débogage peuvent être enregistrées par produit ; il suffit d’ajouter/retirer dans le panneau des machines de débogage.
Q6 : Si le produit est de type « promotion seule » ou sans prix configuré, puis-je déboguer l’achat ? Non. Les produits en promotion seule ne sont pas synchronisés dans le catalogue Waffo ; sans prix valide, la synchronisation du produit test échoue. Pour ces produits, seuls l’essai et la chaîne de vérification peuvent être débogués.
Q7 : Que se passe-t-il si j’oublie de désactiver l’interrupteur de débogage avant la mise en ligne ? L’impact se limite à la machine que vous avez enregistrée — elle continue de passer par la chaîne test ; tous les utilisateurs réels ne sont pas affectés. Une fois la stabilité confirmée, il suffit de la retirer du panneau des machines de débogage.
8. Liste d’intégration (à vérifier point par point avant la mise en ligne)
Scénario A (chaîne complète de la plateforme)
- Publier le produit sur PowerSoftware.net, choisir le modèle de vente « Essayer avant d’acheter »
- Configurer les jours d’essai (recommandé 7~14 jours)
- Configurer les éditions de licence (code d’édition + nom + prix + liste de fonctionnalités)
- Confirmer que « La plateforme encaisse les frais de licence » est coché (obligatoire pour Essayer avant d’acheter)
- Noter le
productUniqueCode - Copier le code source du SDK dans le projet (voir 2.3.1)
- Implémenter
claimTrial→ obtenir l’essai au premier lancement - Implémenter
activate→ activation par saisie du code par l’utilisateur - Implémenter
verifyCached→ vérification au clic sur une fonction payante - Implémenter
purchaseUrl→ redirection vers la page d’achat sans licence (site international.appuniforme, pas de choix de site) - Implémenter la persistance locale des identifiants (
licenseCode+activationToken) - Implémenter la logique de comparaison des niveaux d’édition (voir 3.2)
- Implémenter le traitement des codes d’erreur
LicenseError(voir 3.3) - Enregistrer la machine de débogage et parcourir la liste de débogage à double environnement (voir 4.4)
- Soumettre la revue → revue approuvée → vérification de mise en ligne (voir 5.4)
Scénario B (commandes hors plateforme)
- Publier le produit sur PowerSoftware.net, activer
licenseEnabled - Configurer les éditions de licence (code d’édition + nom) ; si l’encaissement plateforme est souhaité, cocher « La plateforme encaisse les frais de licence » et renseigner les prix
- Obtenir
licenseApiSecretdans le backend développeur - Noter le
productUniqueCode - Mettre en place un serveur qui conserve le secret de licence
licenseApiSecretet implémente l’interface d’émission (le secret ne doit pas être distribué au client) - Côté client, copier le code source du SDK dans le projet
- Côté serveur, implémenter
generateForSoftware(émission) - Côté serveur, implémenter
upgradeForSoftware(mise à niveau/renouvellement) - Côté client, implémenter
activate/verifyCached - Implémenter la persistance locale des identifiants
- Implémenter la logique de comparaison des niveaux d’édition (voir 3.2)
- Implémenter le traitement des codes d’erreur
LicenseError(voir 3.3) - Enregistrer la machine de débogage et vérifier la chaîne des codes
T-(voir 4.4) - Soumettre la revue → revue approuvée → vérification de mise en ligne (voir 5.4)
Annexe : dépôt SDK (GitHub)
github.com/mizhanchengxi/powersoftware-license-sdk
├── node/ code source SDK (ESM, sans dépendances, un seul fichier)
├── python/ code source SDK (py3, sans dépendances, 3 fichiers)
├── java/ code source SDK (Java 8+, sans dépendances, 3 fichiers)
└── docs/ documents de spécification du SDK
Les trois paquets fournissent : machineCode() / sign() / LicenseClient (comprenant activate / verify / deactivate / claimTrial / generateForSoftware / upgradeForSoftware / verifyCached / purchaseUrl).
Ce document est la mise à jour v4 du Guide d’intégration de licence des logiciels clients (CLIENT_SOFTWARE_GUIDE) ; il couvre l’intégralité de son contenu et ajoute le débogage à double environnement ainsi que les capacités de brouillon/soumission de revue.