fix(#163): 購入情報のクライアント検証と復元タイムアウト時のCompleter放置を修正 - #203
Merged
Conversation
- PurchaseValidator を追加。status/productID/serverVerificationData を検証し、 不正・未完了の PurchaseDetails ではプレミアムを有効化しない(一次防御) - RestoreCoordinator を追加。復元の Completer ライフサイクルを一元管理し、 タイムアウト/完了/例外いずれの経路でも内部状態を必ずリセット。 タイムアウト後の再試行が正常動作する - 従来 _restoreCompleter は完了されず常時タイムアウトしていた潜在バグも解消 (restored イベントで signalRestored() を呼び完了させる) - _handleSuccessfulPurchase で検証を行い、不正な購入は拒否ログのみで早期return サーバー側レシート署名検証(対応案#1)と Firestore ルールのロック(#3)は 外部設定を要するため別Issueに切り出す。 完了条件: - 不正な PurchaseDetails でプレミアムが有効化されない → purchase_validator_test.dart - 復元タイムアウト→再試行が正常動作 → restore_coordinator_test.dart - 既存 one_time_purchase_service_test.dart パス(全478テストパス・analyze エラー0) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Visit the preview URL for this PR (updated for commit a09e616): https://maikago2--pr203-fix-163-purchase-va-qz3senm6.web.app (expires Wed, 24 Jun 2026 01:39:48 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: e99c4741b4cd115a589120c0903a3d28c527ebd8 |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
Issue #163 のうち、外部設定なしで完結できる範囲(完了条件3項目)を焦点修正。
サーバー側レシート署名検証(対応案#1)と Firestore ルールのロック(#3)は、Google Play / App Store / Google Cloud の外部設定を要するため別Issueに切り出します。
変更内容
1. 購入情報のクライアント側検証(対応案: 不正な購入の拒否)
lib/services/purchase/purchase_validator.dart(新規)PurchaseValidator.isValidPremiumPurchase()—status(purchased/restored)・productID・serverVerificationData(空・空白のみ不可)を検証する純粋関数_handleSuccessfulPurchase()で検証 → 不正・未完了のPurchaseDetailsではプレミアムを有効化せず拒否ログのみで早期 return2. 復元タイムアウト時の Completer 放置を修正(対応案#2)
lib/services/purchase/restore_coordinator.dart(新規)wait()はタイムアウト/完了/例外いずれの経路でも内部状態を必ずリセット(finally)→ タイムアウト後の再試行が正常動作_restoreCompleterを完了させる箇所が存在せず、restorePurchases()は成功時も常時30秒タイムアウトしてfalseを返していた。restoredイベントでsignalRestored()を呼び完了させるよう修正テスト(TDD: 先に失敗テスト → 実装)
test/services/purchase/purchase_validator_test.dart(新規・8ケース)— 不正なPurchaseDetails(空検証データ/誤ProductID/pending・error・canceled)でプレミアムが有効化されないことを確認test/services/purchase/restore_coordinator_test.dart(新規・6ケース)— タイムアウト→再試行が正常動作、放置されないこと、例外時リセットを確認完了条件
PurchaseDetailsではプレミアムが有効化されないことをテストで確認one_time_purchase_service_test.dartがパス検証
flutter analyze: エラー0flutter test: 全478テストパス(新規14テスト含む)flutter build web: 成功競合・後方互換
serverVerificationData(Android=購入トークン / iOS=レシート)が常に非空のため、本検証で弾かれませんcompletePurchase()(トランザクション確認)は検証結果に関わらず従来どおり実行(プレミアム付与のみをゲート)残課題(別Issue化を推奨)
purchasesドキュメントをロックし、Cloud Functions のみが書き込む構成🤖 Generated with Claude Code