この記事はReact Native未経験からプロジェクト参加半年で不毛な様々なテストによって得られた知見を並べていこうかなと思って書いています。
実装方法については書いてません。 テスト時に出た不具合にどう立ち向かったかという覚書です。
環境は以下の通り
- MacBook Pro 16-inch, 2019 (Ventura 13.6(22G120))
- Xcode: 15.0.1
- openjdk: 11.0.18
- Node.js: 18.15.0
- expo: 48.0.21
- react-native: 0.71.14
- react-native-iap: 12.10.5
- 最新版ではPBL6になったらしいけど、この時点ではPBL5です
- iOS はStoreKitを使っていて、StoreKit2は使っていません
React Nativeにおけるアプリ内課金の実装
使用するアプリ内課金ライブラリです。
react-native-iap
基本的な実装は IapExample にある通りに行えばいいと思います。
テスト内容
1. 通常の購入フロー
特に癖のないオンライン状態で一通り購入処理を流れどおりに行います。
ここで既に意図しない動きをしている場合はおそらく実装が間違っています。
正常完了することだけを目標に修正しておきます。
2. 無料トライアル期間中に解約する
無料期間中の解約は期間終了とともにレシートが消えます。(正確には取得できるものがなくなる)
レシートが取れること前提で購入検証処理を組んでいるとことごとく詰みます。
検証時にネットワークエラー以外でレシートが取れなかった場合は未購入状態に戻すなどのフローが必要です。
3. 本購入期間突入後、更新前に解約する
無料期間が終わり、初めて課金されてからの解約した場合の動きは以下の通り。
- 期間終了後は
getAvailablePurchases()
ではレシートが取れないかも知れない -
getPurchaseHistory()
は期限切れのレシートも取れるので一応確認できるけど、iOS ってレシートが雪だるま式に増えてない?(すごく重い)
という感じなので、こちらもネットワークエラー以外で新しいレシートが取れないor取れたけど期限切れになっている場合は未購入状態に戻すというフローで良さそう。
4. 購入処理中にネットを切断する
世の中絶対なんて言葉はないので、購入ボタンを押したあとにネットに繋がらない状態が発生することを想定したテストです。
各OSネイティブの購入ボタンを押してからの時間経過具合で動きが変化するので結構厄介です。
- そもそも購入前にオフライン
- 購入ボタンを押した直後にオフライン
- OSネイティブの購入が完了するタイミングでオフライン
1つ目は、OSネイティブの購入ボタンを押す前にオフラインにした場合ですね。そもそもストアに購入の意思が送信できないのでネットワークエラーで片付きます。
2つ目は、OSごとに動作が違うような気がします。
iOS はネイティブの購入完了が出てからオフラインにし、レシートの検証などが終わらない状態を作った場合、未購入状態に戻るようです。(買い直しても二重購入にはならなかった)
Androidは購入する意思を示した時点で「購入済み」扱いになるみたいですが、処理中アイテムがキャッシュされてるという状態なんですかね?状態が全く見えない...
- 購入ボタンを押した直後にネット切断→OSの購入画面下に「ネットに接続してください」が出続ける。
- そこでネットに接続すると「購入済みです」の表示が出る。
- しかし、
getAvailablePurchases()
するも有効なレシートが取れない。(そもそも購入が完了してない) - 仕方なく、もう一度購入を実行すると既にこのsku idは購入済みと出る。(多分ここまで来るとレシートが発行される?)
- その後、Play ストアの定期購読に期限までにアプリを開いて購入プランの確認をするようにというメッセージが表示される。(購入が承認されていない場合に発生する猶予期間という扱い)
多分、Play Billing Libraryのレスポンスコード的には1回目の購入ボタンから「購入済みです」が出た時は ITEM_NOT_OWNED
で、2回目の購入ボタンから「sku idは購入済み」と出た時は ITEM_ALREADY_OWNED
かなと勝手に予想立ててますが、ちょっと対処方法で悩んでいます。
後で調べて見たんですが、両方ともResponseCodeは7だったので、ITEM_ALREADY_OWNED
みたいです。
しかし、2回目押さないとレシート取れなかったんですよね...まだ分からないことが残ってる。
ITEM_ALREADY_OWNED
が来る場合はレシートを取得して購入状態を復元すれば使えそうですが、その際、注意が必要なのは、acknowledged
の状態です。
Play ストアに購入プランの確認メッセージが出ている場合、acknowledged
がfalseです。
期限までにPlay Billing Libraryの acknowledgePurchase()
つまり react-native-iapの finishTransaction()
を呼び出さないと自動更新されずに解約されます。
割りと「購入プランの確認」とかで検索すると、クレジットカードの期限が切れてて~みたいな記事しか出てこないので、気づけませんでした。
finishTransaction()
は普段、購入時に取れたレシートに対して行う処理かと思われますが、こういう購入を途中でオフラインにしてしまうみたいなテストすると不具合として出てきたりするんですよね。
3つ目は、次回レシート検証タイミングで取得して検証すればいいかなぐらいですかね。
まとめ
まだ完全解決には至っていませんが、Androidで購入時にオフラインにした時の諸々の不具合に関して、薄っすらと状態が見えてきた気がします。
USB接続で実機検証してても機内モードとかした途端にMetroの接続切れてしまうのでAndroid StudioとかXcodeとかでログ出しながら見ないとダメですね...(そっちでも見られるか分かってない)
仕方ないのでこのあたりも踏まえて、確認に努めていこうと思います。