RORK LABEN
PLAY — Google Play の target API level 36 要件が昨日8月31日に発効しました。今日以降、新規アプリと既存アプリの更新は Android 16 対応が必須ですVISIBILITY — API 35 のままのアプリは掲載こそ続きますが、新しい Android 版のユーザーには表示されなくなります。エラーが出ないまま新規インストールだけが減る点に注意が要りますEXTENSION — 間に合わなかった場合は、Play Console から2026年11月1日までの延長申請が出せます。恒久対応の計画とセットで進めるのが実務的ですAPPLE — Apple 側は9月9日にイベント、iOS 27 の正式リリースは9月14日と報じられています。生成したアプリの iOS 27 実機確認はリリース週の前に済ませておきたいところですEXPO — Expo が expo-paste-input を公開しました(8月28日)。React Native の TextInput に画像・GIF・ステッカーの貼り付けを追加するネイティブモジュールですEAS — EAS Observe が8月20日に GA になりました。クラッシュや性能の観測を、ビルドや配信と同じ EAS 上で持てるようになっていますPLAY — Google Play の target API level 36 要件が昨日8月31日に発効しました。今日以降、新規アプリと既存アプリの更新は Android 16 対応が必須ですVISIBILITY — API 35 のままのアプリは掲載こそ続きますが、新しい Android 版のユーザーには表示されなくなります。エラーが出ないまま新規インストールだけが減る点に注意が要りますEXTENSION — 間に合わなかった場合は、Play Console から2026年11月1日までの延長申請が出せます。恒久対応の計画とセットで進めるのが実務的ですAPPLE — Apple 側は9月9日にイベント、iOS 27 の正式リリースは9月14日と報じられています。生成したアプリの iOS 27 実機確認はリリース週の前に済ませておきたいところですEXPO — Expo が expo-paste-input を公開しました(8月28日)。React Native の TextInput に画像・GIF・ステッカーの貼り付けを追加するネイティブモジュールですEAS — EAS Observe が8月20日に GA になりました。クラッシュや性能の観測を、ビルドや配信と同じ EAS 上で持てるようになっています
記事一覧/開発ツール
開発ツール/2026-07-16上級

生成された課金コードを Sandbox の前に検証する — SKTestSession で返金・失効・購入失敗を自動テストする

Rork Max が生成した StoreKit 2 のコードは、買えることは確かめられても、返金・失効・購入失敗までは確かめられません。StoreKitTest の SKTestSession で、これらのエッジケースを Sandbox に入る前に自動テストする実装をまとめます。

StoreKit 216StoreKitTestSKTestSessionRork Max232テスト7課金8

プレミアム記事

Rork Max が吐き出した購入処理を初めて読んだとき、目が止まったのは Transaction.currentEntitlements を舐めて Bool を返す、十数行の関数でした。読む限り、間違っていません。実際に買えば、ちゃんと機能が開きます。

困ったのは、その先を確かめる手段のほうでした。返金されたら何が起きるのか。更新に失敗したら何が起きるのか。Sandbox アカウントを作って、購入して、1ヶ月待つ。そういうわけにもいきません。

個人開発で課金まわりが怖いのは、バグが「動かない」形で出てこないからです。買えている人の画面には何も起きません。壊れているのは返金された数人の権利だけで、その数人は何も言わずに離れていきます。

StoreKitTest は、この空白を埋めるために Apple が用意したフレームワークです。App Store を呼びに行かず、端末の中に閉じた偽の App Store を立てて、返金も失効も自分の手で起こせます。

Sandbox に入る前に落とせるバグがある

課金の検証というと Sandbox から始めがちですが、Sandbox は「Apple のサーバーと正しく話せるか」を見る場所です。「自分のコードが状態変化に正しく反応するか」を見る場所ではありません。

この2つを混ぜると、確認したいことに対して手続きが重すぎます。返金を1回試すために、Sandbox アカウントを作り、購入し、App Store Connect から返金を発行し、通知が届くのを待つ。1シナリオに数十分かかり、しかも失敗したときに原因がコードなのか環境なのか切り分けられません。

StoreKitTest が担うのは前者ではなく後者です。ネットワークもサーバーも出てきません。テストプロセスの中で完結します。

私はこの2つを、次のように分けて考えています。

確かめたいこと使う場所1回あたりの手間
返金されたら権利が消えるかSKTestSession数百ミリ秒
期限が切れたら権利が消えるかSKTestSession数百ミリ秒
購入失敗を握り潰していないかSKTestSession数百ミリ秒
署名検証がサーバーで通るかSandbox数分
サーバー通知が届いて処理されるかSandbox数分〜
実際の請求と価格表示が合うかSandbox / 本番数分〜

上3行は Sandbox でもできますが、やる意味が薄い作業です。下3行は SKTestSession では絶対にできません。境界はここに引くのが現実的だと考えています。

StoreKitTest は端末の中に偽の App Store を立てます

必要なのは .storekit の Configuration ファイルと、テストターゲットでの import StoreKitTest です。Configuration ファイルは Xcode で作れますが、Rork Max で生成したプロジェクトなら App Store Connect の商品定義から同期させるのが早い方法です。

SKTestSession を作った瞬間から、そのプロセス内の StoreKit 2 API はすべてこのセッションを向きます。Product.products(for:)Transaction.currentEntitlements も、Apple ではなくセッションが答えます。

import XCTest
import StoreKit
import StoreKitTest
@testable import MyApp
 
final class EntitlementTests: XCTestCase {
    var session: SKTestSession!
 
    override func setUpWithError() throws {
        try super.setUpWithError()
        // Products.storekit をテストターゲットに含めておきます
        session = try SKTestSession(configurationFileNamed: "Products")
 
        // 購入確認ダイアログを出さない。出すとテストが人間の指を待ち続けます
        session.disableDialogs = true
 
        // 前のテストのトランザクションを持ち越さない
        session.clearTransactions()
        session.resetToDefaultState()
    }
 
    override func tearDownWithError() throws {
        session = nil
        try super.tearDownWithError()
    }
}

disableDialogsclearTransactions() は、忘れると必ず痛い目を見る2行です。前者を落とすとテストがダイアログの前で固まり、後者を落とすと前のテストで買った購読が次のテストに漏れて、原因の分からない成功が出ます。テストが「なぜか通る」ときは、だいたいここです。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
「買えることは確認したが返金と失効は未検証」という状態の人が、返金・期限切れ・購入失敗を数秒で再現する動く XCTest を今日手に入れられる
SKTestSession の timeRate・expireSubscription・refundTransaction・setSimulatedError を使い、Sandbox で1ヶ月かかる更新シナリオを1テストに畳み込む書き方を習得できる
生成コードが最も落としやすい返金経路の穴を塞ぎ、$99 の Apple Developer Program 契約前でも課金ロジックを検証できる状態になれる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-05-02
Rork のサブスクリプションを Sandbox でテストする実践 — Apple/Google で詰まる箇所と検証手順
Rork で実装したサブスクリプションを Sandbox 環境でテストする際の落とし穴を、Apple/Google の両側から実装コード付きでまとめました。本番ビルド前に必ず潰しておきたい検証ポイントを順序立てて確認できます。
開発ツール2026-07-19
Rork Max の2クリック提出が止まったとき、どの層で詰まったかを自分で見分ける
Rork Max の1クリック実機・2クリック提出は、iOS申請の複雑さを4つの層に畳んで隠しています。抽象が漏れて提出が止まったとき、どの層のエラーかを見分け、自分で直せるようになるための地図を示します。
開発ツール2026-07-18
文字サイズ最大とドイツ語で、生成された画面は静かに詰まる — Rork Max の SwiftUI にレイアウト耐性の検証を通した記録
Rork Max が生成した SwiftUI 画面を疑似ローカライズと最大文字サイズに通し、どこから詰まるかを機械的に洗い出した記録です。ViewThatFits・ScaledMetric・layoutPriority の使いどころと、再生成のたびに回帰を捕まえるスナップショット検証を、実際の数値とともにまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →