🧾

Google Play Billing LibraryでBasePlanIdを購入後に利用する

2023/04/26に公開

環境

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を使って文字列を紐づけておくことができる。具体的には、obfuscatedAccountIdobfuscatedProfileIdを紐づけられる。本来は難読化されたアカウント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を利用できるようになった。

脚注
  1. また、以前にあったdeveloper payloadは非推奨になっているので注意 ↩︎

Discussion