如何在 Android 上使用 Flutter 成功完成应用内购买?

Posted

技术标签:

【中文标题】如何在 Android 上使用 Flutter 成功完成应用内购买?【英文标题】:How to successfully complete an in app purchase using flutter on android? 【发布时间】:2021-03-13 06:43:08 【问题描述】:

我想要什么

我想将 Google Play 在应用购买中集成到我的 Flutter 应用中,我想销售的产品是消耗品。现在我正在使用in_app_purchase: (0.3.4+16) 包。

我做了什么

在 google play 开发者控制台中创建产品 根据in_app_purchase包的文档设置项目 实施了一些购买消耗品的逻辑(见下文) 构建 alpha 版本并将其上传到 alpha 测试轨道以进行测试 在我的开发者手机上创建了一个新的 google 帐户,将其注册为测试人员并下载了 alpha 版本 购买时带有“测试卡,始终认可” 使用我的 PayPal 帐户购买

预期和实际结果

我希望付款正常,所有 api 调用都可以返回。

当我在手机上开始购买时,购买流程开始,我可以选择所需的付款方式。在我接受付款后,_listenToPurchaseUpdated(...) 方法被调用,正如预期的那样。 但是,对InAppPurchaseConnection.instance.completePurchase(p) 的调用返回BillingResponse.developerError,我收到以下调试消息:

W/BillingHelper: Couldn't find purchase lists, trying to find single data.
I/flutter: result: BillingResponse.developerError (Purchase is in an invalid state.)

“测试卡,始终批准”以及我使用 PayPal 开始实际交易时出现此错误。对于 PayPal 购买,我收到了一封确认电子邮件,表明交易成功。 在文档中它说:

警告!购买后 3 天内未调用此方法并获得成功响应将导致 android 退款。

总结问题

如何调用InAppPurchaseConnection.instance.completePurchase(p) 以返回成功的结果?

采购实施

在应用购买中设置的代码如文档所示实现:

InAppPurchaseConnection.enablePendingPurchases();

Stream<List<PurchaseDetails>> purchaseUpdated = InAppPurchaseConnection.instance.purchaseUpdatedStream;

_subscription = purchaseUpdated.listen(_listenToPurchaseUpdated, onDone: () 
    _subscription.cancel();
, onError: (error) 
  // handle error here.
);

...

Future<void> _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) async 
  for (var p in purchaseDetailsList) 
   
    // Code to validate the payment

    if (!p.pendingCompletePurchase) continue;

    var result = await InAppPurchaseConnection.instance.completePurchase(p);

    if (result.responseCode != BillingResponse.ok) 
      print("result: $result.responseCode ($result.debugMessage)");
    
  

购买消耗品我有这个方法,查询商品详情,拨打buyConsumable(...)

Future<bool> _buyConsumableById(String id) async 
  final ProductDetailsResponse response = await InAppPurchaseConnection
      .instance
      .queryProductDetails([id].toSet());

  if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) 
    return false;
  

  List<ProductDetails> productDetails = response.productDetails;

  final PurchaseParam purchaseParam = PurchaseParam(
    productDetails: productDetails[0],
  );

  return await InAppPurchaseConnection.instance.buyConsumable(
    purchaseParam: purchaseParam,
  );

【问题讨论】:

【参考方案1】:

解决方法是不要调用completePurchase(...) 方法购买消耗品。默认情况下,库会为您使用购买,这隐含地充当对 completePurchase(...) 的调用。

背景

InAppPurchaseConnection.instance.buyConsumable(...) 的调用有一个可选的布尔参数autoConsume,它始终为true。这意味着,在 android 上,购买是在回调到 purchaseUpdatedStream 之前消耗的。 completePurchase 方法的文档说明如下:

[consumePurchase] 在 Android 上充当隐式 [completePurchase]

解决问题的代码

Future<void> _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) async 
  for (var p in purchaseDetailsList) 

    // Code to validate the payment

    if (!p.pendingCompletePurchase) continue;
    if (_isConsumable(p.productID)) continue; // Determine if the item is consumable. If so do not consume it

    var result = await InAppPurchaseConnection.instance.completePurchase(p);

    if (result.responseCode != BillingResponse.ok) 
      print("result: $result.responseCode ($result.debugMessage)");
    
  

【讨论】:

以上是关于如何在 Android 上使用 Flutter 成功完成应用内购买?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Flutter 处理应用程序生命周期(在 Android 和 iOS 上)?

如何使用 Flutter 在 iOS 和 Android 上共享多张图片?

Flutter:不使用AppBar时如何在Android和iOS上更改状态栏文本颜色[重复]

如何使用android studio在flutter上加载图像

在 Android 上构建 Flutter 应用程序时如何修复“依赖失败”

如何从 Flutter web 调用原生 Android 代码。?