Appearance
05. .storekit Configuration ファイル作成(Xcode)
目的
シミュレータ / 実機デバッグ時に App Store Connect / Sandbox を経由せずに購入フローをテストできるようにする。Xcode の StoreKit Configuration ファイル(.storekit)で商品定義をローカルにモック化する。
本番リリース時は Scheme から
.storekitを外す(または "None" にする)こと。残したまま提出すると審査でリジェクトされる可能性は低いが、Sandbox / Production の挙動とは異なるため動作確認は別途必要。
前提条件
- Xcode 16+
- 本プロジェクト(
ios/Cycle.xcodeproj)が開ける状態
手順
1. StoreKit Configuration ファイル作成
- Xcode で
Cycle.xcodeprojを開く - File → New → File from Template
- iOS タブ → StoreKit Configuration File を選択 → Next
- Save As:
Configuration.storekit - Group:
Cycleターゲット直下(ios/Cycle/配下)に保存 - Create
2. 商品の追加
.storekit ファイルを開くと空のリストが表示される。
月額プラン
- + → Add Auto-Renewable Subscription
- Reference Name:
Monthly Premium - Product ID:
com.akitoando.CycleJournal.monthly_1800 - Subscription Group:
CycleJournal Premiumを新規作成して選択 - Subscription Duration: 1 month
- Price: ¥1,800 → 1800.00 / JPY
- Family Sharing: Off(必要なら On)
年額プラン
- + → Add Auto-Renewable Subscription
- Reference Name:
Yearly Premium - Product ID:
com.akitoando.CycleJournal.yearly_14400 - Subscription Group: 上で作った
CycleJournal Premiumを選択 - Subscription Duration: 1 year
- Price: ¥14,400 → 14400.00 / JPY
年額プランに Introductory Offer を追加
- 年額プランを選択した状態で Subscription Group / Introductory Offer タブ
- + Add Introductory Offer
- Offer Type:
Free Trial - Duration: 1 Week
- Pricing: 0
- Mode:
Pay As You Go/Pay Up FrontではなくFree Trialが選ばれていることを確認
3. Scheme への紐付け
- Xcode 上部の Cycle スキーム → Edit Scheme...
- Run → Options タブ
- StoreKit Configuration: ドロップダウンで
Configuration.storekitを選択 - Close
4. テスト実行
シミュレータで実行(Cmd+R)し、Paywall に到達:
Product.products(for: [...])がローカル定義から商品 2 つを返す- 「7日間無料で始める」を押すと Sandbox アカウント不要で即購入が走る(パスワードダイアログ出ず)
SubscriptionStore.stateが.trial(...)になる
5. デバッグ操作(時間操作・取消し)
シミュレータ起動中、Xcode Debug → StoreKit → Manage Transactions
- 任意のトランザクションを選択 → Refund で払戻しをシミュレート
- Resolve Issues で課金エラーをシミュレート
- Subscription Group の Time Rate で時間進行速度を倍速にできる(1 second = 1 day など → 7日トライアル終了を数秒で確認可能)
検証
動作確認チェックリスト
- [ ]
Product.products(for:)がエラーなく 2 商品を返す - [ ] 「7日間無料で始める」タップ → ダイアログなし or 簡易確認のみで
state == .trial(...)になる - [ ] Manage Transactions で
Refund→Transaction.updatesに通知が来てstate == .expiredになる - [ ] Time Rate を 1s = 1d にして 7 秒待つ → トライアル終了し自動課金 →
state == .active(...) - [ ] Day3 通知(C-2)の
scheduledAtがローカルで実際に発火するか(Time Rate倍速だと通知も加速)
トラブルシューティング
| 症状 | 原因 | 対処 |
|---|---|---|
Product.products(for:) が空配列 | Scheme で .storekit 未選択 | Edit Scheme → Run → Options → StoreKit Configuration |
| Introductory Offer がアクティブにならない | Subscription Group が違う | 月額・年額・Intro Offer が同一 Group に属しているか |
購入後 state == .unknown のまま | refreshEntitlements 呼び忘れ | Transaction.updates リスナーが起動しているか確認、または手動で await store.refreshEntitlements() |
| Time Rate を変えても何も起きない | シミュレータを完全に再起動 | xcrun simctl shutdown all → 再起動 |
本番リリース前のチェック
- [ ] Scheme から
.storekitを 外す または None にする - [ ] Configuration.storekit はリポジトリに含めて良い(個人情報なし)
- [ ] Sandbox アカウントで実機テストを完了
- [ ] App Store Connect の本番商品で動作することを TestFlight ビルドで確認
公式ドキュメント
- Setting up StoreKit testing in Xcode
- Creating a StoreKit configuration file
- Testing in-app purchases with sandbox