如何通过服务器端验证处理Apple订阅

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

我正在尝试在我的 flutter 应用程序中实现订阅,并进行服务器端验证。我的代码几乎是

in_app_purchase

示例的副本
Future<void> _listenToPurchaseUpdated(
      List<PurchaseDetails> purchaseDetailsList) async {
    for (final PurchaseDetails purchaseDetails in purchaseDetailsList) {
      if (purchaseDetails.status == PurchaseStatus.pending) {
        showPendingUI();
      } else {
        if (purchaseDetails.status == PurchaseStatus.error) {
          handleError(purchaseDetails.error!);
        } else if (purchaseDetails.status == PurchaseStatus.purchased ||
            purchaseDetails.status == PurchaseStatus.restored) {
          final bool valid = await _verifyPurchase(purchaseDetails);
          if (valid) {
            unawaited(deliverProduct(purchaseDetails));
          } else {
            _handleInvalidPurchase(purchaseDetails);
            return;
          }
        }
        if (Platform.isAndroid) {
          if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) {
            final InAppPurchaseAndroidPlatformAddition androidAddition =
                _inAppPurchase.getPlatformAddition<
                    InAppPurchaseAndroidPlatformAddition>();
            await androidAddition.consumePurchase(purchaseDetails);
          }
        }
        if (purchaseDetails.pendingCompletePurchase) {
          await _inAppPurchase.completePurchase(purchaseDetails);
        }
      }
    }
  }

我的

_verifyPurchase
方法调用后端来验证购买的真实性,并返回有效性状态。

Apple 实施的问题在于,它将所有购买流式传输到此方法。这意味着所有旧的购买都将通过此方法进行。如果用户订阅了两年,则每次打开应用程序时,该方法都会被调用 24 次。这并不理想并会导致问题。

我尝试过滤过期交易,但无法在手机上解码验证数据,因此无法访问过期日期。

如何区分新购买的商品和已验证的商品?

ios flutter in-app-purchase in-app-subscription
1个回答
0
投票

通过使用purchasing_flutter包,您可以首先获取您的产品,向用户展示它们(如果尚未订阅),然后为每个产品提供购买按钮。

获取产品,您将得到 StoreProduct 列表

  final List<StoreProduct> products = await Purchases.getProducts([
    inAppProductPremiumMonthly,
    inAppProductPremiumYearly,
  ]);

向用户显示 StoreProduct 列表并创建购买选项,如下所示:

Future<void> _buyProduct(StoreProduct product) async {
try {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (context) => const LoadingWidget(),
  );
  await Purchases.purchaseStoreProduct(product);
  widget.callback(product);
} catch (e) {
  widget.errorCallback(e);
} finally {
  if (context.mounted) {
    Navigator.pop(context);
  }
}}
© www.soinside.com 2019 - 2024. All rights reserved.