How to tie back iTunes connect Subscription Status URL to a unique user - ios

Hello I am currently trying to take advantage of the Subscription Status URL that iTunes connect gives you to get updates on a auto renewable in app subscription.
I have my endpoint up and running, and I am getting all the receipt info I need and the status of the update, however I have no current way of tying this update back to a specific user of my application.
For example, every user of my app has a UUID, and in a perfect world I would somehow like to tell Apple during a purchase which user uuid purchased this subscription and then get that UUID back in the POST request from the Subscription Status URL.
Is this possible?

You have identified what I consider to be one of the biggest flaws in StoreKit, that the receipt does not contain a way to identify the user (iTunes account in this case).
The way around this is: When your users make a purchase and your app processes a transaction, you need to post the transaction identifier (and probably the receipt data) to your backend and associate it with your user's backend record. Then when you get a push from Apple, you can look up the user it relates to by transaction id.
This is not an ideal solution, since different app users can be sharing a receipt via the same iTunes account and other edge cases like that, buts it is a good as you can do with the way app receipts work.

Related

iOS & Firebase Auto-renewable Subscriptions

My problem:
I am having a hard time figuring out a way to safely manage auto-renewable subscriptions in iOS with Firebase.
Purchase process:
User1 purchases a subscription
Update User1's account on Firebase w/ the subscription identifier
(used to unlock content)
Store original_transaciton_identifier(OTI) w/ uid of User1 to match w/ receipt verification from Apple.
Grant user access
Edge cases causing my brain to implode:
User1 logs out of AppleId used to purchase subscription, but remains logged in to app w/ Firestore credentials.
Therefore, when I go to verify if the subscription has expired it does not return a valid subscription. I want the user to be able to keep their access until it is expired or canceled. Any tips on achieving this?
User2 logs into the same device User1 was previously using.
Therefore, the same AppleId is being used for both users. I can check if the current user has a subscription, and check the OTI to see if it corresponds to User2...which it won't.
We will show the 'purchase iAPs' screen, but what if this user wants to buy a subscription as well under the same AppleId? Is it normal for me to handle this saying, "Apple Id already connected with another account or something"?
Relevant articles I've been able to find:
How to tie auto-renewable subscriptions to in house user, not appled id
I've been struggling with this for sometime and haven't been able to find many resources. All help is appreciated.
For case #1:
When you attempt to access the receipt Apple will trigger a login prompt for the user to enter their iTunes credentials. If a receipt is still unavailable, you won't be able to verify the subscription status. The "right" way to do this is to store the entire receipt on your server, and periodically refresh it with /verifyReceipt. You'll check if the subscription was cancelled, and update the expiration_date so you know when to cut off access for the user.
For case #2:
Is it normal for me to handle this saying, "Apple Id already connected
with another account or something"?
Yes! If you're able to look at how some other large subscription apps handle this (Netflix, Spotify, HBO, etc.) - it's similar to what you describe. Instead of checking the receipt locally every time, if you maintain the subscription status on your server (as mentioned in #1) this would only happen if the user tries to "Restore Purchases".
This is a pretty extreme edge case, since not many people try to make a purchase on their friends phone and would require TouchID/FaceID in most cases - so it's more of a fraud prevention feature. Once you get millions of users you can get fancy and send them an automated email link to signup with Stripe if you detect this.
Alternative:
RevenueCat can handle all the subscription tracking and these edge cases out-of-the-box, and it plays nice with an official Firebase integration. Disclaimer: I work there.

iOS In App Purchase Receipt Duplicate Management

When building In App Purchases into an iOS app, Apple gives you access to a receipt that you can send to your server to view all In App Purchase transactions for that given iTunes user related to your application.
If in my application I require users to login or create an account through my system before making a purchase, how can I guarantee that iTunes receipt will not be duplicated?
For example, if a user makes a purchase, the application sends the user ID, and iTunes receipt to my server. The server then stores that receipt along with the user ID in a database. The next time the server wants to check the users purchases we can retrieve all the receipts for that given user ID out of the database and run checks on it.
But if the user logs out and logs in as a different user and makes another purchase the receipt will be sent to the server again, with a different user ID. Effectively, allowing 1 purchase to be used on unlimited user accounts.
Due to the fact that the receipts change over time (auto renewing subscriptions, etc), I don't think it's safe to rely on the receipt being the same every time it's sent to my server and using the receipt data as a unique identifier.
I also considered storing the original_transaction_id for one of the transactions, but I don't think that would work since an application might have multiple non-consumable items, or multiple subscriptions, therefor there might be multiple completely valid original_transaction_id's in one receipt. So it doesn't really associate that receipt, but just the transaction.
Ideally, I'd like a system where when a user logs out, and logs in (as a different user or same), the application will send the receipt to the server, and dissociate any of the same receipts for all existing users, and link this new receipt to the user that logged in. Problem is, it doesn't look like there is any type of unique identifier for a given receipt that I can use to check for duplicate receipts in my system.
What is the best way to detect duplicate receipts sent to my server (so I can dissociate the old receipts accordingly)?
PS. I think this system is most important for subscriptions, and non-consumable items. For consumable items it will always have to be linked to 1 specific user, and I can just store the transaction_id and original_transaction_id for that consumable item to ensure it doesn't get duplicated.

iOS In-app purchase in multi user app

I just run into a problem with in-app auto-renewable subscription. The app contains this kind of subscription and the app can be used by multiple users but the subscription is bind to the apple id is used on the device. So if a different user log in to the app than the system say he has a valid subscription. If I log the subscribed users on my backend server than if a user without subscription log into the app can not make a new subscription according to the Apple's response because the apple id used on the device. An other problem if a keep track of the subscriptions on my backend server if the user unsubscribe on the apple's webpage I can't notify the server about if.
What do I do wrong? What is the right workflow for this case?
I hope do you understand my dilemma.
Thanks!
Your use case is absolutely valid and that's exactly how the subscriptions In-App purchase work with any platform (Apple/Google).
In case of Subscriptions in-app purchase the content delivery is entirely the responsibility of the app provider and not the platform. You have no direct way of identifying if the app user has been switched to a different user as you can't access the current logged in user on iTunes account on the device.
You need to manage this use case on your own by keeping some data locally on the device and maintain user purchase history but still that wouldn't solve the purpose 100%. When user will go for purchase of the subscription it will show the service as already subscribed unless the iTunes user account is also switched on the device.
You can keep track of the unsubscribed state from the backend as when the subscription is successful you will get a receipt from iTunes which you can use to save in your DB. You need to run a backend job on the server side to validate the saved receipt to check the updated receipt which will give you details if the subscription has been expired or not.

How to use Non-Renewable Subscriptions in multiple devices?

I'm implementing an application with Non-Renewal Subscriptions. For that i have referred many sites and most of the answers that i found as like,
We need to manage the expire date by ourself in our server side/local, once you verify a receipt with Apple.
We can implement authentication module as optional to share use the Non-Renewal Subscriptions across multiple devices.
Actually my application doesn't have authentication modules like registration/login to track user on multiple devices. So How can i able to use the Non-Renewable in multiple devices without allowing user to register/login. Do we have any common field to trace the user on multiple devices without authenticating them.
Thanks in advance, Can anyone please give any suggestions to handle this scenario.
You will need some server side support. If you are fine with receiving unauthenticated traffic, you can use the original transaction id. For each subscription purchase you make for a given Apple Id, that purchase will have a unique original transaction id (in the receipt).
If the user initially purchases the subscription on device A, let's say they get back a transaction id of 1234 (note this is not the format, I am just using this as an example). Now the user goes to device B and makes the same purchase. Note this is a subscription, so Apple will already know the purchase was made for that Apple Id. It will indicate the subscription was already purchased, but will let the person still "purchase" (they won't be charged). Upon this, they will get a receipt. This receipt will have the same transaction id.
So here is where your server would need to tie the two together. You would most likely use a UUID, such as [[UIDevice currentDevice] identifierForVendor]. Now your server will know that transaction id 1234 is used by device A and device B.
You can choose how to send this information. You can either send it by way of the receipt (in which case your server will need to unpack it to get the transaction id) or the app can do it for you.
You should do what you can to increase security measures. For example, the method above could be easily spoofed.

Auto-renewable subscriptions on iPhone and Android: sync

We want to use auto-renewable subscriptions in our app (iOS/Android). But I don't understand what is the best way to sync these subscriptions between devices and platforms.
We are using user email for authentification but it seems that all subscriptions are linked to user's Apple account.
Does it mean that I can't sell subscription to some user if another user (from the same device) already bought one on this device because this device is already subscribed?
What is the best way to sync subscriptions between platforms? Should I write some server code to check subscription status for the current user? But, again, right now I don't have any information about user except his/her email. Of course, it is possible for me to put subscription status on our server but what to do with this case:
user A bought auto-renewable subscription on iPhone from the app;
user A cancelled this subscription via subscription management (app doesn't know anything about it yet)
user A logged-in on Android device, and he is subscribed because I don't have any information about him/her cancelling his subscription yet.
I understand that I am able to check his/her subscription status from my server, but his/her in this case means I am able to check his/her Apple account status, not his/her account in my app. So, for example, if I have two/three/million users on the same Apple device (first is a paying user, and the second cancelled his subscription) it means that I will always get the good receipt from Apple, right?
It's possible that my understanding of how it works is not very good, or, maybe, I can't see the good working pattern here, but I don't understand how to create convenient subscriptions that would work for iOS/Android both.
At the same time I know it's possible because of Wunderlist and dozen other apps with this functionality. Could someone please describe high-level logic behind that?
If your app offers auto-renewable subscriptions, you can receive server notifications from the App Store about key events by setting up an optional URL that links to your server.
https://help.apple.com/itunes-connect/developer/#/dev0067a330b

Resources