ライセンス認可コード 開発・デバッグ・リリース全プロセスガイド

v1.0.0

クライアントソフトウェア開発 → デバッグ → リリース 全プロセスガイド(v4)

対象:PowerSoftware.net でクライアントソフトウェアを公開し、ライセンスコード体系を組み込む開発者。 本文書は「製品作成」から「実ユーザーによる購入」までの完全なライフサイクルをカバーし、重点は v4 で新たに追加されたデュアル環境デバッグ機能です:リリース前に実際の決済パイプライン(Waffo Test 環境)を使い、自分のパソコンをデバッグ機として全フローを検証できます。

1. 全プロセス概要

┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│ ① 開発段階   │ → │ ② デバッグ   │ → │ ③ リリース   │ → │ ④ 運用       │
│              │   │              │   │              │   │              │
│ 製品下書き   │   │ デバッグ機   │   │ 審査提出     │   │ 注文確認     │
│ SDK 統合     │   │ 実パイプライン│  │ 審査通過     │   │ 解除/返金    │
│ 下書き保存   │   │ (Test環境) │   │ 本番同期     │   │ バージョン   │
└──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘
段階 製品状態 ライセンス/注文の保存先 実際の収益が発生するか
① 開発 下書き(DRAFT) いいえ
② デバッグ 下書き / 審査中 テストテーブル(ライセンスコードに T- プレフィックス) いいえ(テスト決済チャネル)
③ リリース 公開済み 本番テーブル はい

コアルール:デバッグと本番は完全に隔離されます。 デバッグ機上で発生するすべて(試用、注文、決済、コード発行、アクティベーション、返金)はテストテーブルにのみ影響し、収益分配・精算に入らず、実ユーザーには一切影響しません。デバッグ機以外からのアクセスは常に本番パイプラインを通ります。

2. 開発段階

2.1 製品を作成する

  1. PowerSoftware.net 開発者センターにログイン → 製品を公開、製品形態で「クライアントソフトウェア」を選択
  2. 販売方式で 後払い(Try-Before-You-Buy) を選択し、試用日数を入力(7〜14 日推奨)
  3. ライセンスバージョン(edition)を設定:デフォルトは 3 段階の BASIC / PRO / ULTIMATE、code・名称・価格・機能リストはカスタマイズ可能
  4. 「プラットフォームがライセンス料を代理徴収」にチェック(後払いでは必須)
  5. ソフトウェアパッケージと紹介素材をアップロード

2.2 下書き保存(新機能)

製品フォームの下部には 2 つのボタンがあります:

ボタン 動作
下書き保存 製品は DRAFT 状態で保存され、審査キューに入らず、いつでも編集を継続可能
保存して審査に提出 製品が審査キューに入る(PENDING_RELEASE

下書き/審査提出の保存後、プラットフォームは非同期で商品を Waffo Test 環境に同期します(失敗時はアラートのみで保存をブロックしません)。これはデバッグ段階で注文できる前提です。そのため推奨:開発期間中はまず下書き保存すればデバッグを開始でき、審査提出は不要です

保存後、productUniqueCode を控えておいてください(公開ページで確認可能、秘密情報ではありません)。

2.3 ライセンス SDK の統合(2 つの接続シナリオ)

PowerSoftware.net はクライアントソフトウェア向けに 2 つのライセンス接続方式を提供します。ご自身の状況に応じて選択してください:

シナリオ A:プラットフォーム完全パイプライン(後払い) シナリオ B:注文がプラットフォームにない
対象製品 クライアントソフトウェア + 後払い販売方式 プロモーション専用ソフトウェア(自行集金);またはサーバー/クライアントソフトウェアの前払い(PAY_FIRST)販売方式・VIP 機能の自行集金
決済の担当 PowerSoftware.net プラットフォーム(Waffo、Alipay、PayPal);デバッグ時は Waffo テスト環境を決済チャネルとして使用 開発者自身(アプリ内決済またはその他のチャネル)
コード発行の担当 プラットフォームが決済成功後に自動発行 ソフトウェアがプラットフォーム API を呼び出して発行(HMAC 署名)
ライセンス秘密鍵 licenseApiSecret は必要? ❌ 不要 ✅ 必要(サーバーのみ保管、クライアントには保存不可)
サーバーは必要? ❌ 不要、純クライアントで十分 ✅ 必要(licenseApiSecret を保管し、発行リクエストを転送)
試用ライセンス ✅ 対応(claimTrial ❌ 試用なし(試用は後払い製品のみ対応)
購入ページ プラットフォーム提供、SDK 一行で遷移 プラットフォーム購入ページなし、開発者が自行処理

バージョン設定について:すべての製品形態(クライアント/サーバー/プロモーション専用)でライセンスコードを有効化し、バージョンをカスタマイズできます(BASIC/PRO/ULTIMATE など)。バージョン価格と機能リストは、開発者が「プラットフォームがライセンス料を代理徴収」(licensePlatformPayment)にチェックした場合のみ購入ページに表示されます;チェックしない場合は開発者が自行集金し、プラットフォームはライセンスコードの発行と検証機能のみ提供します。

選び方

  • 個人開発者 / 小チームで自分のサーバーがない → シナリオ A を選択(本文書第 4・5 章のフローはシナリオ A を主線とします)
  • すでに決済チャネル(WeChat/Alipay マーチャントなど)があり、プラットフォームのコード発行・検証のみ利用したい → シナリオ B を選択

2.3.1 SDK インストール

3 言語(Node.js / Python / Java)ともすべてゼロ依存で、ソースコードを直接コピーしてプロジェクトに入れるだけで、パッケージマネージャーは不要です。マシンコードアルゴリズムは言語間で一致します(同じマシンで同じ machineCode を生成)。SDK リポジトリ:github.com/mizhanchengxi/powersoftware-license-sdk

2.3.2 シナリオ A:プラットフォーム完全パイプライン(後払い)

前提条件:製品の販売方式が後払い、試用日数とライセンスバージョンを設定済み、「プラットフォームがライセンス料を代理徴収」にチェック済み。ライセンス秘密鍵 licenseApiSecret は不要

# Python
from ps_license_sdk import LicenseClient, machine_code

client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="")  # api_secret は空のまま
mc = machine_code()
// Node.js
import { LicenseClient, machineCode } from './index.js';

const client = new LicenseClient({ productUniqueCode: 'PRO-2026-001', apiSecret: "" });  // シナリオ A:秘密鍵は空のまま
const mc = machineCode();
// Java
import com.powersoftware.sdk.LicenseClient;

LicenseClient client = new LicenseClient("PRO-2026-001", "");  // シナリオ A:秘密鍵は空のまま
String mc = LicenseClient.machineCode();

完全な接続フロー:

初回起動
    │
    ├─ claimTrial(machineCode) ────────────→ 試用ライセンスを取得
    │     ↓ { licenseCode, activationToken, licenseUpgradeMode } を返す
    │     ↓ ローカルに永続化保存
    │
    ├─ 試用期間内:すべての機能が利用可能
    │     │
    │     └─ 有料機能をクリック → verifyCached() 60 秒キャッシュ検証 → 通過
    │
    └─ 試用期限切れ / 未アクティベーション
          │
          ├─ verifyCached() が invalid/expired を返す
          ├─ 「購入してライセンスをアクティベーションする必要があります」とダイアログ表示
          └─ purchaseUrl(machineCode) → プラットフォーム購入ページへ遷移
                │
                ↓ ユーザーがプラットフォームで決済 → プラットフォームがコード発行 + メール送信
                │
          ユーザーがソフトウェアに戻り、ライセンスコードを入力
                │
                ├─ activate(licenseCode, machineCode)
                │     ↓ { activationToken, licenseUpgradeMode } を返す、ローカルに永続化保存
                │
                └─ 以降の使用 → verifyCached() 検証 → 通過

実装が必要:claimTrial(初回起動時に試用を取得)→ verifyCached(有料機能の検証)→ purchaseUrl(未ライセンス時に購入ページへ遷移)→ activate(ユーザー入力コードでアクティベーション)→ licenseCode + activationToken のローカル永続化 → LicenseError エラーコード処理。

コアコード(Python):

import json
from pathlib import Path
from ps_license_sdk import LicenseClient, machine_code

# ---------- 初期化 ----------
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))

# ---------- 初回起動:試用を取得 ----------
def claim_trial():
    mc = machine_code()
    try:
        result = client.claim_trial(mc)
        save_cred({
            "licenseCode": result["licenseCode"],
            "activationToken": result["activationToken"],
        })
        print(f"試用が有効になりました。ライセンスコード:{result['licenseCode']}")
    except Exception as e:
        print(f"試用の取得に失敗しました:{e}")

# ---------- ライセンス検証(有料機能クリック時に呼び出し) ----------
def check_license(required_edition="PRO"):
    cred = load_cred()
    if not cred.get("licenseCode"):
        return {"valid": False, "reason": "未アクティベーション"}

    mc = machine_code()
    try:
        result = client.verify_cached(
            cred["licenseCode"], mc, cred["activationToken"]
        )
        if not result.get("valid"):
            return {"valid": False, "reason": "ライセンスが無効または期限切れ"}

        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"{required_edition} 以上のバージョンが必要"}

        return {"valid": True, "edition": user_edition,
                "expiryTime": result.get("expiryTime"),
                "trialExpiryTime": result.get("trialExpiryTime")}
    except Exception as e:
        return {"valid": False, "reason": str(e)}

# ---------- ライセンスコードのアクティベーション(ユーザー購入後の入力) ----------
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"アクティベーション失敗:{e}")
        return False

# ---------- 購入ページへ遷移 ----------
def open_purchase_page():
    mc = machine_code()
    url = client.purchase_url(mc)
    import webbrowser
    webbrowser.open(url)

機能ゲートの例:

# 機能ごとのバージョン要件を定義
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"この機能は使用できません:{result['reason']}")
        open_purchase_page()

2.3.3 シナリオ B:注文がプラットフォームにない(自行集金)

対象製品:プロモーション専用ソフトウェア(自行集金)、またはサーバー/クライアントソフトウェアの前払い(PAY_FIRST)販売方式・VIP 機能の自行集金。

前提条件:製品で licenseEnabled を有効化;開発者コンソールで licenseApiSecret を取得(サーバーのみ保管、クライアントに漏洩不可)。アーキテクチャ:

クライアント            あなたのサーバー                    PowerSoftware プラットフォーム
  │                       │                                 │
  │ ユーザー決済(あなたの決済)│                       │
  ├──────────────────────→│                                 │
  │                       │ generateForSoftware(            │
  │                       │   machineCode, edition,         │
  │                       │   clientOrderId)                │
  │                       │ (HMAC 署名 + timestamp)         │
  │                       ├────────────────────────────────→│
  │                       │ ← licenseCode を返す            │
  │ ← licenseCode を返す  │                                 │
  │                       │                                 │
  │ activate(licenseCode, machineCode)                     │
  ├───────────────────────────────────────────────────────→│
  │ ← activationToken を返す                               │
  │                       │                                 │
  │ verifyCached(...)     │                                 │
  ├───────────────────────────────────────────────────────→│
  │ ← { valid, edition, expiryTime }                       │

サーバー側(ライセンス秘密鍵 licenseApiSecret を保管、コード発行):

from ps_license_sdk import LicenseClient, machine_code

server_client = LicenseClient(
    product_unique_code="PRO-2026-001",
    api_secret="あなたの発行秘密鍵_FROM_DEVELOPER_CONSOLE",
)

def issue_license(user_machine_code, edition="PRO", order_id=""):
    """ユーザーの支払い後、サーバーがプラットフォームを呼び出してコードを発行"""
    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"]

クライアント側(licenseApiSecret は不要、アクティベーションと検証):

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"]})

実装が必要:サーバー側 generateForSoftware(コード発行)+ upgradeForSoftware(アップグレード/更新);クライアント側 activate / verifyCached + ローカル資格情報の永続化 + LicenseError エラーコード処理。

2.3.4 SDK メソッド早見表

メソッド シナリオ A シナリオ B 署名 説明
machine_code() マシンコード生成(言語間で一致)
claim_trial(mc) 試用ライセンス取得(後払い製品のみ)
activate(code, mc) ライセンスコードをアクティベーション、マシンにバインド
verify(code, mc, token) ライセンス状態を検証
verify_cached(code, mc, token) ローカルキャッシュ(60 秒)付き検証
deactivate(code, mc) マシンのバインド解除(ログイン要、ブラウザシナリオ)
purchase_url(mc) プラットフォーム購入ページ URL を生成
generate_for_software(mc, edition, ...) HMAC アプリ内コード発行(サーバーのみ)
upgrade_for_software(code, edition, ...) HMAC アプリ内アップグレード/更新(サーバーのみ)

戻り値フィールドの説明activate / verify / claimTrial の 3 つのインターフェースの成功レスポンスにはいずれも licenseUpgradeMode(製品のアップグレードポリシー:SAME_CODE コード不変更 / NEW_CODE コード再バインド)が付含されます。クライアントはこれを基に「ライセンスキー入力欄」を表示するかを判断します:SAME_CODE ではライセンスキーが変わらないため再入力は不要;NEW_CODE ではアップグレード/更新時に新コードが発行されるため、インターフェースが返す新しい licenseCode でローカル保存分を上書きすること。未設定時は SAME_CODE として扱います。verify の結果は約 60 秒キャッシュされるため、設定変更は最大 60 秒で反映されます。また、成功レスポンスには trialExpiryTime(試用期限スナップショット、ISO 8601 文字列。試用からのアップグレードでない場合は null)も含まれます。クライアントはこれを猶予期間として利用できます:ユーザーが全機能を試用した後に下位エディションを購入した場合も、上位機能は trialExpiryTime まで開放し続けられます。また、成功レスポンスには trialExpiryTime(試用期限スナップショット、ISO 8601 文字列。試用からのアップグレードでない場合は null)も含まれます。クライアントはこれを猶予期間として利用できます:ユーザーが全機能を試用した後に下位エディションを購入した場合も、上位機能は trialExpiryTime まで開放し続けられます。また、成功レスポンスには trialExpiryTime(試用期限スナップショット、ISO 8601 文字列。試用からのアップグレードでない場合は null)も含まれます。クライアントはこれを猶予期間として利用できます:ユーザーが全機能を試用した後に下位エディションを購入した場合も、上位機能は trialExpiryTime まで開放し続けられます。また、成功レスポンスには trialExpiryTime(試用期限スナップショット、ISO 8601 文字列。試用からのアップグレードでない場合は null)も含まれます。クライアントはこれを猶予期間として利用できます:ユーザーが全機能を試用した後に下位エディションを購入した場合も、上位機能は trialExpiryTime まで開放し続けられます。

デュアル環境デバッグは両シナリオに対して完全に透明です

  • シナリオ A:デバッグ機の claimTrial / プラットフォーム購入ページ決済は全パイプラインが自動的に Test 環境を通ります(第 4 章参照)
  • シナリオ B:デバッグ機が generateForSoftware を呼び出すときも、プラットフォームはマシンコードで Test 環境にルーティングし、T- プレフィックスのライセンスコードを返します;サーバーコードは一切変更不要です
  • SDK の呼び出し方法はデバッグ期間とリリース後で完全に一致し、環境パラメーターやコード分岐は不要です;環境ルーティングはプラットフォームサーバーが自動で完了します

3. ライセンス統合の詳細(両シナリオ共通)

3.1 ローカル資格情報の保存規範

SDK 自体は永続化を担当せず、開発者が自行実装します。保存内容:

{
  "licenseCode": "XXXXXXXXXXXX",
  "activationToken": "YYYYYYYYYYYY",
  "lastVerify": {
    "valid": true,
    "edition": "ULTIMATE",
    "expiryTime": 1735689600000,
    "trialExpiryTime": 1735000000000,
    "trialExpiryTime": 1735000000000,
    "trialExpiryTime": 1735000000000,
    "trialExpiryTime": 1735000000000,
    "cachedAt": 1735689600000
  }
}

原則:

  • licenseCode + activationToken + 直近の verify 結果のみ保存する
  • 復号可能な完全なライセンス情報は保存しない(リバース防止に意味はなく、キャッシュとしてのみ扱う)
  • verifyCached の 60 秒キャッシュは SDK プロセス内にあり、再起動後に失効するため verify を再度呼び出す必要がある

3.2 バージョン階層比較(edition)

開発者が edition code(BASIC / PRO / ULTIMATE など)を自行定義し、プラットフォームの公開ページで設定します。すべての製品形態(クライアント/サーバー/プロモーション専用)はライセンスコード有効化後にバージョンをカスタマイズできます。クライアント検証時は階層で比較します:

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)

よくあるマッピング(参考):

機能档位 edition code 階層 典型的な機能
基本版 BASIC 0 基本画像編集、フォーマット変換
上位版 PRO 1 バッチ処理、高解像度アップスケール
旗艦版 ULTIMATE 2 AI 修復、カバーアシスタント

バージョン名と code は開発者がプラットフォームで自行定義し、BASIC/PRO/ULTIMATE という名称は必須ではありません。バージョン価格と機能リストは「プラットフォームがライセンス料を代理徴収」にチェックした場合のみ購入ページに表示されます。

3.3 エラーコード処理(LicenseError)

SDK は error_code 属性付きの LicenseError を送出します:

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("ライセンスは取り消されました。カスタマーサポートにご連絡ください")
    elif e.error_code == "machineLimit":
        show_message("マシンバインド上限に達しました。マイページで旧デバイスのバインドを解除してください")
    elif e.error_code == "NETWORK_ERROR":
        show_message("ネットワーク異常です。ネットワークを確認して再試行してください")
    else:
        show_message(f"検証失敗:{e}")
エラーコード 意味 クライアント側の推奨処理
codeNotFound ライセンスコードが存在しない 入力を確認
revoked 取り消し済み サポートへの連絡を案内
expired 期限切れ 購入/更新へ誘導
machineLimit マシンバインド数が上限 マイページでのバインド解除へ誘導
tooManyAttempts レート制限発生 しばらくしての再試行を案内
trialNotEnabled 製品で試用が有効でない プラットフォーム設定を確認
trialAlreadyPurchased この製品は購入済みのため試用不要 購入済みであることを提示し購入ページへ誘導
trialAlreadyPurchased この製品は購入済みのため試用不要 購入済みであることを提示し購入ページへ誘導
trialAlreadyPurchased この製品は購入済みのため試用不要 購入済みであることを提示し購入ページへ誘導
trialAlreadyPurchased この製品は購入済みのため試用不要 購入済みであることを提示し購入ページへ誘導
NETWORK_ERROR ネットワーク/タイムアウト オフライン猶予または再試行を案内

3.4 購入ページへの遷移(シナリオ A のみ)

3.4.1 購入ページ URL

https://www.powersoftware.app/product/license/purchase?productUniqueCode={productUniqueCode}&machineCode={machineCode}

SDK メソッド:

url = client.purchase_url(mc)

デバッグ機でこのページにアクセスすると、上部に「デバッグモード(テスト環境)」バッジが表示され、決済はテストチャネルを通ります(第 4 章参照)。 言語は購入ページがユーザーのブラウザから自動検出します(URL プレフィックス / Accept-Language)。SDK は関与不要です。

3.4.2 サイト:国際サイト .app を統一使用、開発者が購入サイトを選択する必要はありません

powersoftware.app(国際サイト) powersoftware.cn(中国サイト)
決済方式 Waffo(カード / Apple Pay / Google Pay など)+ PayPal + Alipay Alipay のみ
国/通貨 Cloudflare が IP で自動識別(CN→CNY、その他→USD) 固定 country=CN、人民元
言語 URL プレフィックス / Accept-Language で自動検出 固定 zh-CN
位置づけ 開発者が唯一使用する購入入口 国際サイト Alipay 決済の受け皿サイト
開発者が購入サイトを選択する必要はありませんpurchaseUrl は統一して国際サイト .app を指します。海外ユーザーは .app で直接 Waffo / PayPal 決済を完了;中国国内ユーザーが .app で Alipay を選択すると、プラットフォームが自動的に中国サイト .cn に遷移して Alipay 決済を完了します(ログイン状態は自動同期、再ログイン不要)。決済成功後はライセンスフローに戻ります。全パイプラインはユーザーと開発者の双方に透明です。
# 正しい:国際サイトを固定使用し、地域/言語で base を切り替えないこと
url = client.purchase_url(mc)

# 非推奨:自行で地域を判定して .cn base を渡すこと——Alipay 遷移はプラットフォームが処理済みで、
# .cn のハードコードは Waffo / PayPal 決済方式を失わせます

4. デバッグ段階(デュアル環境、v4 で新規追加)

リリース前の最も確実な受け入れ方法:普段開発に使っているパソコンを「デバッグデバイス」として登録し、実際の決済パイプラインで全フローを一度実行することです。

4.1 マシンコードを登録する

  1. マイページ →「マイマシンコード」→ デバッグ用パソコンのマシンコードを登録する
    • マシンコードは SDK の machine_code() で生成可能(同一マシンなら 3 言語の結果は一致)
  2. そのマシンコードを控えておく

4.2 デバッグデバイスを登録する

  1. 開発者センター → 製品リスト → 対象製品の「デバッグデバイス」ボタン
  2. ダイアログで登録済みマシンコードから選択し、本製品に追加(メモ記入可)
  3. 制限:製品ごとに最大 3 台のデバッグデバイス;スイッチ(ルーティングの一時停止)と削除に対応

4.3 デバッグ機で何が起きるか

登録済みかつ有効なデバッグ機では、当該製品の全パイプラインが自動的に Waffo Test 環境に切り替わります:

デバッグ機(あなたのPC)   PowerSoftware プラットフォーム(サーバーが環境を自動判定)
    │                  │
    │ claimTrial(machineCode)
    ├─────────────────→│ このマシンは本製品のデバッグ機 → Test パスを通る
    │                  │
    │ ← 試用ライセンス(T- プレフィックスコード、テストライセンステーブルに書き込み)
    │                  │
    │ purchaseUrl(machineCode)
    ├─────────────────→│ 購入ページに「デバッグモード(テスト環境)」バッジを表示
    │                  │ → Waffo Test テストカードで決済(実際の請求なし)
    │                  │ → 注文はテスト注文テーブルに入り、プラットフォームがテストコード(T- コード)を発行
    │ ← プラットフォームがコード発行(T- コード)
    │                  │
    │ activate(T-コード, machineCode)
    ├─────────────────→│ T- プレフィックスでテストテーブルを直接特定
    │ ← activationToken│
    │                  │
    │ verifyCached(...)
    ├─────────────────→│ 検証通過
    │ ← { valid, edition, expiryTime }

要点:

  • 識別方法:ライセンスコードに T- プレフィックスがあればテストライセンス;購入ページ上部に「デバッグモード(テスト環境)」バッジが表示されます
  • 決済:Waffo Test チェックアウトを通り、テストカード(4576 ... 0110 など)で決済を完了、実際の請求は発生しません
  • ゼロコード変更:クライアントは一切変更不要で、同じコードがデバッグ機と実ユーザーのマシンで同じ挙動をします(バックエンドの保存テーブルが異なるだけです)

4.4 推奨デバッグチェックリスト

  • デバッグ機の初回起動 → claimTrial 成功、T- プレフィックス試用コードを取得
  • 試用期間内に verifyCachedvalid を返し、有料機能が通過
  • purchaseUrl で購入ページを開き、「デバッグモード」バッジの表示を確認
  • テストカードで決済完了 → テストライセンスコードを受信(メール/ページ)
  • activate でアクティベーション成功 → verifyCached 通過
  • バージョンゲートが正しい(下位バージョンコードで上位機能アクセスがブロックされる)
  • マシンバインド上限(machineLimit)とバインド解除パスが正常
  • (シナリオ B のみ) デバッグ機で generateForSoftware を呼ぶと T- プレフィックスコードが返り、アクティベーション・検証が正常;同じインターフェースを未登録マシンで呼ぶと正式コードが返る
  • 未登録の別のマシンclaimTrial を繰り返し、本番パイプラインを通ることを確認(対照検証)

4.5 デバッグ時の注意事項

事項 説明
テストデータ整理 テストライセンス/注文は本番に影響しないため整理不要;リセットが必要な場合はデバッグデバイスパネルで削除後に再追加
デバッグスイッチ 一時的にテストパイプラインを使いたくない場合、デバッグデバイスパネルでスイッチをオフにすればよく、デバイスの削除は不要
プロモーション専用製品 製品形態が「プロモーション専用」の場合は Waffo 商品カタログに同期されず、デバッグ購入パイプラインなし
有効価格なし メイン/サブ価格とすべてのライセンスバージョンに正規価格がない場合、テスト商品同期が失敗します(DingTalk アラート)。少なくとも 1 つのバージョン価格を設定してください

5. リリース段階

5.1 審査に提出する

  1. デバッグチェックリストがすべて通過した後、製品フォームで「保存して審査に提出」をクリック
  2. 製品が審査キューに入る(PENDING_RELEASE

デバッグ期間中に下書き保存した製品は、審査提出時の内容が最新の草稿内容そのものです;審査期間中に再編集すると自動的に草稿状態に戻ります(審査中の内容変更を防止するため)、再提出が必要です。

5.2 審査通過 → 本番へ自動同期

プラットフォーム運営の審査通過後:

  1. 製品状態が公開済みに変わり、上架される
  2. プラットフォームが自動的に商品を Waffo 本番環境に同期(waffo_product_id を書き戻し)、本番チェックアウト商品を作成/復元
  3. 製品詳細ページ・検索結果が全ユーザーに表示される

5.3 実ユーザーのパイプライン(本番)

実ユーザー(デバッグ機以外)のパイプラインはデバッグと完全に一致し、すべてが本番テーブルに保存される点だけが異なります:

初回起動 → claimTrial で試用取得(正式ライセンスコード、T- プレフィックスなし)
        → 試用期限切れ → purchaseUrl で購入ページへ(Alipay / PayPal の実決済)
        → プラットフォームが決済成功後に自動発行 + メール送信
        → activate でアクティベーション → verifyCached 検証通過

シナリオ B(自行集金)のユーザーはプラットフォーム購入ページを通りません:ユーザーがあなたのチャネルで支払った後、あなたのサーバーが generateForSoftware を呼び出して正式ライセンスコードを発行し、以降のアクティベーション/検証パイプラインはシナリオ A と同じです。

5.4 リリース検証チェックリスト

  • デバッグ機として未登録のパソコンで製品詳細ページにアクセスし、正常に表示されることを確認
  • 購入ページに「デバッグモード」バッジがないことを確認
  • 実際の少額決済 → コード発行 → アクティベーション成功
  • 開発者センターの注文リストに当該注文が表示される(テスト注文はここには表示されません)

6. リリース後の運営

操作 入口 説明
注文確認 開発者センター → マイ注文 本番注文のみ;テスト注文は収益分配・精算に参加しない
ユーザーのバインド解除 ユーザーのマイページ / 開発者の手動ライセンス 再バインド枠:解除後 30 日間は再解除不可
バージョン迭代 製品編集 → 下書き保存 / 審査提出 編集時に Waffo Test へ再度非同期同期され、デバッグ機で新バージョンを検証し続けられる
返金 Waffo Dashboard 購入者がチケットを起こし、出店者が Dashboard で審査;テスト注文の返金はテストライセンスの取り消しのみ
デバッグ終了 デバッグデバイスパネルでデバイスを削除 バージョン安定後にデバッグ機を削除し、テストパイプラインの誤用を避けることを推奨

7. よくある質問(FAQ)

Q1:デバッグ期間中にクライアントのコードや設定を変更する必要がありますか? 不要です。環境ルーティングはプラットフォームサーバーが「マシンコードがデバッグデバイスリストにあるか」で自動判定し、SDK の呼び出しは完全に一致します。

Q2:デバッグ機で取得したライセンスコードを実ユーザーに使えますか? 使えず、推奨もしません。T- コードはテストテーブルでのみ有効で、デバッグデータは一切の本番ロジックに参加しません;実ユーザーにテストコードを発行すると、正常な検証パスを通れずアフターサポートを受けられなくなります。

Q3:デバッグには費用がかかりますか? かかりません。テスト決済チャネルはテストカードを使用し、実際の請求は発生しません;テスト注文は収益分配/精算に参加しません。

Q4:デバッグは製品の審査に影響しますか? しません。デバッグデータと審査は完全に分離;草稿状態でもデバッグ可能で、審査提出の可否はあなたが決められます。

Q5:複数のパソコンでデバッグしたい場合は? 製品ごとに最大 3 台のデバッグデバイスを登録可能;デバッグデバイスパネルで追加/削除できます。

Q6:製品形態が「プロモーション専用」または価格未設定の場合、購入のデバッグはできますか? できません。プロモーション専用製品は Waffo 商品カタログに同期されず;有効価格がない場合はテスト商品同期が失敗します。これらの製品は試用と検証パイプラインのみデバッグ可能です。

Q7:デバッグスイッチを切り忘れてリリースしたらどうなりますか? 影響範囲はあなたが登録したそのマシンに限定されます——そのマシンはテストパイプラインを通り続けます;すべての実ユーザーは影響を受けません。安定を確認後、デバッグデバイスパネルで削除すればよいだけです。

8. 統合チェックリスト(リリース前に項目ごとに確認)

シナリオ A(プラットフォーム完全パイプライン)

  • PowerSoftware.net で製品を公開し、販売方式で「後払い」を選択
  • 試用日数を設定(7〜14 日推奨)
  • ライセンスバージョンを設定(edition code + 名称 + 価格 + 機能リスト)
  • 「プラットフォームがライセンス料を代理徴収」にチェック済みであることを確認(後払いでは必須)
  • productUniqueCode を控える
  • SDK ソースコードをプロジェクトにコピー(2.3.1 参照)
  • claimTrial を実装 → 初回起動時に試用を取得
  • activate を実装 → ユーザー入力コードでアクティベーション
  • verifyCached を実装 → 有料機能クリック時に検証
  • purchaseUrl を実装 → 未ライセンス時に購入ページへ遷移(国際サイト .app を統一使用、サイト選択不要)
  • ローカル資格情報の永続化を実装(licenseCode + activationToken
  • edition 階層比較ロジックを実装(3.2 参照)
  • LicenseError エラーコード処理を実装(3.3 参照)
  • デバッグ機を登録しデュアル環境デバッグチェックリストを完了(4.4 参照)
  • 審査提出 → 審査通過 → リリース検証(5.4 参照)

シナリオ B(注文がプラットフォームにない)

  • PowerSoftware.net で製品を公開し、licenseEnabled を有効化
  • ライセンスバージョンを設定(edition code + 名称);プラットフォーム代理徴収が必要な場合は「プラットフォームがライセンス料を代理徴収」にチェックし価格を記入
  • 開発者コンソールで licenseApiSecret を取得
  • productUniqueCode を控える
  • サーバーを構築してライセンス秘密鍵 licenseApiSecret を保管し、発行インターフェースを実装(秘密鍵はクライアントに配布不可)
  • クライアントは SDK ソースコードをプロジェクトにコピー
  • サーバーに generateForSoftware(コード発行)を実装
  • サーバーに upgradeForSoftware(アップグレード/更新)を実装
  • クライアントに activate / verifyCached を実装
  • ローカル資格情報の永続化を実装
  • edition 階層比較ロジックを実装(3.2 参照)
  • LicenseError エラーコード処理を実装(3.3 参照)
  • デバッグ機を登録し T- コードパイプラインを検証(4.4 参照)
  • 審査提出 → 審査通過 → リリース検証(5.4 参照)

付録:SDK リポジトリ(GitHub)

github.com/mizhanchengxi/powersoftware-license-sdk
├── node/      SDK ソース(ESM、ゼロ依存、単一ファイル)
├── python/    SDK ソース(py3、ゼロ依存、3 ファイル)
├── java/      SDK ソース(Java 8+、ゼロ依存、3 ファイル)
└── docs/      SDK 規範ドキュメント

3 パッケージとも提供:machineCode() / sign() / LicenseClientactivate / verify / deactivate / claimTrial / generateForSoftware / upgradeForSoftware / verifyCached / purchaseUrl を含む)。

本文書は クライアントソフトウェアライセンス接続ガイド(CLIENT_SOFTWARE_GUIDE) の v4 アップグレード版で、その全内容を完全にカバーし、さらにデュアル環境デバッグと下書き/審査提出機能を追加しています。