如何在 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)
包。
我做了什么
- 在 google play 开发者控制台中创建产品
- 根据in_app_purchase包的文档设置项目
- 实现了购买消耗品的一些逻辑(见下文)
- 构建了一个 alpha 版本并将其上传到 alpha 测试轨道以进行测试
- 在我的开发者 phone 上创建了一个新的 google 帐户,将其注册为测试人员并下载了 alpha 版本
- 购买时带有“测试卡,始终认可”
- 使用我的 PayPal 帐户购买
预期和实际结果
我希望付款有效,所有 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})");
}
}
}
我想要的
我想把Google Play in app purchase集成到我的flutter app中,我想卖的产品是消耗品。现在我正在使用 in_app_purchase: (0.3.4+16)
包。
我做了什么
- 在 google play 开发者控制台中创建产品
- 根据in_app_purchase包的文档设置项目
- 实现了购买消耗品的一些逻辑(见下文)
- 构建了一个 alpha 版本并将其上传到 alpha 测试轨道以进行测试
- 在我的开发者 phone 上创建了一个新的 google 帐户,将其注册为测试人员并下载了 alpha 版本
- 购买时带有“测试卡,始终认可”
- 使用我的 PayPal 帐户购买
预期和实际结果
我希望付款有效,所有 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})");
}
}
}