【问题标题】:Flutter - How to verify InAppPurchases (iOS)Flutter - 如何验证 InAppPurchases (iOS)
【发布时间】:2020-04-24 07:30:23
【问题描述】:

我尝试实现非消耗品的应用内购买,但至少在 iOS 上无法验证购买。
每当我让函数“_verifyPurchase()”返回 true 时,一切都很好。
这就是让我认为验证过程是问题的原因。

  Future<bool> _verifyPurchase(String productID) async {
    final appState = Provider.of<AppState>(context);
    PurchaseDetails purchase = await _hasPurchased(productID);
    SharedPreferences prefs = await SharedPreferences.getInstance();
    print('verify'+purchase?.productID.toString()+(purchase?.error).toString());
    if (purchase != null &&
        (purchase.status == PurchaseStatus.purchased || purchase.transactionDate != null) &&
        _kProductIds.contains(productID)) {
      if(productID == _kProductIds[0]) {
        print('has purchased remove ads');
        prefs.setBool(productID, true);
        setState(() {
          appState.setBoughtRemoveAds = true;
        });
      }else if(productID == _kProductIds[1]){
        print('has purchased premium');
        prefs.setBool(productID, true);
        setState(() {
          appState.setBoughtPremium = true;
        });
      }
      return true;
    }
    return false;
  }

我不想在服务器端验证购买,并认为“_hasPurchased()”函数很可能已损坏

Future<PurchaseDetails> _hasPurchased(String productID) async {
    final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
    return response.pastPurchases.firstWhere((purchase) => purchase.productID == productID,
        orElse: () => null);
  }

我已按照Fireship.io 的教程进行操作

编辑:代码中的小错误。

【问题讨论】:

    标签: flutter in-app-purchase


    【解决方案1】:

    花了几个小时终于解决了这个问题,不幸的是,flutter 的两个插件(in_app_purchaseflutter_inapp_purchase)都没有非常清楚地共享此信息,如何验证您的购买收据,这里是示例代码。

    解决方案 1:从应用发出帖子请求(不推荐)

         Future<http.Response> validateReceiptIos(receiptBody,isTest) async {
              final String url = isTest
                ? 'https://sandbox.itunes.apple.com/verifyReceipt'
                 : 'https://buy.itunes.apple.com/verifyReceipt';
               return  await http.post(
               Uri.parse(url),
                headers: {
                'Accept': 'application/json',
                 'Content-Type': 'application/json',
                  },
                body: json.encode(receiptBody),
                  );
                 }
    

    传递函数参数

        var receiptBody = {
        'receipt-data': purchaseDetails.verificationData.localVerificationData, // receipt key you will receive in request purchase callback function 
        'exclude-old-transactions':true,
         'password':'You can get this from App store-> In app purchase-> App specific shared secert'
         };
    

    解决方案 2:(推荐解决方案) 在您的 API 服务器上创建一个 API 并调用 [沙箱] 或用于 [生产] 3 这个,然后在你的应用程序中使用这个 api。

    【讨论】:

      【解决方案2】:

      虽然我喜欢 fireship.io。本教程的不足之处在于他没有教您如何正确验证购买。

      我也按照教程进行了操作,但发现它在验证方面有所欠缺。我专注于 Android 进行订阅,我遇到了这些文档 https://developer.android.com/google/play/billing/billing_library_overview#Verify,因为我想尝试在设备上进行验证,所以这些文档有点难以理解。

      我切换到 RevenueCat https://pub.dev/packages/purchases_flutter,他们会为您处理服务器端的验证,我发现它更容易。

      我希望这会有所帮助!

      【讨论】:

      • 请引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。有关如何在此处写出好的答案的更多信息:stackoverflow.com/help/how-to-answer
      【解决方案3】:

      我认为您应该将return true 行移到嵌套的 if 语句中,因为该函数将验证用户是否购买了所有产品,即使他/她可能刚刚购买了一种产品。此外,嵌套 if 语句中的条件是相同的,都是 productID == _kProductIds[0]

       if (purchase != null &&
              (purchase.status == PurchaseStatus.purchased || purchase.transactionDate != null) &&
              _kProductIds.contains(productID)) {
            if(productID == _kProductIds[0]) {
              print('has purchased remove ads');
              prefs.setBool(productID, true);
              setState(() {
                appState.setBoughtRemoveAds = true;
              });
              return true;
            }else if(productID == _kProductIds[0]){
              print('has purchased premium');
              prefs.setBool(productID, true);
              setState(() {
                appState.setBoughtRemoveAds = true;
              });
              return true;
            }
            return false;
          }
          return false;
      

      【讨论】:

      • 感谢您让我知道我更正了代码,但遗憾的是它仍然无法正常工作。
      【解决方案4】:

      如果我相互检查购买 ID,我就可以使用“_hasPurchased”功能。再次检查整个对象彼此失败。可以进行更多的比较,而不仅仅是 id。

      所以我添加了这个:

      bool _comparePurchaseDetails(PurchaseDetails pd0, PurchaseDetails pd1){
      if(pd0.purchaseID != pd1.purchaseID)return false;
      if(pd0.verificationData.serverVerificationData != pd1.verificationData.serverVerificationData)return false;
      if(pd0.verificationData.localVerificationData != pd1.verificationData.localVerificationData)return false;
      return true;
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-12
        • 2021-07-13
        • 2020-07-01
        • 2021-10-11
        • 1970-01-01
        • 2021-01-05
        • 2021-11-01
        • 2020-09-17
        相关资源
        最近更新 更多