I am using sever to server notifications of ios https://developer.apple.com/documentation/storekit/in-app_purchase/enabling_server-to-server_notifications.
It is giving me the notifications but there are no information that to which user this transaction belongs or who paid for it, so am I missing something or there are other ways to know?
You can only rely on original_transaction_id. It's unique identifier of subscription. In case you have one subscription group it also identifies your user. However you have to implement your own logic by matching your users with original_transaction_ids.
You can also use ready-to-use solution to handle Apple notifications, like Apphud.
Related
I used flutter_inapp_purchase (5.1.2) to set up IAP subscription purchases for iOS.
Now, I'd like to receive subscription updates (ie. user cancelled subscription). I'm setting up a Firebase cloud function to receive the IAP notifications from Apple.
However, how do I link these with the user in my Firebase database to update their premium status?
What is the standard best practice for how to link these notifications to users in my syste?
Options:
unique_vendor_identifier = based on device ID. However, I read some articles that said this changed over time, which doesn't seem like
the best way to match up a user
original_transaction_id = match to the original subscription transaction using the original transaction id field passed over on
the IAP notification from Apple. However, I see edge cases where this
wouldn't work, for example if a user unsubscribes and the re-instates
their subscription--would the original_transaction_id be preserved?
Maybe this would work for my use case.
Does anyone have any other ideas for elements that could be preserved to match up the user with the right notifications?
Separately, is app_account_token from IAP notifications the same thing as purchaseToken in the flutter_inapp_purchase library and is this preserved at all in a way that could be useful for this purpose?
Good day! I'm trying to implement notifications for auto-renew subscriptions and some parts of the whole system are not clear for me. Could you please help?
First of all, when user creates a subscription I get a receipt from user's device, verify it and create a record in database with all needed information. Now, the notifications are coming to server.
INITIAL_BUY notification - When does it come and why? I just got a receipt from device, verified it and I'm happy. Why do I need it?
Correct me if I'm wrong, this part is unclear for me, When user UPGRADES subscription level I get CANCEL notification for oldSubscription and a receipt with a new purchase for newSubscription, right?
So theoretical question is - if on my server side content available in oldSubscription and content available in newSubscription are different entities than when I get CANCEL for oldSubscription I just deny user's access to oldSubscription content and when I get receipt from client I create newSubscription with access to new content, right?
DOWNGRADE and CROSSGRADE. As far as I see I get DID_CHANGE_RENEWAL_PREF or DID_CHANGE_RENEWAL_STATUS. So I will get auto_renew_status in notification for this subscription and when payed period will expire I will get a receipt from user device with info about new purchase? Or I have to figure out how to handle DOWNGRADE and CROSSGRADE only by DID_CHANGE_RENEWAL_PREF and DID_CHANGE_RENEWAL_STATUS notifications?
Thank you
The problem with server receipt validation is that there is not only one way. There are endless possibility to implement this and it depends on your use case of the usage of subscriptions and how you want the communication between your app and server to happen.
In your second paragraph is the first example of those possibilities: your server will get the receipt from the device only if you implemented it that way. Also, maybe you update your database solely based on the notifications instead of the send receipt. You see, it is all up to you ;-)
Regarding you questions:
1)
Occurs at the user’s initial purchase of the subscription.
See documentation
Theoretically this is correct, but your described use case isn't an upgrade. Would be odd, if the better subscription wouldn't contain the content of the lower one.
There isn't much to handle with down- or crossgrade. The notifications only tell you that there will be a change with the next auto-renewal. Because, the user is still eligible to access the better content until the next auto-renewal. After the better subscription expired you will receive a normal DID_RENEW with the down- or crsssgrade product id.
I have followed some tutorials on implementing In-App purchases and subscriptions for iOS (especially Ray Wenderlich) but I have doubts on how to integrate our iOS app with our website so that if someone subscribes to the app they can access the content on the web as well.
Our website and app offer access to videos. All subscribers have access to all videos. Our web works with PHP and MySQL. When someone subscribes on the web, a record for their account is created in our MySQL database and they are flagged as subscribers so that they can access the content.
We want to implement in-app subscription in our app, but we need for a record to be created in our database when the subscription takes place.
The question is, should we do this upon receipt validation (we'll be doing this in PHP)? Also, is there a way to know when a user unsubscribes through iOS so that the database can be updated accordingly?
Our closest example of how we would like it to work is Gaia.
Should we do this upon receipt validation?
Yes, you should wait until you validate the receipt to mark the subscription as active for the user.
Is there a way to know when a user unsubscribes through iOS so that
the database can be updated accordingly?
The correct way to implement this is to store the entire IAP receipt on your server and periodically refresh it with Apple to get the current subscription status. Just because somebody started a subscription doesn't mean it will still be active the next time you check it (e.g. they may have turned off auto-renew or been issued a refund).
This blog posts explains some of the nuances in further detail: iOS Subscriptions Are Hard
Is there a way to know when a user unsubscribes through iOS so that
the database can be updated accordingly?
Use status update notification.
A statusUpdateNotification is a server-to-server notification service
for auto-renewable subscriptions. A notification specifies the status
of a subscription at the time the notification is sent.
As status update notification is not a reliable service, Apple recommend to use this in combination of other method such as polling the verifyreceipt end point. creating a scheduler in server will be best option along with notification.
I'm creating an iOS app with an auto-renewal subscription. I've been reading a lot of tutorials and documentation but I'm a bit confused about how to handle certain scenarios.
Here's how my app works:
User installs app
User creates account within signup flow
User is asked to select a plan and pay within signup flow
The payment receipt is uploaded to my server and I activate their account in my database.
My server polls the /verifyReceipt endpoint on regular basis to renew the user's account or deactivate it depending on what the latest info from apple. (or use Apple's new Status Update Notification, both serve the same purpose to get me the latest subscription info on my server)
After a month when the subscription renews I know a transaction will appear on the SKPaymentQueue on the user's device. Because of this a lot of tutorials/documentation recommend having your AppDelegate implement the SKPaymentTransactionObserver protocol so that you can handle a transaction at any time.
But, I didn't use AppDelegate. I used the view controller in signup where the user picks their plans to implement SKPaymentTransactionObserver.
My reasoning is that since I'm getting info on the backend do I need to care about the transactions that will show up in the queue in the client each month when the subscription renews? Can't I just ignore these transactions, or will I need to call queue.finishTransaction on them?
I also read some things about restoring transactions when the user deletes the app and re-installs or gets a new phone. Again, do I need to worry about this? Because I should still know about the subscription on the backend and all the user has to do when they get a new phone is log in to their account for my service and it'll check the backend to see if their subscription is active.
I guess my larger question is: When you have a backend to handle IAP auto-renewal subscriptions, can you ignore some of the stuff happening on the client with the payment queue because that feature was built for apps that don't have a backend.
It's best practice to implement the observer immediately in the AppDelegate in case something goes wrong between the user being charged by Apple and you upgrading their account - if they close the app or it crashes you may lose that transaction.
Also, I think I've had cases where I forgot to call finishTransaction and that annoying iTunes login prompt kept popping up, not sure if that was a Sandbox only event though.
Like #Paulw11 said. Don't rely on the Status Notifications. At time of writing, they don't provide enough info to update a user's status, namely any sort of user identifier. Refreshing receipts from the backend is the way to go. If a new receipt is posted to the SKPaymentQueue (say on a renewal), you can handle it like any other receipt refresh for the user on your server.
Here's a good blog post that provides more detail on what should be happening exactly on the server: iOS Subscriptions are Hard
For your restore logic, you don't need to use the StoreKit restore method if you've implemented your own restore functionality through an account based system. If that's the route you want to go, you should definitely listen to SKPaymentQueue in the AppDelegate to avoid as many edge cases as possible where you could lose track of someone's subscription status. The good 'ol "Restore Purchases" button is a great way to fix some slightly flawed in-app purchase code :)
I guess my larger question is: When you have a backend to handle IAP
auto-renewal subscriptions, can you ignore some of the stuff happening
on the client with the payment queue because that feature was built
for apps that don't have a backend.
Don't ignore the payment queue. You can ignore the "Restore Transactions" if you have your own account based restore system.
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.