跳至内容

Android Play Store IAP评审指南

GitHub

在 Google Play 上发布 Android 应用程序需要遵守 Google 的政策,尤其是那些包含内购和订阅功能的应用程序。这份指南涵盖了您需要通过审核的所有内容。

  1. 构建一个已签名的 Android App Bundle

    新 Google Play 应用程序应以 Android App Bundle(.aab)的形式上传,而不是 sideloaded debug APK。

    如果您使用Play App Signing, versionCode 每次上传时都会增加并安全存储您的上传密钥。

    Android App Bundle流程

  2. 在Play Console中创建应用记录

    如果您尚未注册开发者账户,请先在 Play Console注册。然后,在 Home > 创建应用,选择语言、应用/游戏类型、免费/付费状态、支持邮箱并接受所需的声明。

    选择免费/付费设置时要小心。Google允许您将付费应用切换为免费应用,但一旦应用被免费提供后,就无法将其切换为付费应用。

    在Play Console中创建应用

  3. 完成应用内容和商店列表

    在生产前审查之前,完成所需的Play Console申报:

    • 隐私政策
    • 广告
    • 应用程序访问
    • 目标受众和内容
    • 内容评级
    • 数据安全
    • 如果适用,敏感权限申报
  4. 在Play-Installed Test Track中运行

    内部测试 开始快速QA。 如果您的开发者帐户是11月13日,2023年之后创建的个人帐户,则您还必须完成一个 关闭测试 在 14 天内至少有 12 名测试者参与测试后才开放生产访问。

    Play Console 内部测试

  5. 验证结算端到端

    从 Google Play 安装应用,而不是从本地导出的 APK。然后确认:

    • 产品从 Play 正确加载
    • 购买单据显示一个 测试购买 许可测试者的广告牌
    • 许可证解锁后
    • 恢复和订阅管理流程工作

Google Play Billing 要求

《Google Play Billing Requirements》

必须使用的付费系统

《必须使用的付费系统》

对于数字商品和服务, 必须

使用Google Play的付费系统:

  • 数字商品(必须使用Play付费):
  • 高级功能的订阅
  • 应用内货币或积分
  • 数字内容(电子书,音乐,视频)
  • 游戏升级和强化

实物商品(无法使用Play Billing):

  • 实物商品
  • 现实世界服务
  • 一次性捐赠给非营利组织

:::note 订阅设置 在Play控制台中,使用当前 订阅->基础计划->优惠 模型。在 native-purchases,将基础计划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 需要:

  • 明确的续订通知
  • 续订价格的提示
  • 取消的便捷访问

跨平台定价透明度

《跨平台定价透明度》

If you sell the same entitlement on multiple platforms, keep the product naming, billing period, included benefits, and renewal language aligned so users are not surprised.

由于税费、当地货币或商店经济而导致的价格差异是合理的,但在Google Play中购买的UI必须不会隐藏这些差异或暗示Google Play将收取的续费成本与实际不同。

隐私政策要求

《隐私政策要求》

在Google Play商店列表中添加链接

  1. 在Play Console中添加隐私政策URL

    • 必须是公开可访问的
    • 必须与您的应用程序语言相同
    • 在应用程序内部添加链接
  2. __CAPGO_KEEP_0__

    • 在应用设置中显示隐私政策
    • 在收集任何用户数据之前显示
    • 使其容易发现

示例实现:

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(用于欺诈防御)
  • __CAPGO_KEEP_0__
  • __CAPGO_KEEP_1__

__CAPGO_KEEP_2__

__CAPGO_KEEP_3__

__CAPGO_KEEP_4__

__CAPGO_KEEP_5__ __CAPGO_KEEP_6__.

__CAPGO_KEEP_7__

  • __CAPGO_KEEP_8____CAPGO_KEEP_9__
  • __CAPGO_KEEP_10____CAPGO_KEEP_11__
  • App访问: 如果屏幕有任何限制,请向审阅者提供工作凭证或明确的测试路径
  • 目标受众和内容: 匹配应用的真实受众
  • 内容评级: 完成IARC问卷,以确保应用不被标记为未评级
  • 数据安全: 准确声明数据收集、共享和安全性实践

常见拒绝原因

标题:常见拒绝原因

1. 缺失或错误的计费实现

标题:1. 缺失或错误的计费实现

为什么会失败:

  • 未使用Google Play 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 个位置!”)

描述最佳实践

营销指南

预防:

  • 平等显示所有订阅等级
  • 让取消变得明确和易于访问
  • 避免使用倒计时器或假的稀缺性
  • 不要使用黑暗模式来推广昂贵的选项

为什么会失败:

  • App 购买时会崩溃
  • 产品无法加载
  • 购买确认信息未显示
  • 购买后premium功能未解锁
  • 测试仅在sideloaded构建中进行,而不是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);
}
}

5.隐私政策违规

标题:5.隐私政策违规

为什么会失败:

  • 应用中没有隐私政策链接
  • 无法访问隐私政策
  • 数据收集未披露
  • 数据安全部分不准确

预防措施:

  • 在Google Play商店列表中添加隐私政策
  • 在应用设置中包含链接
  • 准确填写数据安全部分
  • 在添加新数据收集时更新政策

替代付费计划

标题:替代付费计划

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

《预提交清单》

《预提交清单》

验证Billing实施

  1. 使用Google Play Billing (via native-purchases)

    • 所有在Play Console中创建的订阅产品
    • All subscription products created in Play Console
    • Base plans and offers configured correctly
    • Products are activated and published
    • Pricing set for all target countries
  2. Test Purchase Flows

    • Create license test account
    • Install the build from a Play testing track
    • Test each subscription tier
    • Verify products load correctly
    • Test purchase completion
    • Confirm the test purchase banner appears
    • 验证高级功能解锁
    • 测试订阅恢复
    • 测试多台设备
  3. 查看所有复制

    • 价格在购买前清晰显示
    • 所有费用在订阅前公开
    • 订阅条款清晰
    • 取消订阅流程解释
    • 无误导性声明
  4. 应用内容和隐私

    • 隐私政策在Play Console中链接
    • 隐私政策在应用中可访问
    • __CAPGO_KEEP_0__已完成
    • 如果应用程序被锁定,应用程序访问说明已添加
    • 数据安全部分准确完成
    • 已对权限进行了说明和文档
  5. 内容评级和受众

    • 完成内容评级问卷
    • 完成目标受众和内容部分
    • 确保评级与实际内容相符
    • 在问卷中声明应用内购买
  6. 准备商店列表

    • 应用描述准确
    • 短描述在80个字符以内
    • 所有描述均在 4000 个字符以内
    • 至少上传 2 张手机截图
    • 上传 1024x500 的特征图
    • 截图显示当前版本
    • 已上传所有必需资产

新个人账户的生产访问: 通常在申请后 7 天或更短时间 首次生产审查: 通常几天,偶尔会更长,如果涉及 billing 或政策问题 更新: 通常比首次发布更快,但仍然经过了审查 吸引力: 计划几天时间并提供准确的修复和审查者指示

:::tip 滚动审查 与苹果不同,谷歌会持续审查应用程序。您的应用程序可能在审查期间随时发布,而不是在固定的时间发布。 :::

提交之前的测试

标题:提交之前的测试
  1. 添加测试账户:

    • 前往Play控制台
    • 设置>许可测试
    • 添加Gmail账户进行测试
  2. 测试环境中测试:

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日之后创建,请至少在14个连续的日子内保持12名测试者在关闭测试中激活

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

如果您的应用被拒绝

《如果您的应用被拒绝》

常见政策违规

《常见政策违规》

__CAPGO_KEEP_0__:

  • 未使用Google Play Billing
  • 误导性订阅条款
  • 隐含费用

__CAPGO_KEEP_0__:

  • 缺少隐私政策
  • 不准确的数据安全声明
  • 过多权限

__CAPGO_KEEP_1__

解决步骤
  1. __CAPGO_KEEP_2__:

    • 查看违反通知
    • 了解 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中监控状态

Navigating Google Play Store review can be complex, especially when you need to combine billing compliance, App content declarations, and testing-track setup. If you need personalized assistance:

预约与我们的团队进行视频会议 为帮助您解决以下问题:

  • 完成Google Play Store的审核准备
  • 测试跟踪设置和测试者招募
  • IAP实施审核
  • 数据安全和隐私合规
  • 拒绝处理和申诉
  • 完成应用程序提交流程

我们的专家已经帮助数百个应用程序成功通过Google Play Store的审核,并且可以帮助您了解当前的要求。

需要帮助实现吗?

继续从Android Play Store Review指南中获取IAP

标题为“继续从Android Play Store Review指南中获取IAP”

如果您正在使用 Android Play Store Review指南中获取IAP 来规划安全性和合规性,连接它 使用 @capgo/native-purchases 使用 @capgo/native-purchases 加密 加密 合规 合规 Capgo 安全扫描器 Capgo 安全 Capgo Security for the product workflow in Capgo Security.