【Swift】SwiftyStoreKitでアプリ内課金の実装【iOSアプリ開発】
はじめに
iOSのアプリ開発をしている上で、課金システムを導入する場合に処理が複雑で実装するにはハードルが高かった。そこで何か良いライブラリがないか探していたところ「SwiftyStoreKit」ライブラリを見つけた。実際使ってみたところ大変わかりやすく便利だったので、この記事では「SwiftyStoreKit」の使い方を説明していく。なお、この記事では「非消耗型の課金アイテム」を対象としている。
https://github.com/bizz84/SwiftyStoreKit
アプリ内課金を実現するSwiftyStoreKitのインストール
今回はpodでSwiftyStoreKitをプロジェクトから使えるようにしていく。pod 'SwiftyStoreKit'
でSwiftyStoreKitをインストールしよう。そしてSwiftyStoreKitを使いたいクラスに、import SwiftyStoreKit
を記述しておく。SwiftyStoreKitの初期化のために、下記コードを
application(:didFinishLaunchingWithOptions)
に追加する。
// おまじないのようなもの。下記コードをapplication(:didFinishLaunchingWithOptions)などに追加しよう。
.completeTransactions(atomically: true) { purchases in
SwiftyStoreKitfor purchase in purchases {
switch purchase.transaction.transactionState {
case .purchased, .restored:
if purchase.needsFinishTransaction {
.finishTransaction(purchase.transaction)
SwiftyStoreKit}
// Unlock content
case .failed, .purchasing, .deferred:
break // do nothing
}
}
}
説明では一度だけ呼ばれるべきだと書いてあるので注意しておく。
Note that completeTransactions() should only be called once in your code, in application(:didFinishLaunchingWithOptions:).
価格などのプロダクト情報を取得
次の非同期処理で、価格などのプロダクト情報を取得することができる。少し時間がかかるので、呼び出すタイミングを工夫したい。
.retrieveProductsInfo(["プロダクトID"]) { result in
SwiftyStoreKitif let product = result.retrievedProducts.first {
// ここでプロダクト情報が得られるので、うまく使いまわしたい。
("Product: \(product.localizedDescription), price: \(priceString)")
print
} else if let invalidProductId = result.invalidProductIDs.first {
// print("Invalid product identifier: \(invalidProductId)")
} else {
// print("Error: \(result.error)")
}
}
はじめて課金アイテム購入した場合の処理
はじめて課金アイテム購入した場合の処理は次の通り。成功したか失敗したかを返してくれるので、課金処理が非常にラク。
.purchaseProduct("プロダクトID", quantity: 1, atomically: true) { result in
SwiftyStoreKitswitch result {
case .success(let purchase):
// print("Purchase Success: \(purchase.productId)")
// 購入後の処理はここに記述しよう。例えばUser Default などのフラグを変更するとか。
case .error(let error):
// switch error.code {
// case .unknown: print("Unknown error. Please contact support")
// case .clientInvalid: print("Not allowed to make the payment")
// case .paymentCancelled: break
// case .paymentInvalid: print("The purchase identifier was invalid")
// case .paymentNotAllowed: print("The device is not allowed to make the payment")
// case .storeProductNotAvailable: print("The product is not available in the current storefront")
// case .cloudServicePermissionDenied: print("Access to cloud service information is not allowed")
// case .cloudServiceNetworkConnectionFailed: print("Could not connect to the network")
// case .cloudServiceRevoked: print("User has revoked permission to use this cloud service")
}
}
}
リストア処理
最後にリストア処理の紹介。restorePurchases
を呼び出すことで、購入済みのアイテムが配列で返ってくるので、for文で回してチェックすれば良い。
.restorePurchases(atomically: true) { result in
SwiftyStoreKitfor product in result.restoredPurchases {
if product.needsFinishTransaction {
.finishTransaction(product.transaction)
SwiftyStoreKit}
if product.productId == "プロダクトID1" {
// プロダクトID1のリストア後の処理を記述する
} else if product.productId == "プロダクトID2" {
// プロダクトID2のリストア後の処理を記述する
}
}
}