Google Play Billing LibraryでBasePlanIdを購入後に利用する
環境
Google Play Billing Library 5.1.0
問題
Google Play Billing Library v5を用いて、サブスクリプションの実装を行うケースを考える。
フローとして、ストアでのサブスクリプションの購入後、その検証とサブスクリプションの利用権がサーバーサイドで行使(ユーザーへの紐付けなどの何らかの処理)した後、承認する。
サーバーサイドでは、サブスクリプションの基本プランID(basePlanId
)が必要になるケースがある。
Google Play Billing Libraryのv5から、サブスクリプションモデルの刷新が行われた。これにより、サブスクリプションには基本プランとオファーという新たなエンティティが登場する。
以前は製品ID(productId
)のみでプランが一意に定まっていたが、基本プランの登場でそうではなくなった。なので、サーバーサイド側でユーザーが契約したプランを取得するには基本プランIDが必要になる。
しかし、Purchaseは基本プランIDを持っていないので、ストアからアプリに購入が通知される際に取得できない。なので、ここでは力技でPurchase
から基本プランIDを取得できるようにする。
解決法
購入にはAccountIdentifiers
を使って文字列を紐づけておくことができる。具体的には、obfuscatedAccountId
とobfuscatedProfileId
を紐づけられる。本来は難読化されたアカウントIDが紐づけられる空間だが、ProfileIdはストア側で利用されていないので、ここに基本プランIDを詰める[1]。
// queryProductDetails等からProductDetailsを取得して、対象の基本プランIDを抽出する
val basePlanId: String = TODO()
// ...
val billingFlowProductParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(listOf(billingFlowProductDetailsParams))
.setObfuscatedAccountId("unused") // obfuscatedProfileId を設定するには、obfuscatedAccountIdも指定しておく必要がある
.setObfuscatedProfileId(basePlanId)
.build()
// 購入フローの起動
billingClient.launchBillingFlow(activity, billingFlowProductParams)
そして、購入後にonPurchasesUpdated
で購入の通知を受ける際には、purchases
から取り出す。
purchases?.forEach { purchase ->
val basePlanId = purchase.accountIdentifiers?.obfuscatedProfileId ?: TODO()
}
これで、サーバーサイドにリクエストを投げる際に、得られた基本プランIDをリクエストに与えておくか、レシート(originalJson
)内のobfuscatedProfileIdを参照することで、基本プランIDを利用できるようになった。
-
また、以前にあったdeveloper payloadは非推奨になっているので注意 ↩︎
Discussion