GS2-SDK‎ > ‎GS2 SDK for Unity‎ > ‎

GS2-Money

GS2-Money は仮想通貨(いわゆる魔法石)を取り扱うためのサービスです。
仮想通貨は一定の条件を満たすと 資金決済法 の管理下に置かれます。詳しくは 事業者としてやらなければならないこと を参照してください。

仮想通貨を作成する

GS2-Money を利用するにはまずは仮想通貨 というデータを作成する必要があります。
マネージメントコンソールで GS2-Money にアクセスします。


『仮想通貨の新規作成』 を選択します。

『消費優先度』 は有償付与の仮想通貨と無償付与の仮想通貨のどちらを優先して消費するかを指定します。
『無償仮想通貨の共有』は異なるスロット間(iOS/Androidで有償仮想通貨はガイドライン上分けて管理しなければならないが、無償仮想通貨はその義務はない)で無償仮想通貨を共有するかを指定します。
『レシート検証機能の利用』は Apple や Google の決済機能を利用した後に発行されるレシートの妥当性検証を GS2 上で行うかどうかを指定します。Unity SDK を使用する際にはチェックを入れてください。


『レシート検証機能の利用』 にチェックを入れると、追加でレシートの妥当性検証を行うために必要な情報の入力欄が出てきます。
ここで入力するべき情報については 各販売プラットフォームの設定 を参照してください。

商品の作成

仮想通貨の登録ができたら、次は商品を登録します。


仮想通貨の『商品』タブを選択し『商品の新規作成』を選択します。


『商品名』は英数字で指定してください。この値が画面に表示されることはありません。
『付与する仮想通貨の数』にはこの商品を購入した際に付与する仮想通貨の数を指定してください。

プラットフォーム個別商品の作成

次に、商品に対して Apple / Google といったプラットフォーム上でどういった商品を販売しているかを登録します。



商品を選択したあとで『プラットフォーム個別商品の新規作成』を選択します。


『販売プラットフォーム』には登録する商品を販売しているプラットフォームを選択します。
『商品ID』には 各販売プラットフォームの設定 で指示されたアプリ内課金の商品固有のIDを指定します。
『販売価格』にはその商品を販売している価格を設定します。売上帳簿や未使用残高の計算に使用しますので、正確な値を入力してください。
『通貨』には 日本円・米ドル のいずれかを指定します。米ドルを指定した場合は、別途定めた為替レートに従って未使用残高が計算されます。

Unity IAP のインストール

GS2-Money SDK for Unity は内部的に Unity IAP を使用します。


Unity の右側にある In-App Purchasing を有効にして、アセットをインストールしてください。

ウォレットを取得

ここからは Unity での実装になります。
仮想通貨の所持数を取得します。

  1. public class GameLogic : MonoBehaviour {
  2.     private const string CLIENT_ID = "your client id";
  3.     private const string CLIENT_SECRET = "your client secret";
  4.     private const string MONEY_NAME = "money-0001";
  5.     Gs2.Client gs2;
  6.     Gs2.GameSession session;
  7.     void Start () {
  8.         gs2 = new Gs2.Client (new Gs2.Profile ()
  9.             .WithClientId (CLIENT_ID)
  10.             .WithClientSecret (CLIENT_SECRET));
  11.         StartCoroutine (Login ());
  12.     }
  13.     IEnumerator Login() {
  14.         string GAME_NAME = "game-0001";
  15.         string KEY_NAME = "account";
  16.         string USER_ID = "user";
  17.         string PASSWORD = "password";
  18.         string authenticationToken = null;
  19.         yield return gs2.Account.Authentication (
  20.             result => {
  21.                 if(result.Error != null) throw result.Error;
  22.                 authenticationToken = result.Result;
  23.             },
  24.             GAME_NAME,
  25.             KEY_NAME,
  26.             USER_ID,
  27.             PASSWORD);
  28.         yield return gs2.Auth.Login (
  29.             result => {
  30.                 if(result.Error != null) throw result.Error;
  31.                 session = result.Result;
  32.             },
  33.             USER_ID,
  34.             KEY_NAME,
  35.             authenticationToken);
  36.         StartCoroutine (Initialize ());
  37.     }
  38.     IEnumerator Initialize()
  39.     {
  40.          while(gs2.Money.Status != Status.INITIALIZED) {
  41.               yield return gs2.Money.Dispatch(
  42.                    result => {
  43.                         if(result.Error != null) throw result.Error;
  44.                    },
  45.                    session,
  46.                    MONEY_NAME);
  47.               Thread.Sleep(100);
  48.          }
  49.         StartCoroutine (GetWallet ());
  50.     }
  51.     IEnumerator GetWallet()
  52.     {
  53.         Gs2.Money.Wallet wallet = null;
  54.         yield return gs2.Money.GetWallet(
  55.             result => {
  56.                 if(result.Error != null) throw result.Error;
  57.                 wallet = result.Result;
  58.             },
  59.             session,
  60.             MONEY_NAME,
  61.             0 // スロット番号
  62.         );
  63.         Debug.Log("userId: " + wallet.UserId + ", slot: " + wallet.Slot + ", paid: " + wallet.Paid + ", free: " + wallet.Free);
  64.     }
  65.     void Update () {
  66.         
  67.     }
  68. }

販売中の商品(仮想通貨)一覧を取得

販売している商品(仮想通貨)一覧を取得します。
この情報を利用してUIを組み立てて、次にサンプルを示す購入に繋げてください。

  1. public class GameLogic : MonoBehaviour {
  2.     private const string CLIENT_ID = "your client id";
  3.     private const string CLIENT_SECRET = "your client secret";
  4.     private const string MONEY_NAME = "money-0001";
  5.     Gs2.Client gs2;
  6.     Gs2.GameSession session;
  7.     void Start () {
  8.         gs2 = new Gs2.Client (new Gs2.Profile ()
  9.             .WithClientId (CLIENT_ID)
  10.             .WithClientSecret (CLIENT_SECRET));
  11.         StartCoroutine (Login ());
  12.     }
  13.     IEnumerator Login() {
  14.         string GAME_NAME = "game-0001";
  15.         string KEY_NAME = "account";
  16.         string USER_ID = "user";
  17.         string PASSWORD = "password";
  18.         string authenticationToken = null;
  19.         yield return gs2.Account.Authentication (
  20.             result => {
  21.                 if(result.Error != null) throw result.Error;
  22.                 authenticationToken = result.Result;
  23.             },
  24.             GAME_NAME,
  25.             KEY_NAME,
  26.             USER_ID,
  27.             PASSWORD);
  28.         yield return gs2.Auth.Login (
  29.             result => {
  30.                 if(result.Error != null) throw result.Error;
  31.                 session = result.Result;
  32.             },
  33.             USER_ID,
  34.             KEY_NAME,
  35.             authenticationToken);
  36.         StartCoroutine (Initialize ());
  37.     }
  38.     IEnumerator Initialize()
  39.     {
  40.          while(gs2.Money.Status != Status.INITIALIZED) {
  41.               yield return gs2.Money.Dispatch(
  42.                    result => {
  43.                         if(result.Error != null) throw result.Error;
  44.                    },
  45.                    session,
  46.                    MONEY_NAME);
  47.               Thread.Sleep(100);
  48.          }
  49.          Product[] products = gs2.Money.ListItem();
  50.         foreach(var product in products) {
  51.             Debug.Log("title: " + product.metadata.localizedTitle + ", description: " + product.metadata.localizedDescription + ", price: " + product.metadata.localizedPriceString);
  52.         }
  53.     }
  54.     void Update () {
  55.         
  56.     }
  57. }

仮想通貨の購入

商品を指定して、商品に設定された数量の仮想通貨を購入します。
内部処理で 各プラットフォームのレシート検証と仮想通貨の付与処理が実行されます。

  1. public class GameLogic : MonoBehaviour {
  2.     private const string CLIENT_ID = "your client id";
  3.     private const string CLIENT_SECRET = "your client secret";
  4.     private const string MONEY_NAME = "money-0001";
  5.     Gs2.Client gs2;
  6.     Gs2.GameSession session;
  7.     void Start () {
  8.         gs2 = new Gs2.Client (new Gs2.Profile ()
  9.             .WithClientId (CLIENT_ID)
  10.             .WithClientSecret (CLIENT_SECRET));
  11.         StartCoroutine (Login ());
  12.     }
  13.     IEnumerator Login() {
  14.         string GAME_NAME = "game-0001";
  15.         string KEY_NAME = "account";
  16.         string USER_ID = "user";
  17.         string PASSWORD = "password";
  18.         string authenticationToken = null;
  19.         yield return gs2.Account.Authentication (
  20.             result => {
  21.                 if(result.Error != null) throw result.Error;
  22.                 authenticationToken = result.Result;
  23.             },
  24.             GAME_NAME,
  25.             KEY_NAME,
  26.             USER_ID,
  27.             PASSWORD);
  28.         yield return gs2.Auth.Login (
  29.             result => {
  30.                 if(result.Error != null) throw result.Error;
  31.                 session = result.Result;
  32.             },
  33.             USER_ID,
  34.             KEY_NAME,
  35.             authenticationToken);
  36.         StartCoroutine (Initialize ());
  37.     }
  38.     IEnumerator Initialize()
  39.     {
  40.          while(gs2.Money.Status != Status.INITIALIZED) {
  41.               yield return gs2.Money.Dispatch(
  42.                    result => {
  43.                         if(result.Error != null) throw result.Error;
  44.                    },
  45.                    session,
  46.                    MONEY_NAME);
  47.               Thread.Sleep(100);
  48.          }
  49.          Product[] products = gs2.Money.ListItem();
  50.          StartCoroutine (Buy (products[0]));
  51.     }
  52.     IEnumerator Buy(Product product)
  53.     {
  54.          gs2.Money.Buy(0, product);
  55.          bool purchaseComplete = false;
  56.          Gs2.Money.Wallet wallet = null;
  57.          while(!purchaseComplete) {
  58.               yield return gs2.Money.Dispatch(
  59.                    result => {
  60.                         Debug.Log(result.Error);
  61.                         if(result.Error != null) throw result.Error;
  62.                        if(result.Result.Type == Gs2.Money.EventType.PURCHASE_COMPLETE) {
  63.                             purchaseComplete = true;
  64.                              wallet = result.Result.Wallet;
  65.                         }
  66.                    },
  67.                    session,
  68.                    MONEY_NAME);
  69.               Thread.Sleep(100);
  70.           }
  71.          Debug.Log("userId: " + wallet.UserId + ", slot: " + wallet.Slot + ", paid: " + wallet.Paid + ", free: " + wallet.Free);
  72.     }
  73.     void Update () {
  74.         
  75.     }
  76. }

仮想通貨を消費

本来、仮想通貨の消費は対価の引き渡しと同時にサーバサイドで実行するべきです。
なぜなら、チート行為によって仮想通貨の消費ロジックを回避し、対価だけ得ることが出来てしまうからです。
GS2 はガチャ・ストアなど、仮想通貨の消費をしつつ対価を渡せるサービスを拡充する予定です。
(サーバサイドSDKを使用して、仮想通貨の消費・対価の付与をすればGS2の対応を待つ必要はありません)

  1. public class GameLogic : MonoBehaviour {
  2.     private const string CLIENT_ID = "your client id";
  3.     private const string CLIENT_SECRET = "your client secret";
  4.     private const string MONEY_NAME = "money-0001";
  5.     Gs2.Client gs2;
  6.     Gs2.GameSession session;
  7.     void Start () {
  8.         gs2 = new Gs2.Client (new Gs2.Profile ()
  9.             .WithClientId (CLIENT_ID)
  10.             .WithClientSecret (CLIENT_SECRET));
  11.         StartCoroutine (Login ());
  12.     }
  13.     IEnumerator Login() {
  14.         string GAME_NAME = "game-0001";
  15.         string KEY_NAME = "account";
  16.         string USER_ID = "user";
  17.         string PASSWORD = "password";
  18.         string authenticationToken = null;
  19.         yield return gs2.Account.Authentication (
  20.             result => {
  21.                 if(result.Error != null) throw result.Error;
  22.                 authenticationToken = result.Result;
  23.             },
  24.             GAME_NAME,
  25.             KEY_NAME,
  26.             USER_ID,
  27.             PASSWORD);
  28.         yield return gs2.Auth.Login (
  29.             result => {
  30.                 if(result.Error != null) throw result.Error;
  31.                 session = result.Result;
  32.             },
  33.             USER_ID,
  34.             KEY_NAME,
  35.             authenticationToken);
  36.         StartCoroutine (Initialize ());
  37.     }
  38.     IEnumerator Initialize()
  39.     {
  40.         while(gs2.Money.Status != Status.INITIALIZED) {
  41.             yield return gs2.Money.Dispatch(
  42.                 result => {
  43.                     if(result.Error != null) throw result.Error;
  44.                 },
  45.                 session,
  46.                 MONEY_NAME);
  47.         }
  48.         StartCoroutine (GetWallet ());
  49.     }
  50.     IEnumerator GetWallet()
  51.     {
  52.         Gs2.Money.Wallet wallet = null;
  53.         yield return gs2.Money.GetWallet(
  54.             result => {
  55.                 if(result.Error != null) throw result.Error;
  56.                 wallet = result.Result;
  57.             },
  58.             session,
  59.             MONEY_NAME,
  60.             0 // スロット番号
  61.         );
  62.         Debug.Log("[Before] userId: " + wallet.UserId + ", slot: " + wallet.Slot + ", paid: " + wallet.Paid + ", free: " + wallet.Free);
  63.         StartCoroutine (ConsumeWallet ());
  64.     }
  65.     IEnumerator ConsumeWallet()
  66.     {
  67.         Gs2.Money.Wallet wallet = null;
  68.         yield return gs2.Money.ConsumeWallet(
  69.             result => {
  70.                 if(result.Error != null) throw result.Error;
  71.                 wallet = result.Result;
  72.             },
  73.             session,
  74.             MONEY_NAME,
  75.             0, // スロット番号
  76.             100, // 消費量
  77.             0, // 用途番号(用途ごとの消費割合を集計できます)
  78.             false // 有償仮想通貨のみ消費対象とするか(有償仮想通貨でしか買えない商品の場合は true を指定します)
  79.             );
  80.         Debug.Log("[After] userId: " + wallet.UserId + ", slot: " + wallet.Slot + ", paid: " + wallet.Paid + ", free: " + wallet.Free);
  81.     }
  82.     void Update () {
  83.         
  84.     }
  85. }

Comments