$30 off During Our Annual Pro Sale. View Details »

iOSとAndroidで定期購入の意図しない解約を防ぐ/droidkaigi2023-day1

 iOSとAndroidで定期購入の意図しない解約を防ぐ/droidkaigi2023-day1

DroidKaigi 2023 Day1 「iOSとAndroidで定期購入の意図しない解約を防ぐ」 というテーマで発表しました。 #DroidKaigi 2023/09/14
https://2023.droidkaigi.jp/timetable/493521/

More Decks by 日本経済新聞社 エンジニア採用事務局

Other Decks in Technology

Transcript

  1. DroidKaigi 2023, Electric Eel - 2023/09/14 14:20-15:00 Ryo Yamazaki &

    Yuya Sato iOSとAndroidで 定期購入の意図しない解約を防ぐ 1
  2. • Ryo Yamazaki / Android Engineer ◦ GitHub: @ymnder •

    Yuya Sato / iOS Engineer ◦ GitHub: @yutosa261 Speakers 3
  3. • 非自発的解約を防ぐための機能について解説する ◦ Grace PeriodとAccount Hold • 非自発的解約を防ぐための実装について説明する ◦ Google

    Play ストア(以降Play Store)とApp Storeの仕様差 ◦ アプリとサーバーのAPIについて 本セッションのスコープ 5
  4. • Android ◦ Google Play Billing Library 6.0の詳細な実装・解説 ◦ Amazonアプリストアのアプリ内課金について

    • iOS ◦ StoreKit 2の詳細な実装・解説 本セッションで扱わないもの 6
  5. 定期購入の解約の種類と原因(Play Store) ストアでの解約 アカウントの削除 サポートへの解約の申し込み Google Play Developer API での解約

    注文管理による定期購入の解約 自発的解約 支払いに問題があった(残高の不足やアカ ウントの削除など) 価格変更の確認が行われなかった 非自発的解約 8
  6. • Grace Period ◦ 支払いが失敗した場合に購読を解約せず、購読状態を一定期間保ち続ける機能 ▪ ユーザーが定期購入失敗時に自動解約されなくなる ▪ ユーザーに支払い情報の修正を促すことができる •

    Account Hold ◦ 支払いの失敗が解決されなかった場合にアカウントを一時停止する機能 ▪ ユーザーは有料機能は使えないが、支払いを修正すればすぐ再開できる ▪ サービスの利用期間のカウントがリセットされない ◦ iOSではBilling RetryのうちGrace Periodを除いた期間に相当 ▪ 本セッションでは便宜的にAccount Holdと呼ぶ 非自発的解約を減らすための機能 9
  7. 有効な定期購入 Grace Period 有料機能を維持 Account Hold 有料機能を制限 解約 Grace PeriodとAccount

    Hold 有効な定期購入 Grace Period 有料機能を維持 Billing retry state 有料機能を制限 解約 Play Store App Store 10 支払いに問題が発生 💥 支払いに問題が発生 💥
  8. Grace PeriodとAccount Holdの効果は高い > Developers on Google Play who use

    a grace period see a 57% higher recovery rate from renewal declines. > ref: https://medium.com/googleplaydev/how-to-win-back-subscribers-who-cancel-9960731adeb > For example, account hold has helped developers achieve 8% lower involuntary churn and 35% higher payment decline recovery rate compared to developers without account hold. > ref: https://android-developers.googleblog.com/2020/06/new-features-to-acquire-and-retain-subscri bers.html note: 引用文のBoldは発表者が追加した 11
  9. Grace PeriodとAccount Holdの期間 Play Store App Store Grace Period 3,

    7, 14, 30日間 3, 6, 16, 28 日間 Account Hold 30日間 60日間 12
  10. Grace PeriodとAccount Holdの期間 Play Store App Store Grace Period 3,

    7, 14, 30日間 3, 6, 16, 28 日間 Account Hold 30日間 60日間 Play StoreはデフォルトON、App StoreはデフォルトOFF 13
  11. Grace PeriodとAccount Holdの期間 Play Store App Store Grace Period 3,

    7, 14, 30日間 3, 6, 16, 28 日間 Account Hold 30日間 60日間 設定がなく常に有効である 14
  12. Grace Periodがoffの場合(Play Store) 有効な定期購入 Account Hold (30 days) 解約 4/1

    5/1 有効な定期購入 5/20 6/20 17 支払いに問題が発生 💥 支払いを修正
  13. Grace Periodがoffの場合(Play Store) 有効な定期購入 Account Hold (30 days) 解約 4/1

    5/1 有効な定期購入 5/20 6/20 新しい定期購入期間となる 18
  14. Grace Periodがonの場合(Play Store) 有効な定期購入 Grace Period Account Hold (30 days)

    解約 4/1 5/1 5/14 有効な定期購入 5/10 6/1 19 支払いを修正 支払いに問題が発生 💥
  15. Grace Periodがonの場合(Play Store) 有効な定期購入 Grace Period Account Hold (30 days)

    解約 4/1 5/1 5/14 有効な定期購入 5/10 6/1 Grace Periodの期間が算入 定期購入期間に変更はない 20
  16. Grace Periodがoffの場合(App Store) 有効な定期購入 Billing retry state (60days) 解約 4/1

    5/1 有効な定期購入 5/20 6/20 21 支払いを修正 支払いに問題が発生 💥
  17. Grace Periodがonの場合(App Store) 有効な定期購入 解約 4/1 5/1 5/16 有効な定期購入 5/10

    6/1 Grace Period (16 days) Billing retry state (60 days) 22 支払いを修正 支払いに問題が発生 💥
  18. 1. ライセンステスターの登録をする a. Play Consoleで[設定] > [ライセンス テスト] を選択 b.

    メーリング リストからライセンステスターを選択する c. メールアドレスを追加する 2. ライセンステスターアカウントでPlay ストアアプリにログインする a. 注意:Play ストアアプリに複数のアカウントでログインしている場合、 最初にログインしたアカウントがテスト対象となる テストができる環境を整える(Play Store) 26
  19. テストサイクル(Play Store) 有効な定期購入 Grace Period Account Hold 解約 00:00 00:05

    00:10 00:01 常に不承認を選択 00:20 30 Account Holdまで検証するには 20分かかる
  20. テストサイクル(Play Store) 有効な定期購入 Grace Period Account Hold 解約 00:00 00:05

    00:10 00:01 常に不承認を選択 00:20 Play ストア アプリから通 知とメールがくる Play ストア アプリから通 知とメールがくる 31
  21. 1. Sandboxテスターアカウントを作成する a. App Store Connectで [ユーザーとアクセ ス] > [Sandboxテスター]

    を選択 b. メールアドレスなど、必要情報を入力しアカウ ント作成 テストができる環境を整える(App Store) 33
  22. 2. デバイスでログインする a. iPhoneの [設定] > [App Store] を選択 b.

    メールアドレス、パスワードを入力しログイン テストができる環境を整える(App Store) 34
  23. 3. 猶予期間の設定 a. App Store Connectで [請求 の猶予期間] に移動 b.

    猶予期間を何日にするか設定 c. サーバー環境を選択することが でき、Sandbox環境のみで設 定可能 テストができる環境を整える(App Store) 35
  24. テストのサイクル(App Store) 有効な定期購入 Grace Period Billing retry state 解約 00:00

    00:05 00:10 00:01 [購入と更新を許可する] をオフにする 00:15 • ユーザー単位で更新間隔を変更できる • 更新間隔に応じてGrace PeriodとBilling retry stateの時間も変わる • テスト中に契約状態が変更されたことを知らせ るメールはこない 37
  25. • 購入ステータスを確認するAPIが用意されている ◦ deprecated: purchases.subscriptions.get ▪ 2022年5月に新機能がリリースされたがサポートがない ◦ purchases.subscriptionsv2.get ▪

    すべての機能が移行されているわけではないため、2022 年 5 月の定期購入変更ガイドを参照すること Google Play Developer API (Play Store) 39
  26. • subscriptionStateをチェックする ◦ SUBSCRIPTION_STATE_ACTIVE ◦ SUBSCRIPTION_STATE_IN_GRACE_PERIOD ◦ SUBSCRIPTION_STATE_ON_HOLD ◦ SUBSCRIPTION_STATE_CANCELED

    ◦ SUBSCRIPTION_STATE_EXPIRED ◦ … purchases.subscriptionsv2.get 複雑な判定を行わず に済むようになった 43
  27. • 購入ステータスを確認するため次のAPIを呼ぶ ◦ deprecated: verifyReceipt ◦ Get All Subscription Statuses

    • StoreKit 2、Get All Subscription Statuses、App Store Server Notifications V2の登場により従来のverifyReceiptと状況が変わった ◦ クライアントでレシートが検証されているため、購入ステータスに集中 できるようになった App Store Server API (App Store) 44
  28. • is_in_billing_retry_period ◦ 1はbilling retryの状態を示す • expiration_intent ◦ 2はBilling errorで支払い情報が有効でな

    い場合を示す • grace_period_expires_date_ms > 現在時刻 ◦ expires_date_msはGrace Periodで延長 されない verifyReceipt (App Store) 47
  29. • lastTransactionsItem.statusの値をチェックする ◦ 1: 定期購入は有効である ◦ 2: 定期購入は有効期限切れである ◦ 3:

    定期購入はAccount Holdである ◦ 4: 定期購入はGrace Periodである ◦ … Get All Subscription Statuses 複雑な判定を行わず に済むようになった 51
  30. • subTypeを見ることで現在の購入ステータスを把握できる ◦ BILLING_RETRY ◦ GRACE_PERIOD • アプリ > アプリ情報

    > App Storeサーバ通知から設定する ◦ プロダクション環境とSandbox環境でURLを分けられる ◦ V1とV2のバージョンを切り替えて検証できる App Store Server Notifications V2 55
  31. • Play Store ◦ showInAppMessages • App Store ◦ StoreKit2

    Message API アプリの中で支払いを修正できる機能 59
  32. • Play Store ◦ showInAppMessages • App Store ◦ StoreKit2

    Message API アプリの中で支払いを修正できる機能 60 通常はPlay Store / App Storeの アプリを開いて修正を行う必要が ある
  33. • Google Play Billing Library 4.1から追加された ◦ Grace PeriodとAccount Hold中に1日1回だけお支払い方法を修

    正するUIを表示する ◦ アプリ内から直接支払いの問題を修正できる • 注意 ◦ 1日1回表示したら再表示されない ◦ テストカードでも回数制限がかかる ◦ 判定と表示の機能はまとめて提供されている showInAppMessagesを実装する 61
  34. 実装コード val params = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageParams. InAppMessageCategoryId .TRANSACTIONAL) .build() billingClient.showInAppMessages(activity

    , params) { inAppMessageResult -> when(inAppMessageResult. responseCode) { InAppMessageResult. InAppMessageResponseCode .NO_ACTION_NEEDED -> { // The flow has finished and there is no action needed from developers. } InAppMessageResult. InAppMessageResponseCode .SUBSCRIPTION_STATUS_UPDATED -> { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } } 62
  35. 63

  36. Messageが表示される頻度 Billing retry interval Message frequency 1~3日目 24時間毎 4~16日目 72時間毎

    17~30日目 96時間毎 31~60日目 120時間毎 67 メッセージの表示頻度はだんだん少なくなる
  37. • Step1 ◦ 何もしない。ストアの通知・メールに任せる ◦ アプリ内では何も表示されない。ユーザーに気が付かれにくい。 • Step2 ◦ 公式ライブラリのアプリ内での支払い修正機能を実装する

    ◦ シンプルに訴求できる。表示内容や頻度に制限がある。 • Step3 ◦ アプリ内で独自のダイアログやバナーを表示する ◦ 自由に訴求できる。実装コストがかかる。アプリ外での支払い修正となる。 Grace Period / Account HoldのUI/UX対応 72 前提:API側でのハンドリングを行う