React Native 应用内购买与付费墙概述
0:02:00欢迎来到 RevenueCat 的 React Native SDK Codelab!
目标: 在本 Codelab 中,您将学习如何将 RevenueCat React Native SDK 集成到新的 React Native 应用程序中,以获取产品方案并显示预构建的原生付费墙 UI。
您将构建的内容:
一个简单的单屏应用,显示加载指示器,从 RevenueCat 获取您配置的"产品方案",然后显示 RevenueCatUI 付费墙。
前提条件
在开始之前,您必须完成以下设置:
- React Native 环境: 您的 React Native 开发环境应已准备就绪,包括 Node.js、React Native CLI 和所需的平台特定工具。
- 平台要求:
- RevenueCat 账户: 在 revenuecat.com 注册的免费账户。
- App Store / Play Store 配置:
- 在您的 RevenueCat 控制台中将此产品链接到权益和产品方案。这是最关键的步骤。如果您没有"当前"产品方案,付费墙将不会显示。
- 物理设备或配置好的模拟器: 用于测试应用内购买。
完成本 Codelab 后,您将能够在 React Native 应用中成功实现应用内购买,并使用 RevenueCat 的 React Native SDK 显示动态付费墙。
导入 RevenueCat SDK
0:05:00首先,在实现应用内购买之前,您需要将 RevenueCat SDK 导入到您的现有或新项目中。首先,将以下依赖项添加到您的项目中:
您可以在 GitHub 上查看最新发布版本。
安装
使用 npm:
npm install --save react-native-purchases或使用 yarn:
yarn add react-native-purchases平台特定配置
iOS 设置
对于 iOS,您需要启用"应用内购买"功能:
- 在 Xcode 中打开您的项目
- 选择您的项目目标
- 转到"Signing & Capabilities"
- 点击"+ Capability"并添加"In-App Purchase"
Android 设置
对于 Android,将计费权限添加到您的 AndroidManifest.xml:
<uses-permission android:name="com.android.vending.BILLING" />此外,确保您的 Activity 的 launchMode 在 AndroidManifest.xml 中设置为 standard 或 singleTop:
<activity
android:name=".MainActivity"
android:launchMode="standard"
...
/>初始化 RevenueCat SDK
现在,让我们初始化 RevenueCat SDK。我们将在您的主 App.js 或 App.tsx 文件中完成此操作。
- 打开
App.js(或 TypeScript 项目的App.tsx) - 在文件顶部导入 SDK
- 将您的 API 密钥粘贴到常量中
// App.js
import React, { useEffect, useState } from 'react';
import { Platform, View, Text, ActivityIndicator, StyleSheet } from 'react-native';
import Purchases from 'react-native-purchases';
// --- 在此处粘贴您的 REVENUECAT 密钥 ---
const androidApiKey = 'goog_YOUR_KEY_HERE';
const iosApiKey = 'appl_YOUR_KEY_HERE';
const App = () => {
const [isConfigured, setIsConfigured] = useState(false);
useEffect(() => {
const initializePurchases = async () => {
try {
// 为开发启用调试日志
Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);
// 使用适当的 API 密钥配置 SDK
if (Platform.OS === 'ios') {
await Purchases.configure({ apiKey: iosApiKey });
} else if (Platform.OS === 'android') {
await Purchases.configure({ apiKey: androidApiKey });
}
console.log('RevenueCat 配置成功!');
setIsConfigured(true);
} catch (e) {
console.error('配置 RevenueCat 时出错:', e);
}
};
initializePurchases();
}, []);
if (!isConfigured) {
return (
<View style={styles.centered}>
<ActivityIndicator size="large" />
<Text style={styles.loadingText}>正在初始化 RevenueCat...</Text>
</View>
);
}
// 主应用内容将在后续步骤中添加
return (
<View style={styles.container}>
<Text>RevenueCat 已准备就绪!</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
centered: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
marginTop: 10,
fontSize: 16,
},
});
export default App;我们刚刚创建了一个基本的 React Native 应用,使用 useEffect 钩子初始化 RevenueCat SDK。这确保在进行任何购买之前 SDK 已配置并准备就绪。这是初始化需要从一开始就可用的插件的正确方式。
太棒了!您现在已经完成了 50% 的实现工作。
验证用户权益
0:03:00现在让我们继续验证用户权益。
如前所述,权益(Entitlement)代表用户在购买后解锁的访问级别或功能。这对于确定是否显示广告横幅或授予高级访问权限等场景非常有用。
您可以使用以下代码片段轻松检查用户是否拥有活跃的权益:
const ENTITLEMENT_IDENTIFIER = ".."; // 从您的 RevenueCat 控制台获取特定的权益标识符
try {
const customerInfo = await Purchases.getCustomerInfo();
const isEntitled = customerInfo.entitlements.active[ENTITLEMENT_IDENTIFIER]?.isActive;
if (isEntitled) {
// 用户有权访问此权益
console.log('用户有权益');
} else {
// 用户没有访问权限
console.log('用户没有权益');
}
} catch (e) {
console.error('检查权益时出错:', e);
}一旦您检查了用户是否拥有特定权益,就可以根据您应用的商业模式决定如何继续。
例如,如果您的应用是广告支持的,您可能会选择显示或隐藏 AdMob 横幅。或者,您可以选择显示付费墙或购买对话框,让用户解锁高级功能或内容。
以下是如何实现该逻辑的示例:
if (isEntitled) {
// 如果用户被授予此权益的访问权限,则不需要显示横幅。
} else {
// 在此处显示横幅 UI 或显示付费墙
}实现应用内购买
0:04:00现在,让我们实现应用内购买以提供无广告体验。首先,您需要从 RevenueCat 控制台获取相关产品信息。这些产品数据将用于向用户展示购买选项。
您可以通过调用 Purchases.getProducts() 来获取可用产品,如以下示例所示:
// 从 RevenueCat 服务器获取产品信息
const products = await Purchases.getProducts(['paywall_tester.subs']);
// 执行应用内购买
const purchaseResult = await Purchases.purchaseStoreProduct(products[0]);如果您提供多种产品变体,例如 paywall_tester.subs:weekly、paywall_tester.subs:monthly 和 paywall_tester.subs:yearly,您可以使用基础产品标识符 paywall_tester.subs 作为 productIds 字段的值来简化产品获取。这将告诉 RevenueCat 以列表形式获取所有相关产品变体,以便您可以在付费墙 UI 中动态展示它们。
一旦您获取了产品数据,就可以通过调用 Purchases.purchaseStoreProduct(product) 来启动应用内购买流程。这将自动触发 Google Play 购买对话框或 Apple 的购买弹窗,使用户能够在您的应用内完成交易。
就这样,您只用几行代码就集成了一个完整功能的应用内购买流程——无需处理收据、商店 API 或手动购买验证的复杂性。
完整的代码示例如下所示:
import Purchases from 'react-native-purchases';
/**
* 通过产品 ID 获取特定产品并启动购买流程。
*
* 此函数处理潜在错误,如产品未找到、
* 用户取消购买或其他商店错误。
*/
const purchaseProduct = async () => {
// 1. 定义要获取的产品标识符。
const productId = 'paywall_tester.subs';
try {
// 2. 从 RevenueCat 获取 StoreProduct
console.log('正在获取产品...');
const products = await Purchases.getProducts([productId]);
// 3. 检查产品列表是否不为空
if (products.length === 0) {
console.error('错误:未找到产品。请检查 ID 和您的 RevenueCat 设置。');
// 可选:向用户显示错误消息
return;
}
const productToPurchase = products[0];
console.log('找到产品:', productToPurchase.title, '。正在启动购买...');
// 4. 启动购买流程
const { customerInfo } = await Purchases.purchaseStoreProduct(productToPurchase);
// 5. 通过验证权益来检查购买是否成功
// 将 "your_premium_entitlement" 替换为您在 RevenueCat 中的实际权益标识符
if (customerInfo.entitlements.active['your_premium_entitlement']?.isActive) {
console.log('购买成功!用户现在拥有高级访问权限。');
// 授予高级内容访问权限
} else {
console.log('购买完成,但权益未激活。');
}
} catch (e) {
// 6. 处理潜在错误
if (e.code === Purchases.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR) {
console.log('用户取消了购买。');
} else {
console.error('购买失败,错误:', e.message);
}
}
};实现付费墙
0:07:00现在,是时候在 React Native 中实现付费墙了。
步骤 1:安装 RevenueCatUI 包
首先,安装提供预构建付费墙组件的 RevenueCatUI 包:
npm install --save react-native-purchases-ui
# 或
yarn add react-native-purchases-ui步骤 2:导入 RevenueCatUI
在文件顶部导入付费墙展示方法:
import { presentPaywallIfNeeded } from 'react-native-purchases-ui';步骤 3:获取产品方案并显示付费墙
让我们更新 App.js 以获取产品方案并显示付费墙。用以下代码替换您现有的应用代码:
// App.js
import React, { useEffect, useState } from 'react';
import {
Platform,
View,
Text,
ActivityIndicator,
StyleSheet,
SafeAreaView,
} from 'react-native';
import Purchases from 'react-native-purchases';
import { presentPaywallIfNeeded } from 'react-native-purchases-ui';
// --- 在此处粘贴您的 REVENUECAT 密钥 ---
const androidApiKey = 'goog_YOUR_KEY_HERE';
const iosApiKey = 'appl_YOUR_KEY_HERE';
const App = () => {
const [isConfigured, setIsConfigured] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [offering, setOffering] = useState(null);
const [errorMessage, setErrorMessage] = useState(null);
useEffect(() => {
const initializePurchases = async () => {
try {
// 为开发启用调试日志
Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);
// 使用适当的 API 密钥配置 SDK
if (Platform.OS === 'ios') {
await Purchases.configure({ apiKey: iosApiKey });
} else if (Platform.OS === 'android') {
await Purchases.configure({ apiKey: androidApiKey });
}
console.log('RevenueCat 配置成功!');
setIsConfigured(true);
} catch (e) {
console.error('配置 RevenueCat 时出错:', e);
setErrorMessage('初始化 RevenueCat 失败');
setIsLoading(false);
}
};
initializePurchases();
}, []);
useEffect(() => {
if (!isConfigured) return;
const loadOfferings = async () => {
try {
setIsLoading(true);
setErrorMessage(null);
// 从 RevenueCat 获取当前产品方案
const offerings = await Purchases.getOfferings();
if (offerings.current !== null) {
setOffering(offerings.current);
} else {
setErrorMessage('未找到当前产品方案。请检查您的 RevenueCat 控制台。');
}
} catch (e) {
console.error('获取产品方案时出错:', e);
setErrorMessage(`加载产品方案失败: ${e.message}`);
} finally {
setIsLoading(false);
}
};
loadOfferings();
}, [isConfigured]);
useEffect(() => {
if (!offering) return;
const showPaywall = async () => {
try {
const paywallResult = await presentPaywallIfNeeded({
offering: offering,
});
console.log('付费墙结果:', paywallResult);
if (paywallResult === Purchases.PAYWALL_RESULT.PURCHASED) {
console.log('用户完成了购买!');
} else if (paywallResult === Purchases.PAYWALL_RESULT.RESTORED) {
console.log('用户恢复了购买!');
} else if (paywallResult === Purchases.PAYWALL_RESULT.CANCELLED) {
console.log('用户取消了付费墙');
}
} catch (e) {
console.error('展示付费墙时出错:', e);
}
};
showPaywall();
}, [offering]);
if (isLoading) {
return (
<SafeAreaView style={styles.centered}>
<ActivityIndicator size="large" color="#6366f1" />
<Text style={styles.loadingText}>正在加载付费墙...</Text>
</SafeAreaView>
);
}
if (errorMessage) {
return (
<SafeAreaView style={styles.centered}>
<Text style={styles.errorText}>{errorMessage}</Text>
</SafeAreaView>
);
}
return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>RevenueCat 付费墙演示</Text>
<Text style={styles.subtitle}>付费墙显示成功!</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
padding: 20,
},
centered: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
loadingText: {
marginTop: 16,
fontSize: 16,
color: '#666',
},
errorText: {
fontSize: 16,
color: '#ef4444',
textAlign: 'center',
padding: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 8,
color: '#111',
},
subtitle: {
fontSize: 16,
color: '#666',
},
});
export default App;- 我们创建了状态变量来管理加载状态、产品方案和错误消息。
- 我们首先在组件挂载时初始化 RevenueCat SDK。
- 配置完成后,我们使用
Purchases.getOfferings()获取产品方案。 - 当产品方案可用时,我们使用
presentPaywallIfNeeded()自动展示付费墙。 - 我们处理各种付费墙结果,包括购买、恢复和取消。
步骤 4:运行您的应用程序
完成!
现在,在设备或模拟器上运行您的应用程序:
对于 iOS:npx react-native run-iosnpx react-native run-android- 带有加载器的"正在加载付费墙..."消息。
- 然后是您完整功能的原生付费墙 UI,如下图所示。
故障排除
如果付费墙未显示,请检查调试控制台并查看这些常见问题: "未找到当前产品方案":这是最常见的错误。这意味着您的 RevenueCat 控制台缺少"当前"产品方案。前往产品方案,选择一个产品方案,并确保它被标记为"当前"。 API 密钥错误:仔细检查您是否复制了正在测试的平台的正确公共 API 密钥。 产品未配置:确保您在商店控制台中的应用内产品已正确设置,并在 RevenueCat 中链接到权益和产品方案。 沙盒/测试用户问题:确保您使用沙盒测试账户登录(iOS)或您的电子邮件已添加为许可证测试人员(Android)。 平台特定问题: iOS:验证 In-App Purchase 功能已在 Xcode 中启用- Android:检查 BILLING 权限是否在 AndroidManifest.xml 中
配置完成!现在,每当用户没有所需权益时,您就可以显示付费墙,使用的正是您在付费墙编辑器中配置的设计。
正如您在 Codelab:RevenueCat Google Play 集成(创建付费墙)中所见,付费墙系统建立在服务端驱动的 UI 之上。这意味着您可以直接从控制台动态更新付费墙的内容和设计,无需推送应用更新或经过审核流程。
总结
在本 Codelab 中,您学习了如何集成 RevenueCat 的 React Native SDK、实现应用内购买以及在 React Native 中构建付费墙。现在是时候发布您的应用并赚取更多收入了!
您还可以通过以下资源了解更多关于使用 RevenueCat SDK 的信息:
- 产品教程:帮助您入门并充分利用 RevenueCat 的视频教程。
- React Native SDK 参考:React Native 的完整 SDK 文档。
- RevenueCat 社区:加入我们的社区提问并分享您的经验。