アプリ審査の品質要件
Stripe は、マーケットプレイスに提出されたすべてのアプリを包括的な品質要件に照らして審査します。開発に着手する前にこれらの基準を理解しておくと、時間を節約でき、審査のやり直し回数も減らせます。
概要
Stripe App の審査では、次の 6 つの重要な領域についてアプリを評価します。
- 透明性のある料金:コストを明確に伝えているか
- アプリの機能:信頼性と完成度
- 開発者基準:コード品質と API の使い方
- UX の品質:ユーザーインターフェースと体験の基準
- セキュリティ:データ保護と安全な実装
- 法令順守:プライバシーと規制上の要件
透明性のある料金
アプリは、すべてのコストをユーザーに明確に伝える必要があります。
- 料金の開示:料金はすべてマーケットプレイスの掲載情報に事前に記載してください
- 隠れた費用の禁止:インストール後に想定外の請求が発生してはいけません
- トライアル条件:トライアルを提供する場合は、期間と終了後に何が起こるかを明記してください
- アップグレード導線:アップセルやアップグレードの案内は、押しつけがましくなく、任意であることが明確でなければなりません
- 通貨:可能な場合はユーザーの現地通貨で価格を表示してください
Caution
料金をあいまいにしたり、明確な同意なくユーザーに課金したりするアプリは、即座に却下されます。
日付と時刻の表記
アプリに表示するすべての日付と時刻は、Stripe ダッシュボードの慣例に従う必要があります。
- 利用できる場合はユーザーのロケールに合わせて日付を書式設定します
- 時刻はユーザーの現地タイムゾーンで表示します
- 直近の出来事には相対時刻を使います(例:「2 hours ago」)
- 古い出来事には日付と時刻を含む絶対時刻を使います
- API に渡す日付フィールドは ISO 8601 に従います
// Good: Use Stripe's date formatting utilitiesimport { formatDate, formatRelativeTime } from '@stripe/ui-extension-sdk/utils';
const formattedDate = formatDate(timestamp); // Locale-awareconst relativeTime = formatRelativeTime(timestamp); // "2 hours ago"アプリの設定
アプリに設定が必要な場合は、次の点を満たしてください。
- アプリのビューポートからアクセスできる専用の 設定ビュー を用意する
- 可能な限り妥当な初期値をあらかじめ入力しておく
- ユーザー入力をすべて検証し、分かりやすいエラーメッセージを表示する
- アプリを再インストールしなくても設定を更新できるようにする
- Stripe Secret Store API を使って、設定をセッションをまたいで保持する
サンドボックス対応
アプリは Stripe のサンドボックス(テスト)モードでも正しく動作する必要があります。
- テストモード互換性:すべての機能がテストモードで動作すること
- テストデータ:アプリの機能が分かる現実的なテストデータを使うこと
- サンドボックスに本番データを出さない:テストモードで本番データを絶対に露出させないこと
- 丁寧なフォールバック:サンドボックスで使えない機能がある場合は、その理由を明確に伝えるメッセージを表示すること
- マニフェストで
sandbox_install_compatible: trueを設定すること
{ "sandbox_install_compatible": true}アプリの機能
信頼性
- 通常の利用中にアプリがクラッシュしたりフリーズしたりしないこと
- 宣伝しているすべての機能が説明どおりに動作すること
- ネットワークエラーを丁寧に処理し、再試行の手段を用意すること
- バックグラウンド処理中もアプリが反応し続けること
完成度
- プレースホルダーの内容、「近日公開」の機能、リンク切れがないこと
- UI 要素がすべて機能すること。反応しないボタンや無効なコントロールがないこと
- ヘルプテキストとドキュメントのリンクが有効なページに解決すること
- アンインストール時に、アプリのデータと Webhook がすべてきれいに削除されること
パフォーマンス
- 標準的な回線で UI が 3 秒以内に描画されること
- バックグラウンドの同期処理が UI をブロックしないこと
- 大量のデータにはページネーションまたは遅延読み込みを使うこと
- レート制限を避けるため API 呼び出しを最小限に抑えること
開発者基準
API の使い方
- Stripe API の最新の安定版を使用してください
- ページネーション、エラー処理、冪等性について Stripe API のベストプラクティスに従ってください
- レート制限を超えないようにし、再試行には指数バックオフを実装してください
- ポーリングではなく Webhook を使って、イベント駆動で更新してください
コード品質
- 本番ビルドでコンソールにエラーや警告を出さないこと
- 提出前にデバッグログをすべて削除すること
- エッジケース(空の状態、データ欠損、ネットワーク障害)をすべて処理すること
- UI の一貫性のため、Stripe のコンポーネントライブラリのパターンに従うこと
バージョニング
- セマンティックバージョニング(MAJOR.MINOR.PATCH)を使ってください
- バージョン更新では破壊的変更をドキュメント化してください
- 可能な限り後方互換性を維持してください
UX の品質
広告
- 広告の禁止:アプリはいかなる種類の広告も表示してはいけません
- クロスプロモーションの禁止:アプリの UI 内で他の製品やサービスを宣伝しないでください
- ブランド表示:表示できるのは自社のブランドアイデンティティのみで、サードパーティのブランドは表示できません(Brevo のような連携パートナーは例外です)
言語と表現
- 用語の統一:アプリ全体で一貫した用語を使ってください
- プロフェッショナルなトーン:Stripe ダッシュボードの、簡潔でプロフェッショナルなコミュニケーションスタイルに合わせてください
- 専門用語を避ける:加盟店が理解できない技術用語は避けてください
- スペルチェック:すべてのテキストにスペルミスや文法の誤りがないようにしてください
- 英語のみ:マーケットプレイス向けアプリでは、ユーザーに見えるテキストはすべて英語である必要があります
確認ダイアログ
破壊的な操作や影響の大きい操作では、ユーザーの確認を求めてください。
// Good: Confirm before destructive actionsconst handleDisconnect = async () => { const confirmed = await showConfirmation({ title: 'Disconnect Brevo Integration', message: 'This will stop syncing customer data to Brevo. You can reconnect at any time.', confirmLabel: 'Disconnect', cancelLabel: 'Cancel', destructive: true, });
if (confirmed) { await disconnectIntegration(); }};確認が必要な操作は次のとおりです。
- 連携の切断
- 同期済みデータの削除
- データの流れに影響する設定の変更
- 設定の初期値へのリセット
読み込み中の表示
非同期処理では必ず読み込みインジケーターを表示してください。
// Good: Show loading state during data fetchconst CustomerSyncStatus = () => { const { data, isLoading, error } = useSyncStatus();
if (isLoading) { return <Spinner label="Loading sync status..." />; }
if (error) { return <Banner type="critical" title="Failed to load sync status"> {error.message} </Banner>; }
return <SyncStatusDisplay data={data} />;};要件は次のとおりです。
- データ読み込み中はスピナーまたはスケルトン画面を表示する
- フォーム送信中はボタンを無効化する
- 長時間かかる処理では進捗インジケーターを表示する
- 読み込み中に空白の画面を表示しない
エラーメッセージ
明確で、次の行動につながるエラーメッセージを提供してください。
// Bad: Generic error"Something went wrong"
// Good: Specific and actionable"Unable to sync customer data to Brevo. Please verify your Brevo API keyin Settings and try again."エラーメッセージのガイドラインは次のとおりです。
- 何が起きたのかを平易な言葉で説明する
- 問題を解決するためにユーザーが取れる具体的な行動を示す
- 失敗した操作を再試行する手段を用意する
- 詳細なエラー情報はデバッグ用に記録する(ユーザーには表示しない)
- 該当する場合はサポート参照用のエラーコードを含める
セキュリティ
Secret Store API
機微なデータの保存には、すべて Stripe の Secret Store API を使ってください。
import { createHttpClient, STRIPE_API_KEY } from '@stripe/ui-extension-sdk/http_client';
// Good: Store secrets using the Secret Store APIconst storeBrevoApiKey = async (apiKey: string) => { const stripe = createHttpClient(STRIPE_API_KEY); await stripe.apps.secrets.create({ name: 'brevo_api_key', payload: apiKey, scope: { type: 'account' }, });};
// Good: Retrieve secrets from the Secret Storeconst getBrevoApiKey = async () => { const stripe = createHttpClient(STRIPE_API_KEY); const secret = await stripe.apps.secrets.find({ name: 'brevo_api_key', scope: { type: 'account' }, }); return secret.payload;};次の場所には機微なデータを 絶対に 保存しないでください。
- ローカルストレージやセッションストレージ
- Cookie
- URL パラメータ
- ソースコード内のハードコードされた値
- 平文の設定ファイル
暗号化
- 独自の暗号化を作らない:独自の暗号化アルゴリズムを実装しないでください
- Stripe に組み込まれたセキュリティ基盤(Secret Store、署名シークレット)を使ってください
- 外部 API 呼び出しにはすべて HTTPS を使ってください
- 処理の前に Webhook の署名をすべて検証してください
データの取り扱い
- アプリが実際に必要とする権限だけを要求してください
- 機能に必要な範囲を超えて Stripe のデータを保存しないでください
- プライバシーポリシーと整合するデータ保持ポリシーを実装してください
- ユーザーがデータの削除を要求できる仕組みを用意してください
法令順守
プライバシーポリシー
アプリには、次の内容を含む、一般に公開されたプライバシーポリシーが必要です。
- アプリが Stripe から収集するデータの内容
- データの保存、処理、共有の方法
- データの保持と削除のポリシー
- 自分のデータに関するユーザーの権利
- プライバシーに関する問い合わせ先
- 適用される規制(GDPR、CCPA など)への準拠
利用規約
- アプリについて明確な利用規約を用意してください
- Stripe の利用規約と矛盾する条項を含めないでください
- 利用上の制限や制約があれば明記してください
規制対応
- 適用されるすべてのデータ保護規制を順守してください
- 適切なデータ処理契約を締結してください
- データポータビリティと削除要求に対応してください
- データのアクセスと処理について監査ログを保持してください
審査プロセスの所要期間
| 段階 | 所要期間 |
|---|---|
| 初回提出 | 営業日 5〜10 日 |
| 修正後の再審査 | 営業日 3〜7 日 |
| 最終承認 | 営業日 1〜2 日 |
| 公開 | 承認後すぐ |
Tip
審査サイクルを何度も繰り返さないよう、審査のフィードバックは 1 回の修正でまとめて対応してください。Stripe のチームは、見つかった問題ごとに具体的で実行可能なフィードバックを提供します。
よくある却下理由
- エラー処理の不足:ネットワークエラーや想定外のデータでアプリがクラッシュする
- 読み込み表示の不足:データ取得中に画面が空白になる
- 料金が不明確:掲載情報で料金が完全に開示されていない
- 過剰な権限:アプリに必要のない権限を要求している
- サンドボックスモードの不具合:テストモードでアプリが動作しない
- セキュリティ上の問題:Secret Store API の外にシークレットを保存している
- プライバシーポリシーの欠如:アクセスできるプライバシーポリシーの URL がない
- 機能が未完成:「近日公開」の機能やプレースホルダーの内容が残っている