Unity IAP v5 イベントの発生タイミングについて調べてみた
こんにちは!情熱開発部プログラム1課の金澤です。
夏も真っ盛りで、いろいろなソーシャルゲームでもイベントが開催されていますね!
私も自分がやっているゲームではついつい課金をしてしまいます。
今回はそんな課金周りで重要になるUnity IAPのイベント周りについて調べてみたのでご紹介したいと思います!
今回の環境
- Unity6.2
- Unity IAP 5.0.4
- iPhoneXS IOS16
- Android Android16
- サンドボックス/内部テスト環境
- サーバー通信あり
Unity IAP v5のイベントについて
Unity IAPv5でよく使う基本イベントについては以下になります。
本ブログでは以下のイベントたちがどのタイミングで呼ばれるかをこれからご紹介させていただきます。
| イベント名 | 概要 |
|---|---|
| OnStoreDisconnected | ストアとの接続失敗 |
| OnProductsFetched | 商品情報(カタログ)の取得完了 |
| OnProductsFetchFailed | 商品情報の取得失敗 |
| OnPurchasesFetched | 購入履歴(所有情報)の取得完了 |
| OnPurchasesFetchFailed | 購入履歴の取得失敗 |
| OnPurchasePending | 購入処理中(アプリ側の確認待ち) |
| OnPurchaseConfirmed | 購入の最終確定(完了) |
| OnPurchaseFailed | 購入の失敗・キャンセル |
正常なフローにおけるイベントのタイミング
まずはエラー等が起きない正常なフローにおけるタイミングから見ていきます。
初期化

初期化処理はアプリ起動時から始まり、まずはストアとの接続を行います。
ストア接続は await で完了を待機できるため成功時のコールバックイベントは用意されておらず、接続に失敗した場合のみ OnStoreDisconnected が呼び出される仕様になっています。
ストアとの接続が確認できたら、「商品情報の取得」➔「購入情報の取得」 の順で処理を進めます。
それぞれの実行関数と、対応するイベントの関係は以下の通りです。
| リクエスト(呼び出し) | 対応コールバック | 処理内容 |
|---|---|---|
| StoreController.FetchProducts() | OnProductsFetched | 商品情報の取得 |
| StoreController.FetchPurchases() | OnPurchasesFetched | 購入情報の取得 |
購入

購入ボタンを押してからのフローは、まずストア側の決済処理を走らせるためにPurchaseProductを呼びます。
ストア側での決済処理が完了すると、OnPurchasePendingイベントが呼び出されます。
OnPurchasePendingでは、アプリ側でレシート検証などの必要な処理が終了したらConfirmPurchaseを呼び出してストアへ取引完了の通知を送信します。
ストア側が完了通知を受け取るとOnPurchaseConfirmedが返ってくるのでこれが返ってきた段階で購入フローは終了となります。
リストア

リストア処理については、ストアコントローラからRestoreTransactionsを呼び出した後に二つの処理が走ります。
リストア自体に専用のコールバックは無く、リストアが呼び出されると基本的にはOnPurchasesFetchedが呼ばれます。
ただこの際に購入が未完了のものがある場合はOnPurchasePendingも同時に呼ばれます。
購入が失敗した場合などは?
では、購入の途中で通信が途切れてしまったり、アプリが終了してしまった場合はどうなるのでしょうか?
先ほどの購入処理のフローを再度見てみましょう。

通信切断やアプリ落ちが発生するタイミングとしては主に以下の2パターンがあります。
ストア側の決済「前」に切断された場合

この場合はユーザーが決済をキャンセル(もしくはエラー)したという扱いになるため、アプリ側はOnPurchaseFailedの通知を受け取り処理することが出来ます。
お金も引き落とされる前のため、アプリ側としては「購入失敗」として処理をそのまま終了して問題ありません。
ストア側の決済「後」に切断された場合

発生してほしくないものの、開発時に最も遭遇しやすいのがこのパターンです。
ストア側での決済は完了したにも関わらず、アプリ側でConfirmPurchaseを呼び出す前に切断されてしまう形になります。
しかし、ConfirmPurchase を呼び出されず終了できなかった取引については、「未完了の購入」としてストア側のデータに残ります。
この「未完了の購入」については以下のタイミングで再度OnPurchasePendingの呼び出しが行われます。
- 初期化時など
OnPurchasesFetchedが呼ばれた場合 - 手動でリストア処理を呼び出した場合
- ユーザーが別の商品を購入しようとした場合
初期化時やリストアを実行した際の挙動については、比較的イメージしやすいかと思います。
OnPurchasesFetched が呼ばれることで、「未完了の購入」があることがストアが認識するため、改めてアプリ側へ OnPurchasePending を呼び出してくれます。
そのため、特に注意が必要なのが3つ目の「別の商品を購入しようとした場合」です。
ストアは未完了の購入を優先して終わらせようとするため、新しく買おうとした商品とは別に、過去の未完了商品の購入処理が手前に割り込んで流れてきます。
なので、「今どの商品の処理が走っているのか」をアプリ側でしっかり管理しておく必要があります。
「未完了の購入」については、ConfirmPurchase を呼ぶまで上記のタイミングで何度も通知され続けます。
だからこそ、購入処理が終わったら必ず ConfirmPurchase を呼んで取引を完了させることが何より重要になります!
まとめ
今回は、Unity IAP v5における主要なイベントの発火タイミングについてご紹介しました。
本記事では初心者の方向けに、細かい仕様をすべて詰め込むのではなく、まず押さえておきたい重要ポイントを中心にまとめています。
最後に、今回解説したイベントタイミングのおさらいをしておきましょう。
- 初期化時: ストア接続後に
OnProductsFetchedやOnPurchasesFetchedが順に走る - 通常購入時:
OnPurchasePending➔ レシート検証など ➔ConfirmPurchase➔OnPurchaseConfirmed - 未完了の購入がある時: アプリ起動時やリストア時、さらに別商品を買おうとした時にも遅れて
OnPurchasePendingが割り込んで届く
通常購入のフローだけでなく、通信エラーやアプリ落ちといった失敗・未完了時に「何がどのタイミングで呼ばれるのか」をあらかじめ知っておくだけで、いざ実装した際に起きる「なぜ今このイベントが呼ばれたんだろう?」という不安や疑問をぐっと減らすことができます。
Unity IAP v5を使い始めた際の実装のヒントとして、本記事が少しでもお役に立てば嬉しいです!
【免責事項】
本サイトでの情報を利用することによる損害等に対し、
株式会社ロジカルビートは一切の責任を負いません。