◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-07-16上級

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

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

StoreKit 217StoreKitTestSKTestSessionRork Max236テスト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()
    }
}

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

✦

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

この記事の続きを読む

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

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

この記事を購入する

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

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

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

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

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

関連記事

⬡ 開発ツール2026-07-18
文字サイズ最大とドイツ語で、生成された画面は静かに詰まる — Rork Max の SwiftUI にレイアウト耐性の検証を通した記録
Rork Max が生成した SwiftUI 画面を疑似ローカライズと最大文字サイズに通し、どこから詰まるかを機械的に洗い出した記録です。ViewThatFits・ScaledMetric・layoutPriority の使いどころと、再生成のたびに回帰を捕まえるスナップショット検証を、実際の数値とともにまとめました。
⬡ 開発ツール2026-05-17
Rork Max の SwiftUI 機能を壁紙アプリ開発で検証した結果 — 実際に動いた機能と手を入れた機能
運用中の壁紙アプリの本番コードを基準に、Rork Max の SwiftUI ネイティブ生成を検証しました。そのまま使えた機能、手を入れた機能、生成を諦めた機能を、動くコードと実機での計測値とともにお伝えします。
⬡ 開発ツール2026-05-16
Rork Max 製 iOS アプリの Firebase CocoaPods を Swift Package Manager へ移行した実録——2026年10月の廃止前に対応した手順と3つの落とし穴
Firebase Apple SDK の CocoaPods 配信が2026年10月に停止します。Rork Max 製 iOS アプリ4本を Swift Package Manager へ移行した実体験をもとに、手順・落とし穴・Dropbox競合コピー問題の解決策を詳細に解説します。