跳转到正文

Android Play Store IAP 审核指南

GitHub

让您的 Android 应用通过 Google Play 审核,需要遵守 Google 的政策,特别是对于包含应用内购买和订阅的应用。本指南将涵盖通过审核所需的所有内容。

  1. 构建已签名的 Android App Bundle

    新的 Google Play 应用应以 Android App Bundle 格式上传 (.aab),而不是通过 sideload 方式安装 debug 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 日之后创建的个人账号,您还必须完成一次 封闭测试 在获得正式版发布权限前,需至少有 12 名测试人员连续加入测试并持续 14 天。

    Play Console 中的内部测试

  5. 验证端到端计费流程

    请从 Google Play 安装应用,而非使用本地导出的 APK。然后确认以下事项:

    • 商品能从 Play 正确加载
    • 购买界面显示 测试购买 许可测试人员横幅
    • 购买后即可解锁权限
    • 恢复购买与订阅管理流程正常工作

对于数字商品和服务,您必须 必须 使用 Google Play 的结算系统:

数字商品(必须使用 Play Billing):

  • 高级功能的订阅服务
  • 应用内货币或积分
  • 数字内容(电子书、音乐、视频)
  • 游戏升级与道具
  • 应用解锁与高级会员层级

实物商品(不能使用 Play Billing):

  • 实物周边商品
  • 现实世界中的服务
  • 向非营利组织的单次捐赠

:::note 订阅设置 在 Play Console 中,使用当前的 订阅 -> 基本方案 -> 优惠进行 Android 订阅配置 模型。在 native-purchases,请通过 Base 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 要求:

  • 明确的续费通知
  • 价格提醒
  • 便捷的取消流程

如果您在多个平台上销售相同的权益,请保持产品命名、计费周期、包含权益及续订说明的一致性,以免用户产生困惑。

由于税收、当地货币或商店经济政策的原因,价格差异是合理的,但购买 UI 绝不能隐藏这些差异,或暗示的续订费用与 Google Play 实际收取的费用不符。

如果您的应用包含应用内购买,则必须:

  1. 在 Play Store 应用详情页中添加链接

    • 在 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 APIs
  • 为订阅服务实现了自定义支付方案

预防措施:

// ✅ 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 个名额!”)

描述最佳实践

营销指南

预防措施:

  • 同等展示所有订阅档位
  • 让取消流程清晰且易于操作
  • 避免使用倒计时或制造虚假紧迫感
  • 不要用欺骗性设计诱导用户选择高价选项

失败原因:

  • 购买时应用崩溃
  • 商品无法加载
  • 未显示购买确认信息
  • 购买后高级功能未解锁
  • 仅在侧载 build 上测试,而非通过 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);
}
}

失败原因:

  • 应用内缺少隐私政策链接
  • 隐私政策无法访问
  • 未披露数据收集情况
  • Data Safety 部分信息不准确

预防措施:

  • 在 Play Store 应用详情中添加隐私政策
  • 在应用设置中包含隐私政策链接
  • 准确填写 Data Safety 部分
  • 添加新数据收集项时更新政策

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. 验证测试横幅:
    • 使用测试账号进行购买时
    • 应显示 “Test purchase” 通知
    • 不会产生实际费用

在正式发布前:

  1. 创建一个 内部测试 用于快速 QA 的轨道,或 封闭测试 用于更广泛测试的轨道
  2. 上传已签名的 .aab 并发布测试版本
  3. 添加测试人员邮箱并分享加入链接
  4. 让测试人员从 Google Play 安装该 build
  5. 验证从 Play Store 安装的构建能否端到端跑通购买流程
  6. 如果您的个人开发者账号创建于 2023 年 11 月 13 日之后,在申请正式版前,请确保至少有 12 名测试人员连续 14 天参与封闭测试

在验证 Google Play Billing 时,侧载的 debug 构建不能替代从 Play Store 安装的测试构建。

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);
}
}

如果您的 App 被拒绝

“如果您的 App 被拒绝”章节

常见的政策违规行为

“常见的政策违规行为”章节

付款政策:

  • 未使用 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”中的原生能力, 加密 了解 Encryption 的实现细节, 合规性 了解合规部分的实现细节, Capgo 安全扫描器 用于 Capgo Security Scanner 中的产品工作流,以及 Capgo 安全 用于 Capgo Security 中的产品工作流。