React-native-iap: getAvailablePurchases on iOS let appear a dialog "Sign in to iTunes Store"

Created on 1 Oct 2019  ·  21Comments  ·  Source: dooboolab/react-native-iap

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

❓ question 📱 iOS 🙏 help wanted 🚶🏻 stale

Most helpful comment

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?

All 21 comments

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.

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.

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.

@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?!)

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

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?

1+ same

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?

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.

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.

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.

  • same

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.

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.

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?

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.

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?

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)

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

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.

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.

Was this page helpful?
0 / 5 - 0 ratings