Reputation: 41
For purchases, I am using the inapppurchase package. The package provides features for upgrading and downgrading packages. But I am unable to upgrade or downgrade the package. I am sharing details found on their package page.
*
Currently, I am stuck fetching the PurchaseDetails object (oldPurchaseDetails). Has anyone used this feature of the in_app_purchase package?
I reviewed that package code and followed their shared code. But I didn't find a way to get the old purchase details.
Upvotes: 2
Views: 1781
Reputation: 81
Here's a complete flow code for restoring old subscription and upgrade/downgrade subscriptions, on both Android & iOS.
In iOS, you don't need to write any code for upgrading/downgrading subscriptions, the underlying store (Appstore) handles it itself.
In Android, you need to pass changeSubscriptionParam
inside GooglePlayPurchaseParam
, this purchase param contains purchaseParams of current subscription.
Here's step by step guide to implement this.
// this method should be called once inside subscription business logic class
Future<void> init() async {
final purchaseUpdated = _inAppPurchase.purchaseStream;
_subscription = purchaseUpdated.listen(
_listenToPurchaseUpdated,
onDone: () {
_subscription.cancel();
},
onError: (Object error) {
log(error.toString());
},
);
if (Platform.isIOS) {
final iosPlatformAddition = _inAppPurchase
.getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();
await iosPlatformAddition.setDelegate(ExamplePaymentQueueDelegate());
} else {
await InAppPurchase.instance.restorePurchases();
}
}
Maintain a list to keep track of restored or purchased subscription.
final _purchases = <String, PurchaseDetails>{};
In _listenToPurchaseUpdated
, store recent subscriptions inside a map.
if (purchaseDetails.status == PurchaseStatus.purchased ||
purchaseDetails.status == PurchaseStatus.restored) {
_purchases[purchaseDetails.productID] = purchaseDetails;
}
Use _purchases
to fetch old subscriptions.
GooglePlayPurchaseDetails? _getOldSubscription() {
if (_purchases.isEmpty) return null;
return _purchases.values.last as GooglePlayPurchaseDetails?;
}
var purchaseParam = PurchaseParam(
productDetails: subscriptionPlans[state.selectedIndex!].productDetail,
applicationUserName: _sharedPreferencesManager.localUser!.id.toString(),
);
if (Platform.isAndroid) {
// for subscription upgrade or downgrade in Android
final oldSubscription = _getOldSubscription();
purchaseParam = GooglePlayPurchaseParam(
productDetails: subscriptionPlans[state.selectedIndex!].productDetail,
changeSubscriptionParam: (oldSubscription != null)
? ChangeSubscriptionParam(
oldPurchaseDetails: oldSubscription,
replacementMode: ReplacementMode.withTimeProration,
)
: null,
applicationUserName: _sharedPreferencesManager.localUser!.id.toString(),
);
}
await _inAppPurchase.buyNonConsumable(
purchaseParam: purchaseParam,
);
Upvotes: 0
Reputation: 3444
To get old purchase details: (Source)
Call the below method:
_inAppPurchase.restorePurchases();
Listen for restored purchase:
final Stream<List<PurchaseDetails>> purchaseUpdated =
_inAppPurchase.purchaseStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
// Get & Handle your old Purchase Detail from purchaseDetailsList
}, onDone: () {
_subscription.cancel();
}, onError: (error) {
// handle error here.
});
Upvotes: 0
Reputation: 12263
the sample doesn't work if you're not testing it with recent stuff. If you stored the transaction token on the server, here you go:
import 'package:in_app_purchase_android/in_app_purchase_android.dart';
import 'package:in_app_purchase_android/billing_client_wrappers.dart';
final verificationData = PurchaseVerificationData(localVerificationData: token!, serverVerificationData: token!, source: token!);
// the only thing here that matters for this object is token!
final wrapper = PurchaseWrapper.fromJson({
"orderId": "",
"packageName": "",
"purchaseTime": 0,
"purchaseToken": token!,
"signature": "",
"products": [],
"isAutoRenewing": false,
"originalJson": "",
"isAcknowledged": false,
"purchaseState": 0
});
final oldPurchaseDetails = GooglePlayPurchaseDetails(
productID: currentPlan!, // <-- plan id for the old one
verificationData: verificationData,
transactionDate: DateTime.now().millisecondsSinceEpoch.toString(),
billingClientPurchase: wrapper,
status: PurchaseStatus.purchased,
);
Had to go dink with the source, but here it is so u can see if it changes in the future or something. Hope this helps!
Upvotes: 1
Reputation: 153
For getting the old purchase you need to send the previous purchased plan id only then you can get old purchase details here is code that may be help you
GooglePlayPurchaseDetails? _getOldSubscription(
ProductDetails productDetails, Map<String, PurchaseDetails> purchases) {
// This is just to demonstrate a subscription upgrade or downgrade.
// Please remember to replace the logic of finding the old subscription Id as per your app.
// The old subscription is only required on Android since Apple handles this internally
// by using the subscription group feature in iTunesConnect.
var _kSubscriptionId =
"<Product ID which you want to purchase>";
var _kPastSubscriptionId = "<Old Product ID which you already purchased>";
GooglePlayPurchaseDetails? oldSubscription;
if (productDetails.id == _kSubscriptionId &&
purchases[_kPastSubscriptionId] != null) {
oldSubscription =
purchases[_kPastSubscriptionId]! as GooglePlayPurchaseDetails;
}
return oldSubscription;
}
This will return you the old plan detail.
Upvotes: 0