# 手動開発による連携ガイド（9 言語、AI 不要）

このガイドは Licentivo プロバイダー向けです。別のライセンスシステムをお持ちの事業者は、管理画面の「ライセンスの選択とカスタマイズ」でカスタムサービスを選択し、[カスタムライセンス API と連携フロー](/ja/launch-documents/external-licensing/)に従って連携したうえで、引き続き自社ライセンスシステムの SDK を使用できます。

> 現在未公開の変更ではアカウント ID の交換を採用しています。具体的な責務と移行上の制約は [購入期間とアカウント SDK の境界](/ja/launch-documents/account-purchase-boundary/)を参照してください。Launch が購入期間を計算し、Licentivo SDK がライセンスを実行します。

対象言語の Launch 連携パッケージのみをインストールします。Launch パッケージには公式 SDK、デフォルトアダプター、リンク設定が含まれます。公式ライセンス URL は `https://www.licentivo.com` に固定されています。アプリは購入者が現在の Launch ストアに登録したアカウントでログインします。

## 入力済みの初期化コードを取得する

1. Launch の管理画面でソフトウェア、販売プラン、Licentivo ライセンスポリシーの関連付けを完了し、対象環境に公開します。
2. **アプリ連携 → 連携チェックとコード** を開き、ソフトウェア、言語、テスト／本番環境を選択します。
3. 「製品情報を取得して連携コードを生成」をクリックします。Launch はサイトの現在の公開 URL、既存の製品マッピング、署名公開鍵を自動的に取得します。
4. ページ上の接続関数を自分のプロジェクトにコピーし、以下に従って画面と業務呼び出しを手動で実装します。自動入力されたパラメーターを確認して、対象言語の `Connect/connect` を自分で呼び出すこともできます。

2 つの内部製品 ID を手入力したり、`launch-config.json` や `product.json` を生成したりする必要はありません。ページから保存できるのはソースコードの接続関数です。サーバーの非公開 `config.yaml` は Launch サービスの起動専用で、顧客向けソフトウェアに同梱して配布してはいけません。

サイト URL は現在のインスタンスの有効な公開 URL（起動設定の `public_url` または管理画面のサイト設定にある有効な公開 URL）から取得します。ドメインまたはポート付き IP アドレスを使用できますが、プロトコルが必要です。本番連携では有効な HTTPS を使用します。待受アドレス `http_addr` は顧客のアクセス先ではありません。サイト URL、製品マッピング、環境を変更したら、現在のサイトから接続関数を再取得してください。旧サイトのセッションやキャッシュを新サイトの認可に使用してはいけません。

2 つの製品番号はシステムに既存の内部対応関係、すなわち Launch のソフトウェア商品と Licentivo のライセンス製品です。連携ページでは選択したソフトウェアに応じて自動入力され、購入者はストアのアカウントだけを入力します。署名公開鍵はサーバーが設定済みの Licentivo 接続を使用して取得し、管理キーや顧客のライセンス認証情報はソースコードに含まれません。

## `Connect/connect` の役割

`Connect/connect` は「Launch アプリケーションクライアントを作成する」操作を各言語で表す名前です。Go、C#、一部のネイティブ API は先頭が大文字の `Connect` を使用し、Python、JavaScript、Ruby などは各言語の慣例に従って `connect` を使用します。管理画面で生成される `connectLaunch()`、`connect_launch()`、`LaunchConnection.Open()` は公開パラメーターをあらかじめ入力したプロジェクト関数で、内部で対象言語のエントリーポイントを呼び出します。

接続では初期化のみが行われます。ストア URL、製品マッピング、環境、署名公開鍵を検証し、Launch クライアントを作成して、パッケージ内の公式 Licentivo SDK を設定します。顧客の本人確認や有料機能の直接開放は行いません。全体の順序は次のとおりです：

```text
Connect/connect → Login or Restore → RunFeature → Logout / Close
                                       └──────────→ ReleaseDevice (explicit device unlink only)
```

アプリの実行中は同じクライアントオブジェクトを維持し、SDK がハートビートとフローティング席を正常に処理できるようにします。通常終了ではデバイスの紐付けを保持します。顧客の明示的なログアウトと ReleaseDevice 互換エントリーポイントは、同じ公式 SDK のログアウト処理を呼び出します。

## インストールと初期化のエントリーポイント

0.1.6 の 9 言語の公開インストール検証はすべて成功しており（9/9）、以下の表のインストール方法はすべて検証済みです。[GitHub Release](https://github.com/spf86/licentivo-launch-sdk/releases/tag/v0.1.6) にはネイティブパッケージとオフラインファイルも用意されています。使い方は[ダウンロードしたパッケージのインストール手順](/ja/launch-documents/integration-packages/#install-a-downloaded-distribution)を参照してください。

| 言語 | Launch のみをインストール | ページで提供される接続関数 | パッケージ内の直接初期化 API |
| --- | --- | --- | --- |
| Go | `go get github.com/spf86/licentivo-launch-sdk/pkg/launchclient@v0.1.6` | `connectLaunch()` | `launchclient.Connect` |
| Python 3.10+ | `python -m pip install licentivo-launch==0.1.6` | `connect_launch()` | `Application.connect` |
| C# / .NET 8+ | `dotnet add package Licentivo.Launch --version 0.1.6` | `LaunchConnection.Open()` | `Application.Connect` |
| Java 17+ | Maven/Gradle：`com.licentivo.launch:launch-client:0.1.6` | `LaunchConnection.open()` | `Launch.connect` |
| Node.js 20.3+ | `npm install @licentivo/launch@0.1.6` | `connectLaunch()` | `Application.connect` |
| Rust 1.85+ | `cargo add licentivo-launch@=0.1.6` | `connect_launch()` | `Application::connect` |
| Ruby 3.1+ | `gem install licentivo-launch --version 0.1.6` | `connect_launch` | `Application.connect` |
| C11 | [GitHub Release](https://github.com/spf86/licentivo-launch-sdk/releases/tag/v0.1.6) からネイティブパッケージをダウンロードし、CMake でインポート | `connect_launch()` | `launch_application_connect` |
| C++17 | 同じ Launch ネイティブパッケージを使用 | `connectLaunch()` | `Application::Connect` |

公開ソースと各言語の README は [Launch SDK リポジトリ](https://github.com/spf86/licentivo-launch-sdk)、ネイティブパッケージとオフラインファイルは [v0.1.6 Release](https://github.com/spf86/licentivo-launch-sdk/releases/tag/v0.1.6)、公開インストール結果は [9 言語のレジストリ検証](https://github.com/spf86/licentivo-launch-sdk/blob/main/docs/registry-verification.json)を参照してください。各パッケージの README にインストールコマンドと API が記載されています。JavaScript パッケージには TypeScript 宣言が含まれます。Python の cryptography、C# の BouncyCastle、Ruby の base64 などの通常の言語依存関係はパッケージマネージャーが解決します。公式 SDK パッケージを別途インストールする必要はありません。

Go の公開モジュール名は `github.com/spf86/licentivo-launch-sdk`、インポートパスは `github.com/spf86/licentivo-launch-sdk/pkg/launchclient` です。アプリでローカルの replace は不要です。Windows ネイティブパッケージは amd64 GNU/MinGW を採用し、Linux amd64 ネイティブパッケージもあります。Ruby のプラットフォームパッケージと Rust/native の Windows 配布には curl が含まれます。他のプラットフォームでソースからビルドするには通常の C11、curl/OpenSSL 開発依存関係が必要です。プラットフォームのツールチェーンについては各パッケージの README を参照してください。

## ログインと保護された操作

以下の断片では前の手順でコピーした接続関数を使用します。`email`、`password` は独自のログイン画面から取得し、パスワードをソースコードや設定に書き込んではいけません。`export` はプランのポリシーに実在する機能名に置き換える必要があります。

### Go

```go
app, err := connectLaunch()
if err != nil { return err }
defer app.Close()
if _, err := app.Login(ctx, email, password); err != nil { return err }
return app.RunFeature("export", func() error {
    return exportReport()
})
```

`ctx` にはアプリのライフサイクルのコンテキストを使用し、ログインリクエスト終了時に直ちにハートビートをキャンセルしないでください。ネットワーク操作はバックグラウンドのワーカースレッドで実行します。復元には `Restore(ctx)`、ログアウトには `Logout(ctx)`、デバイスの解放には `ReleaseDevice(ctx)` を呼び出します。

### Python

```python
with connect_launch() as app:
    app.login(email, password)
    result = app.run_feature("export", export_report)
```

`restore()` は既存の安全なセッションを復元します。セッションがない場合はログイン画面を表示します。`logout()` はアカウントを消去し、`release_device()` は明示的にデバイスを解放します。同期ネットワーク操作でデスクトップのイベントループをブロックしないでください。

### C# / .NET

```csharp
await using var app = LaunchConnection.Open();
await app.Login(email, password);
await app.RunFeature("export", async () => {
    await ExportReport();
});
```

`await Restore()`、`await Logout()`、`await ReleaseDevice()` を使用します。アプリの稼働中は SDK のライフサイクルを維持し、非同期の画面フローを使用します。

### Java

```java
try (var app = LaunchConnection.open()) {
    app.login(email, passwordChars);
    app.runFeature("export", () -> exportReport());
}
```

パスワードには `char[]` を使用します。`restore()` はセッションがない場合に `NO_SESSION` エラーを返すため、ログイン画面を表示してください。他の失敗を認可と見なしてはいけません。`logout()` と `releaseDevice()` は異なる操作です。try-with-resources がクローズを処理します。

### JavaScript / Node.js / TypeScript

```javascript
const app = connectLaunch();
try {
  await app.login(email, password);
  const result = await app.runFeature('export', () => exportReport());
} finally {
  await app.close();
}
```

`restore()` はセッションがない場合に `null` を返します。正常に復元されてから業務処理を実行してください。`logout()` の真偽値はリモートのログアウトが確認されたかを示し、デバイス解放に失敗した場合はエラーを表示します。コードは Node.js、Electron のメインプロセス、または信頼できるバックエンドで実行します。ブラウザーと Electron のレンダラープロセスにはライセンス認証情報を保存しません。

### Rust

```rust
let mut app = connect_launch()?;
app.login(&email, &password)?;
let result = app.run_feature("export", || {
    export_report()?;
    Ok(())
})?;
app.close();
```

コールバックは `Result<T, Failure>` を返します。`restore()`、`logout()`、`release_device()` は結果を返すため、失敗を処理する必要があります。`Drop` もランタイムの終了を処理します。デフォルトのネイティブコアは build.rs がコンパイルしてリンクするため、公式 SDK を自分でリンクする必要はありません。

### Ruby

```ruby
app = connect_launch
begin
  app.login(email, password)
  result = app.run_feature('export') { export_report }
ensure
  app.close
end
```

`restore` はセッションを復元し、`logout` はログアウト、`release_device` はデバイスを解放します。保護対象の操作にはコードブロックを使用し、例外を成功に変換してはいけません。

### C

```c
static int export_action(void *context) {
    return export_report(context); /* Return 1 only on success. */
}

launch_application *app = connect_launch();
if (!app) return 0;
int ok = launch_application_login(app, email, password);
if (ok) ok = launch_application_run_feature(app, "export", export_action, context);
/* Check launch_application_error(app) on failure; never log credentials. */
launch_application_close(app);
return ok;
```

`launch_application_restore` は 3 状態です：`1` は復元済み、`0` はセッションなし、`-1` は失敗です。セッションがない場合に限り通常のログイン画面を表示します。拒否や例外を成功と見なしてはいけません。`logout` と `release_device` の戻り値も必ず確認してください。

CMake では Launch のみをインポートします：

```cmake
find_package(LicentivoLaunch CONFIG REQUIRED)
add_executable(myapp main.c)
licentivo_launch_link(myapp)
```

### C++

```cpp
auto app = connectLaunch();
app.Login(email.c_str(), password.c_str());
app.RunFeature("export", [&] { exportReport(); });
```

`Restore()`、`Logout()`、`ReleaseDevice()` は C++ の例外セマンティクスに従います。RAII デストラクターがクローズを処理します。CMake では `licentivo_launch_link(myapp CXX)` を使用し、Launch が SDK のリンクと配布パッケージ内のランタイムライブラリを自動的に処理します。

## ライフサイクル、安全なストレージ、エラー

接続オブジェクトの作成では初期化のみが行われます。アプリはログインまたは復元に成功し、各業務操作で機能保護コールバックを使用する必要があります。注文の支払い完了、セッションの存在、ボタンをクリックできることは、いずれも SDK の検証の代わりにはなりません。

デフォルトではセッションはメモリにのみ保存されます。ログインを記憶するには安全なストレージが必要です。Go、Python、C#、ネイティブ C/C++ は Windows の現在のユーザーの DPAPI を提供し、Java、Node、Rust、Ruby は呼び出し元の鍵を使用する AES-GCM ストレージを提供します。クロスプラットフォームアプリはシステムの認証情報ストアと連携してください。鍵と暗号文を同じ通常のディレクトリに置いてはいけません。

通常終了ではユーザーが明示的に記憶したセッションを保持し、ランタイムを停止します。ログアウト時はまず公式 SDK の統一ログアウトを呼び出し、その後 Launch 自体のアカウント記録を消去します。ReleaseDevice は同じ処理の互換エントリーポイントです。リモートでの取り消しが未完了の場合、解放成功と表示してはいけません。公式 SDK のキャッシュディレクトリやログアウト復旧ログを消去しないでください。Launch のセッション保護は公式 SDK のすべてのデバイスファイルが暗号化されていることを意味しないため、キャッシュディレクトリの権限を制限してください。

| ステータス | アプリの処理 |
| --- | --- |
| アカウントまたはパスワードの失敗 | アカウントの存在を漏らさず、一般的なログイン失敗を表示 |
| EMAIL_VERIFICATION_REQUIRED | ストアのメールアドレス認証を完了するよう案内 |
| ENTITLEMENT_PENDING | 同期中と表示し、パッケージの有限回の再試行と Retry-After に従って待機 |
| ENTITLEMENT_NOT_PURCHASED | 購入またはアカウント切り替えを案内 |
| ENTITLEMENT_EXPIRED | 更新を案内し、古い認証情報で拒否を回避しない |
| ENTITLEMENT_SUSPENDED | 保護された機能を停止し、事業者に連絡 |
| デバイス数の上限に到達 | デバイスの管理または明示的な解放を案内 |
| ネットワーク／HTTP 5xx | SDK が検証済みで、まだ有効期間内のオフラインライセンスのみ使用可能 |

明示的な 401/403/404、アカウントの不一致、キャンセル、レート制限をオフラインライセンスの成功に変えてはいけません。初回アクティベーションとオフラインを禁止するポリシーには引き続きネットワークが必要です。サーバーのドメイン／IP にアクセスできない場合は接続の問題を表示し、別のサイトに無断で接続してはいけません。

## 受け入れ確認と参考資料

実際のログイン、対象アカウントのライセンス、保護された操作、再起動後の復元、有効なオフライン利用とオフライン期限切れ、キャッシュの改ざん、ログアウト、アカウント切り替え、デバイス解放を検証します。本文では AI の使用を要求しません。テストツールと外部受け入れ確認の境界は [acceptance.md](/ja/launch-documents/acceptance/)、ローカルパッケージとビルド手順は [integration-packages.md](/ja/launch-documents/integration-packages/) を参照してください。

設定チェック、コード生成、ローカルテストは、実際の決済、ライセンス発行、公式サイトでのアクティベーションの成功を自動的に証明するものではありません。外部ストアと決済サンドボックスは設定後に個別に受け入れ確認が必要です。
