0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Storekit2を使った課金処理でpending時の挙動をデバッグ&テストする

Posted at

概要

StoreKit2ではpurchaseの実行時、Product.PurchaseResultがレスポンスとして返却される。
その中のPurchaseResult.pendingについて、XCode上でのデバッグ及びStoreKitTestを用いたユニットテストを実装したのでその備忘録。

pendingとは

何らかの事情により、購入が一時保留となり、承認後に購入が確定する状態のこと。

主に子どもがアプリ内課金で製品を購入しようとした際に、親や保護者の承認がないと通らないパターン。
アプリの性質上あまり該当者はいないと思うが、とは言え対応は必要。

デバッグ方法

pending時には、保留ダイアログが表示される実装を行ったので、その動作確認を行う。

StoreKitConfigを使ってXCode上でデバッグ可能な状態にしてあるので、Configを設定する。

スクリーンショット 2024-09-28 21.52.17.png

Purchase Options のAsk to BuyをEnabledにする

デバッグ用のアプリを起動し、課金処理を行うと承認を求める旨がダイアログで表示されるようになる

スクリーンショット 2024-09-28 21.53.41.png

Askを選択。これで保留状態になり、PurchaseResult.pendingが返ってくる、自前で実装したダ
イアログも表示されることが確認できた。

スクリーンショット 2024-09-28 21.58.35.png

実際に承認/非承認を行う際はXCodeで
Debug > Manage Transactions からpendingになっているトランザクションを選択し、赤枠のどちらかのボタンを押す。

スクリーンショット 2024-09-28 22.00.40.png

なお、下記実装によりアプリ起動中にトランザクションを監視しているため、承認直後、購入完了状態が即座に反映される。
(復元ボタンは実装しているが、実際はこの監視によりユーザの操作はほぼ不要)

func updatePurchasedProducts() async {
        for await result in Transaction.currentEntitlements {
            guard case .verified(let transaction) = result else {
                continue
            }
            
            if transaction.revocationDate == nil {
                //承認された場合、このスコープの処理が実行される。(トランザクションを終了させる)
                self.purchasedProductIds.insert(transaction.productID)
                await transaction.finish()
            } else {
                self.purchasedProductIds.remove(transaction.productID)
            }
    
        }
    }
    
    // アプリの外部で作成されたトランザクションの更新の監視。init時にこのメソッドを実行している。
    private func observeTransactionUpdates() -> Task<Void, Never> {
        Task(priority: .background) { [unowned self] in
            for await _ in Transaction.updates {
                await self.updatePurchasedProducts()
            }
        }
    }

テスト

Ask to BuyをEnabledにする設定をStoreKitTestで書く場合、SKTestSession.askToBuyEnabledをtrueにするだけでよい

final class PurchaseManagerTest: XCTestCase {
    
    var session: SKTestSession!
    var purchaseManager: PurchaseManager!

    // setUp関数でsessionを初期化しておく

    func testPurchasePending() async throws {
       
        session.askToBuyEnabled = true // この1行を書くだけ
        
        await purchaseManager.purchase(product)
        
        //...
    }

##まとめ
PurchaseResult.pendingのデバッグ及びユニットテストの実装が問題なくできた。

アプリ内課金全般に言えることだが、やはりStoreKitConfigで簡単にデバッグ出来るのがありがたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?