Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
App Store/Google Play Store サブスクリプション連携の勘所
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
vilagia
January 29, 2026
Programming
0
9
App Store/Google Play Store サブスクリプション連携の勘所
vilagia
January 29, 2026
Tweet
Share
Other Decks in Programming
See All in Programming
エンジニアの「手元の自動化」を加速するn8n 2026.02.27
symy2co
0
140
LangChain4jとは一味違うLangChain4j-CDI
kazumura
1
180
TipKitTips
ktcryomm
0
160
「抽象に依存せよ」が分からなかった新卒1年目の私が Goのインターフェースと和解するまで
kurogenki
0
110
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
210
モックわからないマン卒業記 ~振る舞いを起点に見直した、フロントエンドテストにおけるモックの使いどころ~
tasukuwatanabe
2
110
Cyrius ーLinux非依存にコンテナをネイティブ実行する専用OSー
n4mlz
0
140
API Platformを活用したPHPによる本格的なWeb API開発 / api-platform-book-intro
ttskch
1
130
米国のサイバーセキュリティタイムラインと見る Goの暗号パッケージの進化
tomtwinkle
2
560
コーディングルールの鮮度を保ちたい / keep-fresh-go-internal-conventions
handlename
0
200
文字コードの話
qnighy
44
17k
ふつうの Rubyist、ちいさなデバイス、大きな一年
bash0c7
0
840
Featured
See All Featured
Docker and Python
trallard
47
3.8k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
140
Building an army of robots
kneath
306
46k
Making Projects Easy
brettharned
120
6.6k
ラッコキーワード サービス紹介資料
rakko
1
2.6M
Paper Plane
katiecoart
PRO
0
48k
Between Models and Reality
mayunak
2
230
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
82
Site-Speed That Sticks
csswizardry
13
1.1k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
780
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
Transcript
App Store/Google Play Store サブスクリプション連携の勘所 〜リストア・割引施策における仕様理解のポイント〜 2025/12/09 YAPC::Fukuoka 非公式リジェクトコン 2025
株式会社はてな vilagia
自己紹介 • 名前: vilagia(う゛ぃらと呼んでください) • 所属: 株式会社はてな テクノロジーソリューション本部 第2グループ •
普段の仕事: GigaViewerの開発を担当するWebアプリケーションエンジニア • 趣味: 小説を書くこと
GigaViewerについて • 17社・26サービス(2025年12月時点)に採用いただいている出版社向けマンガ ビューワ • Webブラウザで閲覧するGigaViewer for Webと、iOS/Androidアプリで閲覧する GigaViewer for
Appsがある • サブスクリプション型課金機能あり
サブスクリプション型課金 • いわゆる「サブスク」。 • 一定期間(通常は一ヶ月)ごとにお金を頂いて、その代わりにサービス提供を行うタ イプの課金 => 今回はこのタイプの課金の注意点 & 向き合い方について話したい
今回伝えたいこと: 定期購読の開発時の注意点を紹介 1. リストアにまつわるもの 2. フルマネージドなロジックにまつわるもの
リストアにまつわる注意点たち • アプリストアでの購入物を、機種変更後などに再適用する機能 • App StoreもGoogle Play Storeも、アプリ内課金で購入したサブスクリプションの 「リストア」機能を要求している •
当然、GigaViewerもリストア機能を搭載 出典: https://developer.apple.com/jp/documentation/storekit/original_api_for_in-app_purchase/
こんなことは経験ありませんか • 機種を変更したけど、やっていたスマホゲームの引継コードを発行し忘れた • ゲーム開始時に作成される「ゲストアカウント」は端末ごとに発行されるから、失わ れてしまう • メールアドレスなどでアカウント登録をしていればこんなことには…… • このとき揃えたキャラなどは、「◦◦石」という「消耗型プロダクト」を使って得た権利な
ので、アプリストアが要求するリストア対象にはならない • しかし、「買い切り500円で広告を非表示にする」や、「毎月500円払う代わりに◦◦石 を受け取れる権利」などは、「非消耗型プロダクト」や「サブスクリプション」なので、 リストアが必要
リストアで権利が往復しうる
対応の考え方 • 権利は一つなので、増殖しないような工夫が必要 • 往復で済まない「渡り歩く」ケースも考えられる • アプリストアからやってくる購入履歴は絶対なので、最優先される • この「往復」が後から追えるようなデータ構造にしないと、ユーザーサポートで苦労 する可能性あり
◦ 具体的には、UPDATEで持ち主を移して終わり、という方法は避けたい ◦ ということはINSERTとなるが、うかつなユニーク制約を掛けていると ……
データモデルのミスマッチ • アプリストアのAPIは、「今の状態」にフォーカスした設計 • よくあるアプリのサブスクを想定すると、自然なこと
サブスクリプションには違う形もある • サブスクリプション中にコンテンツの権利が付与され、解約後もアクセス可能 ◦ 物理的な雑誌の定期購読に近い形 • GigaViewerでは両方のパターンをサポートしている • 今回問題になるのは後者のパターンで、チーム内では「定期購入型定期購読」と呼 んでいる
定期購入型定期購読とのギャップ • 「サブスクリプションが一時的に無効だった期間」内に配られたコンテンツを渡して はいけない • そのユーザーさんが過去に購入した履歴を全て把握できないと、正しい復元ができ ない
App Storeの場合 • 情報量は多め • そのユーザーさんの全購入履歴が取得できる • ただし、「サブスクリプションが一時的に無効だった期間」などはわからない
Google Playの場合 • 情報量は少なめ • 現在有効なサブスクリプションと、直近に有効だったサブスクリプションの購入履歴 が取得できる
対応の考え方 • 定期購入型定期購読に適したデータ構造でGigaViewer側が保存する • アプリストア側とのギャップが出たら、アプリストア側を正として補正する • ただでさえ複雑なライフサイクルを持つ各アプリストアのサブスクリプションを表現 するのはかなり大変なので、歯を食いしばる https://developer.android.com/google/play/billing/lifecycle/subscriptions?hl=ja
リストアにまつわる注意点 • 定期購読の権利はユーザーを渡り歩く ◦ 増殖したり消えてしまったりしないようにしよう ◦ 後から追跡できるようにしよう • アプリストアのデータモデルは、アプリの要件と必ずしも整合しない ◦
整合しなければ、サーバサイドで別途管理しよう ◦ アプリストアのサブスクリプションライフサイクルは複雑。マッピングは頑張ろう
フルマネージドなロジックとの付き合い • アプリストアには、フルマネージドなロジックを提供してくれる機能がある • 代表的なのは、割引施策などに関するもの • 便利なのだが、文化的バイアスなどもあり、思わぬ仕様が隠れていることも
我々のやりたかったこと • サブスクリプションの割引施策を行いたかった ◦ 例: 1ヶ月1000円のところ、初月だけ 500円にする • 2025/04/01 00:00(JST)〜2025/04/30
23:59(JST)までの申し込みが対象 ※ 金額や日付などは一例です
Google Play Storeは「デベロッパー指定」が可能 • サーバサイドのロジックに基づいて任意に割引を行える https://support.google.com/googleplay/android-developer/answer/12154973?hl=ja
お試しオファー • 新規加入者に割引を訴求するためのApp Storeにある機能 • 設定しておくと、指定期間内に申し込んだ新規加入ユーザーに対して自動で割り引 いてくれる
その他のオファー • オファーコードは適用フローの都合上、要件に合わず検討から外した • プロモーションオファーは「デベロッパー指定」に近いが、獲得の目的では使えない https://developer.apple.com/jp/app-store/subscriptions/#providing-subscription-offers
予想外のお試しオファー適用 • お試しオファーを適用するかどうかはApp Store側の制御下 • 適用期間の設定は日単位であることは事前に把握しており、ユーザーのタイム ゾーンに依存することもドキュメントで確認していた • 実挙動を事前確認すると、終了日前日(4/29)の23:59(JST)時点でお試しオファー が不適用になっていることに気付く。一体なぜ???
突然のサマータイム https://developer.apple.com/jp/help/app-store-connect/reference/pricing-and-availability/app-store-pricing-and-availability-start-times-by-country-or-region/
何が起こっていたのか • お試しオファーの適用期間は、アメリカにおいてサマータイム期間内だった • このとき、ユーザーのタイムゾーンにかかわらず、サマータイムに基づく価格反映 の前倒しが行われていた • また、お試しオファーの設定期間において、「2025/04/30まで」とは、2025/04/30 00:00:00まで、であった •
上記処理の結果、2025/04/30 23:59:59までのつもりで設定していた施策は、 2025/04/29 22:59:59までの施策になってしまっていた(※) ※ 事前の動作確認での知見なので、実際の設定値は異なる
• 事前の動作確認は確実に行う ◦ 当たり前ではあるが、現物を実際に動かして、その挙動を確かめることは重要 • 技術的な困難を迂回することも一案 ◦ 今回の場合、0時ちょうどに手動でオファーを無効化する運用回避を行った 対応の考え方
• ストアサーバーに実装は任せられても、動作確認は任せきれない ◦ 設定ミスは大いにありうる • グローバルなサービスを使っていることを自覚する ◦ 「日本での常識」は通用しない ◦ 仕様に文句を言うのは簡単だが、それより見落としを避ける動きを取りたい
フルマネージドなロジックにまつわる注意点
教訓 • 地道なことを大切に ◦ 動作確認、ドキュメント精査など • 関係者間の関係性構築とコミュニケーション ◦ 運用回避などでご協力頂くからには、日頃からの信頼関係が大切 ◦
それに甘えず、なぜ運用回避が必要なのか、などのコミュニケーションも丁寧に • 暗黙の前提を疑う ◦ 文化的バイアス ◦ 確認しづらいエッジケース