[in_app_purchase] Fix upgrading subscription by deferred proration mode on android. (#4560)
This PR is for updating the bug of upgrading subscription by deferred mode on android, the purchaseStream of PurchaseStatus will return error.
Fixes [flutter/flutter#94439]
diff --git a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md
index 9bce54c..5c34de2 100644
--- a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md
+++ b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.2
+
+* Fixes the `purchaseStream` incorrectly reporting `PurchaseStatus.error` when user upgrades subscription by deferred proration mode.
+
## 0.2.1
* Deprecated the `InAppPurchaseAndroidPlatformAddition.enablePendingPurchases()` method and `InAppPurchaseAndroidPlatformAddition.enablePendingPurchase` property. Since Google Play no longer accepts App submissions that don't support pending purchases it is no longer necessary to acknowledge this through code.
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart
index 7deec6e..7c8ca52 100644
--- a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart
+++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart
@@ -270,13 +270,17 @@
if (purchases.isNotEmpty) {
return Future.wait(purchases);
} else {
+ PurchaseStatus status = PurchaseStatus.error;
+ if (resultWrapper.responseCode == BillingResponse.userCanceled) {
+ status = PurchaseStatus.canceled;
+ } else if (resultWrapper.responseCode == BillingResponse.ok) {
+ status = PurchaseStatus.purchased;
+ }
return [
PurchaseDetails(
purchaseID: '',
productID: '',
- status: resultWrapper.responseCode == BillingResponse.userCanceled
- ? PurchaseStatus.canceled
- : PurchaseStatus.error,
+ status: status,
transactionDate: null,
verificationData: PurchaseVerificationData(
localVerificationData: '',
diff --git a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
index 63bfa13..4d88643 100644
--- a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
+++ b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
@@ -2,7 +2,7 @@
description: An implementation for the Android platform of the Flutter `in_app_purchase` plugin. This uses the Android BillingClient APIs.
repository: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/in_app_purchase_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
-version: 0.2.1
+version: 0.2.2
environment:
sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart
index 9f00bc7..9c167e5 100644
--- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart
+++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart
@@ -682,6 +682,51 @@
GooglePlayPurchaseDetails result = await completer.future;
expect(result.status, PurchaseStatus.canceled);
});
+
+ test(
+ 'should get purchased purchase status when upgrading subscription by deferred proration mode',
+ () async {
+ final SkuDetailsWrapper skuDetails = dummySkuDetails;
+ final String accountId = "hashedAccountId";
+ const String debugMessage = 'dummy message';
+ final BillingResponse sentCode = BillingResponse.ok;
+ final BillingResultWrapper expectedBillingResult = BillingResultWrapper(
+ responseCode: sentCode, debugMessage: debugMessage);
+ stubPlatform.addResponse(
+ name: launchMethodName,
+ value: buildBillingResultMap(expectedBillingResult),
+ additionalStepBeforeReturn: (_) {
+ // Mock java update purchase callback.
+ MethodCall call = MethodCall(kOnPurchasesUpdated, {
+ 'billingResult': buildBillingResultMap(expectedBillingResult),
+ 'responseCode': BillingResponseConverter().toJson(sentCode),
+ 'purchasesList': []
+ });
+ iapAndroidPlatform.billingClient.callHandler(call);
+ });
+
+ Completer completer = Completer();
+ PurchaseDetails purchaseDetails;
+ Stream purchaseStream = iapAndroidPlatform.purchaseStream;
+ late StreamSubscription subscription;
+ subscription = purchaseStream.listen((_) {
+ purchaseDetails = _.first;
+ completer.complete(purchaseDetails);
+ subscription.cancel();
+ }, onDone: () {});
+ final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam(
+ productDetails: GooglePlayProductDetails.fromSkuDetails(skuDetails),
+ applicationUserName: accountId,
+ changeSubscriptionParam: ChangeSubscriptionParam(
+ oldPurchaseDetails: GooglePlayPurchaseDetails.fromPurchase(
+ dummyUnacknowledgedPurchase),
+ prorationMode: ProrationMode.deferred,
+ ));
+ await iapAndroidPlatform.buyNonConsumable(purchaseParam: purchaseParam);
+
+ PurchaseDetails result = await completer.future;
+ expect(result.status, PurchaseStatus.purchased);
+ });
});
group('complete purchase', () {