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

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

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



## モデル

### EzWallet

ウォレット<br>

ウォレット内の通貨は大きく有償で購入した通貨と、無償で入手した通貨が分けて管理されます。<br>
有償で購入した通貨は更に購入時の単価毎に管理され、サービス終了になってしまった際の返金や資金決済法に該当するだけの残高が存在するかが集計できます。<br>

ウォレットにはスロットがあり、スロットごとに異なる残高を管理できます。<br>
プラットフォームをまたいで残高を共有できない場合にはプラットフォーム毎に異なるスロットを利用することで分けて管理することができます。<br>
その際に無償で入手した通貨は全てのプラットフォームで共通した値を利用することもできます。

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| slot | int |  | ✓ |  | 0 ~ 100000000 | スロット番号<br/>プラットフォームやコンテキストごとにウォレット残高を分離するための識別子。<br/>異なるスロットにより、別々の有償通貨プールを管理できます（例: iOS購入はスロット0、Androidはスロット1）。<br/>無償通貨はネームスペースの shareFree 設定により、全スロット間で共有することもできます。 |
| paid | int |  |  | 0 | 0 ~ 2147483646 | 有償通貨所持量<br/>このウォレットスロット内の有償（購入済み）通貨の合計量。<br/>単価が0でないすべての WalletDetail エントリの合計です。<br/>ストア購入による入金で増加し、消費優先度に従った出金で減少します。 |
| free | int |  |  | 0 | 0 ~ 2147483646 | 無償通貨所持量<br/>このウォレットスロット内の無償（付与された）通貨の合計量。<br/>単価が0の WalletDetail エントリに対応します。<br/>ネームスペースで shareFree が有効な場合、この値はスロット0から全ウォレットスロットに同期されます。 |
| shareFree | bool |  |  | false |  | 無償通貨の共有<br/>このウォレットの無償通貨が全スロット間で共有されるかどうか。<br/>この値はウォレット作成時にネームスペース設定から継承されます。<br/>true の場合、無償通貨がスロット0から他のすべてのウォレットスロットに同期されます。 |
| updatedAt | long |  | ※ | 現在時刻 |  | 最終更新日時<br/>UNIX 時間・ミリ秒<br/>※ サーバーが自動で設定 |


**関連するメソッド:**
get - プレイヤーの課金通貨ウォレットの残高を取得する
withdraw - プレイヤーのウォレットから課金通貨を消費する


---

## メソッド

### get

プレイヤーの課金通貨ウォレットの残高を取得する<br>

指定したスロットのプレイヤーのウォレットを取得し、有償通貨と無償通貨それぞれの現在の残高を確認できます。<br>
「有償」通貨はプレイヤーがリアルマネーで購入したもの（例: 100ジェムを¥120で購入）、「無償」通貨はゲームプレイで獲得したもの（例: イベント報酬、ログインボーナス）です。<br>
一部の機能で有償通貨のみを要求する場合があるため（例: 特定のガチャや特別オファー）、別々に管理されています。<br>
プレイヤーの通貨残高を表示するのに使います。たとえば、ショップ画面やヘッダーUIで「ジェム: 350（有償: 100、無償: 250）」のように表示するのに便利です。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br/>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| slot | int |  | ✓|  | 0 ~ 100000000 | スロット番号<br/>プラットフォームやコンテキストごとにウォレット残高を分離するための識別子。<br/>異なるスロットにより、別々の有償通貨プールを管理できます（例: iOS購入はスロット0、Androidはスロット1）。<br/>無償通貨はネームスペースの shareFree 設定により、全スロット間で共有することもできます。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzWallet](#ezwallet) | ウォレット|

#### 実装例



**Unity (UniTask)**
```csharp
    var domain = gs2.Money.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Money.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Money->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Wallet(
        0 // slot
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```


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




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

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

```

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

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

```

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

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

```


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

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

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

---

### withdraw

プレイヤーのウォレットから課金通貨を消費する<br>

プレイヤーのウォレットから指定した量の課金通貨を差し引きます。<br>
デフォルト（paidOnly = false）では、無償通貨が先に消費され、不足分は有償通貨から消費されます。これにより、プレイヤーは購入した通貨を使う前に無償通貨を使い切ることができます。<br>
paidOnly を true にすると、有償通貨のみが消費されます。法律上有償通貨のみを使用しなければならない機能（例: 一部地域の有償限定ガチャ）に必要です。<br>
プレイヤーが課金通貨で購入する際に使います。たとえば、特別なアイテムの購入やガチャを引くためにジェム100個を消費する、といった場合です。<br>
注意: GS2-Showcase を通じた商品購入の対価として通貨を消費する場合は、自動的に処理されるため、このAPIを呼ぶ必要はありません。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br/>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| slot | int |  | ✓|  | 0 ~ 100000000 | スロット番号<br/>プラットフォームやコンテキストごとにウォレット残高を分離するための識別子。<br/>異なるスロットにより、別々の有償通貨プールを管理できます（例: iOS購入はスロット0、Androidはスロット1）。<br/>無償通貨はネームスペースの shareFree 設定により、全スロット間で共有することもできます。 |
| count | int |  | ✓|  | 1 ~ 2147483646 | 消費する課金通貨の数量 |
| paidOnly | bool |  | | false |  | 有償通貨のみを対象とするか |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzWallet](#ezwallet) | 消費後のウォレット|
| price | float | 消費した通貨の価格|

#### Error

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

| 型 | 基底クラス | 説明 |
| --- | --- | --- |
| ConflictException | ConflictException | ウォレットの操作処理が衝突しました。リトライが必要です |
| InsufficientException | BadRequestException | ウォレットの残高が不足しています |

#### 実装例



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

try {
    var domain = gs2.Money.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var result = await domain.WithdrawAsync(
        count: 50,
        paidOnly: null
    );
    var item = await result.ModelAsync();
    var price = result.Price;
} catch(Gs2.Gs2Money.Exception.ConflictException e) {
    // The wallet operation process conflicted. Retry required.
} catch(Gs2.Gs2Money.Exception.InsufficientException e) {
    // Wallet balance is insufficient.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Money.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var future = domain.WithdrawFuture(
        count: 50,
        paidOnly: null
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Money.Exception.ConflictException)
        {
            // The wallet operation process conflicted. Retry required.
        }
        if (future.Error is Gs2.Gs2Money.Exception.InsufficientException)
        {
            // Wallet balance is insufficient.
        }
        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;
    var price = future.Result.Price;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Money->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Wallet(
        0 // slot
    );
    const auto Future = Domain->Withdraw(
        50 // count
        // paidOnly
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Money::Error::FConflictError::Class))
        {
            // The wallet operation process conflicted. Retry required.
        }
        if (e->IsChildOf(Gs2::Money::Error::FInsufficientError::Class))
        {
            // Wallet balance is insufficient.
        }
        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();
    const auto Price = Result->Price;

```


---



