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

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

モデル

EzWallet

ウォレット

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

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

有効化条件必須デフォルト値の制限説明
slotint
0 ~ 100000000スロット番号
ウォレットスロットを識別します。プラットフォーム間の残高共有が許可されていない場合、異なるスロットを使用してプラットフォームごとに通貨を分けて管理できます(例:iOS用とAndroid用)。
summaryEzWalletSummary
ウォレットの状態
ウォレットの現在の残高サマリーで、有償通貨、無償通貨、合計額に分けて表示されます。入金トランザクションから算出されます。
sharedFreeCurrencybool
無償通貨を共有するか
このウォレットの無償通貨がすべてのスロット間で共有されるかどうかを示します。ウォレット作成時にネームスペースの設定から継承されます。
updatedAtlong
現在時刻最終更新日時
UNIX 時間・ミリ秒
※ サーバーが自動で設定

EzSubscribeTransaction

サブスクリプションの購入情報

ストアプラットフォームからのサブスクリプション購入レコードを表します。有効、トライアル、初回割引、猶予期間、解約、期限切れ、取り消しなどのライフサイクルを通じた詳細なサブスクリプションステータスを追跡します。各トランザクションは特定のストアプラットフォームとユーザーに紐づけられます。

有効化条件必須デフォルト値の制限説明
contentNamestring
~ 128文字ストア定期課金コンテンツモデル名
store文字列列挙型
enum {
  “AppleAppStore”,
  “GooglePlay”,
  “fake”
}
ストア
購入が行われたストアプラットフォームです。レシート検証に使用される検証方法を決定します。
定義説明
“AppleAppStore”Apple App Store
“GooglePlay”Google Play
“fake”Fake
transactionIdstring
~ 1024文字トランザクションID
ストアプラットフォームによって割り当てられた一意のトランザクション識別子です。同一購入の重複処理を防止するために使用されます。
statusDetail文字列列挙型
enum {
  “active@active”,
  “active@converted_from_trial”,
  “active@in_trial”,
  “active@in_intro_offer”,
  “grace@canceled”,
  “grace@grace_period”,
  “grace@on_hold”,
  “inactive@expired”,
  “inactive@revoked”
}
ステータス
詳細なサブスクリプションステータスです。簡易カテゴリ(active/grace/inactive)の後に具体的な状態が続きます。active 状態はサブスクリプションが利用可能であることを、grace 状態は支払いに問題があるが一時的にアクセス可能であることを、inactive 状態はサブスクリプションが無効であることを示します。
定義説明
“active@active”有効
“active@converted_from_trial”無料トライアルが終了し、有料プランに移行
“active@in_trial”無料トライアル期間中
“active@in_intro_offer”初回割引期間中
“grace@canceled”ユーザーが手動で解約済み
“grace@grace_period”支払いが失敗したが、猶予期間内
“grace@on_hold”支払いが失敗し、一定期間内に支払いが完了しなければ利用不可
“inactive@expired”サブスクリプションが期限切れになった
“inactive@revoked”払い戻しなどで強制的にキャンセルされた
expiresAtlong
有効期限
このサブスクリプショントランザクションが期限切れになる日時です。ストアプラットフォームによってサブスクリプションが更新されると更新されます。

EzSubscriptionStatus

サブスクリプションの契約状況

特定のサブスクリプションコンテンツに対するユーザーのサブスクリプション契約状況を追跡します。詳細なサブスクリプショントランザクションの状態から導出された簡易的な有効/無効ステータスと、有効期限、関連するサブスクリプショントランザクションのリストを提供します。

有効化条件必須デフォルト値の制限説明
contentNamestring
~ 128文字ストア定期課金コンテンツモデル名
userIdstring~ 128文字ユーザーID
status文字列列挙型
enum {
  “active”,
  “inactive”
}
ステータス
簡易的なサブスクリプションステータスです。“active” は有効、トライアル、初回割引、猶予期間の状態を含みます。“inactive” は期限切れと取り消しの状態を含みます。
定義説明
“active”有効
“inactive”無効
expiresAtlong
有効期限
サブスクリプションが期限切れになる日時です。サブスクリプションが更新されたりステータスが変化した際に更新されます。
detailList<EzSubscribeTransaction>[]0 ~ 100 items契約状況の詳細
このサブスクリプションに関連するサブスクリプショントランザクションのリストです。各トランザクションはストアプラットフォームからの購入レコードで、詳細なステータス情報(有効、トライアル、猶予期間、期限切れ、取り消しなど)を持ちます。

EzStoreContentModel

ストアコンテンツモデル

各種ストアプラットフォームのコンテンツを格納するモデルです。

有効化条件必須デフォルト値の制限説明
namestring
~ 128文字ストアコンテンツモデル名
metadatastring~ 1024文字メタデータ
メタデータには任意の値を設定できます。
これらの値は GS2 の動作には影響しないため、ゲーム内で利用する情報の保存先として使用できます。
appleAppStoreEzAppleAppStoreContentApple AppStore のコンテンツ
このストアコンテンツの Apple App Store 商品情報(プロダクトID)です。レシート検証時に購入された商品との照合に使用されます。
googlePlayEzGooglePlayContentGoogle Play のコンテンツ
このストアコンテンツの Google Play 商品情報(プロダクトID)です。レシート検証時に購入された商品との照合に使用されます。

EzWalletSummary

ウォレットの状態

ウォレットの通貨残高のサマリービューで、有償と無償の金額を分離しています。ウォレット内のすべての入金トランザクションを価格に基づいて集計して算出されます(価格 > 0 は有償、価格 = 0 は無償)。

有効化条件必須デフォルト値の制限説明
paidint00 ~ 2147483646有償通貨
実際のお金で購入された通貨の合計量です(価格 > 0 の入金トランザクション)。
freeint00 ~ 2147483646無償通貨
無償で入手した通貨の合計量です(価格 = 0 の入金トランザクション)。ログインボーナスやイベント報酬などが含まれます。
totalint00 ~ 2147483646総数
通貨残高の合計(有償 + 無償)。ウォレットで利用可能な全体量を表します。

EzDepositTransaction

入金トランザクション

ウォレット内の単一の入金レコードを表します。有償の入金(価格 > 0)は正確な返金計算と資金決済法への準拠のために単価ごとに追跡されます。無償の入金(価格 = 0)は別途追跡されます。出金時には、ネームスペースの通貨消費優先度に基づいて入金トランザクションが消費されます。

有効化条件必須デフォルト値の制限説明
pricedouble
0.0 ~ 100000000.0購入価格
この入金に対して現地通貨で支払われた実際の金額です。0 は無償通貨を示します。返金目的の単価計算に使用されます。
currencystring{price} > 0
✓※
~ 8文字通貨コード
実際の支払いのISO通貨コード(例:“JPY”、“USD”)です。有償の入金(価格 > 0)の場合のみ適用されます。

※ price が 0 より大きければ 必須
countint
0 ~ 2147483646課金通貨の数量
この入金における仮想通貨の単位数です。ウォレットから出金されると減少します。

EzAppleAppStoreContent

Apple AppStore のコンテンツ

アプリ内課金商品に対応する Apple App Store のプロダクトIDを含みます。レシート検証時の照合に使用されます。

有効化条件必須デフォルト値の制限説明
productIdstring~ 1024文字プロダクトID
このアプリ内課金アイテムについて App Store Connect に登録されている Apple App Store のプロダクト識別子です。

EzGooglePlayContent

Google Play のコンテンツ

アプリ内課金商品に対応する Google Play のプロダクトIDを含みます。レシート検証時の照合に使用されます。

有効化条件必須デフォルト値の制限説明
productIdstring~ 1024文字プロダクトID
このアプリ内課金アイテムについて Google Play Console に登録されている Google Play のプロダクト識別子です。

EzAppleAppStoreSubscriptionContent

Apple AppStore の期間課金コンテンツ

サブスクリプションベースの商品の Apple App Store サブスクリプショングループ識別子を含みます。自動更新サブスクリプションの管理と検証に使用されます。

有効化条件必須デフォルト値の制限説明
subscriptionGroupIdentifierstring~ 64文字サブスクリプショングループID
App Store Connect に登録されたサブスクリプショングループ識別子です。同じグループ内のサブスクリプションは相互排他的で、ユーザーは同時に1つしか契約できません。

EzGooglePlaySubscriptionContent

Google Play の期間課金コンテンツ

サブスクリプションベースの商品の Google Play プロダクトIDを含みます。Google Play での自動更新サブスクリプションの管理と検証に使用されます。

有効化条件必須デフォルト値の制限説明
productIdstring~ 1024文字プロダクトID

メソッド

get

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

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

Request

有効化条件必須デフォルト値の制限説明
namespaceNamestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
gameSessionGameSession
GameSession
slotint
0 ~ 100000000スロット番号
ウォレットスロットを識別します。プラットフォーム間の残高共有が許可されていない場合、異なるスロットを使用してプラットフォームごとに通貨を分けて管理できます(例:iOS用とAndroid用)。

Result

説明
itemEzWalletウォレット

実装例

    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Wallet(
        0 // slot
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
値の変更イベントハンドリング
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

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

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

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

list

プレイヤーの課金通貨ウォレット一覧を取得する

プレイヤーが現在持つすべてのウォレットを取得します。各ウォレットはそれぞれ独立した残高を持ち、有償通貨と無償通貨が別々に管理されます。
「有償」通貨はプレイヤーがリアルマネーで購入したもの(例: 100ジェムを¥120で購入)、「無償」通貨はゲームプレイで獲得したもの(例: イベント報酬、ログインボーナス)です。
プレイヤーの通貨の全体像を表示するのに使います。たとえば、通貨管理画面で全ウォレットスロットとその残高を一覧表示する場合に便利です。

Request

有効化条件必須デフォルト値の制限説明
namespaceNamestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
gameSessionGameSession
GameSession

Result

説明
itemsList<EzWallet>ウォレットのリスト
nextPageTokenstringリストの続きを取得するためのページトークン

実装例

    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.WalletsAsync(
    ).ToListAsync();
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Wallets(
    );
    List<EzWallet> items = new List<EzWallet>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Wallets(
    );
    TArray<Gs2::UE5::Money2::Model::FEzWalletPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
値の変更イベントハンドリング
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeWallets(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeWallets(callbackId);
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeWallets(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeWallets(callbackId);
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->SubscribeWallets(
        []() {
            // リストの要素が変化した時に呼び出される
        }
    );

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

withdraw

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

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

Request

有効化条件必須デフォルト値の制限説明
namespaceNamestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
gameSessionGameSession
GameSession
slotint
0 ~ 100000000スロット番号
ウォレットスロットを識別します。プラットフォーム間の残高共有が許可されていない場合、異なるスロットを使用してプラットフォームごとに通貨を分けて管理できます(例:iOS用とAndroid用)。
withdrawCountint
1 ~ 2147483646消費する課金通貨の数量
paidOnlyboolfalse有償通貨のみを対象とするか

Result

説明
itemEzWallet消費後のウォレット
withdrawTransactionsList<EzDepositTransaction>消費した入金トランザクションリスト

Error

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

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

実装例

try {
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var result = await domain.WithdrawAsync(
        withdrawCount: 50,
        paidOnly: null
    );
    var item = await result.ModelAsync();
    var withdrawTransactions = result.WithdrawTransactions;
} catch(Gs2.Gs2Money2.Exception.ConflictException e) {
    // The wallet operation process conflicted. Retry required.
} catch(Gs2.Gs2Money2.Exception.InsufficientException e) {
    // Wallet balance is insufficient.
}
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Wallet(
        slot: 0
    );
    var future = domain.WithdrawFuture(
        withdrawCount: 50,
        paidOnly: null
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Money2.Exception.ConflictException)
        {
            // The wallet operation process conflicted. Retry required.
        }
        if (future.Error is Gs2.Gs2Money2.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 withdrawTransactions = future.Result.WithdrawTransactions;
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Wallet(
        0 // slot
    );
    const auto Future = Domain->Withdraw(
        50 // withdrawCount
        // paidOnly
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Money2::Error::FConflictError::Class))
        {
            // The wallet operation process conflicted. Retry required.
        }
        if (e->IsChildOf(Gs2::Money2::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 WithdrawTransactions = Result->WithdrawTransactions;

allocateSubscriptionStatus

ストアレシートを使ってサブスクリプションを登録する

App Store や Google Play のレシートを検証して、サブスクリプション購入をプレイヤーに紐づけます。
プレイヤーが端末でサブスクリプション(例: 「月額パス」)を購入した後、ストアレシートをこのAPIに渡してサーバー側でサブスクリプションを有効にします。
ストア購入をプレイヤーのアカウントに結びつけるための重要なステップです。この呼び出しがないと、サーバーはプレイヤーが契約したことを認識できません。
購入フローで使います。たとえば、アプリ内課金ダイアログでプレイヤーが「月額パス」を購入した後、レシートを送信してVIP特典を有効にする、といった場合です。

Request

有効化条件必須デフォルト値の制限説明
namespaceNamestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
gameSessionGameSessionGameSession
receiptstring
~ 1024文字レシート

Result

説明
itemEzSubscriptionStatusサブスクリプションの契約状況

Error

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

基底クラス説明
AlreadyUsedExceptionBadRequestExceptionすでにその期間課金契約は他のユーザーによって利用されています

実装例

try {
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.AllocateSubscriptionStatusAsync(
        receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}"
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Money2.Exception.AlreadyUsedException e) {
    // The subscription contract for that period has already been used by another user.
}
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.AllocateSubscriptionStatusFuture(
        receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}"
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Money2.Exception.AlreadyUsedException)
        {
            // The subscription contract for that period has already been used by another user.
        }
        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;
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->AllocateSubscriptionStatus(
        "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" // receipt
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Money2::Error::FAlreadyUsedError::Class))
        {
            // The subscription contract for that period has already been used by another user.
        }
        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();

getSubscriptionStatus

特定のサブスクリプション契約状況を取得する

コンテンツ名を指定して、特定のサブスクリプションの契約状況を取得します。
ステータスには、プレイヤーが現在契約中かどうかと、有効期限などの関連情報が含まれます。
プレイヤーが特定のサブスクリプションを持っているか確認するのに使います。たとえば、デイリーボーナス報酬を付与する前に「月額パス」が有効か確認したり、プレイヤープロフィールに「VIPメンバーシップ: 有効」と表示する場合に便利です。

Request

有効化条件必須デフォルト値の制限説明
namespaceNamestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
gameSessionGameSessionGameSession
contentNamestring
~ 128文字ストア定期課金コンテンツモデル名

Result

説明
itemEzSubscriptionStatusサブスクリプションの契約状況

実装例

    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SubscriptionStatus(
        contentName: "content-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SubscriptionStatus(
        contentName: "content-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->SubscriptionStatus(
        "content-0001" // contentName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
値の変更イベントハンドリング
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SubscriptionStatus(
        contentName: "content-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SubscriptionStatus(
        contentName: "content-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->SubscriptionStatus(
        "content-0001" // contentName
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Money2::Model::FSubscriptionStatus> value) {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

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

listSubscriptionStatuses

プレイヤーのサブスクリプション契約状況一覧を取得する

プレイヤーが契約している可能性のあるすべてのサブスクリプションコンテンツの契約状況を取得します。
サブスクリプションとは、App Store や Google Play で購入する「月額パス」や「VIPメンバーシップ」のような定期購入です。
各ステータスは、プレイヤーがそのコンテンツを現在契約しているかどうかを示します。
サブスクリプションの概要を表示するのに使います。たとえば、メンバーシップ画面で「月額パス: 有効(3月15日まで)」「VIPメンバーシップ: 未契約」のように表示するのに便利です。

Request

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

Result

説明
itemsList<EzSubscriptionStatus>サブスクリプションの契約状況のリスト

実装例

    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.SubscriptionStatusesAsync(
    ).ToListAsync();
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.SubscriptionStatuses(
    );
    List<EzSubscriptionStatus> items = new List<EzSubscriptionStatus>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->SubscriptionStatuses(
    );
    TArray<Gs2::UE5::Money2::Model::FEzSubscriptionStatusPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
値の変更イベントハンドリング
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeSubscriptionStatuses(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeSubscriptionStatuses(callbackId);
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeSubscriptionStatuses(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeSubscriptionStatuses(callbackId);
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->SubscribeSubscriptionStatuses(
        []() {
            // リストの要素が変化した時に呼び出される
        }
    );

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

takeOverSubscriptionStatus

他のアカウントからこのプレイヤーにサブスクリプションを移行する

現在別のプレイヤーアカウントに紐づいているサブスクリプションを、このプレイヤーのアカウントに移動します。
プレイヤーがアカウント移行を行う場合に使います。たとえば、機種変更で新しいアカウントを作成した場合、ストアレシートを使って旧アカウントの「月額パス」サブスクリプションを新アカウントに移行できます。
サブスクリプションは旧アカウントから解除され新アカウントに紐づけられるため、旧アカウントではサブスクリプション特典を受けられなくなります。
アカウント移行フローで使います。たとえば、プレイヤーが新アカウントにログインし、移行を確認した後に呼び出します。

Request

有効化条件必須デフォルト値の制限説明
namespaceNamestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
gameSessionGameSessionGameSession
receiptstring
~ 1024文字レシート

Result

説明
itemEzSubscriptionStatusサブスクリプションの契約状況

Error

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

基底クラス説明
LockPeriodNotElapsedExceptionBadRequestException前回のユーザーの付け替えから、ロック期間が経過していません

実装例

try {
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.TakeOverSubscriptionStatusAsync(
        receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}"
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Money2.Exception.LockPeriodNotElapsedException e) {
    // The lock period has not elapsed since the last user change.
}
    var domain = gs2.Money2.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.TakeOverSubscriptionStatusFuture(
        receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}"
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Money2.Exception.LockPeriodNotElapsedException)
        {
            // The lock period has not elapsed since the last user change.
        }
        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;
    const auto Domain = Gs2->Money2->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->TakeOverSubscriptionStatus(
        "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" // receipt
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Money2::Error::FLockPeriodNotElapsedError::Class))
        {
            // The lock period has not elapsed since the last user change.
        }
        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();

イベントハンドラ

OnChangeSubscriptionStatus

期間課金の契約状況が変化したときに使用するプッシュ通知

名前説明
namespaceNamestringネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
userIdstringユーザーID
contentNamestringストア定期課金コンテンツモデル名

実装例

    gs2.Money2.OnChangeSubscriptionStatus += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var contentName = notification.ContentName;
    };
    gs2.Money2.OnChangeSubscriptionStatus += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var contentName = notification.ContentName;
    };
    Gs2->Money2->OnChangeSubscriptionStatus().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto UserId = Notification->UserIdValue;
        const auto ContentName = Notification->ContentNameValue;
    });