タイトルのような問題が起きたので、その原因と対策について調べてみました。
起こったこと
- iOSでアプリ内課金したのに反映されない
- もう一度購入しようとすると、「このアイテムは購入済みです。無料で再入手しますか?」と出て来るが、「OK」を押しても反映されない
- リストアをしようとしても、購入済みアイテムが見つからないというエラーになる
原因
課金処理途中で離脱するとこのような現象が発生します。 具体的には、購入途中でクレカ情報入力するなどしてアプリ外で購入&アプリのプロセス終了した時に発生します。
システム的には、上のようなフローをたどる事でアプリ上でSKPaymentTransactionが終了せずに残ってしまい、それが悪さをしていました。
再現方法
開発環境では下のようなフローで再現する事ができます。 1. アプリ内アイテムの購入をする 2. パスワード入力画面などで、Xcodeからアプリを終了する 3. そのままアプリ内課金を最後まで実施する
上フローの後にトランザクションの状態を見ると、たしかに1件未終了のトランザクションが残っていました。
print(SKPaymentQueue.default().transactions.count) // → 1
対策
購入画面のviewDidLoadに下処理を行う事で解決しました。 未終了トランザクションが残っていたらトランザクションを終了します。
SKPaymentQueue.default().transactions.forEach { if $0.transactionState != .purchasing { SKPaymentQueue.default().finishTransaction($0) } }
最初はAppDelegateのdidFinishLaunchingWithOptionsでやろうと思ったのですが、「SKPaymentQueue.default().transactions」が常に0件になってしまったので、購入画面で実施しました。