ライセンス公開APIドキュメント

v1.0

ライセンス公開APIドキュメント

このドキュメントは、自社ソフトウェアに「支払い → 発行 → アクティベーション → 検証」の一連の流れを組み込みたい開発者(クライアントソフトウェア / 販売委託製品)向けです。各APIについて呼び出しタイミング・リクエストパラメータ・レスポンス項目・エラーコードを説明します。

1. 基本概念

概念 項目 / 用語 説明
ソフトウェア発行APIシークレット licenseApiSecret 製品で「ライセンスアクティベーション」を有効にすると自動生成されます。デベロッパーセンターの製品編集フォームで確認できます。ソフトウェアサーバーはこれでHMAC署名を計算し、プラットフォームはこれで署名を検証します。サーバー側にのみ保存し、クライアントに埋め込まないでください。
ライセンスコード licenseCode プラットフォームが発行する一意のコードです。ユーザーはこれを使ってソフトウェアをアクティベートします。
マシンコード machineCode クライアントソフトウェアが生成するデバイス識別子です(PCごとに一意。安定したマシンフィンガープリントをハッシュ化することを推奨、8文字以上)。
アクティベーショントークン activationToken アクティベーション / 発行時にプラットフォームが発行するトークンです。ソフトウェアは保存し、起動検証のたびに送信します。
注文ID clientOrderId ソフトウェア内決済の注文ID(クライアントまたはサーバーが生成)。プラットフォームは「製品 + 注文ID」で冪等化し、二重課金・二重発行を防ぎます。

2. 導入準備

  1. 製品公開時に「ライセンスアクティベーション」を有効にし、生成された**ソフトウェア発行APIシークレット(licenseApiSecret)**を保存します;
  2. 公開フォームでエディション一覧(例: BASIC/PRO/ULTIMATE)とアップグレード戦略(SAME_CODE = 既存コードのままアップグレード / NEW_CODE = 新コードを発行)を設定します;
  3. シークレットはソフトウェアサーバーに保存し、クライアントにはライセンスコードとアクティベーショントークンのみを持たせます。

3. API一覧

ベースパス: https://www.powersoftware.app/frontApi(ローカル / テスト環境ではデプロイドメインに置き換えてください)。

API 呼び出しタイミング 認証 署名
POST /license/software/generate ソフトウェア内決済成功直後 なし(署名検証) 必須
POST /license/software/upgrade 更新 / エディションアップグレードの決済成功直後 なし(署名検証) 必須
POST /license/activate ユーザーの初回アクティベーション / 別マシンへの変更 なし 不要
POST /license/verify ソフトウェア起動のたび なし 不要
POST /license/deactivate ユーザーが旧デバイスをバインド解除(マイページ) ログイン 不要

4. 署名ルール(generate / upgrade で必須)

署名対象文字列: 以下のフィールドをこの順番で改行(\n)区切りで連結します(省略可能なフィールドは空値を使用: edition は空文字、expiryDays は 0):

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

署名: HMAC-SHA256(ソフトウェア発行APIシークレット licenseApiSecret, 署名対象文字列) を計算し、Base64URL エンコードして signature フィールドに入れます。

リプレイ防止: timestamp はミリ秒タイムスタンプです。プラットフォームはサーバー時刻との差が5分以内であることを要求し、超過すると signatureInvalid を返します。

Node.js の例:

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 の例:

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 は標準の Base64 の +- に、/_ に置き換え、末尾の = パディングを除去したものです。)

5. API詳細

5.1 ライセンスコードの生成(ソフトウェア内決済後に呼び出し)

呼び出しタイミング: ユーザーがソフトウェア内で決済を完了した直後に、サーバーが1回呼び出し、返されたライセンスコードとアクティベーショントークンを保存します。同じ注文は1回だけ送信してください。冪等のため、繰り返し呼び出しても二重発行はされません。

POST /license/software/generate

リクエストパラメータ(JSON body):

パラメータ 必須 生成元 説明
productId number 必須 ソフトウェア内蔵 / サーバー設定 製品ID。プラットフォームで公開した製品と一致
machineCode string 必須 クライアント生成 現在のデバイスのマシンコード、8文字以上
edition string 任意 決済時にクライアントが選択 エディションID。製品のエディション一覧に含まれる必要あり。省略時は製品の最初のエディション
expiryDays number 任意 決済時にクライアントが選択 有効日数、0 = 無期限。範囲 0-3650
clientOrderId string 必須 クライアント / サーバー生成 ソフトウェア内決済の注文ID、1-64文字。冪等キー
timestamp number 必須 サーバー生成 ミリ秒タイムスタンプ
signature string 必須 サーバーで計算 HMAC署名、10文字以上

成功レスポンスの content 項目:

項目 説明
licenseId number ライセンスレコードID
licenseCode string ライセンスコード(ソフトウェアのライセンス情報に書き込む)
productId number 製品ID
edition string エディションID
machineId number バインド済みマシンのレコードID
activatedAt string アクティベーション時刻(ISO8601)
expiryTime string/null 有効期限(ISO8601)、null = 無期限
maxMachines number バインド可能なマシンの最大数
activationToken string アクティベーショントークン。起動検証用に保存

レスポンス例:

{
  "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",
    "maxMachines": 1,
    "activationToken": "eyJhbGciOiJIUzI1NiJ9..."
  }
}

このAPIのエラーコード: productIdRequiredmachineCodeInvalidorderIdRequiredproductNotFoundproductNotEnabledapiSecretMissingsignatureInvalidorderAlreadyUsed

5.2 エディションアップグレード / 更新(決済後に呼び出し)

呼び出しタイミング: ユーザーが更新またはエディションアップグレードの決済を完了した後に呼び出します。同じ注文は1回だけ送信してください。

POST /license/software/upgrade

リクエストパラメータ(JSON body):

パラメータ 必須 生成元 説明
productId number 必須 ソフトウェア内蔵 / サーバー設定 製品ID
licenseCode string 必須 ソフトウェアに保存 現在のライセンスコード、10文字以上
machineCode string 任意 クライアント生成 現在のマシンコード。新コード発行時のバインド移行や追加バインド時に指定
edition string 必須 決済時にクライアントが選択 対象エディションID
expiryDays number 任意 決済時にクライアントが選択 追加有効日数、0 = 無期限。範囲 0-3650
clientOrderId string 必須 クライアント / サーバー生成 今回の注文ID。冪等キー
timestamp number 必須 サーバー生成 ミリ秒タイムスタンプ
signature string 必須 サーバーで計算 HMAC署名

処理戦略(製品設定により決定):

  • SAME_CODE(既存コードのままアップグレード): ライセンスコードは変わらず、マシンのバインドも有効のまま、有効期限が延長されます(無期限は無期限のまま)。レスポンスは5.1の項目に加えて upgraded: true を含みます;
  • NEW_CODE(新コードを発行): 旧コードを失効させ、新コードを発行してマシンのバインドを移行します。レスポンスには追加で oldLicenseId が返り、licenseCode は新コードです。

成功レスポンスの content 項目: 5.1と同じで、さらに upgraded: true。NEW_CODE戦略では oldLicenseId(旧ライセンスレコードID。旧コードは失効済み)も返ります。

このAPIのエラーコード: productIdRequiredlicenseCodeRequiredorderIdRequiredproductNotFoundproductNotEnabledapiSecretMissingsignatureInvalidcodeNotFoundrevokedorderAlreadyUsededitionRequired

5.3 ライセンスのアクティベーション(初回アクティベーション / 別マシン)

呼び出しタイミング: ユーザーがライセンスコード(自助発行、運営発行など)を入手し、クライアントソフトウェアのアクティベーションページで入力してアクティベートするとき。別マシンに変更するときは新マシンで呼び出します。

POST /license/activate

リクエストパラメータ(JSON body):

パラメータ 必須 生成元 説明
licenseCode string 必須 ユーザー入力 ライセンスコード、10文字以上
machineCode string 必須 クライアント生成 現在のデバイスのマシンコード、8文字以上

成功レスポンスの content: 5.1と同じ(licenseId、licenseCode、productId、edition、machineId、activatedAt、expiryTime、maxMachines、activationToken)。

補足:

  • 1つのライセンスコードは複数のマシンにバインドでき、maxMachines(デフォルトは製品設定)が上限です;
  • 同じマシンを再アクティベートすると既存バインドを再利用し、アクティベーショントークンを再発行します(冪等);
  • アクティベーション失敗は IP + ライセンスコード単位でレート制限され、失敗が続くと tooManyAttempts を返します。

このAPIのエラーコード: codeNotFoundrevokedexpiredmachineLimittooManyAttempts

5.4 ライセンスの検証(ソフトウェア起動時)

呼び出しタイミング: ソフトウェアの起動のたび(または機能のロック解除前)に呼び出します。5.1 / 5.2 / 5.3 が返した activationToken を保存しておく必要があります。

POST /license/verify

リクエストパラメータ(JSON body):

パラメータ 必須 生成元 説明
licenseCode string 必須 ソフトウェアに保存 ライセンスコード、10文字以上
machineCode string 必須 クライアント生成 現在のデバイスのマシンコード、8文字以上
activationToken string 必須 プラットフォーム発行、ソフトウェアに保存 アクティベーショントークン、20文字以上

成功レスポンスの content 項目:

項目 説明
valid boolean 常に true(失敗はエラーコードで返る)
licenseId number ライセンスレコードID
productId number 製品ID
edition string 現在のエディションID
expiryTime string/null 有効期限(ISO8601)、null = 無期限

補足:

  • 検証結果は約60秒キャッシュされます。失効・バインド解除・アップグレードなどの書き込み操作はキャッシュを即時無効化するため、遅延の心配はありません;
  • ソフトウェアは expiryTime を確認し、期限切れ後は機能のロック解除を停止してください。

このAPIのエラーコード: tokenInvalidmachineNotActivatedinvalidOrRevokedexpiredtooManyAttempts

5.5 デバイスのバインド解除(機種変更前、ログイン必須)

呼び出しタイミング: ユーザーが「マイページ → マイライセンス」で旧デバイスのバインドを解除し、その後5.3で新デバイスをアクティベートします。

POST /license/deactivate

リクエストパラメータ(JSON body):

パラメータ 必須 生成元 説明
licenseCode string 必須 ユーザーのライセンス一覧 ライセンスコード、10文字以上
machineCode string 必須 ユーザーのライセンス一覧 解除するマシンコード、8文字以上

成功レスポンスの content: true

補足:

  • ライセンスの所有者(購入ユーザー、またはバインド済みマシンコードを登録したユーザー)のみ操作できます;
  • バインド解除の上限: デフォルトでは同じライセンスは30日以内に1回しか解除できません(運営コンソールで設定可能)。超過すると unbindQuotaExceeded を返します。

このAPIのエラーコード: noPermissionmachineNotBoundunbindQuotaExceeded

6. エラーコード

業務エラーは統一レスポンスで返ります(tip は人間が読めるメッセージ):

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

パラメータ検証失敗の場合は code: "PARAM_VALIDATE_FAILED" で、具体的な項目メッセージが tip に入ります。

エラーコード 意味
productNotEnabled 製品でライセンスアクティベーションが有効になっていない
apiSecretMissing 製品にソフトウェア発行APIシークレット(licenseApiSecret)が設定されていない
signatureInvalid 署名検証失敗(シークレット不一致、署名対象文字列の順序誤り、タイムスタンプ超過)
machineCodeInvalid マシンコードが無効(8文字未満)
orderAlreadyUsed この注文では既にライセンスコードが発行されている(冪等の競合: 別マシンコードでの再送)
codeNotFound ライセンスコードが存在しない
revoked ライセンスコードは失効済みまたは使用不可
expired ライセンスコードは期限切れ
invalidOrRevoked 検証時にライセンスが無効または失効
machineNotActivated このマシンはアクティベートされていない
tokenInvalid アクティベーショントークンが無効
machineLimit ライセンスのバインド可能マシン数が上限に達した
machineNotBound このマシンはバインドされていない
noPermission このライセンスを操作する権限がない
unbindQuotaExceeded 30日以内に1回しか解除できません。後でもう一度お試しください
tooManyAttempts 試行回数が多すぎます。後でもう一度お試しください
productNotFound 製品が存在しない
editionRequired 対象エディションを選択してください

7. 典型的なフロー

  1. ソフトウェア内決済ループ: 決済成功 → software/generate(ライセンスコード + アクティベーショントークンを返す)→ ソフトウェアが保存 → 起動のたびに verify → 機能のロック解除。更新 / アップグレード → software/upgrade
  2. 自助発行 / 運営発行: デベロッパーセンターまたは運営コンソールでライセンスコードを生成 → ユーザーがコードを入手 → クライアントで activate しデバイスをバインドしてトークンを取得 → 起動時に verify
  3. 機種変更: マイページの deactivate で旧デバイスを解除 → 新デバイスで activateverify
  4. アップグレード戦略の違い: SAME_CODE はコードが変わらない。NEW_CODE は新コードを発行(旧コードは失効、マシンバインドは自動移行)。

8. 注意事項

  • シークレットはサーバー側のみ: 署名はソフトウェアサーバーでのみ行ってください。クライアントがシークレットを入手するとライセンス体系は無効になります;
  • マシンコードの安定性: 安定したマシンフィンガープリントをハッシュ化することを推奨します。OS再インストールでマシンコードが変わった場合は、先にバインド解除してから再アクティベートしてください;
  • 冪等: clientOrderId はグローバルに一意(例: タイムスタンプ + 乱数)にしてください。重複リクエストでも二重発行されません;
  • キャッシュ: verify の結果は約60秒キャッシュされ、書き込み操作で即時無効化されます;
  • レート制限: アクティベーション / 検証の失敗はレート制限されます。クライアントはエラー表示と再試行間隔を適切に設計してください;
  • プラットフォームの判定を基準に: 有効期限・エディション・マシン数の上限はプラットフォームの判定を基準とし、ソフトウェア側で勝手に緩めないでください。