Easy Mobile Proを使った簡単アプリ内課金実装

Easy Moblie Proを使ってアプリ内課金実装を行ってみました。 ローカルでのレシート検証ではありますがセットアップすればすぐに使えて便利でした。

Easy Mobile Proとは

Easy Mobile Pro はモバイルゲーム開発における多機能プラグインで、アプリ内課金だけでなく広告サービスやゲームサービスなどをサポートしています。 今回は課金機能だけを使いましたがリファレンス に沿って実装することで詰まることなく実装できました。 内容としてはUnityIAPのラッパーになっており、初期化処理の自動化やリストアがシンプルに行えます。

開発環境

Easy Mobile Proを使った実装

In-App Purchaseの項目に従いセットアップを進めます。 英語ですがGoogle Chromeの日本語翻訳を通すだけでだいぶ読みやすくなります。 リファレンス通りに進めることでほとんどは問題なく実装できるため、つまりどころとポイントのみ記載します。

Easy Mobile Proの設定画面が出ない

Easy Mobile ProのImport後はUnityを再起動しましょう。

Assembly Definitionの設定

Easy Mobile ProはAssembly Definitionがないため自分で作成する必要があります。 特にUnityIAP周りのAssembly Definitionを設定する必要があるため注意が必要です。 今回のサンプル実装では以下となりました。

f:id:tetsujp84:20210623200954p:plain
UnityGifDecoderはEasy Mobile Proに含まれるライブラリです。

EasyMoblie/EditorフォルダにもEditor用のAssetmbly Definitionを作成します。 f:id:tetsujp84:20210623201522p:plain
こちらは設定が面倒だったため、関連していそうなものを追加しています。そのため不要なReferenceも含んでいるかもしれません。

Productの設定

課金アイテムにはIDを振ります。App Storeでは製品ID、Google Play StoreではアイテムIDと呼ばれます。 Google Play StoreではアイテムIDに小文字しか使えないため、特別な理由がなければIDは小文字で統一したほうがよいです。 Easy Moblie ProではProductsの項目からストアごとに個別に設定することもできます。参考

ローカルでのレシート検証

Androidではアプリのストアに紐づくRSA 公開鍵が必要です。 Google Play Consoleの収益化のセットアップの項目から公開鍵を取得します。 収益化のセットアップの項目は以下のようなURLになっています。
- https://play.google.com/console/u/1/developers/○○/app/○○/monetization-setup

UnityではWindow->UnityIAP->Receipt Validation Obfuscatorからローカル検証用の難解化を行いセットアップします。 参考

ストアとの連携

課金のテストでは事前に以下を行っておきます。

App Store Connect

  • 銀行口座や納税フォーム、連絡先の登録
  • App内課金の項目で課金アイテムの登録
    • App Store 情報やスクリーンショットは仮でも良いので全部埋める必要があります。
    • 「配信可能」のチェックボックスは有効にします。
    • ステータスが「送信準備完了」になっていればテストできます。
    • ※「一番最初の App 内課金は、App の新しいバージョンと一緒に提出する必要があります。」と表示されますが、テストではストアアプリの更新は不要です。
  • 課金テスターの登録
    • 課金テスターは専用のAppleIdを登録する必要があります。
    • 開発者と同じAppleIdは使えないため、専用のGmailアカウントを取得し別で使用することが多いです。

Google Play Console

  • IAPを有効にしたAPKかAABをアップロード
    • アプリをアップロードすることでストアのセットアップができるようになります。
  • アプリ内アイテムの項目で課金アイテムの登録
    • アイテムのステータスは有効にします。
  • 課金テスターの登録
    • テスターはメールアドレスで登録します。
    • ライセンステストの項目で同一のメールアドレスをライセンス テスターとして追加します。
      • ライセンステスターとして追加していないと課金テストであっても支払いが発生してしまいます。

実機テストでUnavailable product(NoProductsAvailable)が出る場合

  • ストアと同じBundleIdになっているか確認します。BundleIdをストアビルドと開発ビルドで分けていると発生しやすいです。
  • iOSでは「配信可能」にチェックが入っていること、Androidではステータスが「有効」になっていることを確認します。
  • iOSのプロビジョニングプロファイルはAdHocを使います。課金テストのためにTestFlightを経由する必要はありません。
  • AndroidではAPKをGoogle Play Consoleにアップロードし、クローズドテストなどのテストの機能を用いてインストールする必要があります。Unityから直接端末にインストールしても課金のテストが行えません。

サンプルスクリプト

課金用スクリプトのサンプルを記載しました。Easy Moblieの設定画面でAutoInitializationを有効にしておけば初期化処理はアプリ起動時に自動で行われます。OnEnable/OnDisableでイベント管理をしているのでMonoBehaviourにしています。

// 課金プロセスの実行クラス
public class PurchasingProcessController : MonoBehaviour
{
    // 課金成功/失敗の通知
    public IObservable<bool> OnComplete => _onComplete;
    private Subject<bool> _onComplete = new Subject<bool>();

    // すでに購入済みか(非消費型アイテム向け)
    public bool IsOwned(string productionName)
    {
        return InAppPurchasing.IsProductOwned(productionName);
    }

    // 購入実行
    // productNameは製品ID/アイテムID
    public void DoPurchase(string productName)
    {
        InAppPurchasing.Purchase(productName);
    }

    // リストア処理
    public void TryRestore()
    {
        InAppPurchasing.RestorePurchases();
    }

    private void OnEnable()
    {
        InAppPurchasing.PurchaseCompleted += PurchaseCompletedHandler;
        InAppPurchasing.PurchaseFailed += PurchaseFailedHandler;

        InAppPurchasing.RestoreCompleted += RestoreCompletedHandler;
        InAppPurchasing.RestoreFailed += RestoreFailedHandler;
    }

    private void OnDisable()
    {
        InAppPurchasing.PurchaseCompleted -= PurchaseCompletedHandler;
        InAppPurchasing.PurchaseFailed -= PurchaseFailedHandler;

        InAppPurchasing.RestoreCompleted -= RestoreCompletedHandler;
        InAppPurchasing.RestoreFailed -= RestoreFailedHandler;
    }

    // 購入成功処理
    private void PurchaseCompletedHandler(IAPProduct product)
    {
        Debug.Log(product.Name);
        _onComplete.OnNext(true);
    }

    // 購入失敗処理
    private void PurchaseFailedHandler(IAPProduct product, string failureReason)
    {
        Debug.Log("The purchase of product " + product.Name + " has failed with reason: " + failureReason);
        _onComplete.OnNext(false);
    }

    // リストア成功通知
    // 通知のみ
    private void RestoreCompletedHandler()
    {
        Debug.Log("All purchases have been restored successfully.");
    }

    // リストア成功通知
    private void RestoreFailedHandler()
    {
        Debug.Log("The purchase restoration has failed.");
    }
}

使い方例

[SerializeField] private PurchasingProcessController _purchasingProcessController; 

// Viewで購入する商品を選択
_view.OnSelect.Subscribe(productName =>
{
    _purchasingProcessController.DoPurchase(producName);
});

// 購入の成功/失敗に応じて処理を分岐
_purchasingProcessController.OnComplete.Subscribe(isSuccess =>
{
    Debug.Log(isSuccess ? "購入に成功しました" : "購入に失敗しました。\n再度お試しください。");
});

まとめ

課金機能は初期化処理周りのハンドリングが面倒ですが、Easy Mobile Proは初期化も自動で行ってくれます。 Easy Mobile Proは約$100とお高めなアセットですが今回紹介した課金機能以外にも様々な機能が含まれています。 また、アップデートも行われておりUnity2020にも対応していました。 導入の参考になれば幸いです。