Flutter in_app_purchase: ^3.1.4 issue on release production - flutter

hello i am using in_app_purchase: ^3.1.4 official flutter plugin for purchasing item in my app its non_consumable product user can buy it only one time. i have test this app on internal testing.On internal testing it was working fine but issue was its not working production release anyone know what issue here is my code below please check now
final Set<String> _productIds = {'urdubible'};
late List<ProductDetails> _products;
bool _isPurchased = false;
#override
void initState() {
super.initState();
_checkPurchaseStatus();
// initialize the in-app purchase plugin
InAppPurchase .instance.purchaseStream
.listen((List<PurchaseDetails> purchases) {
// handle any purchase updates
_handlePurchaseUpdates(purchases);
});
// load the available products
_loadProducts();
}
Future<void> _loadProducts() async {
// get the product details from the store
ProductDetailsResponse response =
await InAppPurchase.instance.queryProductDetails(_productIds);
// save the product details to state
setState(() {
_products = response.productDetails;
});
}
void _handlePurchaseUpdates(List<PurchaseDetails> purchases) {
for (PurchaseDetails purchase in purchases) {
switch (purchase.status) {
case PurchaseStatus.purchased:
_savePurchaseStatus(true);
// handle the purchase, e.g. update UI, save the purchase to database, etc.
setState(() {
_isPurchased = true;
});
break;
case PurchaseStatus.error:
// handle any purchase errors
break;
case PurchaseStatus.canceled:
// handle cancelled purchases
break;
}
}
}
Future<void> _purchaseProduct() async {
if (_products.isNotEmpty) {
// initiate the purchase flow
final PurchaseParam purchaseParam =
PurchaseParam(productDetails: _products.first);
InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam);
}
}
Future<void> _savePurchaseStatus(bool isPurchased) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('isPurchased', isPurchased);
}
Future<void> _checkPurchaseStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool? isPurchased = prefs.getBool('isPurchased');
if (isPurchased != null && isPurchased) {
setState(() {
_isPurchased = true;
});
}
}

in my case I am facing issue with
buildTypes {
release {
signingConfig signingConfigs.debug
minifyEnabled false
shrinkResources false
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
After disabling shrink resources it's working for me

Related

Run a function immediately after a payment is made

I am using purchases_flutter and revenueCat to offer a subscription on my app.
How can I run a function immediately after the payment is made?
Thank you.
With RevenueCat, you can make any action you want after the purchase line.
Below is an example of my checkout function
static Future<Package?> makePurchases(Package? package, ValueNotifier<bool> isWaiting) async {
try {
isWaiting.value = true;
purchaserInfo = await Purchases.purchasePackage(package!);
await Purchases.syncPurchases();
if (purchaserInfo.entitlements.all["Pro"]!.isActive) {
purchaserInfo = await Purchases.purchasePackage(package);
}
// here purchase is done
// do something
isWaiting.value = false;
} on PlatformException catch (e) {
var errorCode = PurchasesErrorHelper.getErrorCode(e);
if (errorCode != PurchasesErrorCode.purchaseCancelledError) {}
isWaiting.value = false;
}
isWaiting.value = false;
return null;
}

Flutter in_app_purchase, show content after purchase

I take code from offical in_app_purchases documentation, purchases work correctly.
I have function that show paid content, and i need to run it after purchase done correctly, but i don't know where i need to put it, because i steel don't inderstand purchases 100% correctly.
this is my code
final InAppPurchase _inAppPurchase = InAppPurchase.instance;
final String _productID = '1d7ea644f690ffa';
bool _available = true;
List<ProductDetails> _products = [];
List<PurchaseDetails> _purchases = [];
StreamSubscription<List<PurchaseDetails>>? _subscription;
#override
void initState() {
final Stream<List<PurchaseDetails>> purchaseUpdated = _inAppPurchase.purchaseStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
setState(() {
_purchases.addAll(purchaseDetailsList);
_listenToPurchaseUpdated(purchaseDetailsList);
});
}, onDone: () {
_subscription!.cancel();
}, onError: (error) {
_subscription!.cancel();
});
_initialize();
super.initState();
}
#override
void dispose() {
_subscription!.cancel();
super.dispose();
}
void _initialize() async {
_available = await _inAppPurchase.isAvailable();
List<ProductDetails> products = await _getProducts(
productIds: Set<String>.from(
[_productID],
),
);
setState(() {
_products = products;
});
}
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
switch (purchaseDetails.status) {
case PurchaseStatus.pending:
// _showPendingUI();
break;
case PurchaseStatus.purchased:
break;
case PurchaseStatus.restored:
// bool valid = await _verifyPurchase(purchaseDetails);
// if (!valid) {
// _handleInvalidPurchase(purchaseDetails);
// }
break;
case PurchaseStatus.error:
print(purchaseDetails.error!);
// _handleError(purchaseDetails.error!);
break;
default:
break;
}
if (purchaseDetails.pendingCompletePurchase) {
await _inAppPurchase.completePurchase(purchaseDetails);
CheckListModel.addPaidData(purchaseDetails.productID);
}
});
}
Future<List<ProductDetails>> _getProducts({required Set<String> productIds}) async {
ProductDetailsResponse response = await _inAppPurchase.queryProductDetails(productIds);
return response.productDetails;
}
void _subscribe({required ProductDetails product}) {
final PurchaseParam purchaseParam = PurchaseParam(productDetails: product);
_inAppPurchase.buyNonConsumable(
purchaseParam: purchaseParam,
);
}
_subscribe function start when user click on special button in ui
function that show paid contenct name is
CheckListModel.addPaidData(purchaseDetails.productID);
when function start it create file paid.paid in getApplicationDocumentsDirectory, if it doesn't exist, and add in it productID . That what must happen
Where i need to place this function?

"You Already Have This Item" Flutter In App Purchase

I use in-app purchase in my app. Hassle free purchase. But when I want to buy the same product for the second time, this Play Store shows me "You Already Have This Item". I want my products to be bought again and again. I don't have any idea how I can solve it. Thank you very much for the help. I left my source codes below.
InAppPurchase iap = InAppPurchase.instance;
bool available = true;
List<ProductDetails> products = [];
List<PurchaseDetails> purchases = [];
StreamSubscription subscription;
int credits = 0;
#override
void initState() {
initialize();
super.initState();
}
#override
void dispose() {
subscription.cancel();
super.dispose();
}
void initialize() async {
available = await iap.isAvailable();
if (available) {
await getProducts();
verifyPurchase();
subscription = iap.purchaseStream.listen((data) => setState(() {
print('New Purchase');
purchases.addAll(data);
verifyPurchase();
}));
}
}
Future<void> getProducts() async {
Set<String> ids = Set.from(['buy_300_wecoin']);
ProductDetailsResponse response = await iap.queryProductDetails(ids);
setState(() {
products = response.productDetails;
});
}
PurchaseDetails hasPurchased(String productID) {
return purchases.firstWhere((purchase) => purchase.productID == productID,
orElse: () => null);
}
bool verifyPurchase() {
PurchaseDetails purchase = hasPurchased('buy_300_wecoin');
if (purchase != null && purchase.status == PurchaseStatus.purchased) {
return true;
}
}
void buyProduct(ProductDetails prod) {
final PurchaseParam purchaseParam = PurchaseParam(productDetails: prod);
iap.buyConsumable(purchaseParam: purchaseParam, autoConsume: false);
}
you should use Consumable In-App Purchase
A consumable product is one that a user consumes to receive in-app content, such as in-game currency. When a user consumes the product, your app dispenses the associated content, and the user can
then purchase the item again.
Note that the App Store does not have any APIs for querying consumable products, and Google Play considers consumable products to no longer be owned once they're marked as consumed and fails to return them here. For restoring these across devices you'll need to persist them on your own server and query that as well.
Try in_app_purchase library and read about consumable IAP using this library.

Flutter: How to set up Non-Consumable purchase?

I want to set up Non-Consumable purchase in my app. I found a lot of tutorials about Consumable purchases, but unfortunately I haven't found any articles about Non-Consumable.
I tried using in_app_purchase package, but it didn't work.
final String testIdAdvanced = 'advanced_training';
InAppPurchaseConnection _iap = InAppPurchaseConnection.instance;
bool _available = true;
List<ProductDetails> advancedProducts = [];
List<ProductDetails> advancedPurchases = [];
StreamSubscription _subscription;
void _initialize() async {
_available = await _iap.isAvailable();
if (_available) {
await _getProducts();
await _getPastPurchases();
}
}
Future<void> _getProducts() async {
Set<String> ids = Set.from([testIdAdvanced, 'test_a']);
ProductDetailsResponse response = await _iap.queryProductDetails(ids);
setState(() {
advancedProducts = response.productDetails;
});
}
// Gets previous purchases
Future<void> _getPastPurchases() async {
QueryPurchaseDetailsResponse response =
await _iap.queryPastPurchases();
for (PurchaseDetails purchase in response.pastPurchases) {
if (Platform.isIOS) {
InAppPurchaseConnection.instance.completePurchase(purchase);
}
}
setState(() {
advancedPurchases = response.pastPurchases.cast<ProductDetails>();
});
}
void _buyProduct(ProductDetails prod) {
final PurchaseParam purchaseParam = PurchaseParam(productDetails: prod);
_iap.buyNonConsumable(purchaseParam: purchaseParam);
}

Flutter in_app_purchase 0.2.1 purchaseUpdatedStream.listen not working on Android

I am able to buy a subscription on Android, and the subscription shows up in queryPastPurchases(), but the _listenToPurchaseUpdated() method is never triggered after buying the product. I know that this was a bug in previous releases of flutter in_app_purchase, but it was said to be fixed in 0.2.1. However it doesn't seem to work for me... Is there something wrong with my code?
/// The In App Purchase plugin
InAppPurchaseConnection _iap = InAppPurchaseConnection.instance
/// Updates to purchases
StreamSubscription<List<PurchaseDetails>> _subscription;
#override
initState() {
final Stream purchaseUpdates = InAppPurchaseConnection.instance.purchaseUpdatedStream;
_subscription = purchaseUpdates.listen((purchases) {
_purchases.addAll(purchases);
_listenToPurchaseUpdated(_purchases);
});
super.initState();
}
/// Get all products available for sale
Future<void> _getProducts() async {
Set<String> ids = Set.from(['subscription_product']);
ProductDetailsResponse response = await _iap.queryProductDetails(ids);
setState(() {
_products = response.productDetails;
});
if(response.error != null && response.error.message != null){
setState(() {
_iapStoreProblem = response.error.message;
});
}
}
void _buyProduct(ProductDetails prod) {
final PurchaseParam purchaseParam = PurchaseParam(productDetails: prod);
_iap.buyNonConsumable(purchaseParam: purchaseParam);
}
I found the solution.
Turns out I had to use
StreamSubscription _subscription;
instead of
StreamSubscription<List<PurchaseDetails>> _subscription;
and then:
_subscription = _iap.purchaseUpdatedStream.listen((data) => setState(() {
_purchases.addAll(data);
_listenToPurchaseUpdated(data);
}));
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
...
});
}
Also, a small note: PurchaseDetails.status on Android is Null.