如何在 android 上使用 flutter 成功完成应用内购买?

How to successfully complete an in app purchase using flutter on android?

我想要的

我想把Google Play in app purchase集成到我的flutter app中,我想卖的产品是消耗品。现在我正在使用 in_app_purchase: (0.3.4+16) 包。

我做了什么

预期和实际结果

我希望付款有效,所有 api 调用 return 都可以。

当我在 phone 上发起购买时,购买流程开始,我可以 select 选择所需的付款方式。在我接受付款后,将按预期调用 _listenToPurchaseUpdated(...) 方法。 但是,调用 InAppPurchaseConnection.instance.completePurchase(p) returns a 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 购买,我收到一封确认电子邮件,表明交易成功。 在文档中它说:

Warning! Failure to call this method and get a successful response within 3 days of the purchase will result a refund on Android.

问题总结

我怎样才能让对 InAppPurchaseConnection.instance.completePurchase(p) 的调用达到 return 的成功结果?

采购实施

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

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,
  );
}

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

的调用

背景

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

The [consumePurchase] acts as an implicit [completePurchase] on Android

解决问题的代码

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})");
    }
  }
}