Flutter应用内购买界面插件in_app_purchases_paywall_ui的使用

Flutter应用内购买界面插件in_app_purchases_paywall_ui的使用

该插件是一个为Flutter开发的应用内购买界面。支持Dart 3和Flutter 3.10。

支付墙设计面向所有人

这个简单的支付墙界面是为Flutter社区开发的。完全可定制且易于集成。

设计1:简单支付墙

简单支付墙设计是一个没有动画的基本设计。

简单支付墙

设计2:莫里茨支付墙

由莫里茨设计的第二个支付墙自版本0.5起可用。

莫里茨支付墙

简单集成

可以使用Scaffold来显示一个应用栏,也可以将支付墙包裹在PaywallScaffold中。

// 使用Scaffold来显示应用栏
PaywallScaffold(
  appBarTitle: "Premium",
  child: // 你的支付墙作为子组件
);

SimplePaywall(
  // ...
)

MoritzPaywall(
  // ...
)
Flutter导航2.0页面

如果你使用Flutter导航2.0,你可能希望将Scaffold包裹在一个页面元素中,或者使用PaywallPage类:

class PremiumPage extends Page {
  [@override](/user/override)
  Route createRoute(BuildContext context) {
    return MaterialPageRoute(
      settings: this,
      builder: (BuildContext context) {
        return PaywallScaffold(
          // ...
        );
      },
    );
  }
}

包含状态控制

要控制状态,扩展DefaultPurchaseHandler并实现自己的逻辑。

class PurchaseHandler extends DefaultPurchaseHandler {
  [@override](/user/override)
  Future<bool> purchase(SubscriptionData productDetails) async {
    // 显示加载
    isPendingPurchase = true;
    // 你的逻辑
    await Future.delayed(Duration(seconds: 1));
    // 显示成功购买并结束加载
    purchaseState = PurchaseState.PURCHASED;
    isPendingPurchase = false;
    return true;
  }

  [@override](/user/override)
  Future<bool> restore() async {
    // 显示加载
    isPendingPurchase = true;
    // 你的逻辑
    await Future.delayed(Duration(seconds: 1));
    // 显示成功购买并结束加载
    purchaseState = PurchaseState.PURCHASED;
    isPendingPurchase = false;
    return true;
  }
}

简单支付墙成功状态

成功页面链接到订阅页面

自2022年9月30日起,每个应用必须包括一个链接到商店订阅页面的深度链接。我们在成功页面上添加了链接。

你可以通过向支付墙添加一个ActivePlan对象来添加链接:

activePlanList: [
  // 在Android设备上链接到订阅概述:
  GooglePlayGeneralActivePlan(),

  // 在Android设备上链接到特定订阅:
  GooglePlayActivePlan("yearly_pro", "com.tnx.packed"),

  // 在iOS设备上链接到订阅概述:
  AppleAppStoreActivePlan(),
],

具体的App Store文档如下:

活动计划链接

使用linkfive_purchases库进行轻松集成

由于LinkFive使用in_app_purchase包作为依赖项,因此集成非常无缝和轻松。

Pub.dev插件:linkfive_purchases

// 从你的提供者或流中获取订阅数据(如上述描述)
LinkFiveProducts? products = // 通过产品流获得的产品

SimplePaywall(
  // ...
  // 基本上只是linkFivePurchases类
  callbackInterface: LinkFivePurchases.callbackInterface,

  // 你可以使用自己的字符串或使用intl包来自动生成订阅字符串
  subscriptionListData: products?.paywallUIHelperData(context: context) ?? [],
  // ...
);

LinkFive和Flutter完美结合

阅读更多关于简单的Flutter支付墙集成

LinkFive提供者插件(最简单的版本)

LinkFive创建了一个提供者插件,你可以直接使用:linkfive_purchases_provider

对于一个完整的支付墙包括状态管理,注册模块:

MultiProvider(
  providers: [
    // ...
    ChangeNotifierProvider(
      create: (context) => LinkFiveProvider("API_KEY"),
      lazy: false,
    ),
  ]
)

并将回调传递给订阅数据:

PaywallScaffold(
  child: SimplePaywall(
    callbackInterface: LinkFivePurchases.callbackInterface,
    subscriptionListData: provider.getSubscriptionListData(context),
    // ...
  )
)

现在你有了一个功能齐全的订阅系统。

导航器2.0与提供者示例

查看以下示例:提供者和导航器示例

平板响应式布局

我们添加了库responsive_spacing以使支付墙更加响应式。在大屏幕上,它会添加边距并将布局分成两列。

平板横屏

实现

示例:简单支付墙的用法

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  PurchaseHandler purchaseHandler = PurchaseHandler();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return PaywallScaffold(
      // 应用栏标题
      appBarTitle: "Premium",
      child: SimplePaywall(
        // 设置自定义头部
          headerContainer: Container(
              margin: EdgeInsets.all(16),
              height: 100,
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(8.0)),
                  image: DecorationImage(
                      fit: BoxFit.cover,
                      alignment: FractionalOffset.center,
                      image: AssetImage('assets/images/premium_bg.png'))),
              child: Container()),
          // 标题栏
          title: "Go Premium",
          // 子标题
          subTitle: "All features at a glance",
          // 添加任意数量的项目点
          bulletPoints: [
            IconAndText(Icons.stop_screen_share_outlined, "No Ads"),
            IconAndText(Icons.hd, "Premium HD"),
            IconAndText(Icons.sort, "Access to All Premium Articles")
          ],
          // 你想要提供给用户的订阅
          subscriptionListData: [
            SubscriptionData(
                durationTitle: "Yearly",
                durationShort: "1 year",
                price: "€14,99€",
                dealPercentage: 69,
                productDetails: "Dynamic purchase data",
                index: 0),
            SubscriptionData(
                durationTitle: "Quarterly",
                durationShort: "3 Months",
                price: "€6,99",
                dealPercentage: 42,
                productDetails: "Dynamic purchase data",
                index: 2),
            SubscriptionData(
                durationTitle: "Monthly",
                durationShort: "1 month",
                price: "3,99€",
                dealPercentage: 0,
                productDetails: "Dynamic purchase data",
                index: 3)
          ],
          // 如果isPurchaseSuccess为true则显示
          successTitle: "Success!!",
          // 如果isPurchaseSuccess为true则显示
          successSubTitle: "Thanks for choosing Premium!",
          // 可以是任何Widget。如果isPurchaseSuccess为true则显示
          successWidget: Container(
              padding: EdgeInsets.only(top: 16, bottom: 16),
              child:
              Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                ElevatedButton(
                  child: Text("Let's go!"),
                  onPressed: () {
                    print("let‘s go to the home widget again");
                  },
                )
              ])),
          // 如果订阅正在加载,则设置为true
          isSubscriptionLoading: false,
          // 如果购买正在进行,则设置为true。这将显示全屏进度指示器
          isPurchaseInProgress: false,
          // 以显示成功Widget
          purchaseState: PurchaseState.NOT_PURCHASED,
          // 恢复和购买点击事件的回调接口。扩展DefaultPurchaseHandler
          callbackInterface: purchaseHandler,
          purchaseStateStreamInterface: purchaseHandler,
          // 提供你的TOS
          tosData:
          TextAndUrl("Terms of Service", "https://www.linkfive.io/tos"),
          // 提供你的PP
          ppData:
          TextAndUrl("Privacy Policy", "https://www.linkfive.io/privacy"),
          // 添加自定义活动Widget
          campaignWidget: CampaignBanner(
            headline: "🥳 Summer Special Sale",
            subContent: Container(
                padding: EdgeInsets.all(8),
                child: CountdownTimer(
                  endTime: DateTime.now()
                      .add(Duration(days: 2, hours: 7))
                      .millisecondsSinceEpoch,
                )),
          )),
    );
  }
}

更改颜色和字体

class MyApp extends StatelessWidget {
  // 这个小部件是你的应用的根
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // 自定义图标主题
        iconTheme: IconThemeData(color: Colors.green),
        // 你的颜色方案
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.green, brightness: Brightness.light),
      ),
      home: MyHomePage(),
    );
  }
}

示例:莫里茨支付墙

class MyApp extends StatelessWidget {
  // 这个小部件是你的应用的根
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // 主要颜色方案
          primarySwatch: Colors.green,

          // 自定义图标主题
          iconTheme: IconThemeData(color: Colors.lightGreen),

          // 颜色方案
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.amber, brightness: Brightness.light),
          elevatedButtonTheme: ElevatedButtonThemeData(
              style: ElevatedButton.styleFrom(primary: Colors.green)
          )
      ),
      supportedLocales: [
        const Locale('en'),
        const Locale('de'),
      ],
      localizationsDelegates: [
        PaywallLocalizations.delegate,
        GlobalMaterialLocalizations.delegate
      ],
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  PurchaseHandler purchaseHandler = PurchaseHandler();

  [@override](/user/override)
  Widget build(BuildContext context) {
    final translations = PaywallL10NHelper.of(context);
    return PaywallScaffold(
      // 应用栏标题
      appBarTitle: "YourApp Premium",
      child: MoritzPaywall(
        // 标题栏
        title: "Go Premium",
        // 子标题
        subTitle:
        "Enjoy all the advantages of YourApp with the Premium subscription.",
        continueText: "Continue",
        // 添加任意数量的项目点
        bulletPoints: [
          IconAndText(Icons.stop_screen_share_outlined, "No Ads"),
          IconAndText(Icons.hd, "Premium HD"),
          IconAndText(Icons.sort, "Access to All Premium Articles")
        ],
        // 你想要提供给用户的订阅
        subscriptionListData: [
          SubscriptionData(
              durationTitle: translations.yearly.toTitleCase(),
              durationShort: translations.nmonth(12),
              price: "€14,99€",
              highlightText: "Most popular",
              dealPercentage: 59,
              productDetails: "Dynamic purchase data",
              currencySymbol: "€",
              rawPrice: 14.99,
              monthText: translations.month,
              duration: "P1Y",
              index: 3),
          SubscriptionData(
              durationTitle: translations.quarterly.toTitleCase(),
              durationShort: translations.nmonth(3),
              price: "€8,99",
              dealPercentage: 42,
              productDetails: "Dynamic purchase data",
              currencySymbol: "€",
              rawPrice: 8.99,
              monthText: translations.month,
              duration: "P3M",
              index: 2),
          SubscriptionData(
              durationTitle: translations.monthly.toTitleCase(),
              durationShort: translations.nmonth(1),
              price: "€2,99",
              dealPercentage: 0,
              productDetails: "Dynamic purchase data",
              currencySymbol: "€",
              rawPrice: 2.99,
              monthText: translations.month,
              duration: "P1M",
              index: 1)
        ],
        // 如果isPurchaseSuccess为true则显示
        successTitle: "Success!!",
        // 如果isPurchaseSuccess为true则显示
        successSubTitle: "Thanks for choosing Premium!",
        // 可以是任何Widget。如果isPurchaseSuccess为true则显示
        successWidget: Container(
            padding: EdgeInsets.only(top: 16, bottom: 16),
            child:
            Row(mainAxisAlignment: MainAxisAlignment.center, children: [
              ElevatedButton(
                child: Text("Let's go!"),
                onPressed: () {
                  print("let‘s go to the home widget again");
                },
              )
            ])),
        // 如果订阅正在加载,则设置为true
        isSubscriptionLoading: false,
        // 如果购买正在进行,则设置为true。这将显示全屏进度指示器
        isPurchaseInProgress: false,
        // 以显示成功Widget
        purchaseState: PurchaseState.NOT_PURCHASED,
        // 恢复和购买点击事件的回调接口。扩展DefaultPurchaseHandler
        callbackInterface: purchaseHandler,
        purchaseStateStreamInterface: purchaseHandler,
        // 提供你的TOS
        tosData:
        TextAndUrl("Terms of Service", "https://www.linkfive.io/tos"),
        // 提供你的PP
        ppData:
        TextAndUrl("Privacy Policy", "https://www.linkfive.io/privacy"),
        // 添加自定义活动Widget
        /*campaignWidget: CampaignBanner(
            theme: Theme.of(context),
            headline: "🥳 Summer Special Sale",
            subContent: Container(
                padding: EdgeInsets.all(8),
                child: CountdownTimer(
                  endTime: DateTime.now()
                      .add(Duration(days: 2, hours: 7))
                      .millisecondsSinceEpoch,
                )),
          )*/),
    );
  }
}

更多关于Flutter应用内购买界面插件in_app_purchases_paywall_ui的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用内购买界面插件in_app_purchases_paywall_ui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


in_app_purchases_paywall_ui 是一个用于 Flutter 的应用内购买界面插件,它提供了一个预构建的 UI 组件,可以轻松地集成到你的应用中,帮助用户购买订阅或内购项目。这个插件通常与 in_app_purchase 插件结合使用,后者是 Flutter 官方提供的用于处理应用内购买的核心插件。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 in_app_purchases_paywall_ui 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  in_app_purchases_paywall_ui: ^latest_version

然后运行 flutter pub get 来安装依赖。

使用插件

  1. 初始化应用内购买

    在使用 in_app_purchases_paywall_ui 之前,你需要初始化 in_app_purchase 插件。通常在你的应用的 main.dart 文件中进行初始化:

    import 'package:flutter/material.dart';
    import 'package:in_app_purchase/in_app_purchase.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      final InAppPurchase _inAppPurchase = InAppPurchase.instance;
      await _inAppPurchase.isAvailable();
      runApp(MyApp());
    }
    
  2. 创建支付墙界面

    你可以使用 PaywallUI 组件来创建一个支付墙界面。这个组件可以显示应用内购买的商品列表,并提供购买按钮。

    import 'package:flutter/material.dart';
    import 'package:in_app_purchases_paywall_ui/in_app_purchases_paywall_ui.dart';
    import 'package:in_app_purchase/in_app_purchase.dart';
    
    class PaywallScreen extends StatelessWidget {
      final InAppPurchase _inAppPurchase = InAppPurchase.instance;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('订阅'),
          ),
          body: PaywallUI(
            inAppPurchase: _inAppPurchase,
            productIds: {'com.example.subscription_monthly', 'com.example.subscription_yearly'},
            onPurchaseComplete: (ProductDetails productDetails) {
              // 处理购买完成逻辑
              print('购买成功: ${productDetails.id}');
            },
            onError: (error) {
              // 处理错误
              print('购买失败: $error');
            },
          ),
        );
      }
    }
    
  3. 导航到支付墙界面

    你可以在应用的某个地方(例如按钮点击事件)导航到支付墙界面:

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => PaywallScreen()),
    );
回到顶部