MIXI DEVELOPERS NOTE
📘

App Store / Google Play Storeでの定期購入のアップグレードとダウングレード

2022/12/11に公開

App Store / Google Play Storeの定期購入で次の様な要件を満たす方法を下記する。

  • 各ユーザーが購入できる定期購入は1つまで。
  • 定期購入はグレード別で用意されていてアップグレードとダウングレードができる。
    • 例: ベーシックプランからプレミアムプラン(よりサービスが充実していて価格が高い)にアップグレード

実現方法一覧

要件 App Store Google Play
1ユーザーが購入できる定期購入は1つまで App Store Connect上の設定(サブスクリプショングループ) setSubscriptionUpdateParams()を実装
定期購入のアップグレードとダウングレード App Store Connect上の設定(サブスクリプショングループ内の順序で設定) setSubscriptionUpdateParams()を実装
アップグレード/ダウングレード/クロスグレードの適用のされ方 仕様が決まっている setReplaceProrationMode()を実装

詳細は下記の通り。

App Store

全てApp Store Connect上の設定で指定できる(または仕様が決まっている)

1ユーザーが購入できる定期購入は1つまで

公式のサブスクリプションの作成の辺りに詳しく記載がある。
App Store Connectで次の様な設定を行うと実現できる。

  • 対象App内の サブスクリプションサブスクリプショングループ を作成。
    • この中に用意するサブスクリプションは1ユーザーにつき1つになる。

定期購入のアップグレードとダウングレード

作成したサブスクリプショングループ内に 順序に編集 というリンクがあり、そこから各グレードのサブスクリプションの順序を指定できる。
順序が低から高への変更はアップデートになり、その逆はダウングレード、順序が同じならクロスグレードになる。
サブスクリプションレベルの指定のヘルプを見るとわかるのですが、順序の数字が小さいほど高いレベルで、1が最も高いレベルのサブスクリプションになります(これは公式の説明がわかりにくいと思います)。

公式の説明はこちら。
https://help.apple.com/app-store-connect/#/dev75708c031

アップグレード/ダウングレード/クロスグレードの適用のされ方

App Storeに関してはこの仕様は決まっている模様。
https://developer.apple.com/jp/app-store/subscriptions/#ranking から抜粋すると下記の通り。

  • アップグレード ユーザーが、現在のサブスクリプションよりもサービスレベルの高いサブスクリプションを購入することを指します。この場合、ユーザーはただちにアップグレードされ、元々のサブスクリプションの利用日数に基づく金額が返金されます。追加のコンテンツや機能をユーザーがただちに利用できるようにしたい場合は、より高いランクのサブスクリプションとして設定し、ユーザーがアップグレードとして購入できるようにしてください。

  • ダウングレード ユーザーが、現在のサブスクリプションよりもサービスレベルの低いサブスクリプションを選択することを指します。この場合、現在のサブスクリプションは次回の更新日まで継続され、その後低いレベルと価格で更新されます。

  • クロスグレード ユーザーが、同等のレベルの新しいサブスクリプションに切り替えることを指します。サブスクリプションの期間が同じであれば、新しいサブスクリプションはただちに開始されます。期間が異なる場合は、新しいサブスクリプションは次回の更新日に有効になります。

Google Play Store

公式の 定期購入について理解する を見ても上記の様な要件を満たすやり方についての説明が見当たらず(月単位と年単位のプランを基本プランで組む方法はあるが、それはちょっと今回の要件と異なる)。

👇の記事がとても参考になった。
https://zenn.dev/ataka/articles/08cef284cab7ee

また、公式では👇に説明があった。

公式のコード例は多分下記のリポジトリ。
https://github.com/android/play-billing-samples/tree/main/PlayBillingCodelab

1ユーザーが購入できる定期購入は1つまで

Google Playだと
公式の Play Billing Library 5 を使用してアプリ内で定期購入を販売する のコード例のこの辺り。Play Billing Library 4 でもこの指定は可能。

private fun upDowngradeBillingFlowParamsBuilder(
   productDetails: ProductDetails,
   offerToken: String,
   oldToken: String
): BillingFlowParams {
   return BillingFlowParams.newBuilder().setProductDetailsParamsList(
       listOf(
           BillingFlowParams.ProductDetailsParams.newBuilder()
               .setProductDetails(productDetails)
               .setOfferToken(offerToken)
               .build()
       )
   ).setSubscriptionUpdateParams(
       BillingFlowParams.SubscriptionUpdateParams.newBuilder()
           .setOldPurchaseToken(oldToken) // ここで現在購読している定期購入のtokenを指定。tokenは BillingClient.queryPurchasesAsync() から取得できるPurchaseクラスのgetPurchaseToken()から取得できる
           .setReplaceProrationMode(
               BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE // 定期購入の変更時の反映のされ方を指定。
           )
           .build()
   ).build()
}

setSubscriptionUpdateParams()メソッドのパラメータのsetOldPurchaseToken()で現在購読中の定期購入があれば指定する。
そうすると、billingClient.launchBillingFlow()を呼び出した時に、Google Play 購入ダイアログで 定期購入の変更 として表示される。
setSubscriptionUpdateParams()メソッドをコールしない場合は、別の定期購入として(新規購入として) Google Play 購入ダイアログが表示される。

定期購入のアップグレードとダウングレード

#1ユーザーが購入できる定期購入は1つまでで実現

アップグレード/ダウングレード/クロスグレードの適用のされ方

#1ユーザーが購入できる定期購入は1つまでのコードの setReplaceProrationMode()メソッドのパラメータ:BillingFlowParams.ProrationModeで指定できる。
詳細な説明は比例配分モード参照。
抜粋すると下記の通り。

  • IMMEDIATE_WITH_TIME_PRORATION 定期購入は直ちにアップグレードまたはダウングレードされます。残りの期間は価格の差に応じて調整され、次回の請求日との差分が新しい定期購入に充当されます。これがデフォルト設定です。

  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE 定期購入は直ちにアップグレードされますが、請求期間は変わりません。ユーザーには残りの期間の差額が請求されます。

  • IMMEDIATE_WITHOUT_PRORATION 定期購入は直ちにアップグレードまたはダウングレードされ、定期購入の更新時に新しい価格が請求されます。請求期間は変わりません。

  • DEFERRED 定期購入は、更新時にのみアップグレードまたはダウングレードされます。

  • IMMEDIATE_AND_CHARGE_FULL_PRICE 定期購入がアップグレードまたはダウングレードされると、ユーザーには新しい利用資格の全額が直ちに課金されます。以前の定期購入の残額は、同じ利用資格に引き継がれるか、別の利用資格への切り替え時に期間内で比例配分されます。

参考

https://zenn.dev/ataka/articles/08cef284cab7ee
https://developer.android.com/google/play/billing/subscriptions?hl=ja
https://codelabs.developers.google.com/play-billing-codelab?hl=ja#5

MIXI DEVELOPERS NOTE
MIXI DEVELOPERS NOTE

Discussion