iOSアプリの定期購入テスト：StoreKit TestingとSandboxの始め方

[Kanbanize](https://kanbanize.tokyo/)という、iOS・iPadOS標準のリマインダーと自動同期するカンバン型リマインダーアプリを作成した際、アプリ内課金について調査しました。久しぶりに触れてみると手順がかなり変わっていたため、改めてまとめてみます。

## 概要
アプリ内課金やサブスクリプションの実装をテストするために、Appleは2つの主要なテスト環境を提供しています：

1. StoreKit Testing
   - Xcodeに統合された軽量なテスト環境
   - 実際のApp Store Connectの設定なしでテスト可能
   - 迅速な開発とデバッグに最適
   - Configuration Fileを使用して製品定義やテストシナリオを管理
   - トランザクションの即時処理と時間操作が可能

2. App Store Sandbox環境
   - 本番環境に近い完全なテスト環境
   - App Store Connectの設定が必要
   - エンドツーエンドのテストに最適
   - 実際のApp Store環境に近い動作確認が可能
   - サーバーサイド通知の検証も可能

### テスト環境の使い分け
- 開発初期段階：StoreKit Testing
  - 迅速な開発とデバッグ
  - エラーケースの検証
  - 基本的な購入フローの確認

- 本番リリース前：Sandbox
  - エンドツーエンドのフロー確認
  - サーバーサイド通知の検証
  - 実際の課金フローの確認
  - 地域やデバイスをまたいだテスト

### テスト可能な主な機能
- 基本的な購入フロー
- サブスクリプションの更新
- アップグレード/ダウングレード
- 初回特典やプロモーション
- 払い戻しと解約
- エラーハンドリング
- 地域別価格設定

## 種類

| テスト環境 | App Store Connectの設定 | 提供される機能 | サブスクリプション |
|------------|------------------------|----------------|-------------------|
| Xcodeでの StoreKitテスト | いいえ | いいえ（Xcodeによって署名されています） | いいえ（Xcodeによって署名されています） |
| サンドボックス | はい | はい | はい |
| TestFlight (サンドボックスを使用) | はい | はい | はい |

## テストシナリオ

### 基本的なテストシナリオ

| テストシナリオ | サンドボックス | XcodeでのStoreKitテスト |
|----------------|----------------|------------------------|
| さまざまなストアフロントをテストして、価格帯と地域に影響を与える | はい | 限定（価格帯なし） |
| 購入履歴を消去する | はい | はい |
| サブスクリプションのアップグレード、ダウングレード、クロスグレード、自動更新のキャンセルをテストする | はい | はい |
| 初回特典の資格をリセットする | はい | はい |
| テスト用に強制StoreKitエラーを導入する | いいえ | はい |
| サブスクリプション更新のテストにかかる時間を早めたり遅らせたりする | はい | はい |

### 定期購入のテストと購入依頼

アプリが提供するアプリ内購入に応じて、自動更新サブスクリプション、お試しオファー、プロモーション オファー、購入のリクエストなどのシナリオをテストする必要がある場合があります。次の表に、テストシナリオと、それらがサンドボックスまたはXcodeでテスト可能かどうかを示します。

| テストシナリオ | サンドボックス | XcodeでのStoreKitテスト |
|----------------|----------------|------------------------|
| 延期状態になる購入依頼取引を開始する | はい | はい |
| 承認または拒否して購入依頼取引を解決する | いいえ | はい |
| 自動更新サブスクリプションの初回特典を利用する | はい | はい |
| プロモーション オファーを利用して自動更新サブスクリプションを購入する | はい | はい |
| 自動更新サブスクリプションのオファーコードを利用する | いいえ | はい |
| サブスクリプションの更新手続き | はい | はい |
| 取り消しまたは払い戻しされたサブスクリプションを処理する | はい | はい |
| サブスクリプションをキャンセルし、自動更新を無効にする顧客への対応 | はい | はい |
| 期限切れのサブスクリプションに対応する | はい | はい |
| サブスクリプションのアップグレードまたはダウングレードの手続き | はい | はい |
| 同じ期間または異なる期間のサブスクリプションのクロスグレードを処理する | はい | はい |
| 自動更新サブスクリプションの価格引き上げをテストする | いいえ | はい |
| 課金の再試行と課金猶予期間のテスト | はい | はい |

## StoreKit Testing

### 準備
- XcodeでStoreKitを利用するため、テンプレートからstorekitファイルを作成してください。Xcodeのメニューから「File」→「New」→「File」→「StoreKit Configuration File」を選択してください。
- 作成したConfiguration Fileに製品情報を追加します：
  - In-App Purchase製品
  - サブスクリプション
  - 購入依頼の設定
  - ストアフロントの設定
- XcodeでStoreKit Testingを有効にする。Scheme EditorでRunの設定を開き、StoreKit Configuration」を選択し、作成したConfiguration Fileを指定してください。
- シミュレータや実機でアプリを起動して、購入を行なってください。

### サブスクリプションのキャンセル手順
1. Xcodeのデバッグナビゲータを開く
2. StoreKitセクションを選択
3. 管理したいトランザクションを選択
4. 「Expire」または「Refund」ボタンをクリックしてキャンセルを実行

### 注意事項
- SyncでstoreKitの設定を取得してる場合は、storekitでStoreFrontを変更できます。ただし、priceは1つのロケールのものしか取得できません。
- StoreKit Testing環境では、実際の支払いは発生しません。
- テスト中のトランザクションはすべてXcodeのデバッグナビゲータで管理できます。
- エラーケースのテストも可能です（ネットワークエラー、支払い拒否など）。

## Sandbox

### 準備
- App Store ConnectのUsers and Access(ユーザとアクセス)設定画面で、Sandbox用のアカウントを作成してください。既にApp Storeと紐づいてるメールアドレスはSandbox用のアカウントにはできません。存在しないメールアドレスでもアカウントを作成できます。
- App Store Connectで製品の設定を完了させる必要があります：
  - アプリ内課金アイテムの設定
  - サブスクリプショングループの作成
  - 価格設定
  - レビュー情報の提供
- Sandboxを用いた検証はシミュレータと実機で行うことができます：
  - 実機の場合：設定 -> AppStore -> SandboxアカウントからSandboxアカウントを紐づけることができます。
  - シミュレータの場合：直接検証したいアプリを立ち上げて、サブスクリプションを行うとSandboxアカウントのメールアドレスを入力するように促されます。
- テストを開始する前にScheme EditorでRunの設定を開き、StoreKit Testingを無効にしてください。

### サブスクリプションのキャンセル手順
- サブスクリプションのキャンセルは、Webとスマホアプリ内から行えます。
  - Webの場合: App Store Connectのユーザー設定画面で行うことができます。ユーザー -> Sandboxアカウント -> サブスクリプション -> サブスクリプションのキャンセルを行うことができます。
  - スマホアプリ内の場合: 設定 -> AppStore -> SandboxアカウントからSandboxアカウントに紐付けられたサブスクリプションの状態を確認できます。キャンセルも可能です。

### 注意事項
- Sandbox環境では、サブスクリプションの更新サイクルが実際より短縮されます：
  - 1週間 → 3分
  - 1ヶ月 → 5分
  - 2ヶ月 → 10分
  - 3ヶ月 → 15分
  - 6ヶ月 → 30分
  - 1年 → 1時間
- Sandbox環境でのテストは実際の支払いは発生しません。
- App Store Serverからの通知は本番環境と同様に送信されます。
- 価格変更、オファーコード、プロモーションオファーなども本番環境と同様にテスト可能です。

### 注意事項
- Sandbox環境では地域変更にはアカウントの切り替えが必要
- 一度購入したアカウントでは、別地域での再テストは制限される場合あり
- 地域によって利用可能な支払い方法が異なる
- 価格の表示と実際の課金は選択された地域の設定に従う

## まとめ

StoreKitを使用したサブスクリプション機能の実装とテストには、適切な環境選択と段階的なアプローチが重要です。以下に、効果的なテスト戦略と実装のポイントをまとめます。

### 開発フローとテスト戦略

開発プロセスは、大きく分けて3つのフェーズで進めることをお勧めします。

1. 初期開発フェーズ（StoreKit Testing環境）
   開発の初期段階では、XcodeのStoreKit Testing環境を活用します。この環境では、Configuration Fileを使用して様々なシナリオを柔軟にテストでき、素早いイテレーションが可能です。基本的な購入フローやエラーケースの検証を重点的に行います。

2. 中期開発フェーズ（StoreKit Testing + Sandbox）
   基本機能が実装できたら、徐々にSandbox環境でのテストも開始します。この段階では、実際の課金フローや地域による違いなど、より実践的なテストを行います。

3. 後期開発フェーズ（主にSandbox）
   本番リリースに向けて、Sandbox環境での総合テストを重点的に行います。サーバー連携、通知処理、複雑なシナリオの検証など、本番環境に近い形でのテストを実施します。

## 参考
- [Xcode とサンドボックスを使用した開発のあらゆる段階でのテスト | Apple Developer Documentation](https://developer.apple.com/documentation/storekit/testing-at-all-stages-of-development-with-xcode-and-the-sandbox)
- [Sandbox Apple Accountの設定の管理 - App Store Connect - ヘルプ - Apple Developer](https://developer.apple.com/jp/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings/)