GS2-Money2 Deploy/CDK リファレンス

GS2-Deployのスタックを作成する際に使用するテンプレートのフォーマットと、CDKによる各種言語のテンプレート出力の実装例

エンティティ

Deploy処理で操作の対象となるリソース

Namespace

ネームスペース

ネームスペースは、一つのプロジェクト内で同じサービスを異なる用途で複数利用するためのエンティティです。
GS2 の各サービスはネームスペース単位で管理されます。ネームスペースが異なれば、同じサービスでも完全に独立したデータ空間として扱われます。

そのため、各サービスの利用を開始するにあたってネームスペースを作成する必要があります。

Request

リソースの生成・更新リクエスト

型 有効化条件 必須 デフォルト 値の制限 説明
name string
✓
~ 128文字 ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
currencyUsagePriority 文字列列挙型
enum {
  “PrioritizeFree”,
  “PrioritizePaid”
}
✓
消費優先度
ウォレットから出金する際に有償通貨と無償通貨のどちらを先に消費するかを決定します。PrioritizeFree は無償通貨を優先し、PrioritizePaid は有償通貨を優先します。
定義説明
PrioritizeFree無償通貨を優先して使用する
PrioritizePaid有償通貨を優先して使用する
description string ~ 1024文字 説明文
transactionSettingV2 TransactionSettingV2 トランザクション設定(V2)
このネームスペースが発行するトランザクションをどのように実行するかを決める設定です。設定する項目は、実行に使用する GS2-Distributor のネームスペースと、トランザクションに含まれるアクションを 1 件ずつ実行して先に実行されたアクションの結果を後続のアクションから使えるようにするか、まとめて同時に実行してレスポンスタイムを短くするか、の 2 つだけです。
新しく作成するネームスペースではこちらを設定してください。これに置き換えられて非推奨となった transactionSetting は、こちらが設定されていない間だけ使用されます。
sharedFreeCurrency bool
✓
無償通貨を異なるスロットで共有するか
有効にすると、無償通貨の残高がすべてのウォレットスロット(プラットフォーム)間で共有されます。有償通貨はスロットごとに分離されたままです。この設定はネームスペース作成時のみ設定可能で、後から変更できません。
platformSetting PlatformSetting
✓
ストアプラットフォーム設定
サポートされている各ストアプラットフォーム(Apple App Store、Google Play、テスト用Fake)の設定です。各プラットフォームでのレシート検証に必要な認証情報やキーを含みます。
depositBalanceScript ScriptSetting ウォレット残高を加算したときに実行するスクリプトの設定
Script トリガーリファレンス - deposit
withdrawBalanceScript ScriptSetting ウォレット残高を消費したときに実行するスクリプトの設定
Script トリガーリファレンス - withdraw
verifyReceiptScript ScriptSetting レシート検証を実行したときに実行するスクリプトの設定
Script トリガーリファレンス - verifyReceipt
subscribeScript string ~ 1024文字 期間課金を新規契約するときに実行する GS2-Script スクリプトGRN(ユーザーの紐づけ変更時には呼び出されない/一度契約失効後に再度契約した場合も呼び出される)
Script トリガーリファレンス - subscribe
renewScript string ~ 1024文字 期間課金を更新するときに実行する GS2-Script スクリプトGRN
Script トリガーリファレンス - renew
unsubscribeScript string ~ 1024文字 期間課金を解約するときに実行する GS2-Script スクリプトGRN(ユーザーの紐づけ変更時には呼び出されない)
Script トリガーリファレンス - unsubscribe
takeOverScript ScriptSetting 期間課金に紐づけられたユーザーを変更するときに実行するスクリプトの設定
Script トリガーリファレンス - takeOver
changeSubscriptionStatusNotification NotificationSetting 期間課金の契約状況が変化したときのプッシュ通知
サブスクリプションのステータスが変化した際(有効化、更新、解約、期限切れ、取り消しなど)に GS2-Gateway を通じて配信されるプッシュ通知の設定です。ゲームクライアントがサブスクリプション状態の変化にリアルタイムで対応できるようにします。
logSetting LogSetting ログの出力設定
このネームスペースに対するAPIリクエスト・レスポンスログの出力先となる GS2-Log のネームスペースを指定します。入金、出金、レシート検証、サブスクリプションイベントの追跡に役立ちます。

GetAttr

!GetAttrタグで取得可能なリソースの生成結果

型 説明
Item Namespace 作成したネームスペース

実装例

Type: GS2::Money2::Namespace
Properties:
  Name: namespace-0001
  CurrencyUsagePriority: PrioritizeFree
  Description: null
  TransactionSettingV2: null
  SharedFreeCurrency: false
  PlatformSetting: {}
  DepositBalanceScript: null
  WithdrawBalanceScript: null
  VerifyReceiptScript: null
  SubscribeScript: null
  RenewScript: null
  UnsubscribeScript: null
  TakeOverScript: null
  ChangeSubscriptionStatusNotification: null
  LogSetting: 
    LoggingNamespaceId: grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001
import (
    "github.com/gs2io/gs2-golang-cdk/core"
    "github.com/gs2io/gs2-golang-cdk/money2"
)


SampleStack := core.NewStack()
money2.NewNamespace(
    &SampleStack,
    "namespace-0001",
    money2.NamespaceCurrencyUsagePriorityPrioritizeFree,
    false,
    money2.PlatformSetting{
        AppleAppStore: nil,
        GooglePlay:    nil,
        Fake:          nil,
    },
    money2.NamespaceOptions{
        LogSetting: &core.LogSetting{
            LoggingNamespaceId: "grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001",
        },
    },
)

println(SampleStack.Yaml())  // Generate Template
class SampleStack extends \Gs2Cdk\Core\Model\Stack
{
    function __construct() {
        parent::__construct();
        new \Gs2Cdk\Money2\Model\Namespace_(
            stack: $this,
            name: "namespace-0001",
            currencyUsagePriority: \Gs2Cdk\Money2\Model\Enums\NamespaceCurrencyUsagePriority::PRIORITIZE_FREE,
            sharedFreeCurrency: false,
            platformSetting: new \Gs2Cdk\Money2\Model\PlatformSetting(),
            options: new \Gs2Cdk\Money2\Model\Options\NamespaceOptions(
                logSetting: new \Gs2Cdk\Core\Model\LogSetting(
                    loggingNamespaceId: "grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001"
                )
            )
        );
    }
}

print((new SampleStack())->yaml());  // Generate Template
class SampleStack extends io.gs2.cdk.core.model.Stack
{
    public SampleStack() {
        super();
        new io.gs2.cdk.money2.model.Namespace(
                this,
                "namespace-0001",
                io.gs2.cdk.money2.model.enums.NamespaceCurrencyUsagePriority.PRIORITIZE_FREE,
                false,
                new io.gs2.cdk.money2.model.PlatformSetting(),
                new io.gs2.cdk.money2.model.options.NamespaceOptions()
                        .withLogSetting(new io.gs2.cdk.core.model.LogSetting(
                            "grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001"
                        ))
        );
    }
}

System.out.println(new SampleStack().yaml());  // Generate Template
public class SampleStack : Gs2Cdk.Core.Model.Stack
{
    public SampleStack() {
        new Gs2Cdk.Gs2Money2.Model.Namespace(
            stack: this,
            name: "namespace-0001",
            currencyUsagePriority: Gs2Cdk.Gs2Money2.Model.Enums.NamespaceCurrencyUsagePriority.PrioritizeFree,
            sharedFreeCurrency: false,
            platformSetting: new Gs2Cdk.Gs2Money2.Model.PlatformSetting(),
            options: new Gs2Cdk.Gs2Money2.Model.Options.NamespaceOptions
            {
                logSetting = new Gs2Cdk.Core.Model.LogSetting(
                    loggingNamespaceId: "grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001"
                )
            }
        );
    }
}

Debug.Log(new SampleStack().Yaml());  // Generate Template
import core from "@/gs2cdk/core";
import money2 from "@/gs2cdk/money2";

class SampleStack extends core.Stack
{
    public constructor() {
        super();
        new money2.model.Namespace(
            this,
            "namespace-0001",
            money2.model.NamespaceCurrencyUsagePriority.PRIORITIZE_FREE,
            false,
            new money2.model.PlatformSetting(),
            {
                logSetting: new core.LogSetting(
                    "grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001"
                )
            }
        );
    }
}

console.log(new SampleStack().yaml());  // Generate Template
from gs2_cdk import Stack, core, money2

class SampleStack(Stack):

    def __init__(self):
        super().__init__()
        money2.Namespace(
            stack=self,
            name='namespace-0001',
            currency_usage_priority=money2.NamespaceCurrencyUsagePriority.PRIORITIZE_FREE,
            shared_free_currency=False,
            platform_setting=money2.PlatformSetting(),
            options=money2.NamespaceOptions(
                log_setting=core.LogSetting(
                    logging_namespace_id='grn:gs2:ap-northeast-1:YourOwnerId:log:namespace-0001',
                ),
            ),
        )

print(SampleStack().yaml())  # Generate Template

TransactionSettingV2

トランザクション設定(V2)

トランザクション設定(V2)は、ネームスペースが発行するトランザクションをどのように実行するかを決める設定です。

設定する項目は次の 2 つだけです。

  • distributorNamespaceId: トランザクションの実行に使用する GS2-Distributor のネームスペース
  • enableParallelExecution: トランザクションに含まれるアクションを 1 件ずつ実行するか、まとめて同時に実行するか

どちらを選んでも、トランザクションは発行された時点でサーバーが実行し、成否はトランザクション全体でひとつになります。あるアクションが失敗した場合は、それまでに実行されたアクションもろとも取り消され、1 つも反映されません。トランザクションの実行方法に関するそれ以外の項目は推奨構成に固定されているため、設定する必要はありません。

1 件ずつ実行する場合(既定 / enableParallelExecution が false)、各アクションは先に実行されたアクションの書き込みを踏まえて動作します。アクションは verify・consume・acquire の順に実行され、次のことができます。

  • 1 つのトランザクションの中で、同じ行を複数のアクションから更新する(まとめて同時に実行する場合は失敗します)
  • 先に実行されたアクションの書き込みを読む。List や Query の結果でも、入れ子になったトランザクションの内側でも読めます
  • %{Gs2Xxx:ActionName.path[0].field} を使って、先に実行された verify や consume アクションの結果を、後続の verify・consume・acquire アクションの引数として渡す

代わりに、レスポンスタイムは各アクションの実行時間の合計になり、1 つのトランザクションに含められるアクションは最大 20 件になります。また、各フェーズの中での実行順はアクション名、次に対象リソースの順で決まるため、リクエストに並べた順序で実行順を指定することはできません。実行は最初に失敗したアクションで停止します。

まとめて同時に実行する場合(enableParallelExecution が true)、アクションは同一のデータスナップショットに対して並列に実行されるため、レスポンスタイムは最も遅いアクション 1 件分で済み、アクション数の上限もありません。

代わりに、あるアクションから他のアクションの書き込みを読むことはできず、同じ行を 2 つのアクションが書き換えるとトランザクションは database:transaction:same.resource(400)で失敗します。同一トランザクション内で同じデータを 2 つ以上のアクションが書き換えないことを保証できる場合にだけ選択してください。%{...} は先行するフェーズ(verify → consume → acquire の順)の結果だけを参照でき、同じフェーズ内のアクションへの参照は解決されずにそのまま残ります。%{...} を含むフェーズは先行するフェーズの完了を待ってから実行されるため、その分だけレスポンスタイムが伸びます。

トランザクション設定は、トランザクション設定(V2)に置き換えられた非推奨の設定で、トランザクション設定(V2)が存在しなかった頃に作成されたネームスペースのために残されています。トランザクション設定(V2)が設定されていない間だけ適用され、トランザクション設定(V2)を設定するとそちらが優先されます。トランザクション設定で可能だった、トランザクションをクライアント実行のスタンプシートとして実行する・GS2-Distributor による AutoRun の非同期実行を行う・入手アクションを GS2-JobQueue に畳み込む、という 3 つの挙動は、こちらではあえて提供していません。

型 有効化条件 必須 デフォルト 値の制限 説明
distributorNamespaceId string “grn:gs2:{region}:{ownerId}:distributor:default” ~ 1024文字 トランザクションの実行に使用する GS2-Distributor ネームスペース GRN
enableParallelExecution bool false アクションを直列ではなく並列に実行するか

ScriptSetting

スクリプト設定

GS2 ではマイクロサービスのイベントに関連づけて、カスタムスクリプトを実行することができます。
このモデルは、スクリプトの実行をトリガーするための設定を保持します。

スクリプトの実行方式は大きく2種類あり、それは「同期実行」と「非同期実行」です。
同期実行は、スクリプトの実行が完了するまで処理がブロックされます。
代わりに、スクリプトの実行結果を使って API の実行を止めたり、API のレスポンス内容を制御することができます。

一方、非同期実行ではスクリプトの完了を待つために処理がブロックされることはありません。
ただし、スクリプトの実行結果を利用して API の実行を停止したり、API の応答内容を変更することはできません。
非同期実行は API の応答フローに影響を与えないため、原則として非同期実行を推奨します。

非同期実行には実行方式が2種類あり、GS2-Script と Amazon EventBridge があります。
Amazon EventBridge を使用することで、Lua 以外の言語で処理を記述することができます。

型 有効化条件 必須 デフォルト 値の制限 説明
triggerScriptId string ~ 1024文字 API 実行時に同期的に実行される GS2-Script のスクリプト GRN
「grn:gs2:」ではじまる GRN 形式のIDで指定する必要があります。
doneTriggerTargetType 文字列列挙型
enum {
  “none”,
  “gs2_script”,
  “aws”
}
“none” 非同期スクリプトの実行方法
非同期実行で使用するスクリプトの種類を指定します。
「非同期実行のスクリプトを使用しない(none)」「GS2-Scriptを使用する(gs2_script)」「Amazon EventBridgeを使用する(aws)」が選択できます。
定義説明
noneなし
gs2_scriptGS2-Script
awsAmazon EventBridge
doneTriggerScriptId string {doneTriggerTargetType} == “gs2_script” ~ 1024文字 非同期実行する GS2-Script スクリプト GRN
「grn:gs2:」ではじまる GRN 形式のIDで指定する必要があります。
※ doneTriggerTargetType が “gs2_script” であれば 有効
doneTriggerQueueNamespaceId string {doneTriggerTargetType} == “gs2_script” ~ 1024文字 非同期実行スクリプトを実行する GS2-JobQueue ネームスペース GRN
非同期実行スクリプトを直接実行するのではなく、GS2-JobQueue を経由する場合は GS2-JobQueue のネームスペースGRN を指定します。
GS2-JobQueue を利用する理由は多くはありませんので、特に理由がなければ指定する必要はありません。
※ doneTriggerTargetType が “gs2_script” であれば 有効

NotificationSetting

プッシュ通知に関する設定

GS2 のマイクロサービス内で何らかのイベントが発生した際に、プッシュ通知を送信するための設定です。
ここでいうプッシュ通知は GS2-Gateway の提供する WebSocket インターフェースを経由した処理であり、スマートフォンのプッシュ通知とは性質が異なります。
たとえば、マッチメイキングが完了した時やフレンドリクエストが届いた時など、ゲームクライアントの操作とは関係なく状態が変化した際に GS2-Gateway を経由してプッシュ通知をすることで、ゲームクライアントは状態の変化を検知することができます。

GS2-Gateway のプッシュ通知は通知先のデバイスがオフラインだった時に追加の処理としてモバイルプッシュ通知を送信できます。
モバイルプッシュ通知をうまく利用すれば、マッチメイキング中にゲームを終了しても、モバイルプッシュ通知を使用してプレイヤーに通知し、ゲームに戻ってくるフローを実現できる可能性があります。

型 有効化条件 必須 デフォルト 値の制限 説明
gatewayNamespaceId string “grn:gs2:{region}:{ownerId}:gateway:default” ~ 1024文字 プッシュ通知に使用する GS2-Gateway のネームスペース
「grn:gs2:」から始まる GRN 形式で GS2-Gateway のネームスペースIDを指定します。
enableTransferMobileNotification bool? false モバイルプッシュ通知へ転送するか
この通知を送信しようとした時、通知先のデバイスがオフラインだった場合、モバイルプッシュ通知へ転送するかどうかを指定します。
sound string {enableTransferMobileNotification} == true ~ 1024文字 モバイルプッシュ通知で使用するサウンドファイル名
ここで指定したサウンドファイル名は、モバイルプッシュ通知を送信する際に使用され、特別なサウンドで通知を出すことができます。
※ enableTransferMobileNotification が true であれば 有効
mobileNotificationMessages List<MobileNotificationMessage> {enableTransferMobileNotification} == true 0 ~ 100 items モバイルプッシュ通知へ転送するときの言語別のタイトルと本文
オフラインのプレイヤーへモバイルプッシュ通知として転送するときの、言語別のタイトルと本文です。
デバイストークンに登録された locale に一致するエントリ → default → 先頭 の順に採用します。
未設定なら通知の payload の mobile 配列、それも無ければ payload をそのまま本文にします。
※ enableTransferMobileNotification が true であれば 有効
enable 文字列列挙型
enum {
  “Enabled”,
  “Disabled”
}
“Enabled” プッシュ通知を有効にするか
定義説明
Enabled有効
Disabled無効

LogSetting

ログの出力設定

ログデータの出力設定を管理します。この型は、ログデータを書き出すために使用される GS2-Log ネームスペースの識別子(Namespace ID)を保持します。
ログネームスペースID(loggingNamespaceId)には、ログデータを収集し保存する GS2-Log のネームスペースを、GRNの形式で指定します。
この設定をすることで、設定されたネームスペース内で発生したAPIリクエスト・レスポンスのログデータが、対象の GS2-Log ネームスペース側へ出力されるようになります。
GS2-Log ではリアルタイムでログが提供され、システムの監視や分析、デバッグなどに利用できます。

型 有効化条件 必須 デフォルト 値の制限 説明
loggingNamespaceId string
✓
~ 1024文字 ログを出力する GS2-Log のネームスペース GRN
「grn:gs2:」ではじまる GRN 形式のIDで指定する必要があります。

TransactionSetting

トランザクション設定

トランザクション設定は非推奨です。トランザクション設定(V2)がこれに置き換わります。トランザクション設定(V2)が存在しなかった頃に作成されたネームスペースのために残されており、トランザクション設定(V2)が設定されていない間だけ適用されます。新しく作成するネームスペースでは使用しないでください。

この設定は、トランザクションの実行に関わる要素――自動実行(AutoRun)、アトミック実行(AtomicCommit)、GS2-Distributor を利用した非同期実行、スクリプト結果の一括適用、GS2-JobQueue による入手アクションの非同期化、直列実行――をそれぞれ個別の項目として公開しているため、推奨構成以外の組み合わせも作れます。その推奨構成を 1 つの設定としてまとめたものがトランザクション設定(V2)です。トランザクション設定を使い続けるのは、トランザクション設定(V2)が提供しない挙動――トランザクションをクライアント実行のスタンプシートとして実行する、GS2-Distributor による AutoRun の非同期実行を行う、入手アクションを GS2-JobQueue に畳み込む――にすでに依存しているネームスペースに限ってください。

型 有効化条件 必須 デフォルト 値の制限 説明
enableAutoRun bool false 発行したトランザクションをサーバーサイドで自動的に実行するか
enableAtomicCommit bool {enableAutoRun} == true false トランザクションの実行をアトミックにコミットするか
※ enableAutoRun が true であれば 有効
transactionUseDistributor bool {enableAtomicCommit} == true false トランザクションを非同期処理で実行する
※ enableAtomicCommit が true であれば 有効
commitScriptResultInUseDistributor bool {transactionUseDistributor} == true false スクリプトの結果コミット処理を非同期処理で実行するか
※ transactionUseDistributor が true であれば 有効
acquireActionUseJobQueue bool {enableAtomicCommit} == true false 入手アクションを実行する際に GS2-JobQueue を使用するか
※ enableAtomicCommit が true であれば 有効
enableSequentialExecution bool {enableAtomicCommit} == true false アトミックコミットのアクションを直列に実行し、同じ行を複数のアクションで更新できるようにするか
※ enableAtomicCommit が true であれば 有効
distributorNamespaceId string “grn:gs2:{region}:{ownerId}:distributor:default” ~ 1024文字 トランザクションの実行に使用する GS2-Distributor ネームスペース GRN
queueNamespaceId string “grn:gs2:{region}:{ownerId}:queue:default” ~ 1024文字 トランザクションの実行に使用する GS2-JobQueue のネームスペース GRN

PlatformSetting

ストアプラットフォームの設定

サポートされている全ストアプラットフォームの設定を集約します。Apple App Store、Google Play、Fake(Unity Editorでのテスト用)の設定を含みます。各プラットフォーム設定にはレシート検証に必要な認証情報やキーが含まれます。

型 有効化条件 必須 デフォルト 値の制限 説明
appleAppStore AppleAppStoreSetting Apple App Store の設定
Apple App Store のレシート検証に使用する認証情報です。バンドルID、共有秘密鍵、Issuer ID、キーID、秘密鍵を含みます。
googlePlay GooglePlaySetting Google Play の設定
Google Play のレシート検証に使用する認証情報です。パッケージ名と署名検証用の公開鍵を含みます。
fake FakeSetting Fake (Unity Editor) の設定
開発・テスト中に Unity Editor が生成するフェイクレシートの受け入れに関する設定です。

MobileNotificationMessage

モバイルプッシュ通知の言語別メッセージ

通知をモバイルプッシュ通知へ転送する際に使用する、言語別メッセージリストの 1 要素です。1 つの要素が 1 つのロケールに対するタイトルと本文を保持します。
採用される要素は、Firebase デバイストークンに登録されたロケールと locale が一致する要素 → locale が default の要素 → リストの先頭の要素、の順で選択されます。

型 有効化条件 必須 デフォルト 値の制限 説明
locale string ~ 32文字 メッセージの言語
この要素がどの言語に対するものかを表します。Firebase デバイストークンに登録されたロケールと照合されます。ja や en のような任意の文字列を指定できます。default は特別な値で、端末のロケールに一致する要素がなかったときに使われるフォールバックの要素であることを表します。
title string ~ 256文字 プッシュ通知のタイトル
この要素が採用されたときに、モバイルプッシュ通知のタイトルとして表示されるテキストです。省略した場合は、通知の件名が使用されます。
message string ~ 1024文字 プッシュ通知の本文
この要素が採用されたときに、モバイルプッシュ通知の本文として表示されるテキストです。

AppleAppStoreSetting

Apple App Store の設定

Apple App Store のレシート検証のための設定です。Apple のレシート検証サーバーとの通信に必要な認証情報を含みます。バンドルID、共有秘密鍵、App Store Connect の Issuer ID、キーID、秘密鍵が含まれます。

型 有効化条件 必須 デフォルト 値の制限 説明
bundleId string ~ 1024文字 Apple App Store のバンドルID
sharedSecretKey string ~ 1024文字 AppStore Connect で発行したレシートの暗号化に使用する共有秘密鍵
issuerId string ~ 1024文字 AppStore Connect で登録したアプリ内課金の Issuer ID
keyId string ~ 1024文字 Apple に登録済みのキーID
privateKeyPem string ~ 10240文字 Apple から受け取った秘密鍵

GooglePlaySetting

Google Play の設定

Google Play のレシート検証のための設定です。Google Play からの購入署名を検証するために必要なパッケージ名と公開鍵を含みます。

型 有効化条件 必須 デフォルト 値の制限 説明
packageName string ~ 5120文字 Google Play で配信するパッケージ名
publicKey string ~ 5120文字 署名検証に使用する暗号鍵

FakeSetting

デバッグ用の偽のプラットフォームの設定

開発中に Unity Editor が生成するフェイクレシートの処理に関する設定です。フェイクレシートを受け入れるか拒否するかを制御し、実際のストアプラットフォームを使わずにアプリ内課金フローをテストできるようにします。

型 有効化条件 必須 デフォルト 値の制限 説明
acceptFakeReceipt 文字列列挙型
enum {
  “Accept”,
  “Reject”
}
“Reject” Unity Editor が出力する偽のレシートで決済できるようにするか
フェイクレシートの受け入れを制御します。開発・テスト中は Accept に設定し、本番環境では不正な通貨入金を防ぐために Reject に設定してください。
定義説明
Accept受け入れる
Reject拒否する

CurrentModelMaster

現在アクティブなモデルのマスターデータ

現在ネームスペース内で有効なモデルの定義を記述したマスターデータです。
GS2ではマスターデータの管理にJSON形式のファイルを使用します。
ファイルをアップロードすることで、実際にサーバーに設定を反映することができます。

JSONファイルを作成する方法として、マネージメントコンソール内にマスターデータエディタを提供しています。
また、よりゲームの運営に相応しいツールを作成し、適切なフォーマットのJSONファイルを書き出すことでもサービスを利用可能です。

Request

リソースの生成・更新リクエスト

型 有効化条件 必須 デフォルト 値の制限 説明
namespaceName string
✓
~ 128文字 ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
mode 文字列列挙型
enum {
  “direct”,
  “preUpload”
}
“direct” 更新モード
定義説明
directマスターデータを直接更新
preUploadマスターデータをアップロードしてから更新
settings string {mode} == “direct”
✓※
~ 5242880 バイト (5MB) マスターデータ
※ mode が “direct” であれば必須
uploadToken string {mode} == “preUpload”
✓※
~ 1024文字 事前アップロードで取得したトークン
アップロードしたマスターデータを適用するために使用されます。
※ mode が “preUpload” であれば必須

GetAttr

!GetAttrタグで取得可能なリソースの生成結果

型 説明
Item CurrentModelMaster 更新された現在アクティブなモデルのマスターデータ

実装例

Type: GS2::Money2::CurrentModelMaster
Properties:
  NamespaceName: namespace-0001
  Mode: direct
  Settings: {
    "version": "2024-06-20",
    "storeContentModels": [
      {
        "name": "content-0001",
        "appleAppStore":
          {
            "productId": "io.gs2.sample.apple.product1"
          },
        "googlePlay":
          {
            "productId": "io.gs2.sample.google.product1"
          }
      },
      {
        "name": "content-0002",
        "appleAppStore":
          {
            "productId": "io.gs2.sample.apple.product2"
          },
        "googlePlay":
          {
            "productId": "io.gs2.sample.google.product2"
          }
      },
      {
        "name": "apple-only-0001",
        "appleAppStore":
          {
            "productId": "io.gs2.sample.apple.product3"
          }
      },
      {
        "name": "google-only-0001",
        "googlePlay":
          {
            "productId": "io.gs2.sample.google.product3"
          }
      }
    ],
    "storeSubscriptionContentModels": []
    
  }
  UploadToken: null
import (
    "github.com/gs2io/gs2-golang-cdk/core"
    "github.com/gs2io/gs2-golang-cdk/money2"
    "github.com/openlyinc/pointy"
)


SampleStack := core.NewStack()
money2.NewNamespace(
    &SampleStack,
    "namespace-0001",
    money2.NamespaceCurrencyUsagePriorityPrioritizeFree,
    false,
	money2.PlatformSetting{
		AppleAppStore: nil,
		GooglePlay:    nil,
		Fake:          nil,
	},
    money2.NamespaceOptions{},
).MasterData(
    []money2.StoreContentModel{
        money2.NewStoreContentModel(
            "content-0001",
            money2.StoreContentModelOptions{
                AppleAppStore: &money2.AppleAppStoreContent{
                    ProductId: pointy.String("io.gs2.sample.apple.product1"),
                },
                GooglePlay: &money2.GooglePlayContent{
                    ProductId: pointy.String("io.gs2.sample.google.product1"),
                },
            },
        ),
        money2.NewStoreContentModel(
            "content-0002",
            money2.StoreContentModelOptions{
                AppleAppStore: &money2.AppleAppStoreContent{
                    ProductId: pointy.String("io.gs2.sample.apple.product2"),
                },
                GooglePlay: &money2.GooglePlayContent{
                    ProductId: pointy.String("io.gs2.sample.google.product2"),
                },
            },
        ),
        money2.NewStoreContentModel(
            "apple-only-0001",
            money2.StoreContentModelOptions{
                AppleAppStore: &money2.AppleAppStoreContent{
                    ProductId: pointy.String("io.gs2.sample.apple.product3"),
                },
            },
        ),
        money2.NewStoreContentModel(
            "google-only-0001",
            money2.StoreContentModelOptions{
                GooglePlay: &money2.GooglePlayContent{
                    ProductId: pointy.String("io.gs2.sample.google.product3"),
                },
            },
        ),
    },
    []money2.StoreSubscriptionContentModel{
    },
)

println(SampleStack.Yaml())  // Generate Template
class SampleStack extends \Gs2Cdk\Core\Model\Stack
{
    function __construct() {
        parent::__construct();
        (new \Gs2Cdk\Money2\Model\Namespace_(
            stack: $this,
            name: "namespace-0001",
            currencyUsagePriority: \Gs2Cdk\Money2\Model\Enums\NamespaceCurrencyUsagePriority::PRIORITIZE_FREE,
            sharedFreeCurrency: false,
            platformSetting: new \Gs2Cdk\Money2\Model\PlatformSetting(),
        ))->masterData(
            [
                new \Gs2Cdk\Money2\Model\StoreContentModel(
                    name:"content-0001",
                    options: new \Gs2Cdk\Money2\Model\Options\StoreContentModelOptions(
                        appleAppStore:new \Gs2Cdk\Money2\Model\AppleAppStoreContent(
                            options: new \Gs2Cdk\Money2\Model\Options\AppleAppStoreContentOptions(
                                productId: "io.gs2.sample.apple.product1",
                            ),
                        ),
                        googlePlay:new \Gs2Cdk\Money2\Model\GooglePlayContent(
                            options: new \Gs2Cdk\Money2\Model\Options\GooglePlayContentOptions(
                                productId: "io.gs2.sample.google.product1",
                            ),
                        )
                    )
                ),
                new \Gs2Cdk\Money2\Model\StoreContentModel(
                    name:"content-0002",
                    options: new \Gs2Cdk\Money2\Model\Options\StoreContentModelOptions(
                        appleAppStore:new \Gs2Cdk\Money2\Model\AppleAppStoreContent(
                            options: new \Gs2Cdk\Money2\Model\Options\AppleAppStoreContentOptions(
                                productId: "io.gs2.sample.apple.product2",
                            ),
                        ),
                        googlePlay:new \Gs2Cdk\Money2\Model\GooglePlayContent(
                            options: new \Gs2Cdk\Money2\Model\Options\GooglePlayContentOptions(
                                productId: "io.gs2.sample.google.product2",
                            ),
                        )
                    )
                ),
                new \Gs2Cdk\Money2\Model\StoreContentModel(
                    name:"apple-only-0001",
                    options: new \Gs2Cdk\Money2\Model\Options\StoreContentModelOptions(
                        appleAppStore:new \Gs2Cdk\Money2\Model\AppleAppStoreContent(
                            options: new \Gs2Cdk\Money2\Model\Options\AppleAppStoreContentOptions(
                                productId: "io.gs2.sample.apple.product3",
                            ),
                        )
                    )
                ),
                new \Gs2Cdk\Money2\Model\StoreContentModel(
                    name:"google-only-0001",
                    options: new \Gs2Cdk\Money2\Model\Options\StoreContentModelOptions(
                        googlePlay:new \Gs2Cdk\Money2\Model\GooglePlayContent(
                            options: new \Gs2Cdk\Money2\Model\Options\GooglePlayContentOptions(
                                productId: "io.gs2.sample.google.product3",
                            ),
                        )
                    )
                )
            ],
            [
            ]
        );
    }
}

print((new SampleStack())->yaml());  // Generate Template
class SampleStack extends io.gs2.cdk.core.model.Stack
{
    public SampleStack() {
        super();
        new io.gs2.cdk.money2.model.Namespace(
            this,
            "namespace-0001",
            io.gs2.cdk.money2.model.enums.NamespaceCurrencyUsagePriority.PRIORITIZE_FREE,
            false,
            null
        ).masterData(
            Arrays.asList(
                new io.gs2.cdk.money2.model.StoreContentModel(
                    "content-0001",
                    new io.gs2.cdk.money2.model.options.StoreContentModelOptions()
                        .withAppleAppStore(new io.gs2.cdk.money2.model.AppleAppStoreContent(
                            new io.gs2.cdk.money2.model.options.AppleAppStoreContentOptions()
                                .withProductId("io.gs2.sample.apple.product1")
                        ))
                        .withGooglePlay(new io.gs2.cdk.money2.model.GooglePlayContent(
                            new io.gs2.cdk.money2.model.options.GooglePlayContentOptions()
                                .withProductId("io.gs2.sample.google.product1")
                        ))
                ),
                new io.gs2.cdk.money2.model.StoreContentModel(
                    "content-0002",
                    new io.gs2.cdk.money2.model.options.StoreContentModelOptions()
                        .withAppleAppStore(new io.gs2.cdk.money2.model.AppleAppStoreContent(
                            new io.gs2.cdk.money2.model.options.AppleAppStoreContentOptions()
                                .withProductId("io.gs2.sample.apple.product2")
                        ))
                        .withGooglePlay(new io.gs2.cdk.money2.model.GooglePlayContent(
                            new io.gs2.cdk.money2.model.options.GooglePlayContentOptions()
                                .withProductId("io.gs2.sample.google.product2")
                        ))
                ),
                new io.gs2.cdk.money2.model.StoreContentModel(
                    "apple-only-0001",
                    new io.gs2.cdk.money2.model.options.StoreContentModelOptions()
                        .withAppleAppStore(new io.gs2.cdk.money2.model.AppleAppStoreContent(
                            new io.gs2.cdk.money2.model.options.AppleAppStoreContentOptions()
                                .withProductId("io.gs2.sample.apple.product3")
                        ))
                ),
                new io.gs2.cdk.money2.model.StoreContentModel(
                    "google-only-0001",
                    new io.gs2.cdk.money2.model.options.StoreContentModelOptions()
                        .withGooglePlay(new io.gs2.cdk.money2.model.GooglePlayContent(
                            new io.gs2.cdk.money2.model.options.GooglePlayContentOptions()
                                .withProductId("io.gs2.sample.google.product3")
                        ))
                )
            ),
            Arrays.asList(
            )
        );
    }
}

System.out.println(new SampleStack().yaml());  // Generate Template
public class SampleStack : Gs2Cdk.Core.Model.Stack
{
    public SampleStack() {
        new Gs2Cdk.Gs2Money2.Model.Namespace(
            stack: this,
            name: "namespace-0001",
            currencyUsagePriority: Gs2Cdk.Gs2Money2.Model.Enums.NamespaceCurrencyUsagePriority.PrioritizeFree,
            sharedFreeCurrency: false,
            platformSetting: null
        ).MasterData(
            new Gs2Cdk.Gs2Money2.Model.StoreContentModel[] {
                new Gs2Cdk.Gs2Money2.Model.StoreContentModel(
                    name: "content-0001",
                    options: new Gs2Cdk.Gs2Money2.Model.Options.StoreContentModelOptions
                    {
                        appleAppStore = new Gs2Cdk.Gs2Money2.Model.AppleAppStoreContent(
                            options: new Gs2Cdk.Gs2Money2.Model.Options.AppleAppStoreContentOptions
                            {
                                productId = "io.gs2.sample.apple.product1"
                            }
                        ),
                        googlePlay = new Gs2Cdk.Gs2Money2.Model.GooglePlayContent(
                            options: new Gs2Cdk.Gs2Money2.Model.Options.GooglePlayContentOptions
                            {
                                productId = "io.gs2.sample.google.product1"
                            }
                        )
                    }
                ),
                new Gs2Cdk.Gs2Money2.Model.StoreContentModel(
                    name: "content-0002",
                    options: new Gs2Cdk.Gs2Money2.Model.Options.StoreContentModelOptions
                    {
                        appleAppStore = new Gs2Cdk.Gs2Money2.Model.AppleAppStoreContent(
                            options: new Gs2Cdk.Gs2Money2.Model.Options.AppleAppStoreContentOptions
                            {
                                productId = "io.gs2.sample.apple.product2"
                            }
                        ),
                        googlePlay = new Gs2Cdk.Gs2Money2.Model.GooglePlayContent(
                            options: new Gs2Cdk.Gs2Money2.Model.Options.GooglePlayContentOptions
                            {
                                productId = "io.gs2.sample.google.product2"
                            }
                        )
                    }
                ),
                new Gs2Cdk.Gs2Money2.Model.StoreContentModel(
                    name: "apple-only-0001",
                    options: new Gs2Cdk.Gs2Money2.Model.Options.StoreContentModelOptions
                    {
                        appleAppStore = new Gs2Cdk.Gs2Money2.Model.AppleAppStoreContent(
                            options: new Gs2Cdk.Gs2Money2.Model.Options.AppleAppStoreContentOptions
                            {
                                productId = "io.gs2.sample.apple.product3"
                            }
                        )
                    }
                ),
                new Gs2Cdk.Gs2Money2.Model.StoreContentModel(
                    name: "google-only-0001",
                    options: new Gs2Cdk.Gs2Money2.Model.Options.StoreContentModelOptions
                    {
                        googlePlay = new Gs2Cdk.Gs2Money2.Model.GooglePlayContent(
                            options: new Gs2Cdk.Gs2Money2.Model.Options.GooglePlayContentOptions
                            {
                                productId = "io.gs2.sample.google.product3"
                            }
                        )
                    }
                )
            },
            new Gs2Cdk.Gs2Money2.Model.StoreSubscriptionContentModel[] {
            }
        );
    }
}

Debug.Log(new SampleStack().Yaml());  // Generate Template
import core from "@/gs2cdk/core";
import money2 from "@/gs2cdk/money2";

class SampleStack extends core.Stack
{
    public constructor() {
        super();
        new money2.model.Namespace(
            this,
            "namespace-0001",
            money2.model.NamespaceCurrencyUsagePriority.PRIORITIZE_FREE,
            false,
            new money2.model.PlatformSetting()
        ).masterData(
            [
                new money2.model.StoreContentModel(
                    "content-0001",
                    {
                        appleAppStore: new money2.model.AppleAppStoreContent(
                            {
                                productId: "io.gs2.sample.apple.product1"
                            }
                        ),
                        googlePlay: new money2.model.GooglePlayContent(
                            {
                                productId: "io.gs2.sample.google.product1"
                            }
                        )
                    }
                ),
                new money2.model.StoreContentModel(
                    "content-0002",
                    {
                        appleAppStore: new money2.model.AppleAppStoreContent(
                            {
                                productId: "io.gs2.sample.apple.product2"
                            }
                        ),
                        googlePlay: new money2.model.GooglePlayContent(
                            {
                                productId: "io.gs2.sample.google.product2"
                            }
                        )
                    }
                ),
                new money2.model.StoreContentModel(
                    "apple-only-0001",
                    {
                        appleAppStore: new money2.model.AppleAppStoreContent(
                            {
                                productId: "io.gs2.sample.apple.product3"
                            }
                        )
                    }
                ),
                new money2.model.StoreContentModel(
                    "google-only-0001",
                    {
                        googlePlay: new money2.model.GooglePlayContent(
                            {
                                productId: "io.gs2.sample.google.product3"
                            }
                        )
                    }
                )
            ],
            [
            ]
        );
    }
}

console.log(new SampleStack().yaml());  // Generate Template
from gs2_cdk import Stack, core, money2

class SampleStack(Stack):

    def __init__(self):
        super().__init__()
        money2.Namespace(
            stack=self,
            name="namespace-0001",
            currency_usage_priority=money2.NamespaceCurrencyUsagePriority.PRIORITIZE_FREE,
            shared_free_currency=False,
            platform_setting=money2.PlatformSetting(),
        ).master_data(
            store_content_models=[
                money2.StoreContentModel(
                    name='content-0001',
                    options=money2.StoreContentModelOptions(
                        apple_app_store = money2.AppleAppStoreContent(
                            options=money2.AppleAppStoreContentOptions(
                                product_id='io.gs2.sample.apple.product1',
                            ),
                        ),
                        google_play = money2.GooglePlayContent(
                            options=money2.GooglePlayContentOptions(
                                product_id='io.gs2.sample.google.product1',
                            ),
                        )
                    ),
                ),
                money2.StoreContentModel(
                    name='content-0002',
                    options=money2.StoreContentModelOptions(
                        apple_app_store = money2.AppleAppStoreContent(
                            options=money2.AppleAppStoreContentOptions(
                                product_id='io.gs2.sample.apple.product2',
                            ),
                        ),
                        google_play = money2.GooglePlayContent(
                            options=money2.GooglePlayContentOptions(
                                product_id='io.gs2.sample.google.product2',
                            ),
                        )
                    ),
                ),
                money2.StoreContentModel(
                    name='apple-only-0001',
                    options=money2.StoreContentModelOptions(
                        apple_app_store = money2.AppleAppStoreContent(
                            options=money2.AppleAppStoreContentOptions(
                                product_id='io.gs2.sample.apple.product3',
                            ),
                        )
                    ),
                ),
                money2.StoreContentModel(
                    name='google-only-0001',
                    options=money2.StoreContentModelOptions(
                        google_play = money2.GooglePlayContent(
                            options=money2.GooglePlayContentOptions(
                                product_id='io.gs2.sample.google.product3',
                            ),
                        )
                    ),
                ),
            ],
            store_subscription_content_models=[
            ],
        )

print(SampleStack().yaml())  # Generate Template

StoreContentModel

ストアコンテンツモデル

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

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

AppleAppStoreContent

Apple App Store のコンテンツ

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

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

GooglePlayContent

Google Play のコンテンツ

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

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

StoreSubscriptionContentModel

ストア定期課金コンテンツモデル

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

型 有効化条件 必須 デフォルト 値の制限 説明
storeSubscriptionContentModelId string
※
~ 1024文字 期間課金コンテンツモデル GRN
※ サーバーが自動で設定
name string
✓
~ 128文字 ストア定期課金コンテンツモデル名
metadata string ~ 1024文字 メタデータ
scheduleNamespaceId string
✓
~ 1024文字 サブスクリプション期間を連動させる GS2-Schedule のネームスペース GRN
triggerName string
✓
~ 128文字 サブスクリプション期間を反映するトリガー名
サブスクリプションの有効期間を反映するために起動される GS2-Schedule のトリガー名です。トリガーの持続時間はサブスクリプションの有効期限に設定されます。
triggerExtendMode 文字列列挙型
enum {
  “just”,
  “rollupHour”
}
“just” サブスクリプション期間をトリガーに反映する時のモード
サブスクリプションの有効期限をトリガーの持続時間にどのようにマッピングするかを制御します。“just” はサブスクリプション期間をそのまま使用します。“rollupHour” は指定した時刻(UTC)まで延長し、日中の期限切れを回避します。
定義説明
justそのままサブスクリプション期間を反映
rollupHour次の日跨ぎ時刻まで延長してサブスクリプション期間を反映
rollupHour int {triggerExtendMode} == “rollupHour” 0 0 ~ 23 日跨ぎの時刻 (UTC)
triggerExtendMode が “rollupHour” の場合、サブスクリプション期間は有効期限日のこの時刻(0〜23、UTC)まで延長されます。ユーザーのプレイセッション中にサブスクリプションが期限切れになるのを防ぎます。
※ triggerExtendMode が “rollupHour” であれば 有効
reallocateSpanDays int 30 0 ~ 365 サブスクリプションの契約情報を他のユーザーに割り当て可能となる期間(日)
最後の割り当てから、サブスクリプション契約を別のユーザーに再割り当てできるようになるまでの日数です。ユーザーがアカウントを変更する際の不正利用を防止するため、サブスクリプションの移行に待機期間を設けます。
appleAppStore AppleAppStoreSubscriptionContent Apple App Store のコンテンツ
このサブスクリプションコンテンツの Apple App Store のサブスクリプション情報(サブスクリプショングループID)です。
googlePlay GooglePlaySubscriptionContent Google Play のコンテンツ
このサブスクリプションコンテンツの Google Play のサブスクリプション情報(プロダクトID)です。

AppleAppStoreSubscriptionContent

Apple App Store の期間課金コンテンツ

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

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

GooglePlaySubscriptionContent

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

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

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