メインコンテンツへスキップ

IAPに関するAndroid Play Storeのレビューガイドライン

GitHub

AndroidアプリをGoogle Playで承認されるには、Googleのポリシー、特にアプリ内課金やサブスクリプションに関する規定への準拠が必要です。このガイドでは、審査をスムーズに通過するために必要なすべてを解説します。

  1. 署名済みAndroid App Bundleのビルド

    新しいGoogle Playアプリは、Android App Bundleとしてアップロードする必要があります(.aabサイドロード用のデバッグAPKではありません)。

    以下の情報を versionCode アップロードのたびに更新してください。Play App Signingを使用している場合は、アップロードキーを安全に保管してください。

    Android App Bundleのフロー

  2. Play Consoleでのアプリ登録

    デベロッパーアカウントをまだお持ちでない場合は、こちらから開始してください: Play Consoleの登録次に、 ホーム > アプリの作成言語、アプリ/ゲームのタイプ、無料/有料の設定、サポート用メールアドレスを選択し、必要な宣言事項に同意してください。

    無料/有料の設定は慎重に行ってください。Googleでは有料アプリを後から無料に変更することは可能ですが、一度無料として公開したアプリを有料に変更することはできません。

    Play Consoleでアプリを作成

  3. アプリのコンテンツとストア掲載情報の入力

    本番リリースの審査前に、Play Consoleで以下の必須項目を完了させてください:

    • プライバシーポリシー
    • 広告
    • アプリへのアクセス権限
    • ターゲット層とコンテンツ
    • コンテンツのレーティング
    • データの安全性
    • 該当する場合、機密性の高い権限の宣言
  4. Playのテストトラックを実行する

    まずはここから 内部テスト 迅速なQA向け。2023年11月13日以降に作成された個人開発者アカウントの場合、プロダクションへのアクセス前に、以下の手順も完了する必要があります: クローズドテスト 14日間連続で、少なくとも12名のテスターによる参加が必要です。

    Play Consoleでの内部テスト

  5. 決済のE2E検証

    ローカルからエクスポートしたAPKではなく、Google Playからアプリをインストールしてください。その後、以下を確認します:

    • Playから製品が正しく読み込まれること
    • 購入シートには以下が表示されます: テスト購入 ライセンステスター用のバナー
    • 購入後にEntitlementsがアンロックされます
    • 復元およびサブスクリプション管理フローが動作します

デジタルコンテンツやサービスについては、 必ず Google Playの決済システムを使用する必要があります:

デジタル商品(Play Billing 必須):

  • プレミアム機能のサブスクリプション
  • アプリ内通貨やクレジット
  • デジタルコンテンツ(電子書籍、音楽、動画)
  • ゲームのアップグレードやパワーアップ
  • アプリのロック解除やプレミアムプラン

物理的な商品(Play Billing 使用不可):

  • 物理的なグッズ
  • 実世界のサービス
  • 非営利団体への一時的な寄付

:::note サブスクリプションの設定 Play Consoleで、現在の サブスクリプション -> ベースプラン -> オファー モデル。次に、 native-purchasesBase Plan IDを planIdentifier. :::

import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
// Ensure billing is available on the device
const { isBillingSupported } = await NativePurchases.isBillingSupported();
if (!isBillingSupported) throw new Error('Google Play Billing not available');
// Fetch subscription products (Store data is required—never hardcode pricing)
const { products } = await NativePurchases.getProducts({
productIdentifiers: ['premium_monthly', 'premium_yearly'],
productType: PURCHASE_TYPE.SUBS,
});
// Plan identifiers are the Base Plan IDs you create in Google Play Console
const transaction = await NativePurchases.purchaseProduct({
productIdentifier: 'premium_monthly',
planIdentifier: 'monthly-plan', // REQUIRED on Android, ignored on iOS
productType: PURCHASE_TYPE.SUBS,
});
console.log('Purchase token for server validation:', transaction.purchaseToken);

Google Playでは、購入前にすべての費用を明確に開示することが義務付けられています:

必須項目:

  • ユーザーの現地通貨での正確な価格
  • 請求サイクル(月額、年額など)
  • サブスクリプションに含まれる内容
  • 初回特典の総額
  • 課金が発生するタイミング

UIデザインのベストプラクティス

ガイドラインに準拠したUI例:

function SubscriptionCard({ product }) {
return (
<div className="subscription-card">
<h3>{product.title}</h3>
{/* Show intro offer if available */}
{product.introductoryPrice && (
<div className="intro-offer">
<p className="intro-price">{product.introductoryPriceString}</p>
<p className="intro-period">
for {product.introductoryPricePeriod}
</p>
</div>
)}
{/* Regular price */}
<div className="regular-price">
<p className="price">{product.priceString}</p>
<p className="period">per {product.subscriptionPeriod}</p>
</div>
{/* Clear description */}
<p>{product.description}</p>
{/* Renewal terms */}
<p className="terms">
Renews automatically. Cancel anytime in Google Play.
</p>
<button onClick={() => handlePurchase(product)}>
Subscribe Now
</button>
</div>
);
}

サブスクリプションの自動更新前に、Googleが求めていること:

  • 更新が行われる旨の明確な通知
  • 価格のリマインド
  • 解約手続きを容易に

複数のプラットフォームで同じentitlementを販売する場合、ユーザーが混乱しないよう、製品名、請求期間、特典内容、更新に関する文言を統一してください。

税金、現地通貨、ストアの経済状況により価格が異なるのは正当な理由ですが、購入UIでそれらの違いを隠したり、Google Playが請求する金額とは異なる更新コストを暗示したりしてはいけません。

アプリにアプリ内課金が含まれる場合は、以下が必要です:

  1. Play ストアの掲載情報にリンクを記載

    • Play Console にプライバシーポリシーの URL を追加
    • 公開状態でアクセス可能であること
    • アプリと同じ言語で提供すること
  2. アプリ内にリンクを設置

    • アプリの設定画面にプライバシーポリシーを表示
    • ユーザーデータを収集する前に表示すること
    • ユーザーが簡単に見つけられるようにすること

実装例:

function SettingsScreen() {
const openPrivacyPolicy = () => {
window.open('https://yourapp.com/privacy', '_blank');
};
const openTerms = () => {
window.open('https://yourapp.com/terms', '_blank');
};
return (
<div>
<h2>Settings</h2>
<button onClick={openPrivacyPolicy}>
Privacy Policy
</button>
<button onClick={openTerms}>
Terms of Service
</button>
<button onClick={() => NativePurchases.manageSubscriptions()}>
Manage Subscriptions
</button>
</div>
);
}

データ セーフティ セクション

「データ セーフティ」セクション

Google Playでは、「データ セーフティ」セクションでの詳細な開示が求められます:

アプリ内課金(IAP)アプリの場合、以下を宣言してください:

  • 購入履歴の収集
  • メールアドレス(レシート用)
  • デバイスID(不正防止用)
  • 決済情報の取り扱い
  • 分析データの収集

データ セーフティ セクションの記載内容は法的拘束力を持ちます。不正確な宣言を行うと、アプリが削除される可能性があります。

Google Playの審査はバイナリのみを対象とするものではありません。本番リリース前に、以下の宣言を完了させてください。 ポリシーとプログラム > アプリのコンテンツ.

特に注意して確認すべき最小限の項目:

  • プライバシーポリシー: Play Consoleの公開URL、および必要に応じたアプリ内のエントリーポイント
  • 広告: アプリに広告が含まれているかどうかを宣言してください
  • アプリへのアクセス権限: ログインが必要な画面がある場合は、審査員用のテスト用認証情報または明確なテストパスを提供してください
  • ターゲット層とコンテンツ: アプリの実際のターゲット層と一致させてください
  • コンテンツのレーティング: アプリが「未評価」にならないよう、IARCのアンケートに回答してください
  • データの安全性: 収集、共有、およびセキュリティに関する慣行を正確に宣言してください

却下される理由:

  • デジタルコンテンツでGoogle Play Billingを使用していない
  • 非推奨のBilling APIを使用している
  • サブスクリプション向けに独自の決済ソリューションを実装している

対策:

// ✅ Correct: Use native-purchases (uses Google Play Billing)
await NativePurchases.purchaseProduct({
productIdentifier: 'premium_monthly',
planIdentifier: 'monthly-plan',
productType: PURCHASE_TYPE.SUBS,
});
// ❌ Wrong: Custom payment processor for subscriptions
// await CustomPayment.charge(user, 9.99);

却下される理由:

  • 購入ボタンをクリックした後で初めて価格が表示される
  • 追加料金が事前に開示されていない
  • サブスクリプションの規約が曖昧

対策:

function PurchaseScreen({ product }) {
return (
<div>
{/* Show ALL costs upfront */}
<h2>Premium Subscription</h2>
<div className="pricing">
<p className="price">{product.priceString}/month</p>
<p className="taxes">Taxes may apply based on location</p>
</div>
<div className="features">
<h3>Includes:</h3>
<ul>
<li>Ad-free experience</li>
<li>Unlimited cloud storage</li>
<li>Priority support</li>
</ul>
</div>
<div className="terms">
<p>
Subscription renews automatically unless cancelled at least
24 hours before the end of the current period.
</p>
<p>
Manage or cancel in Google Play Subscriptions.
</p>
</div>
<button onClick={handlePurchase}>
Start Subscription
</button>
</div>
);
}

3. 誤解を招くサブスクリプションのパターン

「3. 誤解を招くサブスクリプションのパターン」というセクション

却下される理由:

  • プレミアムプランのデフォルト選択
  • 安価なプランの隠蔽
  • 解約手続きの複雑化
  • 偽の緊急性の演出(「残り3枠!」など)

ベストプラクティス

マーケティングガイドライン

対策:

  • すべてのプランを均等に表示する
  • 解約をわかりやすく、簡単にする
  • カウントダウンタイマーや偽の希少性を避ける
  • 高額なオプションへ誘導するダークパターンを使わない

却下される理由:

  • 購入時にアプリがクラッシュする
  • 商品がロードされない
  • 購入確認が表示されない
  • 購入後にプレミアム機能がアンロックされない
  • Play ストアからインストールしたテストトラックではなく、サイドロードしたビルドでのみテストを行った

対策:

import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
// Comprehensive testing before submission
async function testPurchaseFlow() {
try {
// 1. Test product loading
const { products } = await NativePurchases.getProducts({
productIdentifiers: ['premium_monthly', 'premium_yearly'],
productType: PURCHASE_TYPE.SUBS,
});
console.log('✓ Products loaded:', products.length);
// 2. Test purchase flow
const transaction = await NativePurchases.purchaseProduct({
productIdentifier: 'premium_monthly',
planIdentifier: 'monthly-plan',
productType: PURCHASE_TYPE.SUBS,
});
console.log('✓ Purchase completed', transaction.transactionId);
// 3. Verify entitlements
const { purchases } = await NativePurchases.getPurchases({
productType: PURCHASE_TYPE.SUBS,
});
if (
purchases.some(
(purchase) =>
purchase.productIdentifier === 'premium_monthly' &&
['PURCHASED', '1'].includes(purchase.purchaseState ?? '') &&
purchase.isAcknowledged,
)
) {
console.log('✓ Premium features unlocked');
}
// 4. Test restore
await NativePurchases.restorePurchases();
console.log('✓ Restore works');
} catch (error) {
console.error('✗ Test failed:', error);
}
}

却下される理由:

  • アプリ内にプライバシーポリシーのリンクがない
  • プライバシーポリシーにアクセスできない
  • データ収集に関する開示が不足している
  • データセーフティセクションの内容が不正確

対策:

  • Play Storeの掲載情報にプライバシーポリシーを追加する
  • アプリの設定内にリンクを含める
  • データセーフティセクションを正確に記入する
  • 新しいデータ収集を追加する場合のポリシー更新

Googleの代替決済プログラムは地域限定であり、変更される可能性があります。標準的なGoogle Play Billing以外の方法を検討する場合は、実装の直前にPlay Consoleで対象市場、必要なAPI、および開示文言を必ず確認してください。

ユーザーは以下の操作ができる必要があります:

  • 有効なサブスクリプションを簡単に確認
  • サポートに連絡せず解約が可能
  • 解約の適用タイミングを把握

実装方法:

import { NativePurchases } from '@capgo/native-purchases';
function ManageSubscriptionButton() {
const openManagement = async () => {
try {
// Opens Google Play subscription management
await NativePurchases.manageSubscriptions();
} catch (error) {
// Fallback to direct URL
const playStoreUrl = 'https://play.google.com/store/account/subscriptions';
window.open(playStoreUrl, '_blank');
}
};
return (
<button onClick={openManagement}>
Manage Subscription in Google Play
</button>
);
}

必須の開示事項:

  • 解約はいつ適用されますか?
  • 期間終了までアクセスは維持されますか?
  • 一部返金は可能ですか?
function CancellationInfo() {
return (
<div className="cancellation-info">
<h3>Cancellation Policy</h3>
<ul>
<li>Cancel anytime in Google Play</li>
<li>Access continues until end of billing period</li>
<li>No refunds for partial periods</li>
<li>Resubscribe anytime to regain access</li>
</ul>
<button onClick={() => NativePurchases.manageSubscriptions()}>
Manage in Google Play
</button>
</div>
);
}

提出前のチェックリスト

  1. 課金実装の検証

    • Google Play Billingの使用 (native-purchases経由)
    • Play Consoleで作成済みの全サブスクリプション製品
    • ベースプランとオファーが正しく設定されていること
    • 製品が有効化され、公開されていること
    • すべての対象国で価格が設定されていること
  2. テスト購入フローの確認

    • ライセンステストアカウントの作成
    • Playのテストトラックからビルドをインストール
    • 各サブスクリプションプランのテスト
    • 製品が正しくロードされるか確認
    • 購入完了のテスト
    • 以下の確認 テスト購入 バナーが表示されること
    • プレミアム機能のアンロック確認
    • サブスクリプションの復元テスト
    • 複数デバイスでのテスト
  3. コピー全体を確認

    • 購入前に価格が明示されているか
    • すべての料金が事前に開示されているか
    • サブスクリプション条件の明示
    • 解約プロセスの説明
    • 誤解を招く表現の禁止
  4. アプリのコンテンツとプライバシー

    • Play Consoleへのプライバシーポリシーのリンク
    • アプリ内でのプライバシーポリシーへのアクセス
    • 広告に関する宣言の完了
    • 認証が必要なアプリへのアクセス手順の追加
    • データセーフティ項目の正確な入力
    • 権限の正当性とドキュメント化
  5. コンテンツレーティングと対象層

    • コンテンツレーティングのアンケート回答
    • ターゲット層とコンテンツセクションを完了する
    • レーティングが実際のコンテンツと一致していることを確認
    • アンケートでアプリ内課金を申告する
  6. ストア掲載情報を準備

    • アプリの説明が正確であること
    • 短い説明が80文字以内であること
    • 詳細な説明が4000文字以内であること
    • スマートフォンのスクリーンショットを2枚以上アップロード済み
    • 1024x500のフィーチャーグラフィックをアップロード済み
    • スクリーンショットが現在のバージョンを示していること
    • 必要なアセットがすべてアップロード済み

新規個人アカウントのプロダクションアクセス: 通常、申請から7日以内 初回プロダクションレビュー: 数日かかることが多く、支払い方法やポリシーに関する質問がある場合はさらに長引くことがあります アップデート: 初回リリースよりは早いことが多いですが、審査は行われます 異議申し立て: 数日間の猶予を見込み、正確な修正内容とレビュアーへの指示を準備してください

:::tip ローリングレビュー Appleとは異なり、Googleはアプリを継続的にレビューします。アプリは決まった時間ではなく、レビュー期間中のいつでも公開される可能性があります。 :::

  1. テストアカウントの追加:

    • Play Consoleへ移動
    • 設定 > ライセンス テスト
    • テスト用のGmailアカウントを追加
  2. Sandboxでのテスト:

import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
// Test purchases with license test account
async function testInSandbox() {
const { isBillingSupported } = await NativePurchases.isBillingSupported();
if (!isBillingSupported) {
console.error('Billing not supported in this environment');
return;
}
// Fetch products (returns test pricing when using a license tester)
const { products } = await NativePurchases.getProducts({
productIdentifiers: ['premium_monthly'],
productType: PURCHASE_TYPE.SUBS,
});
console.log('Test products:', products);
// Make test purchase (no charge)
const transaction = await NativePurchases.purchaseProduct({
productIdentifier: 'premium_monthly',
planIdentifier: 'monthly-plan',
productType: PURCHASE_TYPE.SUBS,
});
console.log('Test purchase complete:', transaction.transactionId);
}
  1. テストバナーの確認:
    • テストアカウントで購入時、
    • 「テスト購入」の通知が表示されること
    • 実際の課金は発生しません

本番リリースの前に:

  1. まず、 内部テスト トラックを作成して迅速なQAを行うか、 クローズドテスト トラックを作成してより広範囲なテストを行います。
  2. 署名済みのビルドを .aab テストリリースとして公開します。
  3. テスターのメールアドレスを追加し、オプトイン用リンクを共有します。
  4. テスターにGoogle Playからビルドをインストールしてもらいます。
  5. Playストア経由でインストールしたビルドで、購入フローがエンドツーエンドで動作することを確認してください
  6. 個人開発者アカウントが2023年11月13日以降に作成された場合、本番環境への申請前に、少なくとも12人のテスターがクローズドテストに参加した状態を14日間連続で維持する必要があります

Google Play Billingの検証において、サイドロードしたデバッグビルドは、Playストア経由のテストビルドの代わりにはなりません。

import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
async function handlePurchase(productId: string, planIdentifier?: string) {
try {
setLoading(true);
const transaction = await NativePurchases.purchaseProduct({
productIdentifier: productId,
planIdentifier,
productType: planIdentifier ? PURCHASE_TYPE.SUBS : PURCHASE_TYPE.INAPP,
});
console.log('Purchase token:', transaction.purchaseToken ?? transaction.receipt);
// Success - check entitlements from the store
const { purchases } = await NativePurchases.getPurchases({
productType: planIdentifier ? PURCHASE_TYPE.SUBS : PURCHASE_TYPE.INAPP,
});
const isOwned = purchases.some(
(purchase) =>
purchase.productIdentifier === productId &&
(purchase.purchaseState === 'PURCHASED' || purchase.purchaseState === '1') &&
purchase.isAcknowledged,
);
if (isOwned) {
unlockPremiumFeatures();
showSuccess('Premium activated!');
}
} catch (error: any) {
// Handle specific error cases
switch (error.code) {
case 'USER_CANCELLED':
// User backed out - no error needed
console.log('Purchase cancelled');
break;
case 'ITEM_ALREADY_OWNED':
// They already own it - restore instead
showInfo('You already own this! Restoring...');
await NativePurchases.restorePurchases();
break;
case 'ITEM_UNAVAILABLE':
showError('This subscription is currently unavailable. Please try again later.');
break;
case 'NETWORK_ERROR':
showError('Network error. Please check your connection and try again.');
break;
default:
showError('Purchase failed. Please try again.');
console.error('Purchase error:', error);
}
} finally {
setLoading(false);
}
}
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
function RestorePurchasesButton() {
const [loading, setLoading] = useState(false);
const handleRestore = async () => {
setLoading(true);
try {
await NativePurchases.restorePurchases();
const { purchases } = await NativePurchases.getPurchases({
productType: PURCHASE_TYPE.SUBS,
});
const hasSubscription = purchases.some(
(purchase) => purchase.productType === 'subs' && purchase.isAcknowledged,
);
if (hasSubscription) {
unlockPremiumFeatures();
showSuccess('Subscriptions restored!');
return;
}
// Check one-time unlocks if needed
const { purchases: iaps } = await NativePurchases.getPurchases({
productType: PURCHASE_TYPE.INAPP,
});
const hasInApp = iaps.some((purchase) => purchase.productIdentifier === 'premium_unlock');
if (hasInApp) {
unlockPremiumFeatures();
showSuccess('Previous purchases restored!');
return;
}
showInfo('No previous purchases found.');
} catch (error) {
showError('Failed to restore purchases. Please try again.');
} finally {
setLoading(false);
}
};
return (
<button onClick={handleRestore} disabled={loading}>
{loading ? 'Restoring...' : 'Restore Purchases'}
</button>
);
}

サブスクリプションの状態を確認する

「サブスクリプション状態の確認」セクション
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
async function checkSubscriptionStatus() {
try {
const { purchases } = await NativePurchases.getPurchases({
productType: PURCHASE_TYPE.SUBS,
});
const subscription = purchases.find(
(purchase) =>
purchase.productIdentifier === 'premium_monthly' &&
(purchase.purchaseState === 'PURCHASED' || purchase.purchaseState === '1') &&
purchase.isAcknowledged,
);
if (!subscription) {
showPaywall();
return;
}
console.log('Subscription active:', {
productId: subscription.productIdentifier,
expiresAt: subscription.expirationDate,
willRenew: subscription.willCancel === false,
purchaseToken: subscription.purchaseToken,
});
unlockPremiumFeatures();
} catch (error) {
console.error('Failed to check subscription:', error);
}
}

アプリがリジェクトされた場合

「アプリがリジェクトされた場合」セクション

支払いポリシー:

  • Google Play Billingを使用していない
  • 誤解を招くサブスクリプション条件
  • 隠れたコスト

ユーザーデータポリシー:

  • プライバシーポリシーの欠如
  • データセーフティの宣言内容の不備
  • 過剰な権限要求
  1. 違反通知を確認する

    • 引用されている具体的なポリシーを確認
    • Googleが指摘した内容を把握する
    • 提供された例をチェックする
  2. 問題を修正する

    • 症状だけでなく根本原因に対処する
    • 修正後に徹底的にテストする
    • すべての変更内容を記録する
  3. 異議申し立てを送信(該当する場合)

    説明および異議申し立てのプロセス

    Subject: Policy Violation Appeal - [App Name]
    Dear Google Play Review Team,
    I have received notification that my app violates [Policy X.Y].
    I have made the following changes to comply:
    1. [Specific change made]
    2. [Specific change made]
    3. [Specific change made]
    The updated version [version number] addresses all concerns raised.
    Test account for verification:
    Email: test@example.com
    Password: TestPass123
    Thank you for your consideration.

    ドキュメントの例をリクエスト

  4. 再提出または更新

    • 修正済みバージョンをアップロード
    • 審査のために再提出
    • Play Consoleでステータスを確認

専門家のサポートが必要ですか?

「専門家のサポートが必要ですか?」セクション

Play Store のレビューは、決済コンプライアンス、アプリのコンテンツ宣言、テストトラックの設定などが絡み合い、複雑になることがあります。個別のアシスタンスが必要な場合は、以下をご活用ください:

チームによるコンサルティングを予約する 以下のサポートを提供します:

  • Play Store レビュー準備の完了
  • テストトラックの設定とテスターの募集
  • IAP 実装のレビュー
  • データ安全性とプライバシーへの準拠
  • リジェクト時のトラブルシューティングと異議申し立て
  • アプリ申請プロセスの全工程

当社のエキスパートは、これまで数百ものアプリのPlay Store申請を成功に導いてきました。現在の要件への対応もサポートします。

実装に関するヘルプが必要ですか?

Android Play Store の IAP レビューガイドラインの詳細

「Android Play Store の IAP レビューガイドラインの詳細」セクション

以下を使用している場合: Android Play Store の IAP レビューガイドライン セキュリティとコンプライアンスの計画に使う場合は、以下と連携してください: @capgo/native-purchases の使い方 「@capgo/native-purchases の使い方」のネイティブ機能については、 暗号化 実装の詳細は「暗号化」を参照: コンプライアンス 実装の詳細は「コンプライアンス」を参照: Capgo セキュリティスキャナー Capgo Security Scanner のプロダクトワークフロー、および Capgo セキュリティ Capgo Security のプロダクトワークフローについて。