教程:如何在Flutter应用中实现应用内购买
Updated: March 20, 2023
Flutter是Google开发的一个相对较新的框架,它可以让您快速创建跨平台应用。另一个流行的框架是Facebook的React Native。Flutter应用同时适用于iOS和安卓。因此,购买库必须与StoreKit和Billing Library兼容。
架构方面,任何支付插件——包括我们的Adapty Flutter软件开发工具包(SDK)——都是对本地库、StoreKit和Billing Library的包装器。在我们的例子中,它是我们自己的 Adapty iOS和安卓SDK库的包装器。
在基于Flutter的应用中,用于应用内购买(in-app purchase)的开源库
在Flutter应用中流行的购买解决方案是开源插件in_app_purchase(由Flutter背后的团队开发)和flutter_inapp_purchase(非官方插件)。
这些插件用于实现客户端购买。它们没有服务器端(server-side)收据验证(receipt validation)功能。您需要建立自己的服务器端基础设施来验证收据,并收集有关续订、退款、试用、取消等的付款分析。
更重要的是,这些库在支持新的存储特性方面通常很慢。仅举其中几个例子,它们目前缺乏iOS的优惠推广、现收现付功能和预付功能。
由于我们的库与服务器对话,所以它具有以下特性:
- 购买服务器验证;
- 完全支持本地支付功能;
- DRY句法;
- 订阅和购买分析以及其他数据收集;
- A/B测试(A/B test),以及购买、定价和促销期的快速试验;
- 付费墙(paywall)和优惠推广(promo offer)。
为了让本文简洁易读,我们将链接一些我们以前写过的文章,这些文章都与您开始为您的Flutter应用程序进行购买之前,所应该采取的步骤有关。
在iOS和安卓平台上进行购买
首先,如果您没有开发者账号,就需要先创建一个。接下来,您需要创建面向iOS和安卓的每周购买内容。我们已经在之前的文章中解释过如何做到这一点:
完成之后,就可以开始创建和配置项目了。
创建并配置项目
为了让您的购买在您的实现和我们的系统中运行,您需要填写这些技术细节。
对于iOS,您需要:
- 指定Bundle ID,将Adapty项目链接到应用;
- 在App Store Connect中设置应用商店服务器通知,这样您就可以收到订阅事件的通知了;
- 指定应用商店共享密钥(Shared Secret),Adapty服务器将用它建立到苹果服务器的连接,并验证收据。
对于安卓,必须同时指定包名和服务账号密钥文件。安卓的包名就相当于iOS的Bundle ID。您需要使用与代码中使用所相同的。您可以在/android/app/build.gradle文件中找到,它位于android.defaultConfig.applicationId目录下。
配置产品和付费墙
Adapty产品囊括了各种商店的产品。目前只有App Store和Google Play,但我们将在未来引入其他商店。这种方法背后的想法是让跨平台的统计数据收集更容易,以及让您使用顶级实体,而不是标识符。
Paywall是一个抽象实体,包含一个产品阵列和一个远程配置文件(这是一个JSON文件,包含您在指示板中指定的元数据)。 您将付费墙ID硬编码到应用中——这个ID用于检索配置文件和产品数据。您可以在不更新应用程序的情况下进行编辑。通常情况下,您设计付费墙,然后用我们提供的数据进行填写。
创建产品
让我们使用Google Play Console和App Store Connect来创建一个对应于每周订阅的产品。填写对应产品的ID,可以从支付系统中检索。需要注意的是,因为App Store Connect没有API,所以您需要手动操作。不过,只需要一次。
创建付费墙
创建一个付费墙时,关键是用一种方便的格式指定它的ID。这个标识符稍后将被SDK用来请求付费墙数据。我们相信这是一个很好的方法:使用这种体系结构,不需要在客户端将您的产品进行硬编码。您可以灵活地处理产品管理、版本管理、测试等。另一种选择是带有一组内置产品的Firebase JSON。但是,这并不提供错误验证,也不太友好。
瞧!在创建了产品和付费墙后,您现在就可以进行第一次购买了。让我们继续安装SDK。
如何使用SDK
让我们看看配置和使用订阅所需的主要函数。
安装库
首先,您需要将adapty_flutter库添加到项目中。为此,将以下依赖项添加到您的pubspec.yaml文件中:
dependencies: adapty_flutter: ^1.0.4
之后运行:
flutter pub get
从这里,您就可以像这样将Adapty SDK导入到您的应用中:
import 'package:adapty_flutter/adapty_flutter.dart';
配置
您需要配置您的应用程序才能使用Adapty。为此,将带有公共SDK密钥的AdaptyPublicSdkKey标志添加到Info.plist(用于iOS)或AndroidManifest.xml(安卓)。
您可以在Adapty设置中找到您的SDK密钥:
Info.plist:
<dict> ... <key>AdaptyPublicSdkKey</key>
AndroidManifest.xml:
<application ...> ... <meta-data android:name="AdaptyPublicSdkKey" android:value="PUBLIC_SDK_KEY" /> </application>
接下来,通过调用Flutter端的代码来激活SDK——例如,在您的项目的
void main() { runZoned(() async { Adapty.activate(); final installId = await Service.getOrCreateInstallId(); await Adapty.identify(***customer-user-id***); await Adapty.setLogLevel(AdaptyLogLevel.verbose); runApp(MyApp()); }); }
空隙Adapty.activate()函数激活Adapty_Flutter库:
Future<bool> Adapty.identify(String customerUserId)
Adapty.identify让您可以检索用户id。Adapty将其发送到订阅和分析系统,为该配置文件分配事件。您还可以在配置文件中通过customerUserId找到您的客户。
Adapty记录错误消息和其他重要数据,以帮助您理解正在发生的事情。
Future<void> Adapty.identify(AdaptyLogLevel value)
这个函数允许您从三个可能的值中选择一个:
- AdaptyLogLevel.none(默认设置):不会记录任何内容。
- AdaptyLogLevel.errors:只有错误消息将被记录。
- AdaptyLogLevel.verbose:方法调用、API请求和响应以及错误消息将被记录。
检索付费墙
如需检索付费墙列表,请运行以下代码:
try { final GetPaywallsResult getPaywallsResult = await Adapty.getPaywalls(forceUpdate: Bool); final List<AdaptyPaywall> paywalls = getPaywallsResult.paywalls; } on AdaptyError(adaptyError) {} catch(e) {}
Adapty.getPaywalls()函数返回GetPaywallsResult对象,其中包含:
- 付费墙:一系列付费墙(AdaptyPaywall)。该模型包含产品列表、付费墙ID、自定义负载和其他一些值。
购买
在前面的步骤中,您已经检索了付费墙数组。现在,我们将寻找在用户界面中显示这些产品所需的内容。让我们假设这个付费墙名为your_paywall_id:
final List<AdaptyPaywall>? paywalls = getPaywallsResult.paywalls; myPaywall = paywalls?.firstWhere((paywall) => paywall.developerId == "your_paywall_id", orElse: null);
接下来,使用产品字段中的产品数组,显示其所有项。假设用户想购买第一种产品。为了简单起见,我们假定它是产品数组的第一项。
final AdaptyProduct? product = myPaywall?.products?.first;
如需启动购买,请调用makePurchaseResult函数。(请记住要将其包装在try-catch块中,才能仍然接收来自SDK的所有错误消息。)
final MakePurchaseResult makePurchaseResult = await Adapty.makePurchase(product);
一旦函数执行成功,makePurchaseResult变量会把结果作为它的值。以下是购买完成后检查访问级别的方法:
final isPremium = makePurchaseResult?.purchaserInfo?.accessLevels['premium']?.isActive ?? false;
请注意:AdaptyErrorCode.paymentCancelled的意思是用户自己取消了购买,这意味着它不是一个实际的错误消息。
如需恢复购买,请使用.restorePurchases()方法:
try { final RestorePurchasesResult restorePurchasesResult = await Adapty.restorePurchases(); // "premium" is an identifier of default access level if (restorePurchasesResult?.purchaserInfo?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) {} catch (e) {}
考虑到MakePurchaseResult和RestorePurchasesResult对象都包括purchaserInfo。此对象包含有关访问级别、订阅和购买的数据。通常情况下,您可以通过检查用户的访问级别来判断他们是否可以访问应用的高级功能。
订阅状态
为了避免必须检查前面的整个交易链,我们引入了术语“访问级别”。访问级别是一个标志,说明用户可以访问应用程序的多少功能。如果他们还没有购买任何东西,那么他们的访问级别将为空。否则,它将是您为您的产品指定的访问级别。
例如,您可以有两个访问级别,即银和金。不同的购买将解锁不同的访问级别和功能。大多数应用程序只有一个访问级别。
如需查看订阅是否处于活动状态,只需检查用户是否具有活跃的访问级别即可。您可以使用the.getPurchaserInfo()方法做到这一点:
try { AdaptyPurchaserInfo purchaserInfo = await Adapty.getPurchaserInfo(); // "premium" is an identifier of default access level if (purchaserInfo.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) {} catch (e) {}
您还可以订阅.purchaserInfoUpdateStream流,以便及时了解订阅者访问级别的任何更改。方法如下:
Adapty.purchaserInfoUpdateStream.listen((purchaserInfo) { print('#Adapty# Purchaser Info Updated'); if (purchaserInfo.accessLevels['premium'].isActive) { // grant access to premium features } });
结论
我们设计了SDK,帮助您快速将支付整合到您的应用程序中。此外,我们还试图简化所有其他可能需要的步骤,如AB测试、分析和进一步的集成。
如果您每月的收入少于1万美元,我们将免费提供完整的购买功能。为您自己节省几个月的工作时间,专注于最重要的事情:您的产品。
Further reading