🍑

Android 定期購入 新機能と対応方法を解説 (2020/11/1まで対応必要)

2020/10/27に公開1

Google Play Consoleにアクセスすると、2020/10/25現在、次のようなメッセージが表示されるようになっています。

この記事では、メッセージに表示されている

  1. アカウントの一時停止
  2. アカウントの復元
  3. 定期購入の一時停止
  4. 定期購入の再登録

の内容、そして対応方法とテスト方法を解説します。

① アカウントの一時停止

(※「アカウントの一時停止」は2020/11/1以降、必須の機能となります。)

定期購入の更新タイミングで、支払い処理が失敗すると、支払猶予期間(デフォルトは7日間)に入りますが、猶予を過ぎても支払い処理が失敗し続けている場合、 今までは解約されて終わり でした。

2020/11/1以降は、支払猶予後、30日間 「アカウントの一時停止」 というステータスになります。
(テスト環境では10分)

「アカウントの一時停止」 中は、購入中の商品情報を返す、BillingClient.queryPurchases()に、商品情報が来なくなる ので、一見、解約したように見えます。

しかしレシートを取得すると 「paymentState」 が0になっていることで確認できます。

expiryTimeMills: 過去の日付
autoRenewing: true,
paymentState: 0 // 保留中

Google Playアプリの
設定 > 定期購入
には、エラーメッセージが表示されます。

「修正」を押し、支払い方法を修正して正常に課金が行われるようになると、自動で定期購入が再開されます。

「アカウントの一時停止」中に支払いが再開された場合、定期購入は継続扱いになるため、1年以上継続課金されるとプラットフォーム手数料が30%から15%に下がる恩恵にあずかりやすくなる変更が入った訳です。

対応方法

公式ドキュメントには

定期購入がアクティブでなくなったことを知らせるためにプッシュ通知またはメールをユーザーに送信することをおすすめします。

定期購入のステータスがアカウントの凍結になった場合は、コンテンツやサービスへのアクセスをブロックする必要があります。アカウントの凍結期間は最大 30 日間です。

とありますが、テストしてみたところ、Googleさんがプッシュ通知とメールは送ってくれていた
ので対応は必要なさそうです。

コンテンツやサービスへのアクセスをブロックする必要があります。

は、定期購入中に再び購入しようとしても「定期購入中」ですとストアがエラーを出して購入できないのですが 「アカウントの一時停止」中は購入できてしまい「定期購入の継続期間がリセットされる」 ので必ずブロックしないと損します。

「アカウントの一時停止」中のブロック

定期購入商品を販売する画面で、BillingClient.queryPurchases() が値を返さなかった場合、Google Play Developer APIで、レシートを取得し、

expiryTimeMillis: 過去の日付
paymentState: 0 // 保留中
autoRenewing: true

であることを見て、「アカウントの一時停止」 中であることを確認します。
paymentState: 0 だけでも判断できますが、今後も定期購入の機能は拡張されていくはずなので、3つのパラメータで判断した方が幸せになれると思います。

レシートは Google Play Developer API
「purchases.subscriptions.get」
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptions

で取得しますが「アカウントの一時停止中」はBillingClientの queryPurchases() も、queryPurchaseHistoryAsync() も情報を返さなくなるので、APIに渡す 「purchaseToken」 を定期購入が成立したタイミングでSharedPreferencesに入れて、そちらを使ってレシートを取得する方式にするのが簡単そうです。

「アカウントの一時停止」 中であることを確認したら、ストアの購入ボタン

「支払い方法を修正する」 ボタンに変更して

クリックをしたら、該当商品の詳細画面に飛ばすリンクを仕込んでおきます。

val uri = Uri.parse("https://play.google.com/store/account/subscriptions?sku=${定期購入アイテムのSKU}&package=${packageName}")
val intent = Intent(Intent.ACTION_VIEW, uri)
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
}

リンクを踏むと、Google Playアプリの
設定 > 定期購入
にある、該当商品の詳細画面に一発で飛べます。

「アカウントの一時停止」 前に発生する デフォルト7日間の猶予期間 は、BillingClientの queryPurchases() が普通に情報を返し、レシートにある定期購入の有効期限 expiryTimeMillis にも自動で猶予期間が足された日付が返されるので、特に何も対応をする必要はないと思います。

より厳密に対応をしたい方は、レシート情報の

expiryTimeMillis: 未来の日付
paymentState: 0 // 保留中
autoRenewing: true

から猶予期間だと判定して、支払い方法の修正を促す何かしらのメッセージを、アプリ内に表示するのも良いかもしれません。

テスト

アカウントの一時停止 をテストしてみます。

2020/11/1からは必須になりますが、10/25現在では、Play Consoleの
該当アプリ > 商品 > 定期購入 > 定期購入の設定を管理
「アカウントの一時停止」 欄があり、デフォルトで
「ライセンステスターに対して有効」
になっているので、そのままでテストを行えます。

実装が終わって、早めに「アカウントの一時停止」を有効にしたい場合は、「有効」 に変更しましょう。

定期購入をすると、Google Playアプリの
設定 > 定期購入
に購入したアイテムが表示されます。

本番環境の定期購入期間は、テストしやすいよう、次の表の通り、テスト環境では短くなります。
https://developer.android.com/google/play/billing/billing_testing#testing-renewals

次に、先程のGoogle Playアプリの定期購入情報をタップして詳細情報を表示し、「メインのお支払い方法」「テストカード、常に不承認」 に変更して、次の更新が必ず失敗するようにします。

すると、5分後、定期購入の更新に失敗して、「猶予期間」 に入ります。
このとき、ユーザーには、更新に失敗した旨を伝えるプッシュ通知が届きます。

猶予期間も、テストがしやすいよう、テスト環境では5分 となります。

Google Playアプリの
設定 > 定期購入
には、エラーメッセージが表示されます。

「猶予期間」が過ぎると、「アカウントの一時停止」 状態に入り、その旨を伝えるプッシュ通知とメールがユーザーに届きます。

公式ドキュメントには

定期購入がアクティブでなくなったことを知らせるためにプッシュ通知またはメールをユーザーに送信することをおすすめします。

とありますが、Googleさんが送ってくれていました。

Google Playアプリの
設定 > 定期購入
には、「猶予期間」と同じエラーメッセージが表示され続けます。

「アカウントの一時停止」 中も支払い方法の修正をしなかった場合、30日後、テスト環境では10分後に システムから自動で解約が行われます。

システムからの自動解約後は、Google Playアプリの
設定 > 定期購入
は、次のような表示になります。

② アカウントの復元

「① アカウントの一時停止」 で説明した通り、定期購入の更新に失敗し、猶予期間を過ぎると 「アカウントの一時停止」 となりますが、「アカウントの一時停止」30日間の内に、Google Playアプリの
設定 > 定期購入
欄から 「修正」 を押して、購入処理が行えるカードに変更することで
「アカウントの復元」
が行われ、定期購入が再開されます。

対応方法

「アカウントの復元」 実行に関して必要な実装はありません。
「アカウントの復元」 が実行されると、BillingClient.queryPurchases() が購入した商品の情報が再び返すようになるので、onResumeで、定期購入状態を復元すればいいと思います。

テスト

「① アカウントの一時停止」の「テスト」で説明した手順から 「アカウントの一時停止」 状態にした後、Google Playアプリの
設定 > 定期購入
欄から 「修正」 を押して支払い方法を変えることで 「アカウントの復元」 が実行できます。

③ 定期購入の一時停止

(※「定期購入の一時停止」は2020/11/1以降、デフォルトでONとなります。)

今までは、何かしらの理由で定期購入を更新できない・したくない時は、 「定期購入の解約」 しかありませんでした。

2020/11/1からは、新機能として 「定期購入の一時停止」 機能がデフォルトで利用できるようになります。
ただし

年間定期購入は一時停止できません。

とのことなのでご注意下さい。

定期購入の有効期限中に、Playアプリの
設定 > 定期購入
欄から 「支払いを一時停止」 を押すと、

支払いの一時停止期間(1ヶ月, 2ヶ月, 3ヶ月)が選択できます。
(テスト環境では5分、10分, 15分)

また、「定期購入の一時停止」がON になっていると、解約を選んだ場合にも、定期購入の一時停止を促すポップアップが1枚挟まるようになります。

定期購入の一時停止と再開は

  • 現在の定期購入の更新日から開始
  • 一時停止期間が終わると、定期購入が自動で再開

されます。

対応方法

公式ドキュメントには

定期購入が一時停止している間、ユーザーは定期購入にアクセスできません。

とありますが、普通に買えてしまい、アプリ内から購入されると 「定期購入の継続期間がリセットされる」 ので、独自実装で購入をブロックしないと損します。

「定期購入の一時停止」中のブロック

定期購入商品を販売する画面で、BillingClient.queryPurchases() が値を返さなかった場合、Google Play Developer APIで、レシートを取得し、

expiryTimeMillis: 過去の日付
paymentState: 1 // 受領済
autoRenewing: true

であることを見て、「定期購入の一時停止」 中であることを確認します。

レシートは Google Play Developer API
「purchases.subscriptions.get」
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptions

で取得しますが「定期購入の一時停止中」はBillingClientの queryPurchases() も、queryPurchaseHistoryAsync() も情報を返さなくなるので、APIに渡す 「purchaseToken」 を定期購入が成立したタイミングでSharedPreferencesに入れて、そちらを使ってレシートを取得する方式にするのが簡単そうです。

「定期購入の一時停止」 中であることを確認したら、ストアの購入ボタン

「定期購入を再開する」 ボタンに変更して

クリックをしたら、該当商品の詳細画面に飛ばすリンクを仕込んでおきます。

val uri = Uri.parse("https://play.google.com/store/account/subscriptions?sku=${定期購入アイテムのSKU}&package=${packageName}")
val intent = Intent(Intent.ACTION_VIEW, uri)
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
}

リンクを踏むと、Google Playアプリの
設定 > 定期購入
にある、該当商品の詳細画面に一発で飛べます。

「定期購入の一時停止」 の終了後は BillingClient.queryPurchases() が購入した商品情報を返すので、onResumeで、定期購入状態を復元すればいいと思います。

テスト

2020/11/1からはデフォルトでONになりますが、10/25現在では、Play Consoleの
該当アプリ > 商品 > 定期購入 > 定期購入の設定を管理
「一時停止」 欄があるので、
「ライセンステスターに対して有効」
に変更し、あわせて、定期購入の一時停止が切れた後に、課金処理がうまく行かない場合 「アカウントの一時停止」 状態になるため、
「アカウントの一時停止」 欄も 「ライセンステスターに対して有効」 に変更しておく必要があります。
(が、2020/10/25現在、デフォルトで「アカウントの一時停止」は「ライセンステスターに対して有効」になっています。)

ただ、変更してから定期購入の一時停止が使えるようになるまでラグがあるのか、設定を変えたすぐ後は、Google Playの設定 > 定期購入を見ると一時停止になっていても、アプリ上では普通に定期購入が更新されてしまったので、動作がおかしい場合は、半日ぐらい待ってみて下さい。

④ 定期購入の再登録

(※「定期購入の再開」は既に、デフォルトでONとなっています。)
(※公式ドキュメントは再登録と書いているが、Play consoleには「再開」と書いているので注意)

「定期購入の再登録」をON にしすると、解約した定期購入は、有効期限が切れるまで はGoogle Playアプリの
設定 > 定期購入
欄に表示され続け、そこから定期購入の再登録ができます。

対応方法

「定期購入の再登録」 に必要な実装は特にありません。

テスト

「定期購入の再開」は既に、デフォルトでONとなってる のでテストをするために特別に必要な設定もありません。

公式資料のリンク

便利な資料

queryPurchases と Google Play Developer API purchases.subscriptions.get の関係

Discussion

カットボスカットボス

私も定期購入の対応を終えたばかりでしたので、見直しとして参考になりました。有難う御座います!