【Flutter/Android】アプリ内課金の実装方法!in_app_purchase + テスト方法

【Flutter/Android】アプリ内課金の実装方法!in_app_purchase + テスト方法

この記事からわかること

  • Flutter/Dartアプリ内課金実装する方法
  • Androidアプリでの実装
  • in_app_purchaseパッケージ使い方

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Androidのアプリ内課金

Androidアプリでアプリ内課金を実装する大まかな流れは以下の通りになります。Flutterで実装する場合でも以下の流れは必要になるので先に対応しておいてください。

大まかな実装の流れ

  1. マニフェストファイルへのcom.android.vending.BILLINGの追加
  2. クローズドテストへのAABファイルのアップロード
  3. 商品アイテムの追加
  4. 課金処理の実装(本記事)

詳細な設定手順などは以下の記事を参考にしてください。

in_app_purchaseパッケージ

Flutterでアプリ内課金を実装する場合はin_app_purchaseパッケージを使用します。in_app_purchaseiOS / Androidでのアプリ内課金機能をラップしてFlutterで使えるようにしてくれているパッケージになります。

インストールコマンド

 $ flutter pub add in_app_purchase

pubspec.yamlの中身


dependencies:
  in_app_purchase: ^3.2.3

動作確認用のテスト環境を整える

Androidでのアプリ内課金のテスト環境は「アプリライセンス」にアカウントを登録しておく必要があります。

Google Play Consoleの「設定」 > 「ライセンステスト」で対象のアカウント(メールアドレス)を登録することができるのでここのメールリストに追加してあげればOKです。

またアプリ内課金の動作テストはエミュレーターではIllegalStateExceptionエラーが発生し商品情報を取得できないので実機で行う必要があります。

【Kotlin/Android】Google Play Billing Libraryでアプリ内課金の実装方法

実装の手順

  1. アイテム情報を取得する:queryProductDetails
  2. 購入処理を開始する:buyConsumable / buyNonConsumable
  3. 購入ストリームの観測:purchaseStream
  4. 復元処理の実装

1.アイテム情報を取得する:queryProductDetails

課金アイテムを取得するにはqueryProductDetailsメソッドを使用します。引数には取得対象となる課金アイテムIDを渡します。レスポンスはProductDetailsResponse型で取得できます。

final Set<String> _productIds = { `com.test.removeAds` };  
final _iap = InAppPurchase.instance;

final response = await _iap.queryProductDetails(_productIds);
// 取得に失敗したIDが格納される
print('notFound: ${response.notFoundIDs}');
// 取得に成功したアイテム情報が格納される
print('products: ${response.productDetails}');

ProductDetailsResponse型のnotFoundIDs 取得に失敗したIDが格納され、productDetails取得に成功したアイテム情報が格納されます。List<ProductDetails>型で取得できるのでこれを使用して購入処理や実際にUIに金額などを表示させます。

ProductDetailsのプロパティ

フィールド名 説明
id 製品ID com.test.removeAds
title 表示用タイトル 広告削除
description 商品説明 アプリ内に表示されている広告を削除することができます。
price 価格(通貨記号付き) ¥300
rawPrice 価格 300.0
currencyCode 通貨コード(ISO 4217形式) JPY
currencySymbol 通貨記号(ロケールに準拠) ¥

2.購入処理を開始する:buyConsumable / buyNonConsumable

課金アイテムを購入するにはbuyNonConsumableメソッドを使用します。購入メソッドを呼び出すとOS標準のストアの購入シートが表示され決済フローを開始されます。

Future<void> buy(ProductDetails product) async {
  final PurchaseParam param = PurchaseParam(productDetails: product);
  await InAppPurchase.instance.buyNonConsumable(purchaseParam: param);
}

購入するアイテムはPurchaseParam型でラップして渡します。

今回は非消耗型なのでbuyNonConsumableですが、消耗型であればbuyConsumableを使用する必要がありアイテムによって呼び出すメソッドが異なってくるので注意してください。またbuyConsumableを使用する際はautoConsume: trueの設定をしておかないと正しく動作しないことがあるので注意してください。

await InAppPurchase.instance.buyConsumable(
  purchaseParam: PurchaseParam(productDetails: product),
  autoConsume: true, 
);

3.購入ストリームの観測:purchaseStream

購入処理の開始後には処理中・成功・失敗などのステータスが変化します。in_app_purchaseではストリームとして提供されておりpurchaseStreamから取得することができます。引数にはステータス更新周りのコールバック・完了処理・エラー処理を渡すことができます。トランザクションが無事完了したら明示的にcompletePurchaseを呼び出して処理は完了です。

/// 購入ストリームの監視開始
final purchaseUpdated = _iap.purchaseStream;
_subscription = purchaseUpdated.listen(
  _onPurchaseUpdate,
  onDone: () => _subscription?.cancel(),
  onError: (error) {
    logger('purchaseStream Error: $error');
  },
);

/// 購入更新コールバック
void _onPurchaseUpdate(List<PurchaseDetails> purchaseDetailsList) {
  for (final purchaseDetails in purchaseDetailsList) {
    switch (purchaseDetails.status) {
      case PurchaseStatus.pending:
        logger('購入処理中...');
        break;

      case PurchaseStatus.purchased:
        logger('購入成功!');
        // 購入成功処理
        _deliverProduct(purchaseDetails);
        break;

      case PurchaseStatus.error:
        logger('購入エラー: ${purchaseDetails.error}');
        break;

      case PurchaseStatus.restored:
        logger('購入復元!');
         // 復元成功処理
        _deliverProduct(purchaseDetails);
        break;

      default:
        break;
    }

    // 完了処理
    if (purchaseDetails.pendingCompletePurchase) {
      _iap.completePurchase(purchaseDetails);
    }
  }
}

購入に成功したらユーザーに対してアイテムの付与等をしてあげればOKです。

4.復元処理の実装

iOSでは必須だった「復元処理の実装」ですがAndroidでは必須ではないようですが、機能としてはあったほうが良いので実装しておくことをお勧めします。復元処理は簡単でrestorePurchasesを実行するだけです。これで再度観測していたストリームに復元成功ステータスが流れるのでハンドリングしてあげてください。

/// 購入復元処理
Future<void> _restore() async {
  await InAppPurchase.instance.restorePurchases();
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

Search Box

Sponsor

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index