
Expo + RevenueCat 沙盒测试时购买弹窗无限重显,通常因环境变量(如 REVENUECAT_API_KEY 和 REVENUECAT_APP_USER_ID)未正确注入导致 SDK 初始化失败,进而使购买流程中断、回调不触发、状态无法同步。
expo 应用内购沙盒测试时购买弹窗无限重显,通常因环境变量(如 `revenuecat_api_key` 和 `revenuecat_app_user_id`)未正确注入导致 sdk 初始化失败,进而使购买流程中断、回调不触发、状态无法同步。
在 Expo 项目中集成 RevenueCat 进行 iOS 应用内购(IAP)沙盒测试时,若出现「点击订阅后沙盒弹窗显示“Done”随即关闭,3 秒后又自动弹出,且 console.log 不执行、RevenueCat 后台无用户记录」的现象,根本原因几乎总是 RevenueCat SDK 未能成功初始化——而初始化失败最常见的根源,是关键环境变量未随构建过程注入到运行时环境中。
? 关键点:Expo 不会自动打包 .env 文件中的变量
与 Web 或原生 React Native 项目不同,Expo 的 Metro 打包器默认不会读取或注入 .env 文件中的变量(即使使用 @expo/env 或 dotenv)。这意味着你代码中依赖的 REVENUECAT_API_KEY、REVENUECAT_APP_USER_ID 等常量若仅写在 .env 中,实际运行时将为 undefined,导致 Purchases.configure() 失败(静默失败,无明显报错),后续所有购买调用(如 purchasePackage)均无法建立有效上下文,从而触发沙盒的“购买未确认→自动重试→弹窗循环”行为。
✅ 正确做法:通过 Expo Config 注入环境变量
推荐使用 Expo 的官方方案 —— 在 app.config.js(或 app.json)中声明 extra 字段,并配合 process.env 安全注入:
// app.config.js
export default ({ config }) => {
return {
...config,
extra: {
revenuecatApiKey: process.env.REVENUECAT_API_KEY,
// 注意:iOS 沙盒要求必须设置有效的 App User ID(建议使用 UUID)
appUserId: process.env.REVENUECAT_APP_USER_ID || 'demo_' + Math.random().toString(36).substr(2, 9),
}
};
};
然后在 JS 代码中安全读取(不要直接使用 process.env,它在 Expo 运行时不可用):
import Constants from 'expo-constants';
const REVENUECAT_API_KEY = Constants.expoConfig?.extra?.revenuecatApiKey;
const APP_USER_ID = Constants.expoConfig?.extra?.appUserId;
// 初始化必须放在应用启动早期(如 App.tsx 的 useEffect 或自定义 Hook 中)
useEffect(() => {
if (REVENUECAT_API_KEY) {
Purchases.configure({
apiKey: REVENUECAT_API_KEY,
appUserID: APP_USER_ID,
});
}
}, []);
⚠️ 补充注意事项
- iOS 模拟器不支持 IAP:官方明确说明 iOS Simulator does not support StoreKit,沙盒测试必须在真机上进行(即使已启用 Developer Mode 和 iOS 17+)。模拟器下任何购买行为均为无效,极易引发循环弹窗。
- 沙盒账户需在真实设备上登录:确保测试设备的 App Store 设置中已退出正式账号,并使用 App Store Connect 的沙盒测试员账号 登录(非 iCloud 账号)。
-
验证 Purchases 配置状态:可在购买前添加校验逻辑,避免静默失败:
const isConfigured = await Purchases.isConfigured(); console.log('RevenueCat configured:', isConfigured); // 应为 true if (!isConfigured) { console.warn('RevenueCat not configured — check API key & app user ID'); } -
调试技巧:启用 RevenueCat 日志以定位初始化问题:
Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);
✅ 总结
解决沙盒弹窗循环的核心三步:
1️⃣ 禁用 .env 直接引用,改用 app.config.js + Constants.expoConfig.extra 注入敏感配置;
2️⃣ 务必在真机上测试(模拟器 IAP 功能不可用);
3️⃣ 确认沙盒 Apple ID 已在设备系统级登录,且 RevenueCat 初始化日志无报错。
完成上述配置后,你的 subscribe() 函数将正常触发 purchaserInfo 回调、打印日志、跳转页面,且 RevenueCat 控制台会实时显示沙盒订阅记录——这才是符合预期的端到端测试流。











