> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-SerialKey SDK for Game Engine API リファレンス

ゲームエンジン向け GS2-SerialKey SDK の モデルの仕様 と API のリファレンス



## モデル

### EzSerialKey

シリアルコード<br>

発行されたシリアルコードは1度のみ使用可能です。<br>
シリアルコードは「RPCLP-FP7N-NCDMJ-FLVA-IRI4」のような形式で発行され、データ長を変更することはできません。<br>
シリアルコード内にはキャンペーンの種類の情報も含まれており、シリアルコードを使用する際にはネームスペースを指定するだけで使用できます。

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| campaignModelName | string |  | ✓ |  |  ~ 128文字 | キャンペーン名<br>このシリアルコードが属するキャンペーンモデルの名前です。キャンペーン情報はシリアルコード自体に埋め込まれているため、コード使用時にはネームスペースを指定するだけで利用できます。 |
| metadata | string |  |  |  |  ~ 2048文字 | メタデータ<br>メタデータには任意の値を設定できます。<br>これらの値は GS2 の動作には影響しないため、ゲーム内で利用する情報の保存先として使用できます。 |
| code | string |  | ✓ |  |  ~ 48文字 | シリアルコード<br>「XXXXX-XXXX-XXXXX-XXXX-XXXX」形式のシリアルコード文字列です。各コードは一意で、キャンペーン識別情報が含まれています。コードの形式とデータ長は固定で変更できません。 |
| status | 文字列列挙型<br>enum {<br>"ACTIVE",<br>"USED",<br>"INACTIVE"<br>}<br> |  |  | "ACTIVE" |  | ステータス<br>このシリアルコードの現在の使用状態です。ユーザーが消費すると ACTIVE から USED に遷移します。二重使用を防ぐため楽観的ロックで保護されています。INACTIVE のコードは使用できません。"ACTIVE": 利用可能 / "USED": 使用済み / "INACTIVE": 無効（利用不可） /  |

**関連するメソッド:**
get - シリアルコードの状態を確認する
useSerialCode - シリアルコードを引き換える


---

### EzCampaignModel

キャンペーンモデル<br>

キャンペーンモデルはキャンペーンを定義し、シリアルコードと紐づけて管理するために使用されます。

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128文字 | キャンペーンモデル名 |
| metadata | string |  |  |  |  ~ 2048文字 | メタデータ<br>メタデータには任意の値を設定できます。<br>これらの値は GS2 の動作には影響しないため、ゲーム内で利用する情報の保存先として使用できます。 |
| enableCampaignCode | bool |  |  | false |  | キャンペーンコードによる引き換えを許可するか<br>有効にすると、個別のシリアルコードではなく共通のキャンペーンコード（キャンペーン名）を使って報酬を引き換えられるようになります。これにより、1つのコードを複数のユーザーが使用できます。 |

**関連するメソッド:**
getCampaignModel - 特定のシリアルコードキャンペーンの詳細を取得する
get - シリアルコードの状態を確認する
useSerialCode - シリアルコードを引き換える


---

## メソッド

### getCampaignModel

特定のシリアルコードキャンペーンの詳細を取得する<br>

キャンペーン名を指定して、設定を含む詳細を取得します。<br>

キャンペーンモデルは、同じ目的と設定を共有するシリアルコードのグループを定義します。<br>
たとえば「リリース記念コード」「雑誌プロモーションコード」「イベント配布コード」などを別々のキャンペーンとして管理できます。<br>

レスポンスには以下が含まれます:<br>
- キャンペーン名とメタデータ<br>
- キャンペーンが現在有効でコードの引き換えを受け付けているかどうか<br>

コード入力画面を表示する前にキャンペーンの詳細を確認する際に使います。たとえばプレイヤーにシリアルコードを入力させる前に、キャンペーンが有効かどうかを確認できます。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| campaignModelName | string |  | ✓|  |  ~ 128文字 | キャンペーンモデル名 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzCampaignModel](#ezcampaignmodel) | キャンペーンモデル|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).CampaignModel(
        campaignModelName: "campaign-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).CampaignModel(
        campaignModelName: "campaign-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->SerialKey->Namespace(
        "namespace-0001" // namespaceName
    )->CampaignModel(
        "campaign-0001" // campaignModelName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```


##### 値の変更イベントハンドリング




**Unity (UniTask)**
```csharp
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).CampaignModel(
        campaignModelName: "campaign-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).CampaignModel(
        campaignModelName: "campaign-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->SerialKey->Namespace(
        "namespace-0001" // namespaceName
    )->CampaignModel(
        "campaign-0001" // campaignModelName
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::SerialKey::Model::FCampaignModel> value) {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    Domain->Unsubscribe(CallbackId);

```


{{% alert title="Warning" color="warning" %}}このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。

ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。

そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
{{% /alert %}}

---

### get

シリアルコードの状態を確認する<br>

特定のシリアルコードの詳細を取得します。使用済みかどうか、どのキャンペーンに属しているかなどの情報が含まれます。<br>

コードの引き換え前後に状態を確認する際に使います。たとえば:<br>
- プレイヤーが既に使用されたコードを入力した場合に「このコードは既に使用されています」と表示する<br>
- プレイヤーが引き換えを確定する前にキャンペーン情報（コードで得られる報酬）を表示する<br>
- カスタマーサポート目的でコードを調べる<br>

コードは「XXXXX-XXXX-XXXXX-XXXX-XXXXX」のような形式です。<br>
レスポンスにはシリアルコードの詳細と、関連するキャンペーンモデルが含まれます。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| code | string |  | ✓|  |  ~ 48文字 | シリアルコード<br>「XXXXX-XXXX-XXXXX-XXXX-XXXX」形式のシリアルコード文字列です。各コードは一意で、キャンペーン識別情報が含まれています。コードの形式とデータ長は固定で変更できません。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzSerialKey](#ezserialkey) | シリアルコード|
| campaignModel | [EzCampaignModel](#ezcampaignmodel) | キャンペーンモデル|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).SerialKey(
        serialKeyCode: "code-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).SerialKey(
        serialKeyCode: "code-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->SerialKey->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->SerialKey(
        "code-0001" // serialKeyCode
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```


##### 値の変更イベントハンドリング




**Unity (UniTask)**
```csharp
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).SerialKey(
        serialKeyCode: "code-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).SerialKey(
        serialKeyCode: "code-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->SerialKey->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->SerialKey(
        "code-0001" // serialKeyCode
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::SerialKey::Model::FSerialKey> value) {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    Domain->Unsubscribe(CallbackId);

```


{{% alert title="Warning" color="warning" %}}このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。

ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。

そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
{{% /alert %}}

---

### useSerialCode

シリアルコードを引き換える<br>

シリアルコードを使用（消費）し、現在のプレイヤーによって引き換え済みとしてマークします。<br>
一度使用されたコードは、誰も再使用できません。<br>

ゲーム内の「シリアルコード入力」機能で使うメインAPIです。一般的な流れ:<br>
1. プレイヤーがゲーム内の「コード引き換え」画面を開く<br>
2. プレイヤーがシリアルコードを入力する（プロモーションカード、メール、Webサイトなどから入手したもの）<br>
3. ゲームが入力されたコードで UseSerialCode を呼び出す<br>
4. 成功した場合、コードが使用済みとなる — 報酬配布システムと組み合わせてプレイヤーに報酬を付与する<br>
5. コードが既に使用済みの場合、「使用済み」エラーが返される<br>
6. コードが存在しない場合、「コードが見つかりません」エラーが返される<br>

主な使い方:<br>
- グッズや雑誌に同梱されるプロモーションコード<br>
- イベントやSNSで配布されるギフトコード<br>
- 事前登録特典コード<br>
- コラボレーションキャンペーンコード

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| code | string |  | ✓|  |  ~ 48文字 | シリアルコード<br>「XXXXX-XXXX-XXXXX-XXXX-XXXX」形式のシリアルコード文字列です。各コードは一意で、キャンペーン識別情報が含まれています。コードの形式とデータ長は固定で変更できません。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzSerialKey](#ezserialkey) | シリアルコード|
| campaignModel | [EzCampaignModel](#ezcampaignmodel) | キャンペーンモデル|

#### Error

このAPIには特別な例外が定義されています。<br>
GS2-SDK for Game Engine ではゲーム内でハンドリングが必要そうなエラーは一般的な例外から派生した特殊化した例外を用意することでハンドリングしやすくしています。<br>
一般的なエラーの種類や、ハンドリング方法は [こちら]() のドキュメントを参考にしてください。

| 型 | 基底クラス | 説明 |
| --- | --- | --- |
| AlreadyUsedException | BadRequestException | 指定されたシリアルコードはすでに使用されています |
| CodeNotFoundException | NotFoundException | 指定されたシリアルコードは存在しません |

#### 実装例




**Unity (UniTask)**
```csharp

try {
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SerialKey(
        serialKeyCode: "code-0001"
    );
    var result = await domain.UseSerialCodeAsync(
        code: "code-0001"
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2SerialKey.Exception.AlreadyUsedException e) {
    // The specified serial code has already been used.
} catch(Gs2.Gs2SerialKey.Exception.CodeNotFoundException e) {
    // The specified serial code does not exist.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.SerialKey.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SerialKey(
        serialKeyCode: "code-0001"
    );
    var future = domain.UseSerialCodeFuture(
        code: "code-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2SerialKey.Exception.AlreadyUsedException)
        {
            // The specified serial code has already been used.
        }
        if (future.Error is Gs2.Gs2SerialKey.Exception.CodeNotFoundException)
        {
            // The specified serial code does not exist.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->SerialKey->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->SerialKey(
        "code-0001" // serialKeyCode
    );
    const auto Future = Domain->UseSerialCode(
        "code-0001" // code
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::SerialKey::Error::FAlreadyUsedError::Class))
        {
            // The specified serial code has already been used.
        }
        if (e->IsChildOf(Gs2::SerialKey::Error::FCodeNotFoundError::Class))
        {
            // The specified serial code does not exist.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```


---



