Lizenzcode: Leitfaden für Entwicklung, Debugging und Release
v1.0.0
Client-Software Entwicklung → Debugging → Release: Gesamtprozess-Leitfaden (v4)
Gilt für: Entwickler, die Client-Software auf PowerSoftware.net veröffentlichen und das Lizenzcode-System integrieren. Dieses Dokument deckt den gesamten Lebenszyklus von „Produkt erstellen" bis „Kauf durch echte Nutzer" ab. Der Schwerpunkt liegt auf der in v4 neuen Dual-Environment-Debugging-Fähigkeit: Vor dem Release den vollständigen Ablauf mit einer echten Zahlungspipeline (Waffo Test Environment) auf dem eigenen Rechner als Debug-Maschine durchlaufen.
1. Gesamtprozess-Überblick
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ① Entwicklung│ → │ ② Debugging │ → │ ③ Release │ → │ ④ Betrieb │
│ │ │ │ │ │ │ │
│ Entwurf │ │ Debug- │ │ Review │ │ Bestellungen │
│ SDK einbinden│ │ Maschine │ │ einreichen │ │ lösen/erstatten│
│ Entwurf │ │ echte Pipeline│ │ genehmigt │ │ Versionen │
│ speichern │ │ (Test-Env) │ │ Prod-Sync │ │ iterieren │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
| Phase | Produktstatus | Wo liegen Lizenzen/Bestellungen | Echte Einnahmen? |
|---|---|---|---|
| ① Entwicklung | Entwurf (DRAFT) | — | Nein |
| ② Debugging | Entwurf / im Review | Test-Tabellen (Lizenzcodes mit T- Präfix) |
Nein (Test-Zahlungskanal) |
| ③ Release | Veröffentlicht | Produktions-Tabellen | Ja |
Kernregel: Debugging und Produktion sind vollständig isoliert. Alles, was auf Debug-Maschinen passiert (Testversionen, Bestellungen, Zahlungen, Code-Ausstellung, Aktivierung, Erstattungen), betrifft nur die Test-Tabellen — es fließt nicht in die Umsatzbeteiligung oder Abrechnung ein und beeinflusst keine echten Nutzer; Zugriffe von Nicht-Debug-Maschinen laufen immer über die Produktions-Pipeline.
2. Entwicklungsphase
2.1 Produkt erstellen
- Im PowerSoftware.net Developer Center anmelden → Produkt veröffentlichen, Produkttyp „Client-Software" wählen
- Als Verkaufsmodell Try-Before-You-Buy wählen und Testtage eintragen (empfohlen 7~14 Tage)
- Lizenz-Editionen konfigurieren: standardmäßig drei Stufen
BASIC/PRO/ULTIMATE; Code, Name, Preis und Funktionsliste sind anpassbar - „Plattform zieht Lizenzgebühren ein" aktivieren (bei Try-Before-You-Buy Pflicht)
- Softwarepaket und Vorstellungsmaterial hochladen
2.2 Entwurf speichern (neue Fähigkeit)
Am unteren Rand des Produktformulars gibt es zwei Schaltflächen:
| Schaltfläche | Verhalten |
|---|---|
| Entwurf speichern | Produkt wird als DRAFT gespeichert, kommt nicht in die Review-Warteschlange und kann jederzeit weiter bearbeitet werden |
| Speichern & Review einreichen | Produkt gelangt in die Review-Warteschlange (PENDING_RELEASE) |
Nach dem Speichern als Entwurf / Einreichen zum Review synchronisiert die Plattform das Produkt asynchron in die Waffo Test Environment (Fehler lösen nur Alarme aus und blockieren das Speichern nicht). Dies ist die Voraussetzung für Bestellungen in der Debug-Phase. Empfehlung: Während der Entwicklung genügt das Speichern eines Entwurfs, um mit dem Debugging zu beginnen — kein Review nötig.
Nach dem Speichern den productUniqueCode notieren (auf der Veröffentlichungsseite sichtbar, kein Geheimnis).
2.3 Lizenz-SDK integrieren (zwei Integrationsszenarien)
PowerSoftware.net bietet zwei Lizenz-Integrationswege für Client-Software. Wählen Sie je nach Situation:
| Szenario A: Vollständige Plattform-Pipeline (Try-Before-You-Buy) | Szenario B: Bestellungen außerhalb der Plattform | |
|---|---|---|
| Geeignete Produkte | Client-Software + Verkaufsmodell Try-Before-You-Buy | Nur-Promotion-Software (Selbstinkasso); oder Server-/Client-Software mit Pay-First (PAY_FIRST) oder selbst abgerechneten VIP-Funktionen |
| Wer regelt die Zahlung | PowerSoftware.net Plattform (Waffo, Alipay, PayPal); Debugging nutzt die Waffo Test Environment als Zahlungskanal | Entwickler selbst (In-App-Zahlung oder andere Kanäle) |
| Wer stellt Codes aus | Plattform stellt nach erfolgreicher Zahlung automatisch aus | Software ruft die Plattform-API zur Ausstellung auf (HMAC-signiert) |
Lizenz-Geheimnis licenseApiSecret nötig? |
❌ Nein | ✅ Ja (nur serverseitig, niemals im Client) |
| Server nötig? | ❌ Nein, rein clientseitig ausreichend | ✅ Ja (verwahrt licenseApiSecret, leitet Ausstellungsanfragen weiter) |
| Test-Lizenz | ✅ Unterstützt (claimTrial) |
❌ Keine Testversion (Test nur bei Try-Before-You-Buy) |
| Kaufseite | Von der Plattform bereitgestellt, SDK-Weiterleitung in einer Zeile | Keine Plattform-Kaufseite, Entwickler regelt es selbst |
Zur Edition-Konfiguration: Alle Produkttypen (Client/Server/Nur-Promotion) können Lizenzcodes aktivieren und Editionen anpassen (BASIC/PRO/ULTIMATE usw.). Editionspreise und Funktionslisten werden nur auf der Kaufseite angezeigt, wenn der Entwickler „Plattform zieht Lizenzgebühren ein" (
licensePlatformPayment) aktiviert; andernfalls regelt der Entwickler die Abrechnung selbst und die Plattform bietet nur Code-Ausstellung und -Verifizierung.
Wie wählen:
- Indie-Entwickler / kleines Team ohne eigenen Server → Szenario A (Kapitel 4 und 5 dieses Dokuments nutzen Szenario A als Hauptlinie)
- Bereits Zahlungskanäle vorhanden (z. B. WeChat-/Alipay-Merchant), nur Code-Ausstellung und -Verifizierung der Plattform gewünscht → Szenario B
2.3.1 SDK-Installation
Alle drei Sprachen (Node.js / Python / Java) sind ohne Abhängigkeiten — Quellcode direkt kopieren in Ihr Projekt, kein Paketmanager nötig. Der Maschinen-Code-Algorithmus ist sprachübergreifend konsistent (gleiche Maschine erzeugt gleichen machineCode). SDK-Repository: github.com/mizhanchengxi/powersoftware-license-sdk
2.3.2 Szenario A: Vollständige Plattform-Pipeline (Try-Before-You-Buy)
Voraussetzungen: Verkaufsmodell des Produkts ist Try-Before-You-Buy, Testtage und Lizenz-Editionen sind konfiguriert, „Plattform zieht Lizenzgebühren ein" ist aktiviert. Das Lizenz-Geheimnis licenseApiSecret wird NICHT benötigt:
# Python
from ps_license_sdk import LicenseClient, machine_code
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="") # api_secret leer lassen
mc = machine_code()
// Node.js
import { LicenseClient, machineCode } from './index.js';
const client = new LicenseClient({ productUniqueCode: 'PRO-2026-001', apiSecret: "" }); // Szenario A: Geheimnis leer lassen
const mc = machineCode();
// Java
import com.powersoftware.sdk.LicenseClient;
LicenseClient client = new LicenseClient("PRO-2026-001", ""); // Szenario A: Geheimnis leer lassen
String mc = LicenseClient.machineCode();
Vollständiger Integrationsablauf:
Erster Start
│
├─ claimTrial(machineCode) ────────────→ Testlizenz beziehen
│ ↓ Rückgabe { licenseCode, activationToken, licenseUpgradeMode }
│ ↓ lokal persistent speichern
│
├─ Innerhalb der Testphase: alle Funktionen verfügbar
│ │
│ └─ Klick auf Bezahl-Funktion → verifyCached() 60s-Cache-Prüfung → Freigabe
│
└─ Testphase abgelaufen / nicht aktiviert
│
├─ verifyCached() gibt invalid/expired zurück
├─ Dialog: „Lizenz zum Aktivieren kaufen erforderlich"
└─ purchaseUrl(machineCode) → Weiterleitung zur Plattform-Kaufseite
│
↓ Nutzer zahlt auf der Plattform → Plattform stellt Code aus + E-Mail-Zustellung
│
Nutzer kehrt zur Software zurück und gibt den Lizenzcode ein
│
├─ activate(licenseCode, machineCode)
│ ↓ Rückgabe { activationToken, licenseUpgradeMode }, lokal persistent speichern
│
└─ Weitere Nutzung → verifyCached() Prüfung → Freigabe
Zu implementieren: claimTrial (Testlizenz beim ersten Start beziehen) → verifyCached (Prüfung bei Bezahl-Funktionen) → purchaseUrl (ohne Lizenz zur Kaufseite weiterleiten) → activate (Aktivierung, wenn der Nutzer den Lizenzcode eingibt) → lokale Persistenz von licenseCode + activationToken → LicenseError-Fehlercode-Behandlung.
Kern-Code (Python):
import json
from pathlib import Path
from ps_license_sdk import LicenseClient, machine_code
# ---------- Initialisierung ----------
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))
# ---------- Erster Start: Testlizenz beziehen ----------
def claim_trial():
mc = machine_code()
try:
result = client.claim_trial(mc)
save_cred({
"licenseCode": result["licenseCode"],
"activationToken": result["activationToken"],
})
print(f"Testlizenz aktiviert, Lizenzcode: {result['licenseCode']}")
except Exception as e:
print(f"Bezug der Testlizenz fehlgeschlagen: {e}")
# ---------- Lizenz prüfen (bei Klick auf Bezahl-Funktion) ----------
def check_license(required_edition="PRO"):
cred = load_cred()
if not cred.get("licenseCode"):
return {"valid": False, "reason": "Nicht aktiviert"}
mc = machine_code()
try:
result = client.verify_cached(
cred["licenseCode"], mc, cred["activationToken"]
)
if not result.get("valid"):
return {"valid": False, "reason": "Lizenz ungültig oder abgelaufen"}
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"Edition {required_edition} oder höher erforderlich"}
return {"valid": True, "edition": user_edition,
"expiryTime": result.get("expiryTime"),
"trialExpiryTime": result.get("trialExpiryTime")}
except Exception as e:
return {"valid": False, "reason": str(e)}
# ---------- Lizenzcode aktivieren (nach Kauf durch Nutzer) ----------
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"Aktivierung fehlgeschlagen: {e}")
return False
# ---------- Zur Kaufseite weiterleiten ----------
def open_purchase_page():
mc = machine_code()
url = client.purchase_url(mc)
import webbrowser
webbrowser.open(url)
Beispiel für Funktions-Sperre:
# Editions-Anforderungen je Funktion definieren
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"Diese Funktion ist nicht verfügbar: {result['reason']}")
open_purchase_page()
2.3.3 Szenario B: Bestellungen außerhalb der Plattform (Selbstinkasso)
Geeignete Produkte: Nur-Promotion-Software (Selbstinkasso) oder Server-/Client-Software mit Pay-First-Verkaufsmodell (PAY_FIRST) bzw. selbst abgerechneten VIP-Funktionen.
Voraussetzungen: Produkt hat licenseEnabled aktiviert; im Developer-Backend wird licenseApiSecret bezogen (nur serverseitig speichern, niemals an den Client ausliefern). Architektur:
Client Ihr Server PowerSoftware.net Plattform
│ │ │
│ Nutzer zahlt (Ihre │ │
│ Zahlung) │ │
├──────────────────────→│ │
│ │ generateForSoftware( │
│ │ machineCode, edition, │
│ │ clientOrderId) │
│ │ (HMAC-Signatur + timestamp) │
│ ├───────────────────────────────→│
│ │ ← Rückgabe licenseCode │
│ ← Rückgabe licenseCode│ │
│ │ │
│ activate(licenseCode, machineCode) │
├───────────────────────────────────────────────────────→│
│ ← Rückgabe activationToken │
│ │ │
│ verifyCached(...) │ │
├───────────────────────────────────────────────────────→│
│ ← { valid, edition, expiryTime } │
Server (verwahrt das Lizenz-Geheimnis licenseApiSecret, stellt Codes aus):
from ps_license_sdk import LicenseClient, machine_code
server_client = LicenseClient(
product_unique_code="PRO-2026-001",
api_secret="IHR_AUSSTELLUNGS_SCHLÜSSEL_FROM_DEVELOPER_CONSOLE",
)
def issue_license(user_machine_code, edition="PRO", order_id=""):
"""Nach Zahlung des Nutzers ruft der Server die Plattform zur Code-Ausstellung auf"""
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 (benötigt kein licenseApiSecret, Aktivierung und Prüfung):
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"]})
Zu implementieren: serverseitig generateForSoftware (Code-Ausstellung) + upgradeForSoftware (Upgrade/Verlängerung); clientseitig activate / verifyCached + lokale Persistenz der Zugangsdaten + LicenseError-Fehlercode-Behandlung.
2.3.4 SDK-Methoden-Referenz
| Methode | Szenario A | Szenario B | Signatur | Beschreibung |
|---|---|---|---|---|
machine_code() |
✅ | ✅ | — | Maschinen-Code erzeugen (sprachübergreifend konsistent) |
claim_trial(mc) |
✅ | — | — | Testlizenz beziehen (nur Try-Before-You-Buy-Produkte) |
activate(code, mc) |
✅ | ✅ | — | Lizenzcode aktivieren, an Maschine binden |
verify(code, mc, token) |
✅ | ✅ | — | Lizenzstatus prüfen |
verify_cached(code, mc, token) |
✅ | ✅ | — | Prüfung mit lokalem Cache (60s) |
deactivate(code, mc) |
✅ | ✅ | — | Maschinen-Bindung lösen (Login erforderlich, Browser-Szenario) |
purchase_url(mc) |
✅ | — | — | URL der Plattform-Kaufseite erzeugen |
generate_for_software(mc, edition, ...) |
— | ✅ | HMAC | Code-Ausstellung in der Software (nur Server) |
upgrade_for_software(code, edition, ...) |
— | ✅ | HMAC | Upgrade/Verlängerung in der Software (nur Server) |
Hinweis zu den Rückgabefeldern: Die Erfolgsantworten von
activate/verify/claimTrialenthalten alle zusätzlichlicenseUpgradeMode(Upgrade-Richtlinie des Produkts:SAME_CODE= Lizenzschlüssel bleibt unverändert;NEW_CODE= Schlüssel wird neu gebunden). Der Client entscheidet daran, ob ein Eingabefeld „Lizenzschlüssel binden“ angezeigt wird: BeiSAME_CODEändert sich der Schlüssel nie, eine erneute Eingabe ist nicht nötig; beiNEW_CODEwird beim Upgrade/Verlängerung ein neuer Schlüssel ausgestellt — der lokal gespeichertelicenseCodemuss durch den zurückgegebenen ersetzt werden. Ohne Konfiguration giltSAME_CODE;verify-Ergebnisse werden ca. 60 s gecacht, eine Änderung wirkt spätestens nach 60 s. Die Antworten enthalten zusätzlichtrialExpiryTime(Snapshot des Testablaufs, ISO-8601-Zeichenkette;null, wenn die Lizenz nicht aus einer Testphase hervorging). Clients können dies als Kulanzfenster nutzen: Hat der Nutzer die Vollversion getestet und kauft danach eine niedrigere Edition, bleiben die Funktionen der höheren Edition bistrialExpiryTimefreigeschaltet. Die Antworten enthalten zusätzlichtrialExpiryTime(Snapshot des Testablaufs, ISO-8601-Zeichenkette;null, wenn die Lizenz nicht aus einer Testphase hervorging). Clients können dies als Kulanzfenster nutzen: Hat der Nutzer die Vollversion getestet und kauft danach eine niedrigere Edition, bleiben die Funktionen der höheren Edition bistrialExpiryTimefreigeschaltet. Die Antworten enthalten zusätzlichtrialExpiryTime(Snapshot des Testablaufs, ISO-8601-Zeichenkette;null, wenn die Lizenz nicht aus einer Testphase hervorging). Clients können dies als Kulanzfenster nutzen: Hat der Nutzer die Vollversion getestet und kauft danach eine niedrigere Edition, bleiben die Funktionen der höheren Edition bistrialExpiryTimefreigeschaltet. Die Antworten enthalten zusätzlichtrialExpiryTime(Snapshot des Testablaufs, ISO-8601-Zeichenkette;null, wenn die Lizenz nicht aus einer Testphase hervorging). Clients können dies als Kulanzfenster nutzen: Hat der Nutzer die Vollversion getestet und kauft danach eine niedrigere Edition, bleiben die Funktionen der höheren Edition bistrialExpiryTimefreigeschaltet.
Das Dual-Environment-Debugging ist für beide Szenarien vollständig transparent:
- Szenario A: Auf Debug-Maschinen laufen
claimTrial/ Zahlungen über die Plattform-Kaufseite automatisch über die Test-Environment (siehe Kapitel 4) - Szenario B: Ruft eine Debug-Maschine
generateForSoftwareauf, routet die Plattform ebenfalls anhand des Maschinen-Codes in die Test-Environment und gibt Lizenzcodes mitT--Präfix zurück; der Server-Code benötigt keinerlei Änderungen - Die SDK-Aufrufe sind während des Debuggings und nach dem Release völlig identisch — keine Umgebungsparameter oder Code-Verzweigungen nötig; das Umgebungs-Routing erfolgt automatisch durch den Plattform-Server
3. Details der Lizenz-Integration (für beide Szenarien gültig)
3.1 Spezifikation für lokale Zugangsdaten-Speicherung
Das SDK übernimmt selbst keine Persistenz — dies implementiert der Entwickler selbst. Gespeicherte Inhalte:
{
"licenseCode": "XXXXXXXXXXXX",
"activationToken": "YYYYYYYYYYYY",
"lastVerify": {
"valid": true,
"edition": "ULTIMATE",
"expiryTime": 1735689600000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"cachedAt": 1735689600000
}
}
Prinzipien:
- Nur
licenseCode+activationToken+ letztes verify-Ergebnis speichern - Keine vollständigen, entschlüsselbaren Lizenzinformationen speichern (Reverse-Engineering-Schutz ist sinnlos; dient nur als Cache)
- Der 60s-Cache von
verifyCachedliegt im SDK-Prozess, verfällt nach Neustart und erfordert einen erneutenverify-Aufruf
3.2 Ebenen-Vergleich der Editionen (edition)
Entwickler definieren Edition-Codes selbst (z. B. BASIC / PRO / ULTIMATE) und konfigurieren sie auf der Veröffentlichungsseite der Plattform. Alle Produkttypen (Client/Server/Nur-Promotion) können nach Aktivierung von Lizenzcodes ihre Editionen frei anpassen. Der Client prüft per Ebenen-Vergleich:
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)
Übliche Zuordnung (Referenz):
| Funktionsstufe | Edition-Code | Ebene | Typische Funktionen |
|---|---|---|---|
| Basis | BASIC |
0 | Grundlegende Bildbearbeitung, Formatkonvertierung |
| Pro | PRO |
1 | Stapelverarbeitung, HD-Vergrößerung |
| Ultimate | ULTIMATE |
2 | KI-Restauration, Cover-Assistent |
Editions-Namen und -Codes werden vom Entwickler auf der Plattform frei definiert — BASIC/PRO/ULTIMATE sind keine Pflicht. Editionspreise und Funktionslisten werden nur auf der Kaufseite angezeigt, wenn „Plattform zieht Lizenzgebühren ein" aktiviert ist.
3.3 Fehlercode-Behandlung (LicenseError)
Das SDK wirft LicenseError mit der Eigenschaft 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("Die Lizenz wurde widerrufen, bitte kontaktieren Sie den Support")
elif e.error_code == "machineLimit":
show_message("Maschinen-Bindungslimit erreicht, bitte altes Gerät im Nutzercenter entbinden")
elif e.error_code == "NETWORK_ERROR":
show_message("Netzwerkfehler, bitte prüfen Sie die Verbindung und versuchen Sie es erneut")
else:
show_message(f"Prüfung fehlgeschlagen: {e}")
| Fehlercode | Bedeutung | Empfohlene Client-Behandlung |
|---|---|---|
codeNotFound |
Lizenzcode existiert nicht | Eingabe prüfen |
revoked |
Widerrufen | Hinweis, den Support zu kontaktieren |
expired |
Abgelaufen | Zum Kauf/zur Verlängerung leiten |
machineLimit |
Maschinen-Bindungslimit erreicht | Zur Entbindung im Nutzercenter leiten |
tooManyAttempts |
Ratenbegrenzung ausgelöst | Hinweis, später erneut zu versuchen |
trialNotEnabled |
Produkt hat Testphase nicht aktiviert | Plattform-Konfiguration prüfen |
trialAlreadyPurchased |
Produkt bereits gekauft | Hinweis „bereits gekauft“ anzeigen und zur Kaufseite führen |
trialAlreadyPurchased |
Produkt bereits gekauft | Hinweis „bereits gekauft“ anzeigen und zur Kaufseite führen |
trialAlreadyPurchased |
Produkt bereits gekauft | Hinweis „bereits gekauft“ anzeigen und zur Kaufseite führen |
trialAlreadyPurchased |
Produkt bereits gekauft | Hinweis „bereits gekauft“ anzeigen und zur Kaufseite führen |
NETWORK_ERROR |
Netzwerk/Timeout | Offline-Kulanz oder Wiederholungs-Hinweis |
3.4 Weiterleitung zur Kaufseite (nur Szenario A)
3.4.1 Kaufseiten-URL
https://www.powersoftware.app/product/license/purchase?productUniqueCode={productUniqueCode}&machineCode={machineCode}
SDK-Methode:
url = client.purchase_url(mc)
Wenn eine Debug-Maschine diese Seite aufruft, erscheint oben das Abzeichen „Debug-Modus (Testumgebung)"; die Zahlung läuft über den Testkanal (siehe Kapitel 4). Die Sprache wird von der Kaufseite anhand des Nutzer-Browsers automatisch erkannt (URL-Präfix /
Accept-Language) — das SDK muss sich nicht darum kümmern.
3.4.2 Seiten: einheitlich die internationale Seite .app, Entwickler müssen keine Kaufseite wählen
powersoftware.app (international) |
powersoftware.cn (China) |
|
|---|---|---|
| Zahlungsmethoden | Waffo (Karte / Apple Pay / Google Pay usw.) + PayPal + Alipay | Nur Alipay |
| Land/Währung | Cloudflare erkennt automatisch per IP (CN→CNY, übrige→USD) | Fest country=CN, CNY |
| Sprache | Automatisch per URL-Präfix / Accept-Language |
Fest zh-CN |
| Positionierung | Einziger Kauf-Einstieg, den Entwickler verwenden müssen | Auffangseite für Alipay-Zahlungen der internationalen Seite |
Entwickler müssen keine Kaufseite wählen: purchaseUrl zeigt einheitlich auf die internationale Seite .app. Überseeische Nutzer schließen Waffo-/PayPal-Zahlungen direkt auf .app ab; wählen chinesische Nutzer auf .app Alipay, leitet die Plattform automatisch auf die chinesische Seite .cn zur Alipay-Zahlung weiter (Login-Status wird automatisch synchronisiert, kein erneuter Login nötig) und kehrt nach erfolgreicher Zahlung in den Lizenzablauf zurück. Die gesamte Kette ist für Nutzer und Entwickler transparent.
# Richtig: fest die internationale Seite verwenden, base nicht nach Region/Sprache wechseln
url = client.purchase_url(mc)
# Nicht empfohlen: Region selbst prüfen und .cn base übergeben — die Alipay-Weiterleitung
# übernimmt bereits die Plattform, und hartkodiertes .cn verliert Waffo-/PayPal-Zahlungsmethoden
4. Debugging-Phase (Dual-Environment, neu in v4)
Die zuverlässigste Abnahme vor dem Release: Den eigenen, täglich für die Entwicklung genutzten Rechner als „Debug-Gerät" registrieren und den vollständigen Ablauf über die echte Zahlungspipeline durchlaufen.
4.1 Maschinen-Code registrieren
- Nutzercenter → „Meine Maschinen-Codes" → Maschinen-Code des Debug-Rechners registrieren
- Der Maschinen-Code kann mit
machine_code()des SDK erzeugt werden (gleiche Maschine, drei Sprachen, gleiches Ergebnis)
- Der Maschinen-Code kann mit
- Diesen Maschinen-Code notieren
4.2 Debug-Gerät registrieren
- Developer Center → Produktliste → Schaltfläche „Debug-Geräte" des Zielprodukts
- Im Dialog aus den registrierten Maschinen-Codes auswählen und zum Produkt hinzufügen (Notiz möglich)
- Limit: maximal 3 Debug-Geräte pro Produkt; Schalter (Routing temporär deaktivieren) und Entfernen werden unterstützt
4.3 Was auf der Debug-Maschine passiert
Auf einer registrierten und aktivierten Debug-Maschine wechselt die gesamte Pipeline dieses Produkts automatisch in die Waffo Test Environment:
Debug-Maschine (Ihr Rechner) PowerSoftware.net Plattform (Server ermittelt Umgebung automatisch)
│ │
│ claimTrial(machineCode)
├─────────────────→│ Diese Maschine ist Debug-Maschine dieses Produkts → Test-Pfad
│ │
│ ← Testlizenz (Lizenzcode mit T- Präfix, wird in Test-Lizenz-Tabelle geschrieben)
│ │
│ purchaseUrl(machineCode)
├─────────────────→│ Kaufseite zeigt Abzeichen „Debug-Modus (Testumgebung)"
│ │ → Zahlung mit Waffo-Test-Karte (kein echtes Geld)
│ │ → Bestellung in Test-Bestell-Tabelle, Plattform stellt Test-Code aus (T- Code)
│ ← Plattform stellt Code aus (T- Code)
│ │
│ activate(T-Code, machineCode)
├─────────────────→│ T- Präfix führt direkt zur Test-Tabelle
│ ← activationToken│
│ │
│ verifyCached(...)
├─────────────────→│ Prüfung bestanden
│ ← { valid, edition, expiryTime }
Kernpunkte:
- Erkennung: Lizenzcode mit
T--Präfix ist eine Test-Lizenz; oben auf der Kaufseite erscheint das Abzeichen „Debug-Modus (Testumgebung)" - Zahlung: läuft über den Waffo-Test-Checkout mit Testkarten (z. B.
4576 ... 0110); es erfolgt keine echte Abbuchung - Null Code-Änderungen: Der Client benötigt keinerlei Änderungen — derselbe Code verhält sich auf Debug-Maschine und echten Nutzerrechnern identisch (nur die Backend-Tabellen unterscheiden sich)
4.4 Empfohlene Debugging-Checkliste
- Erster Start der Debug-Maschine →
claimTrialerfolgreich, Testcode mitT--Präfix erhalten - Innerhalb der Testphase gibt
verifyCachedvalidzurück, Bezahl-Funktionen werden freigegeben -
purchaseUrlöffnet die Kaufseite, Abzeichen „Debug-Modus" erscheint - Zahlung mit Testkarte abgeschlossen → Test-Lizenzcode erhalten (E-Mail/Seite)
-
activateerfolgreich →verifyCachedbestanden - Editions-Sperre korrekt (niedriger Code wird bei höherer Funktion blockiert)
- Maschinen-Bindungslimit (
machineLimit) und Entbindungspfad funktionieren - (nur Szenario B)
generateForSoftwareauf der Debug-Maschine gibt Lizenzcode mitT--Präfix zurück, Aktivierung/Prüfung normal; derselbe Aufruf mit nicht registrierter Maschine gibt regulären Code zurück - Auf einem nicht registrierten Rechner
claimTrialwiederholen und bestätigen, dass die Produktions-Pipeline genutzt wird (Kontrollprüfung)
4.5 Debugging-Hinweise
| Thema | Beschreibung |
|---|---|
| Testdaten bereinigen | Test-Lizenzen/-Bestellungen beeinflussen die Produktion nicht, keine Bereinigung nötig; zum Zurücksetzen Gerät im Debug-Geräte-Panel entfernen und erneut hinzufügen |
| Debug-Schalter | Wer temporär nicht über die Test-Pipeline gehen möchte, schaltet den Schalter im Debug-Geräte-Panel aus — Gerät muss nicht gelöscht werden |
| Nur-Promotion-Produkte | Produkte vom Typ „Nur-Promotion" werden nicht in den Waffo-Produktkatalog synchronisiert; keine Debug-Kauf-Pipeline |
| Kein gültiger Preis | Haben Haupt-/Sekundärpreis und alle Lizenz-Editionen keinen regulären Preis, schlägt die Test-Produktsynchronisation fehl (DingTalk-Alarm) — bitte mindestens einen Editions-Preis konfigurieren |
5. Release-Phase
5.1 Review einreichen
- Nachdem alle Punkte der Debugging-Checkliste bestanden sind, im Produktformular „Speichern & Review einreichen" klicken
- Das Produkt gelangt in die Review-Warteschlange (
PENDING_RELEASE)
Für Produkte, die während der Debug-Phase als Entwurf gespeichert wurden, entspricht der eingereichte Inhalt dem neuesten Entwurf; erneutes Bearbeiten während des Reviews setzt den Status automatisch auf Entwurf zurück (verhindert Inhaltsänderungen während des Reviews) — erneutes Einreichen erforderlich.
5.2 Review bestanden → automatische Produktions-Synchronisation
Nach Freigabe durch den Plattform-Betrieb:
- Produktstatus wechselt zu veröffentlicht und gelistet
- Die Plattform synchronisiert das Produkt automatisch in die Waffo-Produktionsumgebung (schreibt
waffo_product_idzurück), erstellt/stellt Produktions-Checkout-Produkte wieder her - Produktdetailseite und Suchergebnisse sind für alle Nutzer sichtbar
5.3 Echte Nutzer-Pipeline (Produktion)
Die Pipeline für echte Nutzer (Nicht-Debug-Maschinen) ist mit dem Debugging völlig identisch — sie liegt nur vollständig in den Produktions-Tabellen:
Erster Start → claimTrial Testlizenz beziehen (regulärer Lizenzcode, ohne T- Präfix)
→ Testphase abgelaufen → purchaseUrl zur Kaufseite (Alipay / PayPal echte Zahlung)
→ Plattform stellt nach erfolgreicher Zahlung automatisch Code aus + E-Mail-Zustellung
→ activate aktivieren → verifyCached Prüfung Freigabe
Nutzer in Szenario B (Selbstinkasso) nutzen nicht die Plattform-Kaufseite: Nachdem der Nutzer über Ihren Kanal gezahlt hat, ruft Ihr Server
generateForSoftwareauf und stellt einen regulären Lizenzcode aus; die anschließende Aktivierungs-/Prüfungspipeline ist identisch mit Szenario A.
5.4 Release-Verifikations-Checkliste
- Mit einem nicht als Debug-Maschine registrierten Rechner die Produktdetailseite aufrufen und normale Anzeige bestätigen
- Auf der Kaufseite erscheint kein Abzeichen „Debug-Modus"
- Echte Kleinstzahlung → Code-Ausstellung → Aktivierung erfolgreich
- Die Bestellung ist in der Bestellliste des Developer Centers sichtbar (Test-Bestellungen erscheinen dort nicht)
6. Betrieb nach dem Release
| Aktion | Einstieg | Beschreibung |
|---|---|---|
| Bestellungen ansehen | Developer Center → Meine Bestellungen | Nur Produktions-Bestellungen; Test-Bestellungen nehmen nicht an Umsatzbeteiligung und Abrechnung teil |
| Nutzer-Entbindung | Nutzercenter des Nutzers / manuelle Lizenz durch Entwickler | Umbindungs-Kontingent: nach Entbindung 30 Tage keine erneute Entbindung möglich |
| Versions-Iteration | Produkt bearbeiten → Entwurf speichern / Review einreichen | Bearbeitung synchronisiert erneut asynchron in Waffo Test; neue Versionen können weiter mit der Debug-Maschine geprüft werden |
| Erstattung | Waffo Dashboard | Käufer eröffnet Ticket, Händler prüft im Dashboard; Erstattungen von Test-Bestellungen widerrufen nur die Test-Lizenz |
| Debugging offline nehmen | Gerät im Debug-Geräte-Panel entfernen | Empfohlen, die Debug-Maschine nach Stabilisierung der Version zu entfernen, um versehentliche Nutzung der Test-Pipeline zu vermeiden |
7. Häufige Fragen (FAQ)
F1: Muss ich während des Debuggings Client-Code oder Konfiguration ändern? Nein. Das Umgebungs-Routing ermittelt der Plattform-Server automatisch anhand der Frage, ob der Maschinen-Code in der Debug-Geräte-Liste steht; die SDK-Aufrufe sind völlig identisch.
F2: Kann ich den auf der Debug-Maschine erhaltenen Lizenzcode echten Nutzern geben?
Nein, und es ist auch nicht empfehlenswert. T--Codes sind nur in den Test-Tabellen gültig, und Debug-Daten nehmen an keinerlei Produktionslogik teil; Test-Codes an echte Nutzer auszugeben führt dazu, dass diese über den regulären Prüfungspfad keinen Support erhalten können.
F3: Kostet das Debugging Geld? Nein. Der Test-Zahlungskanal nutzt Testkarten; es erfolgt keine echte Abbuchung; Test-Bestellungen nehmen nicht an Umsatzbeteiligung/Abrechnung teil.
F4: Beeinflusst das Debugging das Review meines Produkts? Nein. Debug-Daten sind vom Review vollständig entkoppelt; bereits im Entwurfsstatus kann debuggt werden, ob eingereicht wird entscheiden Sie.
F5: Was, wenn ich auf mehreren Rechnern debuggen möchte? Pro Produkt sind maximal 3 Debug-Geräte registrierbar; im Debug-Geräte-Panel hinzufügen/entfernen genügt.
F6: Kann ich Käufe debuggen, wenn der Produkttyp „Nur-Promotion" ist oder kein Preis konfiguriert wurde? Nein. Nur-Promotion-Produkte werden nicht in den Waffo-Produktkatalog synchronisiert; ohne gültigen Preis schlägt die Test-Produktsynchronisation fehl. Bei solchen Produkten können nur Testphase und Prüfungs-Pipeline debuggt werden.
F7: Was passiert, wenn ich den Debug-Schalter vergesse und veröffentliche? Der Einfluss beschränkt sich auf den von Ihnen registrierten Rechner — er läuft weiter über die Test-Pipeline; alle echten Nutzer sind nicht betroffen. Nach bestätigter Stabilität einfach im Debug-Geräte-Panel entfernen.
8. Integrations-Checkliste (vor Release Punkt für Punkt prüfen)
Szenario A (vollständige Plattform-Pipeline)
- Produkt auf PowerSoftware.net veröffentlichen, Verkaufsmodell „Try-Before-You-Buy" wählen
- Testtage konfigurieren (empfohlen 7~14 Tage)
- Lizenz-Editionen konfigurieren (Edition-Code + Name + Preis + Funktionsliste)
- Bestätigen, dass „Plattform zieht Lizenzgebühren ein" aktiviert ist (bei Try-Before-You-Buy Pflicht)
-
productUniqueCodenotieren - SDK-Quellcode ins Projekt kopieren (siehe 2.3.1)
-
claimTrialimplementieren → Testlizenz beim ersten Start beziehen -
activateimplementieren → Aktivierung, wenn der Nutzer den Lizenzcode eingibt -
verifyCachedimplementieren → Prüfung bei Klick auf Bezahl-Funktionen -
purchaseUrlimplementieren → ohne Lizenz zur Kaufseite weiterleiten (einheitlich internationale Seite.app, keine Seitenwahl nötig) - Lokale Persistenz der Zugangsdaten implementieren (
licenseCode+activationToken) - Ebenen-Vergleichslogik der Editionen implementieren (siehe 3.2)
-
LicenseError-Fehlercode-Behandlung implementieren (siehe 3.3) - Debug-Maschine registrieren und Dual-Environment-Debugging-Checkliste durchlaufen (siehe 4.4)
- Review einreichen → Review bestanden → Release-Verifikation (siehe 5.4)
Szenario B (Bestellungen außerhalb der Plattform)
- Produkt auf PowerSoftware.net veröffentlichen,
licenseEnabledaktivieren - Lizenz-Editionen konfigurieren (Edition-Code + Name); falls Plattform-Inkasso gewünscht, „Plattform zieht Lizenzgebühren ein" aktivieren und Preise eintragen
-
licenseApiSecretim Developer-Backend beziehen -
productUniqueCodenotieren - Server aufbauen, der das Lizenz-Geheimnis
licenseApiSecretverwahrt und die Ausstellungs-Schnittstelle implementiert (Schlüssel darf nicht an den Client ausgeliefert werden) - Clientseitig SDK-Quellcode ins Projekt kopieren
- Serverseitig
generateForSoftwareimplementieren (Code-Ausstellung) - Serverseitig
upgradeForSoftwareimplementieren (Upgrade/Verlängerung) - Clientseitig
activate/verifyCachedimplementieren - Lokale Persistenz der Zugangsdaten implementieren
- Ebenen-Vergleichslogik der Editionen implementieren (siehe 3.2)
-
LicenseError-Fehlercode-Behandlung implementieren (siehe 3.3) - Debug-Maschine registrieren und
T--Code-Pipeline verifizieren (siehe 4.4) - Review einreichen → Review bestanden → Release-Verifikation (siehe 5.4)
Anhang: SDK-Repository (GitHub)
github.com/mizhanchengxi/powersoftware-license-sdk
├── node/ SDK-Quellcode (ESM, ohne Abhängigkeiten, eine Datei)
├── python/ SDK-Quellcode (py3, ohne Abhängigkeiten, 3 Dateien)
├── java/ SDK-Quellcode (Java 8+, ohne Abhängigkeiten, 3 Dateien)
└── docs/ SDK-Spezifikationsdokumente
Alle drei Pakete bieten: machineCode() / sign() / LicenseClient (einschließlich activate / verify / deactivate / claimTrial / generateForSoftware / upgradeForSoftware / verifyCached / purchaseUrl).
Dieses Dokument ist die v4-Aktualisierung des Client-Software-Lizenz-Integrationsleitfadens (CLIENT_SOFTWARE_GUIDE), deckt dessen gesamten Inhalt ab und ergänzt das Dual-Environment-Debugging sowie die Entwurfs-/Review-Einreichungs-Fähigkeiten.