Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

MITSUMITSU
September 24, 2021

Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

MITSUMITSU

September 24, 2021
Tweet

More Decks by MITSUMITSU

Other Decks in Technology

Transcript

  1. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play IAB(In-App Billing)
    〜Railsでのサーバサイド対応のすべて〜
    三星祐也 @MITSUBOSHI
    銀座Rails #37

    View Slide

  2. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Company: Quipper Limited
    ➔ GitHub: MITSUBOSHI
    ➔ Twitter: Y_MITSUBOSHI
    self.introduce

    View Slide

  3. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Google Play IABのサーバサイド対応情報があまり発信されていない
    ◆ Androidクライアントサイドの情報は多い
    ◆ Google公式の情報もサーバサイド側の話が少ない
    Motivation

    View Slide

  4. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Agenda | 01
    02
    03
    04
    Google Play IAB(In-App Billing)の仕様
    Google Play IAB(In-App Billing)の対応方針と設計
    Androidクライアント間との処理
    Cloud Pub/Subを用いたRTDNイベント処理

    View Slide

  5. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play IAB(In-App Billing)の仕様
    01

    View Slide

  6. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Google Playの課金システム
    ◆ ざっくり言うと、Androidスマホ・タブレットにおけるアプリ内決済
    Google Play IAB(In-App Billing)とは

    View Slide

  7. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ One-time products
    ➔ Subscriptions
    Google Play IAB(In-App Billing)の種類

    View Slide

  8. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 買い切り型
    ◆ consumable … 複数回購入可能
    ● 例: ゲーム内通貨
    ◆ non-consumable … 一度だけ購入可能
    ● 例: 永久会員権, 電子書籍
    One-time products

    View Slide

  9. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 定期購入型
    ◆ 例: 月額課金系のサービス
    Subscriptions

    View Slide

  10. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 定期購入型
    ◆ 例: 月額課金系のサービス
    ● => スタディサプリ 中学/高校/大学受験講座
    Subscriptions

    View Slide

  11. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ ユーザがIAB Subscriptionを購入してから3日以内に承認をしなかった場合、自動
    返金される
    acknowledge

    View Slide

  12. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ ユーザがIAB Subscriptionを購入してから3日以内に承認をしなかった場合、自動
    返金される
    ➔ acknowledge方法
    ◆ Androidクライアントライブラリ(PBL: Play Billing Library)経由
    ◆ Google Play Developer API経由
    acknowledge

    View Slide

  13. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ ユーザがIAB Subscriptionを購入してから3日以内に承認をしなかった場合、自動
    返金される
    ➔ acknowledge方法
    ◆ Androidクライアントライブラリ(PBL: Play Billing Library)経由
    ◆ Google Play Developer API経由
    acknowledge

    View Slide

  14. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ユーザがSubscription購入を試行
    acknowledge

    View Slide

  15. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Subscriptionの購入に成功
    acknowledge

    View Slide

  16. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    利用権の付与に成功 + acknowledgeする
    acknowledge

    View Slide

  17. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    利用権の付与に失敗 + acknowledgeしない
    acknowledge

    View Slide

  18. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    購入から3日後に自動返金される
    acknowledge

    View Slide

  19. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ IAB Subscriptionの購入(申し込み) + サービス側の役務提供の開始
    (acknowledge)の2つを以って、定期購入開始とする
    acknowledge

    View Slide

  20. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play IAB(In-App Billing)の対応
    方針と設計
    02

    View Slide

  21. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    obfuscatedExternalAccountId

    View Slide

  22. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    IAB Subscriptionとユーザの紐付け

    View Slide

  23. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ obfuscatedExternalAccountId
    ◆ Androidクライアント側(Play Billing Library)でIAB Subscriptionに対して任
    意の文字列を指定出来る
    ● => 難読化されたユーザID
    ◆ Google Play Developer API経由で取得する最新のsubscriptionデータ内に
    もfieldとして表出するようになる
    ◆ Subscriptionの購入者と利用権付与対象者が一致するかの検証にも利用
    IAB Subscriptionとユーザの紐付け

    View Slide

  24. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    サーバ側からSubscriptionの状態を取得する方法

    View Slide

  25. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Google Play Developer API
    ➔ Androidクライアント経由でのレシート情報取得
    ➔ Real Time Developer Notification
    サーバ側からSubscriptionの状態を取得する方法

    View Slide

  26. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play Developer API

    View Slide

  27. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 特定のsubscription(SubscriptionPurchaseリソース)に対する操作が可能
    ◆ Ref:
    https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscri
    ptions
    ➔ 可能な操作
    ◆ 最新リソースの取得(get)
    ◆ subscriptionの承認(acknowledge)
    ◆ etc.
    Google Play Developer API

    View Slide

  28. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ GET
    https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageNa
    me}/purchases/subscriptions/{subscriptionId}/tokens/{token}
    ➔ 必須パラメータ
    ◆ packageName … Android app固有の一意な識別子 (別名: applicationId)
    ◆ subscriptionId … サービスが提供するsubscription毎に一意な識別子(別名: SKU or
    productId)
    ◆ token … ユーザが購入したsubscription毎の一意な識別子 (別名: purchaseToken)
    Subscriptionの最新状態の取得

    View Slide

  29. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Subscriptionの最新状態の取得

    View Slide

  30. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 注意点
    ◆ リクエスト時点のsubscription情報しか取得できない
    ● => 過去時点のsubscription状態を把握したいケースがある場合は、細かく記録しておく
    ことが重要
    Subscriptionの最新状態の取得

    View Slide

  31. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ gem 'google-apis-androidpublisher_v3'
    Google Play Developer API

    View Slide

  32. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Androidクライアント経由でのレシート情報取得

    View Slide

  33. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Play Billing Library(PBL)経由でレシート情報を取得可能
    ◆ https://developer.android.com/reference/com/android/billingclient/a
    pi/Purchase
    Androidクライアント経由でのレシート情報取得

    View Slide

  34. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Androidクライアント経由でのレシート情報取得

    View Slide

  35. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ expiryTimeMillis (有効期限)の値を知るためにはGoogle Play Developer APIを
    利用する必要がある
    Androidクライアント経由でのレシート情報取得

    View Slide

  36. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Real Time Developer Notification

    View Slide

  37. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Subscriptionの状態変化毎に通知を受け取ることが出来る機構
    ◆ Google Cloud Pub/Subを利用する必要がある
    ◆ 受け取るメッセージにはsubscriptionの詳細情報は含まれていないため、
    Google Play Developer APIを利用する必要がある
    ➔ 以降は、RTDNと略します
    Real Time Developer Notification

    View Slide

  38. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    エンドポイント設計

    View Slide

  39. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ サーバサイドの主な役割
    ◆ 購入されたsubscriptionの状態に従って、ユーザに適切なコンテンツ/サービ
    スの利用権を付与する
    エンドポイント設計

    View Slide

  40. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 新規購入 … Androidクライアント間
    ➔ 新規購入以外 … RTDN間
    エンドポイント設計

    View Slide

  41. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 新規購入 … Androidクライアント間
    ◆ 理由: subscriptionの新規購入はアプリ内での操作であるため(+ ユーザに同
    期的にフィードバックをしたい)
    エンドポイント設計

    View Slide

  42. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 新規購入以外 … RTDN間
    ◆ 理由: subscriptionの新規購入以外はアプリ外での操作/状態変化であるた
    め(例: 解約, 再開, 月額更新, 猶予期間)
    エンドポイント設計

    View Slide

  43. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    DB設計

    View Slide

  44. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    DB設計

    View Slide

  45. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 役割
    ◆ サービスが提供するsubscriptionのマスタデータ
    ➔ fields
    ◆ package_name … Android app固有の一意な識別子 (別名: applicationId)
    ◆ product_id … サービスが提供するsubscription毎に一意な識別子(別名:
    SKU or subscriptionId)
    GooglePlayIabPackage

    View Slide

  46. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 役割
    ◆ 各subscriptionの管理用
    ● ※subscriptionの有効期限等は関連のpaymentに同期させている
    ➔ fields
    ◆ purchase_token … ユーザが購入したsubscription毎の一意な識別子
    ◆ google_play_iab_package_id
    ◆ payment_id
    GooglePlayIabReceipt

    View Slide

  47. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 役割
    ◆ 各処理時点でのsubscription情報の履歴管理用 (※追記型)
    ➔ 主なfields
    ◆ raw_subscription_purchase … json型であり、subscriptionの情報をそのまま突っ込んでいる
    ● 検索に必要なものは fieldとして切り出して定義している
    ◆ source_type … Android側が取得したレシート or Google Play Developer API。STIにはしていな
    い。
    ◆ rtdn_type … Real Time Developer Notificationのイベント種別
    GooglePlayIabSubscriptionPurchaseHistory

    View Slide

  48. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Androidクライアント間との処理
    03

    View Slide

  49. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    定期購入開始用エンドポイント

    View Slide

  50. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 定期購入開始用エンドポイント
    ➔ 復元用エンドポイント
    エンドポイントの種類

    View Slide

  51. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    定期購入開始用エンドポイント

    View Slide

  52. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

    新規購入のフロー

    View Slide

  53. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Subscription購入後に、定期購入開始用エンドポイントへリクエストする
    新規購入のフロー

    View Slide

  54. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Endpoint: POST /api/v1/android/iab/subscriptions
    ➔ Request parameter:
    ◆ receipt … クライアントが取得可能な購入情報を含むデータ
    ● https://developer.android.com/reference/com/android/billingclie
    nt/api/Purchase#getOriginalJson()
    ◆ signature … 購入情報を含むreceiptを開発者用の秘密鍵で署名したもの
    ● https://developer.android.com/reference/com/android/billingclie
    nt/api/Purchase#getSignature()
    定期購入開始用エンドポイント

    View Slide

  55. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 主な処理の流れ
    ◆ 署名検証
    ◆ subscriptionの最新状態の取得 + 検証
    ◆ 利用権付与 + acknowledge処理
    定期購入開始用エンドポイント

    View Slide

  56. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証

    View Slide

  57. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Androidクライアント経由でのレシート情報取得

    View Slide

  58. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    定期購入開始用エンドポイント

    View Slide

  59. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証

    View Slide

  60. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証
    LICENSE PUBLIC KEYはGoogle Play Consoleから取得出来る。
    Base64エンコードされているため、デコードする。

    View Slide

  61. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証
    signatureもBase64エンコードされているため、デコードする。

    View Slide

  62. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証
    => true/false

    View Slide

  63. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証の呼び出し側

    View Slide

  64. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    署名検証の呼び出し側

    View Slide

  65. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    subscriptionの最新状態の取得

    View Slide

  66. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ gem 'google-apis-androidpublisher_v3' を拡張
    Google Play Developer API

    View Slide

  67. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ gem 'google-apis-androidpublisher_v3' を拡張
    Google Play Developer API

    View Slide

  68. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

    View Slide

  69. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play Developer API

    View Slide

  70. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play Developer API

    View Slide

  71. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play Developer API

    View Slide

  72. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    subscriptionの検証

    View Slide

  73. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    IAB Subscriptionの検証

    View Slide

  74. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    subscriptionの検証

    View Slide

  75. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    subscriptionの検証

    View Slide

  76. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    subscriptionの検証

    View Slide

  77. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

    View Slide

  78. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    利用権付与 + acknowledge処理

    View Slide

  79. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play Developer API

    View Slide

  80. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    復元用エンドポイント

    View Slide

  81. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    利用権の付与に失敗 + acknowledgeしない
    復元用エンドポイント

    View Slide

  82. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Google Play側の購入状態とサービス側の利用権状態がズレているとき
    ◆ a) Google Play側の購入状態(有) + Quipperの利用権状態(無)の場合
    ● a-1) 対応するGooglePlayIabReceiptが存在しない(≒ 1回も利用権が付
    与出来ていない)
    ● a-2) 対応するGooglePlayIabReceiptが存在する(≒ 最低1回は利用権
    が付与出来ている)
    復元の定義

    View Slide

  83. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Endpoint: POST /api/v1/android/iab/subscriptions/restore
    ➔ Request parameter:
    ◆ receipt … クライアントが取得可能な購入情報を含むデータ
    ◆ signature … 購入情報を含むreceiptを開発者用の秘密鍵で署名したもの
    ※定期購入開始用エンドポイントと同じ
    復元用エンドポイント

    View Slide

  84. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 主な処理の流れ
    ◆ 署名検証
    ◆ GooglePlayIabReceiptの有無の確認
    ◆ subscriptionの最新状態の取得 + 検証
    ◆ 利用権付与 + acknowledge処理
    復元用エンドポイント

    View Slide

  85. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

    View Slide

  86. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    復元用エンドポイント

    View Slide

  87. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subを用いたRTDNイベント処

    04

    View Slide

  88. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 新規購入以外 … RTDN間
    ◆ 理由: subscriptionの新規購入以外はアプリ外での操作/状態変化であるた
    め(例: 解約, 再開, 月額更新, 猶予期間)
    エンドポイント設計 (思い出し)

    View Slide

  89. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ フルマネージドのメッセージングサービス
    ➔ Real Time Developer Notificationを受け取るために利用が必要
    Google Cloud Pub/Subとは

    View Slide

  90. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Topic
    ◆ Publisherがメッセージ(≒ queue)を送信する窓口
    ◆ 複数のsubscriptionを紐付けさせることが出来る
    ◆ 関連付けられたすべてのsubscriptionで対象メッセージがacknowledgeされた時点でメッ
    セージを破棄する
    ➔ Subscription
    ◆ Subscriberがメッセージ(≒ queue)を受け取る窓口
    ◆ 対象メッセージがacknowledgeされた時点でメッセージを破棄する
    Google Cloud Pub/Sub TopicとSubscription

    View Slide

  91. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Pull型
    ◆ 受信方法 … subscriptionに対してメッセージ取得のリクエストをする(能動的)
    ◆ acknowledge方法 … SDKのacknowledgeメソッド呼び出し
    ➔ Push型
    ◆ 受信方法 … subscribe用のendpointを指定し、メッセージをHTTP Requestとして受け取れる
    (受動的)
    ◆ acknowledge方法 … HTTP Status Code(102, 200, etc.)
    Pub/Sub Subscriptionのメッセージ受信/acknowledge方法

    View Slide

  92. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ At-Least-Once delivery
    ◆ 同じメッセージが1回以上配信されることを考慮する必要がある
    ● => 処理の冪等性
    ➔ エラーの処理方針
    ◆ Exponential Backoff
    ◆ Dead letter topic
    ● RTDNの場合は最悪メッセージが処理不可 or 欠如しても困らないため設定していない
    ○ => 想定内のエラー + リトライ不要な場合は acknowledgeする方針にしている
    Pub/Sub Subscriptionの注意点

    View Slide

  93. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    RTDNを受け取る構成

    View Slide

  94. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    RTDNを受け取る構成

    View Slide

  95. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    RTDNを受け取る構成

    View Slide

  96. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    メッセージはacknowledgeされない限り、リトライ対象となる
    RTDNを受け取る構成

    View Slide

  97. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    メッセージはacknowledgeされると、subscriptionおよびtopicから破棄される
    RTDNを受け取る構成

    View Slide

  98. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのpush型エンドポイント

    View Slide

  99. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのpush型エンドポイント

    View Slide

  100. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのpush型エンドポイント

    View Slide

  101. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 主な処理
    ◆ JWT認証
    ◆ messageのRTDN種別に応じた処理
    Cloud Pub/Subのpush型エンドポイント

    View Slide

  102. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証

    View Slide

  103. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 認証ヘッダーにエンコードされたJWTが含まれている
    ◆ header.payload.signature と区切られている
    ● header ... 電子署名のアルゴリズムについて
    ● payload ... GCP サービスアカウントのemailクレームやaudクレームなど
    の情報
    JWT認証

    View Slide

  104. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ https://cloud.google.com/pubsub/docs/push/?hl=ja#authentication_and_a
    uthorization
    JWT認証

    View Slide

  105. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証

    View Slide

  106. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証

    View Slide

  107. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証

    View Slide

  108. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証

    View Slide

  109. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証

    View Slide

  110. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    JWT認証の呼び出し側

    View Slide

  111. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのtopic message

    View Slide

  112. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのtopic message

    View Slide

  113. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのtopic message

    View Slide

  114. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ message.dataに以下3種類のうちどれか1つが排他的に含まれている
    ◆ subscriptionNotification … 定期購入型の場合
    ◆ oneTimeProductNotification … 買い切り型の場合
    ◆ testNotification … テスト用。Google Play Consoleからtest notificationを
    使って通知出来る。
    Cloud Pub/Subのtopic message

    View Slide

  115. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのtopic message

    View Slide

  116. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

    View Slide

  117. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜

    View Slide

  118. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのmessage受け取り

    View Slide

  119. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Handlerのbase処理

    View Slide

  120. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのmessage受け取り

    View Slide

  121. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Cloud Pub/Subのmessage受け取り

    View Slide

  122. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    SUBSCRIPTION_RENEWD

    View Slide

  123. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ notificationType … 2
    ➔ 定期購入(≒月額課金)成功を意味する
    ➔ サーバ側はsubscriptionの状態に応じて、有効期限の延長処理を行う
    SUBSCRIPTION_RENEWED

    View Slide

  124. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    - 更新の処理

    View Slide

  125. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ IAB Subscriptionのacknowledgeは有り難い仕様
    ➔ Google Play Developer API経由で取得できるsubscriptionは最新状態のみのた
    め、処理毎に履歴を保存しておくと良い
    ➔ Real Time Developer Notificationは便利
    Conclusion

    View Slide

  126. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ 公式ドキュメント: Google Play 請求サービス
    ◆ https://developer.android.com/google/play/billing
    ➔ Re:ゼロから始める Play Billing Library
    ◆ https://speakerdeck.com/syarihu/re-zero-starting-uses-of-play-billing-l
    ibrary
    ➔ Google Play アプリ内定期購入を実装する
    ◆ https://techlife.cookpad.com/entry/2018/03/14/090000
    参考資料

    View Slide

  127. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Thank you

    View Slide

  128. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    We’re hiring

    View Slide

  129. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    付録

    View Slide

  130. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Google Play Console

    View Slide

  131. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Subscription毎の設定値

    View Slide

  132. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Free trial
    ◆ 新規購入者向けの無料期間の設定。
    ➔ Introductory price
    ◆ 新規購入者向けの特別価格の設定。
    Subscription毎の設定値

    View Slide

  133. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Grace Period
    ◆ 猶予期間の有効/無効設定
    ● ユーザが定期購入の支払いに失敗した場合、猶予期間の間は有料状態としてサービス
    を使い続けることが出来る(ようにサービス側は対応しなければならない)。
    ➔ Resubscribe
    ◆ アプリ外購入の有効/無効設定
    ● 定期購入の有効期限切れ後、Google Play Store上(≒アプリ外)から新規購入が可能に
    なる。
    Subscription毎の設定値

    View Slide

  134. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Subscription毎の設定値

    View Slide

  135. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    アプリ内全Subscriptionsへの共通設定値

    View Slide

  136. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Pause
    ◆ 定期購入の一時停止機能の有効/無効設定
    ● 一時停止期間終了後に定期購入が再開する
    ➔ Free trial limit
    ◆ 無料期間の付与条件の設定
    ● One per subscription
    ● One across all subscriptions
    アプリ内全Subscriptionsへの共通設定値

    View Slide

  137. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    Subscriptionの購入検証

    View Slide

  138. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ テスト購入が行える仕組みのこと
    ◆ https://developer.android.com/google/play/billing/test
    ➔ 注意点
    ◆ テスト購入ではGoogle Play Store上、pauseやresubscribeが有効になって
    いる
    ● => そのため、subscriptionの設定値の反映確認は実購入で試した
    License Tester

    View Slide

  139. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    監視

    View Slide

  140. #ginzarails Google Play IAB(In-App Billing) 〜Railsでのサーバサイド対応のすべて〜
    ➔ Google Pub/SubのDatadog integrationを使用
    ➔ 採用したメトリクスの種類
    ◆ gcp.pubsub.subscription.oldest_unacked_message_age
    ◆ gcp.pubsub.subscription.num_unacked_messages_by_region
    ◆ gcp.pubsub.subscription.push_request_count
    ◆ gcp.pubsub.subscription.push_request_latencies.avg
    Google Cloud Pub/Subの監視

    View Slide