Flutter in_app_purchase 在 iOS 上出现已知的 SKError

问题描述 投票:0回答:0

我正在为 iOS 上的应用内支付而苦苦挣扎。当我尝试启动应用程序时,我正在恢复过去的购买,有时我会收到代码为 0 的 SKError(未知错误)。 我无法获得可用产品和购买清单。 不知道是什么原因导致错误,我为此苦苦挣扎了几天。

重要的是,有时它能正常工作,有时却不能。 Android 版本运行完美。

Xcode:14.2 颤动版本:3.7.6 飞镖版本:2.19.3 我使用的包和版本:in_app_purchase: ^3.1.5

出现问题的设备: iPhone Xs MAX,iOS 16.3.1 iPhone 6s,iOS 15.7.3 iPad 空气 2,iOS 15.7.3

这是我在 cubit 中的代码:

import 'dart:async';
import 'dart:io';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:in_app_purchase/in_app_purchase.dart';

part 'payments_state.dart';

class PaymentsCubit extends Cubit<PaymentsState> {
  PaymentsCubit()
      : super(PaymentsState(
          isPremium: null,
          avaliable: false,
          products: [],
          purchases: [],
        ));
  late StreamSubscription subscription;
  late InAppPurchase iap;

  void start() async {
    iap = InAppPurchase.instance;

    state.avaliable = await iap.isAvailable();
    if (state.avaliable) {
      //listener must be declared before get products and purchases calls
      subscription = iap.purchaseStream.listen(
        (purchaseDetailsList) {
          listenToPurchaseUpdated(purchaseDetailsList);
        },
        onDone: () => subscription.cancel(),
        onError: (error) => print(error),
      );
      await getProducts();
      await getPastPurchases();
      //it's listening to every changes in purchases e.g. buy new product, restore old products.
      //everytime when change will occur, then function is triggered
      //remember to always cancel listeners to avoid memmory leaks
    }
    emit(state);
  }

  Future<void> getProducts() async {
    Set<String> ids = Platform.isAndroid
        ? {
            'com.example.example.example',
            'com.example.example.exampleNew'
          }
        : {
            'com.example.example.exampleNew',
          };
    ProductDetailsResponse response = await iap.queryProductDetails(ids);
    state.products = response.productDetails;
  }

  Future<void> getPastPurchases() async {
    //this will trigger listener if user made purchases in the past
    await iap.restorePurchases();
  }

  void buyProduct() async {
    state.avaliable = await iap.isAvailable();
    if (state.avaliable) {
      final PurchaseParam purchaseParam = PurchaseParam(
        productDetails: state.products.firstWhere(
          (element) =>
              element.id ==
              (Platform.isAndroid
                  ? 'com.example.example.example'
                  : 'com.example.example.exampleNew'),
        ),
      );
      await InAppPurchase.instance
          .buyNonConsumable(purchaseParam: purchaseParam);
    }
  }

  void listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
    purchaseDetailsList.forEach((element) {
      if (element.status == PurchaseStatus.pending) {
        //handle situation when user pressed button to start purchase, (on iOS it takes more time, android have almost immediately response) maybe show some loading spinners
      } else if (element.status == PurchaseStatus.error) {
      } else if (element.status == PurchaseStatus.canceled) {
      } else if (element.status == PurchaseStatus.purchased ||
          element.status == PurchaseStatus.restored) {
        state.purchases.add(element);
        emit(state.copyWith(
          isPremium: true,
        ));
        iap.completePurchase(element);
      }
    });
    if (state.isPremium == null) {
      emit(state.copyWith(isPremium: false));
    }
  }
}

Start 方法在 MyApp 中的 bloc 声明之后调用,如下所示:

  class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(create: (context) => PaymentsCubit()..start()),
      ],
      child: MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            fontFamily: 'Rubik',
            primarySwatch: Colors.blue,
          ),
          home: const FakeSplashscreen()),
    );
  }
}
ios flutter in-app-purchase flutter-in-app-purchase
© www.soinside.com 2019 - 2024. All rights reserved.