Question

iOS App User being asked to sign in with Apple ID using API checkTrialOrIntroductoryPriceEligibility

  • 19 November 2021
  • 2 replies
  • 882 views

Userlevel 1
Badge +3

I have an iOS App using Purchases SDK version 3.13.0

I have factory reset the iPad I am testing with.

I am running a development build (debug)

I have never made a purchase with this device after factory reset.

On startup of the app I will present an onboarding screen to purchase subscription.

My IAP has a 1 week free trial then a monthly subscription.

I call the API checkTrialOrIntroductoryPriceEligibility to try and know whether I should inform them if the free 1 week trial is available to them.

I was not expecting the dialog “Sign in with Apple ID to pop up” along with soft keyboard over the top of my onboarding screen.

Is this expected behavior?  I would prefer the Apple dialog “Sign in with Apple ID” be user initiated.

I see the following Purchases Log in console if that helps.

2021-11-19 11:16:08.928454-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Debug logging enabled

2021-11-19 11:16:08.928736-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ SDK Version - 3.13.0

2021-11-19 11:16:08.928835-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: 👤 Initial App User ID - (null)

2021-11-19 11:16:08.931387-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Sending latest PurchaserInfo to delegate.

2021-11-19 11:16:08.936017-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Delegate set

2021-11-19 11:16:09.418896-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ applicationDidBecomeActive

2021-11-19 11:16:09.448353-0700 Pick 3 Pro[582:34861] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+049b30dd0f61f47ceb05e72efa25738db

2021-11-19 11:16:09.448937-0700 Pick 3 Pro[582:34861] [Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/$RCAnonymousID:49b30dd0f61f47ceb05e72efa25738db

2021-11-19 11:16:09.451094-0700 Pick 3 Pro[582:34861] [Purchases] - DEBUG: ℹ️ There's a request currently running and 0 requests left in the queue, queueing GET /subscribers/$RCAnonymousID0X0P+049b30dd0f61f47ceb05e72efa25738db/offerings

2021-11-19 11:16:10.110374-0700 Pick 3 Pro[582:34872] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:49b30dd0f61f47ceb05e72efa25738db 304

2021-11-19 11:16:10.113116-0700 Pick 3 Pro[582:34872] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+049b30dd0f61f47ceb05e72efa25738db, 1 requests left in the queue

2021-11-19 11:16:10.113732-0700 Pick 3 Pro[582:34872] [Purchases] - DEBUG: ℹ️ Starting the next request in the queue, <RCHTTPRequest: httpMethod=GET

2021-11-19 11:16:10.114759-0700 Pick 3 Pro[582:34872] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+049b30dd0f61f47ceb05e72efa25738db/offerings

2021-11-19 11:16:10.225105-0700 Pick 3 Pro[582:34866] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:49b30dd0f61f47ceb05e72efa25738db/offerings 304

2021-11-19 11:16:10.225469-0700 Pick 3 Pro[582:34866] [Purchases] - DEBUG: ℹ️ Requesting products from the store with identifiers: {(

2021-11-19 11:16:10.226593-0700 Pick 3 Pro[582:34866] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+049b30dd0f61f47ceb05e72efa25738db/offerings, 0 requests left in the queue

2021-11-19 11:16:10.273867-0700 Pick 3 Pro[582:34865] [Purchases] - DEBUG: ℹ️ Products request finished.

2021-11-19 11:16:10.273994-0700 Pick 3 Pro[582:34865] [Purchases] - DEBUG: 💰 Retrieved SKProducts:

2021-11-19 11:16:10.274063-0700 Pick 3 Pro[582:34865] [Purchases] - DEBUG: 💰 com.pick3pro.subscription1month - <SKProduct: 0x28211ae50>

2021-11-19 11:16:10.274131-0700 Pick 3 Pro[582:34865] [Purchases] - DEBUG: ℹ️ 1 completion handlers waiting on products

2021-11-19 11:16:11.481293-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.

2021-11-19 11:16:12.100791-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.

2021-11-19 11:16:12.105804-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Vending Offerings from cache

2021-11-19 11:16:12.110026-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/E0CFA6A3-3F7E-4D2B-BE56-484E6BEA38AD/StoreKit/sandboxReceipt

2021-11-19 11:16:12.110259-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Receipt empty, refreshing

2021-11-19 11:37:39.997045-0700 Pick 3 Pro[589:38729] <SKReceiptRefreshRequest: 0x281830680>: Finished refreshing receipt with error: Error Domain=ASDErrorDomain Code=907 "Unhandled exception" UserInfo={NSUnderlyingError=0x281600d80 {Error Domain=AMSErrorDomain Code=100 "Authentication Failed" UserInfo={NSLocalizedFailureReason=The verify credentials call failed., NSLocalizedDescription=Authentication Failed, NSUnderlyingError=0x281600de0 {Error Domain=AMSErrorDomain Code=6 "Authentication Failed" UserInfo={NSLocalizedFailureReason=User cancelled, NSLocalizedDescription=Authentication Failed, NSUnderlyingError=0x281600e40 {Error Domain=AMSErrorDomain Code=15 "An unknown error occurred. Please try again." UserInfo=0x2819ae420 (not displayed)}}}}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}

2021-11-19 11:18:57.626731-0700 Pick 3 Pro[582:34641] [Purchases] - ERROR: 🍎‼️ SKRequest failed: An unknown error occurred

2021-11-19 11:18:57.640056-0700 Pick 3 Pro[582:34641] [Purchases] - DEBUG: ℹ️ Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/E0CFA6A3-3F7E-4D2B-BE56-484E6BEA38AD/StoreKit/sandboxReceipt

2021-11-19 11:18:57.640431-0700 Pick 3 Pro[582:34641] [Purchases] - WARN: 🍎‼️ Unable to load receipt, ensure you are logged in to a valid Apple account.

2021-11-19 11:18:57.640689-0700 Pick 3 Pro[582:34641] [Purchases] - WARN: 🍎‼️ App running on sandbox without a receipt file. Unable to determine into eligibility unless you've purchased before and there is a receipt available.

 

Is this just an issue  with debug sandbox testing or should I expect the same behavior with a TestFlight or live environment of sign in dialog popping up in this case?  If the answer is yes then I probably cannot use this API because I think its a bad user experience to ask someone to sign in when presenting an onboarding screen.

 


2 replies

Userlevel 5
Badge +9

Hey @Jimmy Wright!

 

The checkTrialOrIntroductoryPriceEligibility call shouldn’t trigger the login prompt. It uses a local receipt parser and will return a status of .unknown if the receipt doesn’t exist to prevent this behavior.

From your logs, I see that there is a SKReceiptRefreshRequest taking place. This will trigger a login prompt if the customer isn’t signed into an Apple account. Are you calling .restorePurchases anywhere? That would trigger a receipt refresh. Would you be able to put a breakpoint on the checkTrialOrIntroductoryPriceEligibility call and see what the log output is up to that point? It seems like something is trying to refresh the receipt before checking eligibility. 

Userlevel 1
Badge +3

@ryan 

The only time I call restorePurchases is if a user presses a UI button.  So no I didn’t call restorePurchases in this scenario.  I have my own logging of calls related to subscription to a file and it did not show restorePurchases being called.

So there is no receipt on device because I just factory reset the device before running test.  I do not believe anyone was logged in sandbox account either because I factory reset the device so maybe that is the problem?  You don’t show up signed into sandbox account until you make first purchase right after a factory reset of device?  If I commented out the call to checkTrialOrIntroductoryPriceEligibility then it did not ask me to sign in.  So I am pretty sure this is triggering it.

If I am not logged in I would guess you could also not query RevenueCat server for status of subscription either since there is no way to make an association.

What is strange is that I reset device again and instead of using a debug/development build I used an actual TestFlight build.  I would have thought that when the TestFlight build was installed a receipt would also be installed but it was not.  It still thought a receipt was not available.  So it still seems like testing IAP in Testflight is different than production environment.

For now I have added some code to check if the receipt exists and if not to not call checkTrialOrIntroductoryPriceEligibility API call.

To recap for others that may be interested:

  1. When presenting an onboarding screen when app is run for first time, I want to know whether I should display if free trial is available to user on this screen.  I know Apple will present the right thing when they display purchase info but it would be nice if my UI was in sync with Apple/Revenue Cat.
  2. Under no circumstances do I want the sign in login to be displayed unless the user initiated it by attempting to make a purchase or attempting to restore previous purchases.  It needs to be user initiated.  Anything else is just a confusing UI experience.
  3. I don’t want the user to be able to reset their device and get unlimited free trials.  I assume Apple will accurately track this per Apple ID but it’s kind of difficult to verify in testing environments.  IAP purchases have come a long way in the past couple of years but it’s still kind of a pain to verify all the test scenarios.

Thanks Ryan for the reply.

 

Reply