店舗BGMアプリ『Simple BGM』課金ユーザーの非自発的解約防止のためプッシュ通知を実装した件

# 概要
こんにちは！[株式会社ワールドスケープ](https://world-scape.net/)のWakacchiと申します。
弊社は「実力あるアーティストが、公正に、経済的に評価される世界を作る」というミッションのもとに、[Frekul](https://frekul.com/)というアーティストの音楽活動をサポートするプラットフォームを中心としたWEB・スマートフォンアプリの自社サービス開発や受託開発を主な事業としています。

今回、自社サービスの[Simple BGM](https://bgm.world-scape.net/)というアプリの、課金ユーザーの非自発的解約を防止するためのプッシュ通知を実装した件を紹介します。

まず"非自発的解約"について補足します。
Androidアプリの定期購読解約には自発的解約と非自発的解約の２パターンあります。

自発的解約とは、ユーザーが自ら解約の意思をもってGooglePlayストアから解約したもの。
非自発的解約とは、ユーザーの支払いが完了しなかったために解約されたものです。（例：クレカの有効期限が切れていた、残高不足により決済ができなかった）

後者の場合、解約の意志がないのに解約してしまうというケースが考えられます。
そのような非自発的解約の防止策として、２つのことを実施しました。

・Google Playの課金システムにて設定できる通知
・猶予期間に突入したユーザー情報をサーバー上で取得し、支払い情報変更を促すプッシュ通知

その際に学んだことのまとめ記事です。



# Google Playの課金システムにて設定できる通知

Google Play Console を開いて、[定期購入] ページ（[収益化] > [商品] > [定期購入]にて定期購入を作成。
次に作成した定期購入の[定期購入を確認] をクリックして、基本プランを作成。作成した基本プランの[基本プランの表示]をクリックすると下記の設定ができます。

・猶予期間
・ユーザーの基本プランと特典の変更
・再度定期購入

猶予期間をMAXの「30日」、再度定期購入を「許可」とし、支払い情報を変更して再契約できる期間を最大にしました。

下記、Play Console ヘルプからの引用と、実際にユーザーに届く通知のサンプルです。

### 猶予期間突入時の通知
猶予期間の開始時点に、お支払いが不承認となったことが定期購入者にメールで通知されます。定期購入者には、定期購入を中断しないでお支払い方法を更新するための猶予期間が与えられます。定期購入者がお支払い方法を有効な方法に更新すると、次回の定期購入の請求日程は以前と同様になります。

メールに届く通知はこんな感じです↓
![qiita_sample1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2879943/23c031e6-527e-9eca-8d10-dea20b28592d.jpeg)


### アカウント一時停止時の通知

猶予期間終了後、解約ではなくユーザーが定期購入を一時停止できるようにする設定もあります。手順は次のとおりです。

Google Play Console を開き、[収益化のセットアップ] ページ（[収益化] > [収益化のセットアップ]）に移動。
[定期購入の設定] で [一時停止] を [有効] に変更。[変更を保存] をクリック。

猶予期間が終了しても、定期購入者のお支払い方法がまだ不承認となっている場合、Google がお支払い処理を再度試みる間、30 日間にわたってその定期購入は一時停止となり、定期購入者は定期購入コンテンツにアクセスできなくなります。定期購入が一時停止している間、ユーザーは定期購入にアクセスできません。一時停止期間が終了すると、Google は定期購入の更新を試みます。正常に再開できれば、定期購入が再び有効になります。

メールに届く通知はこんな感じです↓
![qiita_sample2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2879943/2666a90b-8461-265e-b679-aa22ac87e494.jpeg)



# 猶予期間に突入したユーザー情報をサーバー上で取得し、支払い情報変更を促すプッシュ通知

#### purchases.subscriptions.get で startTimeMillis を使って判定

日時バッチでv1(purchases.subscriptions.get)で取得した paymentState が0の場合、　startTimeMillis　で最終決済日を取得、32 + 3n日後 (n = 0, 1, 2, ...) にプッシュ通知を送るという仕様です。

要件としては、猶予期間中、3日ごとにプッシュ通知を送れるのであれば、正確に猶予期間の開始日から3日後、6日後でなくてもよかったため、　startTimeMillis を取得し、32日後、35日後というカウントで設定しました。月ごとの差が許容される場合にのみ使える手です。

日時の推移とユーザの行動（支払情報の状況を含む）のパターンとしてはこちら↓のケース4(B-a)に該当します。
[【Androidアプリ内課金】定期購読の猶予期間を1から100まで理解する > ケース別詳細](https://qiita.com/ckm/items/3d50b5f601f2a8ec8fe9#%E3%82%B1%E3%83%BC%E3%82%B94b-a)


#### プッシュ通知実装時に発生した課題

この方法で実装するまでに、下記のエラーが発生し壁にぶちあたりました。
同じような状況に陥った方に参考になるよう、解決法を含め記述しておきます。

【1】
サービスアカウントを作成する前に定期購入を作成していた場合、
Google Play Consoleで定期購入の情報をいったん編集して保存しないと
権限エラーが発生する、という事象があるようです。

何か変更がないと保存できないので、例えば「説明」の欄を少し変更して保存し、
また戻して保存する、といった操作をする必要があります。

https://stackoverflow.com/questions/43536904/google-play-developer-api-the-current-user-has-insufficient-permissions-to-pe

こうすることで、権限エラーが解消され、APIからレスポンスが返されるようになりました。

【2】
subscription APIにアクセスした時のサービスアカウントとは別に、
Firebaseが自動で作るサービスアカウントがあるようで、
こちらを使うとプッシュ通知が送信できました！

（APIにアクセスするサービスアカウントと、
　プッシュ通知に使うサービスアカウントの2つがある、という状態です）


# 参考記事
今回の施策を実施するにあたり、参考にさせていただいた素晴らしい記事を紹介します。
[【iOS/Android】アプリ内課金 定期購読のサーバーサイド知識総まとめ](https://qiita.com/ckm/items/b8cf23ba4bd0ae5bbf34)
[【Androidアプリ内課金】定期購読の猶予期間を1から100まで理解する](https://qiita.com/ckm/items/3d50b5f601f2a8ec8fe9#%E3%82%B1%E3%83%BC%E3%82%B94b-a)

さらに著者である[ウルシステムズさん](https://qiita.com/organizations/ulsystems_inc)から多大なアドバイスをいただきました。本当にありがとうございました。

また、定期購入について基本的な情報を公開している公式記事はこちらです。
[【公式】Play Consoleヘルプ 定期購入について理解する](https://support.google.com/googleplay/android-developer/answer/12154973)
[【公式】Play Consoleヘルプ 定期購入を作成、管理する](https://support.google.com/googleplay/android-developer/answer/140504)
最新情報は必ず公式な情報を確認してください。