Offene Lizenz-API-Dokumentation

v1.0

Offene Lizenz-API-Dokumentation

Dieses Dokument richtet sich an Entwickler, die den Ablauf „Zahlung → Ausstellung → Aktivierung → Verifizierung“ in ihre eigene Software integrieren möchten (Client-Software / reine Vertriebsprodukte). Jede API wird mit Aufrufzeitpunkt, Anfrageparametern, Antwortfeldern und Fehlercodes beschrieben.

1. Grundkonzepte

Konzept Feld / Begriff Beschreibung
Software-API-Geheimnis licenseApiSecret Wird automatisch erzeugt, wenn das Produkt die „Lizenzaktivierung“ aktiviert. Im Produktbearbeitungsformular im Entwicklerzentrum einsehbar. Ihr Softwareserver berechnet damit die HMAC-Signatur, die Plattform verifiziert damit. Nur auf Ihrem Server speichern, niemals im Client einbetten.
Lizenzcode licenseCode Ein von der Plattform erzeugter eindeutiger Code. Benutzer aktivieren damit Ihre Software.
Maschinencode machineCode Eine vom Client erzeugte Gerätekennung (pro Computer eindeutig; stabilen Maschinen-Fingerabdruck hashen, mindestens 8 Zeichen).
Aktivierungstoken activationToken Wird von der Plattform bei Aktivierung / Ausstellung ausgestellt. Die Software speichert ihn und sendet ihn bei jeder Startprüfung zurück.
Bestell-ID clientOrderId Die Bestell-ID der In-Software-Zahlung (vom Client oder Server erzeugt). Die Plattform dedupliziert über „Produkt + Bestell-ID“, um doppelte Abbuchungen und doppelte Ausstellung zu verhindern.

2. Vorbereitung

  1. Aktivieren Sie beim Veröffentlichen des Produkts die „Lizenzaktivierung“ und speichern Sie das erzeugte Software-API-Geheimnis (licenseApiSecret);
  2. Konfigurieren Sie im Veröffentlichungsformular die Editionsliste (z. B. BASIC/PRO/ULTIMATE) und die Upgrade-Strategie (SAME_CODE = Upgrade mit gleichem Code / NEW_CODE = neuen Code ausstellen);
  3. Speichern Sie das Geheimnis auf Ihrem Softwareserver; der Client hält nur Lizenzcode und Aktivierungstoken.

3. API-Übersicht

Basispfad: https://www.powersoftware.app/frontApi (für lokale / Testumgebungen durch Ihre Bereitstellungsdomain ersetzen).

API Aufrufzeitpunkt Authentifizierung Signatur
POST /license/software/generate Direkt nach erfolgreicher In-Software-Zahlung Keine (Signaturprüfung) Erforderlich
POST /license/software/upgrade Direkt nach erfolgreicher Verlängerungs- / Editions-Upgrade-Zahlung Keine (Signaturprüfung) Erforderlich
POST /license/activate Erste Aktivierung durch den Benutzer / Gerätewechsel Keine Nicht erforderlich
POST /license/verify Bei jedem Start der Software Keine Nicht erforderlich
POST /license/deactivate Benutzer hebt Bindung des alten Geräts auf (Profilbereich) Anmeldung Nicht erforderlich

4. Signaturregeln (erforderlich für generate / upgrade)

Signaturtext: Fügen Sie die folgenden Felder in genau dieser Reihenfolge mit Zeilenumbrüchen (\n) zusammen (fehlende optionale Felder mit Leerwerten: edition leere Zeichenkette, expiryDays = 0):

productId \n machineCode \n edition \n expiryDays \n clientOrderId \n licenseCode \n timestamp

Signatur: HMAC-SHA256(Software-API-Geheimnis licenseApiSecret, Signaturtext), Base64URL-kodiert, in das Feld signature eintragen.

Replay-Schutz: timestamp ist ein Zeitstempel in Millisekunden. Die Plattform verlangt eine Abweichung von höchstens 5 Minuten zur Serverzeit, sonst wird signatureInvalid zurückgegeben.

Node.js-Beispiel:

const crypto = require("crypto");
const payload = [productId, machineCode, edition, expiryDays, clientOrderId, licenseCode, timestamp].join("\n");
const signature = crypto.createHmac("sha256", API_SECRET).update(payload).digest("base64url");

Python-Beispiel:

import hashlib, hmac, base64
payload = "\n".join([str(productId), machineCode, edition, str(expiryDays), clientOrderId, licenseCode, str(timestamp)])
signature = base64.urlsafe_b64encode(hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).digest()).decode().rstrip("=")

(Base64URL ist Standard-Base64, bei dem + durch -, / durch _ ersetzt und die =-Auffüllung am Ende entfernt wird.)

5. API-Details

5.1 Lizenzcode erzeugen (nach In-Software-Zahlung aufrufen)

Aufrufzeitpunkt: Direkt nach Abschluss einer In-Software-Zahlung ruft Ihr Server die API einmal auf und speichert Lizenzcode und Aktivierungstoken. Dieselbe Bestellung soll nur einmal gesendet werden; Wiederholungen sind idempotent und führen nicht zu einer zweiten Ausstellung.

POST /license/software/generate

Anfrageparameter (JSON-Body):

Parameter Typ Pflicht Quelle Beschreibung
productId number Ja Fest verdrahtet / Server-Konfiguration Produkt-ID, passend zum auf der Plattform veröffentlichten Produkt
machineCode string Ja Client erzeugt Maschinencode des aktuellen Geräts, mindestens 8 Zeichen
edition string Nein Bei Zahlung vom Client gewählt Editionskennung; muss in der Editionsliste des Produkts stehen; Standard ist die erste Edition
expiryDays number Nein Bei Zahlung vom Client gewählt Gültigkeitsdauer in Tagen, 0 = dauerhaft; Bereich 0-3650
clientOrderId string Ja Client / Server erzeugt Bestell-ID der In-Software-Zahlung, 1-64 Zeichen; Idempotenzschlüssel
timestamp number Ja Server erzeugt Zeitstempel in Millisekunden
signature string Ja Server berechnet HMAC-Signatur, mindestens 10 Zeichen

Antwortfelder von content:

Feld Typ Beschreibung
licenseId number ID des Lizenzdatensatzes
licenseCode string Der Lizenzcode (in Ihre Lizenzdaten schreiben)
productId number Produkt-ID
edition string Editionskennung
machineId number ID des gebundenen Maschinendatensatzes
activatedAt string Aktivierungszeit (ISO8601)
expiryTime string/null Ablaufzeit (ISO8601), null = dauerhaft
trialExpiryTime string/null Snapshot der Testablaufzeit (ISO8601), null = kein Ursprung aus einer Testphase
trialExpiryTime string/null Snapshot der Testablaufzeit (ISO8601), null = kein Ursprung aus einer Testphase
trialExpiryTime string/null Snapshot der Testablaufzeit (ISO8601), null = kein Ursprung aus einer Testphase
maxMachines number Maximale Anzahl bindbarer Maschinen
activationToken string Aktivierungstoken; für die Startprüfung speichern

Antwortbeispiel:

{
  "code": "SUCCESS",
  "requestId": "xxx",
  "success": true,
  "content": {
    "licenseId": 1001,
    "licenseCode": "AB12-CD34-EF56-GH78",
    "productId": 88,
    "edition": "PRO",
    "machineId": 2001,
    "activatedAt": "2026-08-05T10:00:00.000Z",
    "expiryTime": "2027-08-05T10:00:00.000Z",
    "trialExpiryTime": "2026-12-01T10:00:00.000Z",
    "trialExpiryTime": "2026-12-01T10:00:00.000Z",
    "trialExpiryTime": "2026-12-01T10:00:00.000Z",
    "maxMachines": 1,
    "activationToken": "eyJhbGciOiJIUzI1NiJ9..."
  }
}

Fehlercodes dieser API: productIdRequired, machineCodeInvalid, orderIdRequired, productNotFound, productNotEnabled, apiSecretMissing, signatureInvalid, orderAlreadyUsed.

5.2 Edition upgraden / verlängern (nach Zahlung aufrufen)

Aufrufzeitpunkt: Nach Abschluss einer Zahlung für Verlängerung oder Editions-Upgrade. Dieselbe Bestellung soll nur einmal gesendet werden.

POST /license/software/upgrade

Anfrageparameter (JSON-Body):

Parameter Typ Pflicht Quelle Beschreibung
productId number Ja Fest verdrahtet / Server-Konfiguration Produkt-ID
licenseCode string Ja In der Software gespeichert Aktueller Lizenzcode, mindestens 10 Zeichen
machineCode string Nein Client erzeugt Aktueller Maschinencode; bei Bindungsmigration (NEW_CODE) oder zusätzlicher Bindung angeben
edition string Ja Bei Zahlung vom Client gewählt Ziel-Editionskennung
expiryDays number Nein Bei Zahlung vom Client gewählt Zusätzliche Gültigkeitsdauer in Tagen, 0 = dauerhaft; Bereich 0-3650
clientOrderId string Ja Client / Server erzeugt Bestell-ID dieses Kaufs; Idempotenzschlüssel
timestamp number Ja Server erzeugt Zeitstempel in Millisekunden
signature string Ja Server berechnet HMAC-Signatur

Verarbeitungsstrategie (durch Produktkonfiguration bestimmt):

  • SAME_CODE (Upgrade mit gleichem Code): Der Lizenzcode bleibt gleich, Maschinenbindungen bleiben gültig, die Gültigkeit wird verlängert (dauerhaft bleibt dauerhaft). Die Antwort enthält zusätzlich upgraded: true;
  • NEW_CODE (neuen Code ausstellen): Der alte Code wird gesperrt, ein neuer Code wird ausgestellt und die Maschinenbindungen werden migriert. Die Antwort enthält zusätzlich oldLicenseId, und licenseCode ist der neue Code.

Antwortfelder von content: wie in 5.1, zusätzlich upgraded: true; bei NEW_CODE zusätzlich oldLicenseId (ID des alten Lizenzdatensatzes; der alte Code ist bereits gesperrt).

Fehlercodes dieser API: productIdRequired, licenseCodeRequired, orderIdRequired, productNotFound, productNotEnabled, apiSecretMissing, signatureInvalid, codeNotFound, revoked, orderAlreadyUsed, editionRequired.

5.3 Lizenz aktivieren (erste Aktivierung / neues Gerät)

Aufrufzeitpunkt: Nachdem der Benutzer einen Lizenzcode erhalten hat (Selbstausstellung, Verwaltungsausstellung usw.) und ihn auf der Aktivierungsseite der Client-Software eingibt. Beim Gerätewechsel auf dem neuen Gerät aufrufen.

POST /license/activate

Anfrageparameter (JSON-Body):

Parameter Typ Pflicht Quelle Beschreibung
licenseCode string Ja Benutzereingabe Lizenzcode, mindestens 10 Zeichen
machineCode string Ja Client erzeugt Maschinencode des aktuellen Geräts, mindestens 8 Zeichen

Antwortfelder von content: wie in 5.1 (licenseId, licenseCode, productId, edition, machineId, activatedAt, expiryTime, maxMachines, activationToken).

Hinweise:

  • Ein Lizenzcode kann an mehrere Maschinen gebunden werden, begrenzt durch maxMachines (Standard aus Produktkonfiguration);
  • Erneutes Aktivieren derselben Maschine nutzt die bestehende Bindung und stellt ein neues Aktivierungstoken aus (idempotent);
  • Fehlgeschlagene Aktivierungen werden pro IP + Lizenzcode begrenzt; zu viele Fehlversuche ergeben tooManyAttempts.

Fehlercodes dieser API: codeNotFound, revoked, expired, machineLimit, tooManyAttempts.

5.4 Lizenz verifizieren (bei jedem Start)

Aufrufzeitpunkt: Bei jedem Start der Software (oder vor dem Entsperren von Funktionen). Die Software muss das von 5.1 / 5.2 / 5.3 zurückgegebene activationToken speichern.

POST /license/verify

Anfrageparameter (JSON-Body):

Parameter Typ Pflicht Quelle Beschreibung
licenseCode string Ja In der Software gespeichert Lizenzcode, mindestens 10 Zeichen
machineCode string Ja Client erzeugt Maschinencode des aktuellen Geräts, mindestens 8 Zeichen
activationToken string Ja Von der Plattform ausgestellt, von der Software gespeichert Aktivierungstoken, mindestens 20 Zeichen

Antwortfelder von content:

Feld Typ Beschreibung
valid boolean Immer true (Fehler werden als Fehlercodes zurückgegeben)
licenseId number ID des Lizenzdatensatzes
productId number Produkt-ID
edition string Aktuelle Editionskennung
expiryTime string/null Ablaufzeit (ISO8601), null = dauerhaft
trialExpiryTime string/null Snapshot der Testablaufzeit (ISO8601), null = kein Ursprung aus einer Testphase
trialExpiryTime string/null Snapshot der Testablaufzeit (ISO8601), null = kein Ursprung aus einer Testphase
trialExpiryTime string/null Snapshot der Testablaufzeit (ISO8601), null = kein Ursprung aus einer Testphase

Hinweise:

  • Verifizierungsergebnisse werden ca. 60 Sekunden zwischengespeichert; Schreiboperationen (Sperren, Bindung aufheben, Upgrade) invalidierten den Cache sofort, Verzögerungen sind also kein Thema;
  • Die Software sollte expiryTime prüfen und nach Ablauf das Entsperren von Funktionen beenden.
  • Stammt die Lizenz aus einer Testphase, kann trialExpiryTime als Kulanzfenster dienen: Die Funktionen bleiben bis trialExpiryTime freigeschaltet.
  • Stammt die Lizenz aus einer Testphase, kann trialExpiryTime als Kulanzfenster dienen: Die Funktionen bleiben bis trialExpiryTime freigeschaltet.
  • Stammt die Lizenz aus einer Testphase, kann trialExpiryTime als Kulanzfenster dienen: Die Funktionen bleiben bis trialExpiryTime freigeschaltet.

Fehlercodes dieser API: tokenInvalid, machineNotActivated, invalidOrRevoked, expired, tooManyAttempts.

5.5 Gerätebindung aufheben (vor Gerätewechsel, Anmeldung erforderlich)

Aufrufzeitpunkt: Der Benutzer hebt die Bindung des alten Geräts unter „Profilbereich → Meine Lizenzen“ auf und aktiviert anschließend auf dem neuen Gerät über 5.3.

POST /license/deactivate

Anfrageparameter (JSON-Body):

Parameter Typ Pflicht Quelle Beschreibung
licenseCode string Ja Lizenzliste des Benutzers Lizenzcode, mindestens 10 Zeichen
machineCode string Ja Lizenzliste des Benutzers Der aufzuhebende Maschinencode, mindestens 8 Zeichen

Antwortfelder von content: true.

Hinweise:

  • Nur der Eigentümer der Lizenz (Käufer oder Benutzer, der den gebundenen Maschinencode registriert hat) kann dies ausführen;
  • Aufhebe-Kontingent: Standardmäßig kann dieselbe Lizenz innerhalb von 30 Tagen nur einmal aufgehoben werden (im Verwaltungsbereich konfigurierbar); bei Überschreitung wird unbindQuotaExceeded zurückgegeben.

Fehlercodes dieser API: noPermission, machineNotBound, unbindQuotaExceeded.

6. Fehlercodes

Geschäftsfehler werden einheitlich zurückgegeben (tip enthält eine lesbare Meldung):

{
  "code": "BUSINESS_WARNING",
  "requestId": "xxx",
  "success": false,
  "errorMessage": "LICENSE_GENERATE_FAILED",
  "tip": "Signature verification failed"
}

Fehler bei der Parameterprüfung ergeben code: "PARAM_VALIDATE_FAILED" und die konkrete Feldmeldung in tip.

Fehlercode Bedeutung
productNotEnabled Das Produkt hat die Lizenzaktivierung nicht aktiviert
apiSecretMissing Für das Produkt ist kein Software-API-Geheimnis (licenseApiSecret) konfiguriert
signatureInvalid Signaturprüfung fehlgeschlagen (Geheimnis falsch, Reihenfolge des Signaturtexts falsch oder Zeitstempel außerhalb des Fensters)
machineCodeInvalid Maschinencode ungültig (kürzer als 8 Zeichen)
orderAlreadyUsed Diese Bestellung hat bereits einen Lizenzcode erzeugt (Idempotenzkonflikt: mit anderem Maschinencode wiederholt)
codeNotFound Lizenzcode nicht gefunden
revoked Lizenzcode wurde gesperrt oder ist unbrauchbar
expired Lizenzcode ist abgelaufen
invalidOrRevoked Lizenz ist bei der Verifizierung ungültig oder gesperrt
machineNotActivated Diese Maschine ist nicht aktiviert
tokenInvalid Aktivierungstoken ungültig
machineLimit Die Obergrenze gebundener Maschinen ist erreicht
machineNotBound Diese Maschine ist nicht gebunden
noPermission Keine Berechtigung für diese Lizenz
unbindQuotaExceeded Die Lizenz kann innerhalb von 30 Tagen nur einmal aufgehoben werden; später erneut versuchen
tooManyAttempts Zu viele Versuche; später erneut versuchen
productNotFound Produkt nicht gefunden
editionRequired Bitte die Zieledition wählen

7. Typische Abläufe

  1. In-Software-Zahlungsschleife: Zahlung erfolgreich → software/generate (liefert Lizenzcode + Aktivierungstoken) → Software speichert beides → bei jedem Start verify → Funktionen entsperren; Verlängerung / Upgrade → software/upgrade;
  2. Selbstausstellung / Verwaltungsausstellung: Ein Lizenzcode wird im Entwicklerzentrum oder in der Verwaltung erzeugt → der Benutzer erhält den Code → im Client activate, um das Gerät zu binden und das Token zu erhalten → beim Start verify;
  3. Gerätewechsel: Altes Gerät über deactivate im Profilbereich entbinden → auf dem neuen Gerät activateverify;
  4. Unterschied der Upgrade-Strategie: SAME_CODE behält den gleichen Code; NEW_CODE stellt einen neuen Code aus (alter Code gesperrt, Maschinenbindungen werden automatisch migriert).

8. Hinweise

  • Geheimnis nur serverseitig: Die Signatur darf nur auf Ihrem Softwareserver erstellt werden; gelangt das Geheimnis in den Client, ist das Lizenzsystem wirkungslos;
  • Stabilität des Maschinencodes: Verwenden Sie einen stabilen Maschinen-Fingerabdruck und hashen Sie ihn; ändert sich der Maschinencode nach einer Neuinstallation, erst entbinden, dann erneut aktivieren;
  • Idempotenz: Machen Sie clientOrderId global eindeutig (z. B. Zeitstempel + Zufallswert); Wiederholungen führen nicht zu doppelter Ausstellung;
  • Cache: verify-Ergebnisse werden ca. 60 Sekunden gecacht und durch Schreiboperationen sofort invalidiert;
  • Ratenbegrenzung: Fehlgeschlagene Aktivierungen / Verifizierungen werden begrenzt; der Client sollte Fehlermeldungen und Wiederholungsabstände angemessen umsetzen;
  • Vertrauen Sie der Plattformantwort: Gültigkeit, Edition und Maschinenobergrenzen werden von der Plattform bestimmt; lockern Sie diese auf Softwareseite nicht selbst.

6. Testversion anfordern & Kaufseite

Bei "Try first"-Produkten ruft der Client nach dem kostenlosen Download POST /license/trial/claim auf (productUniqueCode / machineCode, idempotent pro Produkt+Maschine). Nach der Testphase sind kostenpflichtige Funktionen durch Kauf einer Lizenzversion freizuschalten. Kaufseite: https://www.powersoftware.app/product/license/purchase?productUniqueCode={productUniqueCode}&machineCode={machineCode}. Nach der Zahlung wird eine Lizenz ausgestellt und per E-Mail gesendet. SDK: ps-help/v3/doc/授权SDK规范_v3.md

7. Offizielle SDKs (Node / Python / Java)

Offizielle SDKs in drei Sprachen sowie Spezifikation (DE/EN):

https://github.com/mizhanchengxi/powersoftware-license-sdk

8. Upgrade-Richtlinie (licenseUpgradeMode)

Die Erfolgsantwort (content) von POST /license/activate, POST /license/verify und POST /license/trial/claim enthält zusätzlich die Upgrade-Richtlinie des Produkts:

Feld Typ Beschreibung
licenseUpgradeMode string SAME_CODE = Lizenzschlüssel bleibt bei Upgrade/Verlängerung unverändert; NEW_CODE = bei Upgrade/Verlängerung wird der alte Schlüssel widerrufen und ein neuer ausgestellt

Verwendung im Client:

  • Damit entscheiden Sie, ob ein Eingabefeld „Lizenzschlüssel binden" angezeigt wird: Bei SAME_CODE ändert sich der Schlüssel nie, eine erneute Eingabe ist nicht nötig; bei NEW_CODE wird beim Upgrade/Verlängerung ein neuer Schlüssel ausgestellt — der lokal gespeicherte Schlüssel muss durch den zurückgegebenen licenseCode ersetzt werden;
  • verify liefert bei jedem Start die aktuelle Konfiguration, sodass der Client stets synchron bleibt.

Hinweise:

  • Produktweite Konfiguration (vom Entwickler im Veröffentlichungsformular festgelegt); ohne Konfiguration gilt SAME_CODE;
  • verify-Ergebnisse werden ca. 60 s gecacht — eine Änderung der Konfiguration wirkt spätestens nach 60 s;
  • software/upgrade liefert je nach Richtlinie bereits den tatsächlichen (alten oder neuen) Schlüssel zurück; dieses Feld wird dort nicht benötigt.

9. Testablauf-Snapshot (trialExpiryTime)

Die Erfolgsantwort (content) von POST /license/activate, POST /license/verify und POST /license/trial/claim enthält zusätzlich den Testablauf-Snapshot:

Feld Typ Beschreibung
trialExpiryTime string | null Ablaufzeit der ursprünglichen Testlizenz (ISO 8601); null = kein Upgrade aus einer Testlizenz (reiner Erstkkauf, vom Entwickler ausgestellter Code oder nicht konvertierte Testlizenz)

Entstehung:

  • Wird beim Anfordern der Testlizenz geschrieben, gleicher Wert wie deren expiryTime;
  • Beim Kauf nach einer Testlizenz (Upgrade mit gleichem Code oder Neuissue) liest die Plattform zuerst die ursprüngliche Ablaufzeit des Testcodes und friert sie in diesem Feld ein; nach dem Kauf wird expiryTime zur Gültigkeit der gekauften Edition, dieses Feld bleibt unverändert;
  • Auch der Kauf nach abgelaufener Testlizenz friert den Wert ein (Vergangenheitszeitpunkt), der Client kann „keine Gnadenfrist" erkennen;
  • Spätere kostenpflichtige Upgrades/Verlängerungen (gleicher oder neuer Code) erhalten dieses Feld.

Verwendung im Client (Empfehlung): Testfirst-Produkte schalten während der Testphase alle Funktionen frei; nach dem Kauf einer niedrigeren Edition werden höherstufige Funktionen sofort durch die Editions-Prüfung gesperrt. Der Client kann trialExpiryTime lesen und seine eigene Übergangsstrategie bestimmen, z. B. die höherstufige Funktion weiter freigeben, solange jetzt < trialExpiryTime, und sie danach sperren und zum Aufpreis-Upgrade führen. Ob und wie genutzt wird, entscheidet der Client; die Plattform erzwingt nichts.

Hinweis: Beim Anfordern einer Testlizenz, wenn die Maschine bereits eine Nicht-Testlizenz für das Produkt besitzt (Test-zu-Kauf-Umwandlung, Erstkkauf, vom Entwickler ausgestellter Code usw., d. h. bereits gekauft), gibt die API den Fehlercode trialAlreadyPurchased zurück und stellt keine weitere Testlizenz aus; widerrufene (erstattete) Lizenzen gelten nicht als gekauft.