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

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

エンティティ

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

Namespace

ネームスペース

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

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

Request

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

有効化条件必須デフォルト値の制限説明
namestring
~ 128文字ネームスペース名
ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。
currencyUsagePriority文字列列挙型
enum {
  “PrioritizeFree”,
  “PrioritizePaid”
}
消費優先度
ウォレットから出金する際に有償通貨と無償通貨のどちらを先に消費するかを決定します。“PrioritizeFree” は無償通貨を優先し、“PrioritizePaid” は有償通貨を優先します。
定義説明
“PrioritizeFree”無償通貨を優先して使用する
“PrioritizePaid”有償通貨を優先して使用する
descriptionstring~ 1024文字説明文
transactionSettingTransactionSettingトランザクション設定
通貨の入金・出金時に使用される分散トランザクションの設定です。
sharedFreeCurrencybool
無償通貨を異なるスロットで共有するか
有効にすると、無償通貨の残高がすべてのウォレットスロット(プラットフォーム)間で共有されます。有償通貨はスロットごとに分離されたままです。この設定はネームスペース作成時のみ設定可能で、後から変更できません。
platformSettingPlatformSetting
ストアプラットフォーム設定
サポートされている各ストアプラットフォーム(Apple App Store、Google Play、テスト用Fake)の設定です。各プラットフォームでのレシート検証に必要な認証情報やキーを含みます。
depositBalanceScriptScriptSettingウォレット残高を加算したときに実行するスクリプトの設定
Script トリガーリファレンス - deposit
withdrawBalanceScriptScriptSettingウォレット残高を消費したときに実行するスクリプトの設定
Script トリガーリファレンス - withdraw
verifyReceiptScriptScriptSettingレシート検証を実行したときに実行するスクリプトの設定
Script トリガーリファレンス - verifyReceipt
subscribeScriptstring~ 1024文字期間課金を新規契約するときに実行する GS2-Script スクリプトGRN(ユーザーの紐づけ変更時には呼び出されない/一度契約失効後に再度契約した場合も呼び出される)
Script トリガーリファレンス - subscribe
renewScriptstring~ 1024文字期間課金を更新するときに実行する GS2-Script スクリプトGRN
Script トリガーリファレンス - renew
unsubscribeScriptstring~ 1024文字期間課金を解約するときに実行する GS2-Script スクリプトGRN(ユーザーの紐づけ変更時には呼び出されない)
Script トリガーリファレンス - unsubscribe
takeOverScriptScriptSetting期間課金に紐づけられたユーザーを変更するときに実行するスクリプトの設定
Script トリガーリファレンス - takeOver
changeSubscriptionStatusNotificationNotificationSetting期間課金の契約状況が変化したときのプッシュ通知
サブスクリプションのステータスが変化した際(有効化、更新、解約、期限切れ、取り消しなど)に GS2-Gateway を通じて配信されるプッシュ通知の設定です。ゲームクライアントがサブスクリプション状態の変化にリアルタイムで対応できるようにします。
logSettingLogSettingログの出力設定
このネームスペースに対するAPIリクエスト・レスポンスログの出力先となる GS2-Log のネームスペースを指定します。入金、出金、レシート検証、サブスクリプションイベントの追跡に役立ちます。

GetAttr

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

説明
ItemNamespace作成したネームスペース

実装例

Type: GS2::Money2::Namespace
Properties:
  Name: namespace-0001
  CurrencyUsagePriority: PrioritizeFree
  Description: null
  TransactionSetting: 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

TransactionSetting

トランザクション設定

トランザクション設定は、トランザクションの実行方法・整合性・非同期処理・競合回避の仕組みを制御する設定です。
自動実行(AutoRun)、アトミック実行(AtomicCommit)、GS2-Distributor を利用した非同期実行、スクリプト結果の一括適用、GS2-JobQueue による入手アクションの非同期化などを組み合わせ、ゲームロジックに応じた堅牢なトランザクション管理を可能にします。

有効化条件必須デフォルト値の制限説明
enableAutoRunboolfalse発行したトランザクションをサーバーサイドで自動的に実行するか
enableAtomicCommitbool{enableAutoRun} == truefalseトランザクションの実行をアトミックにコミットするか
※ enableAutoRun が true であれば 有効
transactionUseDistributorbool{enableAtomicCommit} == truefalseトランザクションを非同期処理で実行する
※ enableAtomicCommit が true であれば 有効
commitScriptResultInUseDistributorbool{transactionUseDistributor} == truefalseスクリプトの結果コミット処理を非同期処理で実行するか
※ transactionUseDistributor が true であれば 有効
acquireActionUseJobQueuebool{enableAtomicCommit} == truefalse入手アクションを実行する際に GS2-JobQueue を使用するか
※ enableAtomicCommit が true であれば 有効
distributorNamespaceIdstring“grn:gs2:{region}:{ownerId}:distributor:default”~ 1024文字トランザクションの実行に使用する GS2-Distributor ネームスペース GRN
queueNamespaceIdstring“grn:gs2:{region}:{ownerId}:queue:default”~ 1024文字トランザクションの実行に使用する GS2-JobQueue のネームスペース GRN

ScriptSetting

スクリプト設定

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

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

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

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

有効化条件必須デフォルト値の制限説明
triggerScriptIdstring~ 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_script”GS2-Script
“aws”Amazon EventBridge
doneTriggerScriptIdstring{doneTriggerTargetType} == “gs2_script”~ 1024文字非同期実行する GS2-Script スクリプト GRN
「grn:gs2:」ではじまる GRN 形式のIDで指定する必要があります。
※ doneTriggerTargetType が “gs2_script” であれば 有効
doneTriggerQueueNamespaceIdstring{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 のプッシュ通知は通知先のデバイスがオフラインだった時に追加の処理としてモバイルプッシュ通知を送信できます。
モバイルプッシュ通知をうまく利用すれば、マッチメイキング中にゲームを終了しても、モバイルプッシュ通知を使用してプレイヤーに通知し、ゲームに戻ってくるフローを実現できる可能性があります。

有効化条件必須デフォルト値の制限説明
gatewayNamespaceIdstring“grn:gs2:{region}:{ownerId}:gateway:default”~ 1024文字プッシュ通知に使用する GS2-Gateway のネームスペース
「grn:gs2:」から始まる GRN 形式で GS2-Gateway のネームスペースIDを指定します。
enableTransferMobileNotificationbool?falseモバイルプッシュ通知へ転送するか
この通知を送信しようとした時、通知先のデバイスがオフラインだった場合、モバイルプッシュ通知へ転送するかどうかを指定します。
soundstring{enableTransferMobileNotification} == true~ 1024文字モバイルプッシュ通知で使用するサウンドファイル名
ここで指定したサウンドファイル名は、モバイルプッシュ通知を送信する際に使用され、特別なサウンドで通知を出すことができます。
※ enableTransferMobileNotification が true であれば 有効
enable文字列列挙型
enum {
  “Enabled”,
  “Disabled”
}
“Enabled”プッシュ通知を有効にするか
定義説明
“Enabled”有効
“Disabled”無効

LogSetting

ログの出力設定

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

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

PlatformSetting

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

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

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

AppleAppStoreSetting

Apple AppStore の設定

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

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

GooglePlaySetting

Google Play の設定

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

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

FakeSetting

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

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

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

CurrentModelMaster

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

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

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

Request

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

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

GetAttr

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

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

実装例

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

ストアコンテンツモデル

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

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

AppleAppStoreContent

Apple AppStore のコンテンツ

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

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

GooglePlayContent

Google Play のコンテンツ

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

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

StoreSubscriptionContentModel

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

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

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

AppleAppStoreSubscriptionContent

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

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

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

GooglePlaySubscriptionContent

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

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

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