Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flutter - How to add unmanaged/non-consumable product for in app purchase in test app? #133

Closed
JayM96 opened this issue Dec 9, 2019 · 12 comments
Labels
help wanted Extra attention is needed no-issue-activity

Comments

@JayM96
Copy link

JayM96 commented Dec 9, 2019

Currently i am performing in app purchase in my test project.

I wanted to add an option in the app for unmanaged/non-consumable product. What i want to do is let say if a user has not purchased an unmanaged/non-consumable product then i will disable some features in the app for the user.

But, if i purchase that unmanaged/non-consumable product then user can access all the app features for the lifetime.

Currently, google play console is showing only managed products and subscriptions tab only. Is there a way to implement in app purchase for unmanaged/non-consumable product in the app ?

Currently i am using the FlutterInApp Plugin for my test project ?

I didn't find documentation for the unmanaged/non-consumable products in flutter anywhere?

Can anyone suggest a worksround?

Is there any way to add unconsumable products using "flutter_inapp_purchase" plugin?

Thanks.

@DevonTomatoSandwich
Copy link

Did you find a solution?
I'm testing this at the moment in my app but not sure if it is right.
Here's what i have so far

I modified this from the docs and the example. i just added setState to change the display when the purchase is made. I didn't add any checks for if the purchase went through (i don't think i need to?).

_purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((purchasedItem) {
  print('purchase-updated: $purchasedItem');
  // do i have to check if the purchasedItem went through?
  setState(() {
    isNonConsumablePurchased = true;
  });
});

As for loading the purchases when you resume later.

verifyFullSolution(){
    if(getPurchasedItemFromId('my_premium') != null){ // a purchase with the product id (my_premium) exists
      // do i have to check if the purchasedItem went through?
      setState(() {
        isNonConsumablePurchased = true;
      });
    }
  }

// Returns PurchasedItem of specific product ID
PurchasedItem getPurchasedItemFromId(String id) {
  return _purchases.firstWhere( (pItem) => pItem.productId == id, orElse: () => null);
}

My only problem is that i cant test again on the same iOS device. It's easy to clear on android (see docs) but i can't clear my purchase history in iOS. I tried making multiple sandbox accounts but my purchase history is the same across different sandbox accounts so it always shows up as being purchased.

@JayM96
Copy link
Author

JayM96 commented Dec 23, 2019

@DevonTomatoSandwich @hyochan @kwmt @Zil85 @lukepighetti @Rockvole I have the same issue on item purchase.

If i refund for an item i still get the item as purchased.

How to manage it?

Also, can you please tell me if i purchase an item like,
FlutterInappPurchase.instance.requestPurchase(item.productId);

If item purchase is successful and then should i have to use finishTranscation or verifyreceipt methods?

I have read somewhere that if i will not finish my transaction then i will get my item purchase refunded and will not be listed as purchased item after 3 days.

If yes then,

Can you please suggest what will be the minimal code to write or finish the transaction or verify purchase for both android and ios ?

Thanks.

@hyochan
Copy link
Owner

hyochan commented Dec 29, 2019

Hi there~! You should always call finishTransaction when the purchase has been done. Otherwise, android will refund your item in production in 3days. Be aware that it is recommended to validate receipt in the middle to prevent hacking.

@hyochan hyochan added the help wanted Extra attention is needed label Dec 29, 2019
@DevonTomatoSandwich
Copy link

DevonTomatoSandwich commented Dec 29, 2019

do you mean changing

_purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((purchasedItem) {
  print('purchase-updated: $purchasedItem');
  // do i have to check if the purchasedItem went through?
  setState(() {
    isNonConsumablePurchased = true;
  });
});

to

_purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((purchasedItem) async {
  print('purchase-updated: $purchasedItem');
  // do i have to check if the purchasedItem went through?
  setState(() {
    isNonConsumablePurchased = true;
  });
  await FlutterInappPurchase.instance.finishTransaction('token???');
});

If so
Do i need async await keywords as finishTransaction is a future? and
What is the token argument that is required?

Edit:

I realised the PurchasedItem has a purchaseToken field should i say:
await FlutterInappPurchase.instance.finishTransaction(purchasedItem.purchaseToken);

@hyochan
Copy link
Owner

hyochan commented Dec 29, 2019

@DevonTomatoSandwich Yes, you should await to ensure finishTransaction finishes. Sorry for the confusing documentation. You should pass purchasedItem.purchaseToken for android and purchasedItem.transactionId for ios. I'm willing to update this soon so that you can only pass purchasedItem.

@hyochan
Copy link
Owner

hyochan commented Dec 29, 2019

@DevonTomatoSandwich You can now just pass purchasedItem from 2.1.0.

@DevonTomatoSandwich
Copy link

Awesome thanks for updating. The documentation is good btw, i think it's a lot better than flutter's in_app_purchase.

@JayM96 's other question was

what will be the minimal code to ... verify purchase for both android and ios ?

From the documentation i saw

you'll have to verify the purchase either by acknowledgePurchaseAndroid, consumePurchaseAndroid, finishTransactionIOS

But doesn't finishTransaction do this anyway? as it says

if you want to abstract three different methods into one, consider using finishTransaction method

So do you only need to call finishTransaction to verify purchase?

@hyochan
Copy link
Owner

hyochan commented Dec 29, 2019

@DevonTomatoSandwich Yes, you can just use finishTransaction and not use consumePurchaseAndroid and finishTransactionIOS separately.

@JayM96 You can verify receipt locally with methods we've provided. However, if you care about more secure transactions, I'd recommend you do this in the backend. There are several other libraries that do this like node-iap.

@DevonTomatoSandwich
Copy link

Ok thanks. I was getting errors on android using:
await FlutterInappPurchase.instance.finishTransaction(purchasedItem);
because i didn't add the android arguments. When i add the android arguments like this:

String result = await FlutterInappPurchase.instance.finishTransaction(
  purchasedItem, 
  developerPayloadAndroid: purchasedItem.developerPayloadAndroid, 
  isConsumable: false
);

It works for the options "Test card, always approves" and "Test card, always declines"
But when the 2 "Slow test card..." options are selected i get errors.
I'll do some more testing and reply soon in this issue

@JayM96
Copy link
Author

JayM96 commented Dec 31, 2019

@hyochan You are doing great job. Also, Thanks for updating the plugin as well.

@hyochan @DevonTomatoSandwich I also want to know even though i refund the item purchased. Still i am getting those items in the list of available purchases.

If i have refunded for a managed product then even for waiting for 2-3 days still getting that item in the available purchases list. Also, i didn't found any parameter in any of the method which tells me the purchase state like item cancelled or not?

Also, let me tell you what i am doing with your plugin is i am purchasing an item which is listed as a managed product in play console. Once purchased i am never calling consume method on it as i want it to treat that item as a non-consumable item. I am also completing the finishTransaction Method as follow.

FlutterInappPurchase.instance.finishTransaction(purchaseToken,isConsumable:false);

Also, in that method there is an argument with isConsumable argument. I am predicting that it is for declaring as a consumable or nonconsumable item. i am always passing isConsumable:false as i want it as a non consumable item.

One more issue i was facing is when i was testing with test accounts and then when the in app purchase prompt opens and continues with payment process and somehow it fails at very late stage it is showing the item as a successful purchase. Is it happening as i have selected the "test card always approves" option or any other issues is still there.

Please correct me if i wrong and what i can do for cancelled or refunded item or how can i manage them.

Thanks.

@DevonTomatoSandwich
Copy link

I've made a repo here if anyone wants to try to reproduce these issues.

The app has a list of non-consumables you can purchase (smiley faces) check out the readme for more details and screenshots. The readme also has detailed instructions on how to set up.

It's my first time making a GitHub repo so let me know if you want to add to it. Or start as many new issues as you want there :)

I feel like these issues might be sorted if we work on the same project together but maybe this is too much work.

@github-actions
Copy link

github-actions bot commented Apr 3, 2020

This issue is stale because it has been open 90 days with no activity. Leave a comment or this will be closed in 7 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed no-issue-activity
Projects
None yet
Development

No branches or pull requests

3 participants