how to test `DID_FAIL_TO_RENEW` , `CANCEL` and any other event in sandbox environment - in-app-purchase

Now I am develop apple in app purchase, I read the docs and find out the sandbox environment only supprot INITIAL_BUY,DID_CHANGE_RENEWAL_PREF,DID_CHANGE_RENEWAL_STATUS,DID_RENEW,INTERACTIVE_RENEWAL. all this support event I have already handled. In the sandbox environmnet the apple server auto renew 6 times. In the subscribe mannagement page in settings->app store->sandbox account shows the all product unsubscribed after 6 times auto renew(I think in sandbox environment, the subscribe workflow are ended,so in the app we should tell user the subscribe ended), but in my app, I did not receive any cancel or other message to tell me the subscribetion cancelled. So what should I do to make the subscribe status keep the same? How to test other events in sandbox environment? is there any way to do this? or I did not need test? or test in production environment? I am not sure my code logic always right, I am first time to develop in app purchase. What should I do to test all workflow works as expect? or I check the exipred time period in my database? This practice seems not a good choice.

what I am doing now is remember the user purchase product id and expired date in the user table, and check the expired user period to make sure the user is auto renew or cancel subscribed. saddly, I could not test other message type in sandbox environment until 2021.07.

Related

How to find user's lost in-app purchases on iOS?

So I followed the official manual and implemented this:
https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1
user pays in app
app gets receipt info from Apple
this receipt info is sent to my server
my server verified receipt by calling Apple API and activates membership for client
The obvious problem is that 3. can fail. I have clients complaining they paid, they are sending me SS of the amount being deducted, but my server was never notified. And I have no way to find these users. Is there some CP where I can search by customer e-mail or transaction ID to check if this is Photoshopped screenshot or valid one?
Is there some API that can be called to list transactions by product and e-mail of client?
https://appstoreconnect.apple.com/ - Apple CP is useless for this
There is no method to correlate the customers details with your transaction details. Only Apple can do this.
My first suspicion is that you may have a logic problem in your purchasing process. If implemented correctly, a transient failure at step 3 doesn't matter.
You should:
Create your transaction queue observer a soon as your app starts. This will enable any pending transactions to be delivered to your observer
When you get a purchase transaction in your observer you verify with your server
Only once you have a response from your server that the purchase has been recorded successfully do you call finishTransaction.
This way if something goes wrong with your server or the app crashes the transaction is still pending in the queue.
If you are using auto-renewing and/or non-consumable IAP then I
strongly suggest you provide a "restore purchases" button in your
UI. This makes it simple for the user if something goes wrong or when
they move to a new device.
If you have users who claim that they did not get what they paid for then you can refer them to Apple App Store support who can refund the transaction.
If step three fails you can fall back to local verification and then let the user through for this session (or some number of sessions before you require it to succeed). Unfortunately local authentication is a pain in the ass because the receipt is encrypted. See this link for an example: https://github.com/andrewcbancroft/SwiftyLocalReceiptValidator . You can also report failures of step 3 to your analytics tool so you can see who is actually affected by this issue (obviously this only works if the analytic eventually get an internet connection.

Auto-renewable subcriptions: handle purchase when user is logged out

I've read a lot of SO answers about handling auto-renewable subscriptions with your own user login system, but there is an issue that I am still not sure how to handle: what to do when the transaction observer is triggered while the user is logged out.
Apple recommends to implement a transaction observer right in the App Delegate:
Adding your app's observer at launch ensures that it will persist
during all launches of your app, thus allowing your app to receive all
the payment queue notifications.
Say the user starts a purchase, but it doesn't complete immediately (for instance because it needs to be approved by their parents, or the app crashes, etc.). The user logs out and opens the app again, and since we are observing transactions in App Delegate, we might receive a transaction immediately when launching the app, before he logs in. We are then unaware of which user to associate the subscription to.
Two ideas:
Non-ideal: should I store the fact that there is a subscription pending and assume that the first user to log in will be the right one, and then associate it in some way to them once they log in? And if so, where would I keep the receipt? KeyChain, UserDefaults? This sounds pretty clunky.
Another way that sounds better: can I store some information about the transaction when it is initiated, and then use one of these fields to actually know exactly whose user's subscription purchase just finished?
(Not particularly relevant, but FYI I am using SwiftyStoreKit).
This is how I would approach this:
When the user tries to purchase a subscription, I first have them login or create an account.
Once the user is logged in, I send their appStoreReceipt to my server and store it there. I check and make sure the user is able to purchase. (At this point they should have the subscription they are trying to purchase)
Once I get a response from the server that the user should be able to purchase I go ahead and start the in-app-purchase
When the in-app-purchase process is done, I send the updated appStoreReceipt to my server and upgrade their account.
The problem you are worried about is what if the user gets done with step 3 but never gets to step 4.
Well, since I have their receipt stored on my server (from step 2), I can just ask Apple to give the latest version of their receipt, and if it shows up that they did purchase, I upgrade their account. You can choose when the right time is to do this check, it can be every time the app launched, or every time the user logs.
Hope this helps.

iOS In-App Purchase Auto-Renewing Subscription Management

I am implementing auto-renewable subscriptions in iOS and want to be able to test the scenario where the user cancels the subscription but I am unable to do so because when I try to manage subscriptions with the sandbox account the app store wants me to associate a payment method with the sandbox account but in my experience once I do that the sandbox account is no longer valid.
Is it even possible to test cancellations or do I just blindly code for cancellations? I have search high and low and have not found anyone who has been able to manage subscriptions in a sandboxed environment.
I realized today that I was thinking about this all wrong and I can see why its not as necessary to be able to manage subscriptions. I was thinking that the 'Cancellation Date' field would reflect when a user cancel's (or really just opts out of auto-renewing) their subscription. But I was mistaken this field is only for the times when a user contacts Apple Support and requests to cancel early and receive some sort of a refund, and this is not something that is managed directly by a user.
Have you tried using a TestFlight build? You can do sandbox IAP testing via TestFlight with a "normal" iTunes account that has a payment method. I would assume that means you could try out canceling the subscription.

Testing IAP subscription when renewed from iTunes or App Store app

I've been implementing auto-renewing In App Purchases and, using the info found here, have had little trouble the purchasing, renewing, & restoring transaction flows.
The problem I am having is finding a way to test when a user renews (after, presumably, canceling some time in the past) from their account page in either iTunes or the App Store app (Detailed here). I'm assuming, since those exist outside of the sandbox and when you log into one of them using a sandbox account that account is invalidated as a test account, there is no way to actually test this use case so I'm just looking for more information on the expected behavior to try and account for it.
I know that keeping a copy of the receipt around to validate will give the latest receipt as part of the JSON payload, I'm more curious for information on how StoreKit will handle this renewal. Will paymentQueue: updatedTransaction: fire with a new SKPaymentTransaction as soon as I add a TransactionObserver or will it stay silent until calling restoreCompletedTransactions and then the new SKPaymentTransaction will be part of that?
Yes, you are correct; paymentQueue:updatedTransactions: will fire, just as if you were making the initial subscription purchase.
You can actually test this since renewals within the sandbox kick in at a much faster pace (up to six times a day) as explained here (scroll down to the bottom under "The Test Environment").
Also when you verify the transaction with Apple's verification service right after you made a test subscription purchase, look for the expires_date field in the response, it will tell you when the next renewal will be triggered.

restoreCompletedTransactions and asking to login

It's my first integration of In-App Purchases. I have everything working: I can buy the item I want, also use restoreCompletedTransactions.
Every time I call restoreCompletedTransactions() I am asked for username and password.
Is this because I am in sandbox mode or will this happen once being live as well?
How do I check if the user has bought it before? (I know I can save it in the user settings, but it would be nice to check if it was bought by polling the Apple server without the user needing to enter username and password).
How do others handle this? Because surely you want to know if they refunded it.
Quote from the Apple Article Instructions on how "not" to do this:
Restoring purchases prompts for the user’s App Store credentials, which interrupts the flow of your app: because of this, don’t automatically restore purchases, especially not every time your app is launched.
The best way to do this would be use receipts.
Steps in general are:
1) Your app would usually request a payment upon first time use
2) Once the customer has paid (or subscribed), then
3) Your app should download the receipt from the AppStore, and then store a copy of the Private Key and certificate details onto your server (or Cloud if it's a non-renewable subscription)
4) Your server should verify that receipt with the AppStore.
5) Optional: Your server can then query-last-receipt to ensure that the user's subscription is always up to date.
6) Once your server is satisfied, then let the app know that content can now be unlocked etc.
In other words, use receipts to verify and not keep retrieving finished transactions otherwise it would put your customers off by keep asking them for the iTunes password every time they need to start your app.
For more information, please watch this apple video
I hope this helps
Regards
Heider

Resources