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

getAvailablePurchases on iOS let appear a dialog "Sign in to iTunes Store" #747

Closed
voxspox opened this issue Oct 1, 2019 · 21 comments
Closed
Labels
🙏 help wanted Extra attention is needed 📱 iOS Related to iOS ❓ question Further information is requested 🚶🏻 stale Stale

Comments

@voxspox
Copy link

voxspox commented Oct 1, 2019

Version of react-native-iap

3.4.13

Version of react-native

0.60.5

Platforms you faced the error (IOS or Android or both?)

iOS

Expected behavior

getAvailablePurchases has no side effects

Actual behavior

Calling getAvailablePurchases on iOS let appear a dialog "Sign in to iTunes Store".

This does not happen on Android.

IMG_0020

I'm calling getAvailablePurchases during app start to restore the purchased items. According to the documentation I understood that this is the common way, right?

To restore the purchased items I'm calling getAvailablePurchases based on changes of AppState. Unfortunately the AppState is not only triggered on app start but also p.ex. after returning to the app from a dialog (caused by the app) p.ex. Sign In to iTunes... :(

For the user this is bothering. Especially if the user is not intending to buy something he would not want to enter his credentials to get rid of this dialog.

Tested environment (Emulator? Real Device?)

real device

Steps to reproduce the behavior

call getAvailablePurchases

@alexpchin
Copy link

When in development, this shows so that you can login with your sandbox account. I don’t believe the docs are very clear on this.

@hyochan hyochan added 🙏 help wanted Extra attention is needed 📱 iOS Related to iOS ❓ question Further information is requested labels Oct 2, 2019
@mifi
Copy link
Member

mifi commented Oct 2, 2019

I think for production it may also show a prompt whenever calling this function, right? The way I implemented this is I call this when the user presses "restore purchase" and after purchaseUpdatedListener is called. To know whether the user has a subscription in the future I store it in backend and present it to the app.

@hyochan
Copy link
Member

hyochan commented Oct 2, 2019

Hey @voxspox @alexpchin is right. @alexpchin Since we are working on the bridge, we assume that people might know little bit about IAP in native. Putting all things which already exist in each platform is quite a burden for maintainers. If there are some works on document that you think might be helpful, please feel free to add anything and push a PR.

@voxspox
Copy link
Author

voxspox commented Oct 14, 2019

@mifi I've never seen an app with a "restore my purchases" button. From a UX perspective such a button is a burden and also unnecessary, because the app should know what I have bought ;)

@hyochan I get the prompt also after distributing the app via TestFlight (I assume this is production mode?!)

@mifi
Copy link
Member

mifi commented Oct 14, 2019

I've seen a few apps with that function. I don't quite remember now but I think it is needed (or required by apple) in some cases. Also in Apple's app store guideline examples they have this button:
https://developer.apple.com/app-store/subscriptions/

Also I thought it would be bad UX if the user ever has to enter their apple ID when opening my app, i think that would be confusing. (i've seen this happen before if session is expired or something happens with SSL MITM which is often the case with public wifi landing pages)

edit: actually seems that apple requires it

@voxspox
Copy link
Author

voxspox commented Oct 15, 2019

Is there maybe a way to know before calling getAvailablePurchases that the prompt will appear? Or in other words, how can I detect if the user is connected to iTunes or not?

@cemocanon
Copy link

1+ same

@Zontex
Copy link

Zontex commented Oct 23, 2019

Hi guys, any answer on this? as I understand this is a debugging functionality but I'm testing with testflight and I want to prevent this from happening, is is it possible to somehow leave the sandbox mode?

@voxspox
Copy link
Author

voxspox commented Nov 12, 2019

Meanwhile, I have found solution for me. I introduced a new variable isRestorePurchasesEnabled which is permanently stored by my app.

Init:

isRestorePurchasesEnabled = false

On app start:

if (Android || isRestorePurchasesEnabled) {
  call getAvailablePurchases
  on error.code === 'E_USER_CANCELLED' -> isRestorePurchasesEnabled= false
}

On purchase:

isRestorePurchasesEnabled = true
requestSubscription ...

Settings:

Button "restore purchases" -> isRestorePurchasesEnabled = true

The user will never see the connect-iTunes-prompt again. The restoring only happens after a purchases was done and thus the credentials have been already typed in + stored and the prompt will not be shown.
The only case where the prompt will be shown, but only once, is if the user logs out in Settings / iTunes / Sandbox Account. Don't know if this is there in production mode.

@stale
Copy link

stale bot commented Feb 10, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

@stale stale bot added the 🚶🏻 stale Stale label Feb 10, 2020
@ahmetfarukekinci
Copy link

Hello,
I am really confused about one topic, can somebody help me ?
I want to construct a controller that checks whether user still own the product or not ?
How can I detect user cancellation with using this library for both apple and google play store ?
I do not even know if its related with this getAvailablePurchase method.
Thanks.

@stale stale bot removed the 🚶🏻 stale Stale label Feb 17, 2020
@VitaliKaniushok
Copy link

  • same

@nathsimpson
Copy link

I'd like to work out if this would also happen in production, rather than just TestFlight.
We're currently using this function as the app loads, rather than on a button press.

@mifi
Copy link
Member

mifi commented Jun 8, 2020

Apple still advices us not to call this function on app automatically or startup

Don't automatically restore purchases, especially when your app is launched. Restoring purchases prompts for the user’s App Store credentials, which interrupts the flow of your app.

https://developer.apple.com/documentation/storekit/in-app_purchase/restoring_purchased_products#:~:text=Restore%20Completed%20Transactions,of%20your%20app's%20completed%20transactions.

The way I implemented it is to send the receipt to the backend when the user presses purchase or restore purchase. Then the backend can provide the app with the subscription status in the future.

@alexpchin
Copy link

Apple still advices us not to call this function on app automatically or startup

Don't automatically restore purchases, especially when your app is launched. Restoring purchases prompts for the user’s App Store credentials, which interrupts the flow of your app.

https://developer.apple.com/documentation/storekit/in-app_purchase/restoring_purchased_products#:~:text=Restore%20Completed%20Transactions,of%20your%20app's%20completed%20transactions.

The way I implemented it is to send the receipt to the backend when the user presses purchase or restore purchase. Then the backend can provide the app with the subscription status in the future.

For an auto-renewing subscription, how do you get the latest receipt without uploading from the client?

@mifi
Copy link
Member

mifi commented Jun 10, 2020

By running a periodic polling in the backend that periodically validates every purchase like this Then take the latest receipt from the validation (which comes from google/apple server) and save it back to the database.

@alexpchin
Copy link

By running a periodic polling in the backend that periodically validates every purchase like this Then take the latest receipt from the validation (which comes from google/apple server) and save it back to the database.

Hi @mifi Thanks for the quick response! I have stored the latestReceipt on the server after the original transaction. So when polling with the original latestReceipt is a new latestReceipt value returned?

@mifi
Copy link
Member

mifi commented Jun 10, 2020

Yes the iap.validate function on backend will call the apple/google apis which return the newest receipt. this can easily be seen when testing renewable subscriptions with a development interval (5min per subscription period)

@alexpchin
Copy link

Thanks @mifi That has really helped my understanding! It just seemed odd to send the "latestReceipt" to receive the "latestReceipt"

@stale
Copy link

stale bot commented Sep 11, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

@stale stale bot added the 🚶🏻 stale Stale label Sep 11, 2020
@stale
Copy link

stale bot commented Oct 11, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

@stale stale bot closed this as completed Oct 11, 2020
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 📱 iOS Related to iOS ❓ question Further information is requested 🚶🏻 stale Stale
Projects
None yet
Development

No branches or pull requests

9 participants