Flutter [in_app_purchase]获取订阅内的所有计划

pprl5pva  于 2022-12-05  发布在  Flutter
关注(0)|答案(2)|浏览(314)

我使用的是in_app_purchase包,但在订阅中只能获得一个套餐
我有3个订阅:

Basic subscription
Premium subscription
Enterprise subscription

在每个订阅中,我希望有两个计划:

Month plan
Year plan

我总是得到启用了“向后兼容性”(“这将是由过时的Google Play计费库方法querySkuDetailsAsync()返回的基线”)的计划。
有没有办法获得所有计划,或者我必须有6个订阅,每个订阅中只有1个计划?
编辑:

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';
import 'package:in_app_purchase_storekit/store_kit_wrappers.dart';
import 'package:motorline_home/widgets/materials/appbar/appbar_title_widget.dart';
import 'package:motorline_home/widgets/materials/pop_button_widget.dart';
import 'package:rxdart/subjects.dart';

class SubscriptionPage extends StatefulWidget {

  const SubscriptionPage({
    Key? key,
  }) : super(key: key);

  @override
  State<SubscriptionPage> createState() => _SubscriptionPageState();
}

class _SubscriptionPageState extends State<SubscriptionPage> {
  // In app subscriptions
  InAppPurchase _inAppPurchase = InAppPurchase.instance;
  late StreamSubscription<List<PurchaseDetails>> _inAppPurchaseSubscription;
  StreamController<List<ProductDetails>> _streamGooglePlaySubscriptions =
      BehaviorSubject();
  final List<String> _subscriptionsIDs = [
    "basic",
    "premium",
    "enterprise",
  ];

  @override
  void initState() {
    super.initState();

    // In app purchase subscription
    _inAppPurchaseSubscription =
        _inAppPurchase.purchaseStream.listen((purchaseDetailsList) {
      _listenToPurchaseUpdated(purchaseDetailsList);
    }, onDone: () {
      print("In app purchase onDone");
      _inAppPurchaseSubscription.cancel();
    }, onError: (error) {
      print("In app purchase error: ${error.toString()}");
      // handle error here.
      _inAppPurchaseSubscription.cancel();
    });
    // Initialize in app purchase
    _initializeInAppPurchase();
  }

  @override
  void dispose() {
    if (Platform.isIOS) {
      final InAppPurchaseStoreKitPlatformAddition iosPlatformAddition =
      _inAppPurchase
          .getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();
      iosPlatformAddition.setDelegate(null);
    }

    // Cancel in app purchase listener
    _inAppPurchaseSubscription.cancel();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: AppBarTitleWidget(
          title: FlutterI18n.translate(context, "subscriptions"),
        ),
        leading: PopButtonWidget(),
      ),
      // Body
      body: Container(),
    );
  }

  void _initializeInAppPurchase() async {
    print("Initializing in app purchase");
    bool available = await _inAppPurchase.isAvailable();
    print("In app purchase initialized: $available");

    if (available) {
      if (Platform.isIOS) {
        final InAppPurchaseStoreKitPlatformAddition iosPlatformAddition =
        _inAppPurchase
            .getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();
        await iosPlatformAddition.setDelegate(ExamplePaymentQueueDelegate());
      }

      // Get subscriptions
      List<ProductDetails> subscriptions = await _getSubscriptions(
        productIds:
          _subscriptionsIDs.toSet(),
      );
      // Sort by price
      subscriptions.sort((a, b) => a.rawPrice.compareTo(b.rawPrice));

      // Add subscriptions to stream
      _streamGooglePlaySubscriptions.add(subscriptions);

      // DEBUG: Print subscriptions
      print("In app purchase subscription subscriptions: ${subscriptions}");
      for (var subscription in subscriptions) {
        print("In app purchase plan: ${subscription.id}: ${subscription.rawPrice}");
        print("In app purchase description: ${subscription.description}");
        // HOW GET ALL PLANS IN EACH SUBSCRIPTION ID?
      }

      await InAppPurchase.instance.restorePurchases();
    }
  }

  // In app purchase updates
  void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
    purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
      // If purchase is pending
      if (purchaseDetails.status == PurchaseStatus.pending) {
        print("In app purchase pending...");
        // Show pending ui
      } else {
        if (purchaseDetails.status == PurchaseStatus.canceled) {
          print("In app purchase cancelled");
        }
        // If purchase failed
        if (purchaseDetails.status == PurchaseStatus.error) {
          print("In app purchase error");
          // Show error
        } else if (purchaseDetails.status == PurchaseStatus.purchased ||
            purchaseDetails.status == PurchaseStatus.restored) {
          print("In app purchase restored or purchased");
        }

        if (purchaseDetails.pendingCompletePurchase) {
          debugPrint("In app purchase complete purchased");
          debugPrint(
              "In app purchase purchase id : ${purchaseDetails.purchaseID}");
          debugPrint(
              "In app purchase server data : ${purchaseDetails.verificationData.serverVerificationData}");
          debugPrint(
              "In app purchase local data  : ${purchaseDetails.verificationData.localVerificationData}");
          // Verify purchase on backend

          try {
            // VALIDADE PURCHASE IN BACKEND
          } catch (error) {
            debugPrint("In app purchase error: ${error.toString()}");
          }
        }
      }
    });
  }

  // Get subscription
  Future<List<ProductDetails>> _getSubscriptions(
      {required Set<String> productIds}) async {
    ProductDetailsResponse response =
        await _inAppPurchase.queryProductDetails(productIds);

    return response.productDetails;
  }
}

/// Example implementation of the
/// [`SKPaymentQueueDelegate`](https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate?language=objc).
///
/// The payment queue delegate can be implementated to provide information
/// needed to complete transactions.
class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper {
  @override
  bool shouldContinueTransaction(
      SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront) {
    return true;
  }

  @override
  bool shouldShowPriceConsent() {
    return false;
  }
}
g52tjvyc

g52tjvyc1#

你想做的是不可能的。你需要为每个订阅创建一个新的计划,你不能说一个高级订阅确实有一个年度和一个月的计划。

fhg3lkii

fhg3lkii2#

这是不可能的时刻,因为它不支持官方插件(我们不知道什么时候会):
https://github.com/flutter/flutter/issues/110909
正如他们所提到的,解决方案是每个订阅一个计划,并在应用中添加必要的额外逻辑(例如,检测ID为PLUS-year的订阅是否为PLUS-month的升级)

相关问题