概要
StoreKit2ではpurchaseの実行時、Product.PurchaseResult
がレスポンスとして返却される。
その中のPurchaseResult.pending
について、XCode上でのデバッグ及びStoreKitTestを用いたユニットテストを実装したのでその備忘録。
pendingとは
何らかの事情により、購入が一時保留となり、承認後に購入が確定する状態のこと。
主に子どもがアプリ内課金で製品を購入しようとした際に、親や保護者の承認がないと通らないパターン。
アプリの性質上あまり該当者はいないと思うが、とは言え対応は必要。
デバッグ方法
pending時には、保留ダイアログが表示される実装を行ったので、その動作確認を行う。
StoreKitConfigを使ってXCode上でデバッグ可能な状態にしてあるので、Configを設定する。
Purchase Options のAsk to BuyをEnabledにする
デバッグ用のアプリを起動し、課金処理を行うと承認を求める旨がダイアログで表示されるようになる
Askを選択。これで保留状態になり、PurchaseResult.pending
が返ってくる、自前で実装したダ
イアログも表示されることが確認できた。
実際に承認/非承認を行う際はXCodeで
Debug > Manage Transactions からpendingになっているトランザクションを選択し、赤枠のどちらかのボタンを押す。
なお、下記実装によりアプリ起動中にトランザクションを監視しているため、承認直後、購入完了状態が即座に反映される。
(復元ボタンは実装しているが、実際はこの監視によりユーザの操作はほぼ不要)
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で簡単にデバッグ出来るのがありがたい。