Missing developer payload after SUBSCRIPTION_IN_GRACE_PERIOD event - in-app-billing

Is it a correct behavior, that assigned developer payload during acknowledgment of a subscription purchase is empty when the subscription is entering in grace period?
After I've got SUBSCRIPTION_IN_GRACE_PERIOD event, I'm calling the get method from Purchases.subscriptions resource and turning out, the developer payload is empty.
I thought that my assignment of the developer payload is failed, but before the subscription entered the grace period my subscription was a few times renewed (SUBSCRIPTION_RENEWED) and the developer payload existed that time.

Related

SwiftUI Auto-Renewable Subscription flow

I have implemented In-App Purchase Auto-Renewable Subscription into my app but I'm not sure if I have done it correctly as the app constantly asks for iTunes login.
In the user case: I am subscribed to monthly payments and my first month is over and expect it to auto-renew.
The flow I have at the moment is as follows...
(in App Delegate) Check receipt is valid
(if receipt IS valid) check all receipts for latest expiration date
(if expired - which seems to be the case after the first month is over) call SKReceiptRefreshRequest to get latest receipts. I have put a count check on this otherwise it gets stuck in a never ending loop.
Do final check to see if latest receipt is in-fact expired.
Is this the correct way to go about this? If not could you shine some light on this?
It all seems to be working fine apart from the annoyance of iTunes login. Which I guess would only be once a month outside of the Sandbox environment which isn't too bad but just want to be sure I'm doing this correctly.
Thanks
Don't call SKReceiptRefreshRequest. This request is usually only for the "restore purchases" mechanism. This is why you're getting the sign in dialogue. StoreKit will return to you as long as you an observer to the payment queue: https://developer.apple.com/documentation/storekit/skpaymentqueue/1506042-add so you should add yourself to the payment queue on app launch. Then keep that object aline to listen for changes for the entire app lifecycle. You will receive the renewals in the updatedTransactions callback https://developer.apple.com/documentation/storekit/skpaymenttransactionobserver/1506107-paymentqueue
Secondly, you should be doing receipt validation on your own server and not on the client as it will be susceptible to a MITM attack. You can also easily control the logic there and receive Server to server notifications which is best for managing subscriptions.

In App Purchase Subscription Auto Renewal

I have implemented a couple of months ago the in app auto renewable subscription on two of my apps. I stored the old receipts of my users and contacted Apple from my server at the end of the subscription period to check if the subscription is still active.
I noticed that some of my users are being auto-renewed form the client code itself.
My app upon entry calls [[SKPaymentQueue defaultQueue] addTransactionObserver:myObserver] and when either SKPaymentTransactionStatePurchased or SKPaymentTransactionStateRestored is returned it calls my server to verify the receipt and give my users the subscription.
I have been trying for quite some time to understand the logic behind the transaction notification the client gets at the end of the renewal period. Does anyone knows why only some of the users get the notifications and the rest require the server to revalidate their receipts? I tried to think maybe it has got something to do with the call to addTransactionObserver. Maybe those users killed the app while it was in the background and entered the app again after the subscription period ended which caused the addTransactionObserver: to be fired and the notification to arrive.
If I can get all of my users to get this notification I wouldn't have to run the server calls anymore at the end of the subscription period as they would be fired from the client when needed.
Any insight would sure help understand this puzzle.
Thanks
Roi
My experience states you'll need to continue periodically verifying receipts on your server. I have noticed the same as you, that these new receipts are sent to the app inconsistently. I think Apple will send the receipt to the client if they happen to freshly launch the app within a certain time frame of the new renewal.

Auto-renewable subscriptions calling SubscriptionsUpdated

I have implemented som auto renewable subscriptions in my app and everything works well. I perform a purchase in the app, everything gets synced to a server, and the server then checks the iTunes API as soon as the subscription has expired to detect if the subscription has been renewed.
One thing confuses me though. Every once in a while I get a call to transactionsUpdated within my app with a transaction with status: Purchased. This is usually done after I restart the app.
Why do I get these calls? Has it something to do with the subscription beeing renewed? Can I safely ignore these calls? Everything seems to work fine.
Thanks in advance!
Yes, what Apple is doing is sending you a receipt for an automatic renewal of the subscription. Because all durations are drastically shortened in the sandbox, the subscription will get automatically renewed by Apple every few minutes, for a limited number of times (like 5), before they stop renewing.
Since you're already checking for new receipts at the right time on your server, you can ignore the receipts they're automatically sending to the app on occasion.

How to restore Auto Renewable Transaction in iPhone? (In App purchase)

In my application, renewing period is 1 month. Validity Time for Auto-Renewables in Sandbox is 5 minutes. So transcation identifier will keep on changing after each 5 minutes.
Initially i will a buy the product. If I am successfull i will get SKPaymentTransaction object it contains all details about transcation like transactionIdentifier, transactionDate, transactionReceipt and transactionState. Till this I understood. If I call restore function, (i.e.restoreCompletedTransactions) I am getting all the completed transaction information. According to my knowledge the first transaction log information will be the late-stet transaction information.
When compare both the object's details are different. How come this is possible. I am totally confused, How to restore this Auto renewable transaction details. Any help is appreciated.
To confirm that user's subscription was renewed or not, restore completed transaction and send first transaction's receipt to apple. In response apple will send you current status of the transaction.
For detailed reference read following link
http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/RenewableSubscriptions/RenewableSubscriptions.html#//apple_ref/doc/uid/TP40008267-CH4-SW2
Specially Table 7-2 Auto-renewable subscription info keys
After that send your data to apple in Json format (Note that receipt part has to base 64 encoded.) and read the response carefully. In response you will find codes given in above table depending upon situation.
Please note that in real environment receipt verification should be dome from another server not from iPhone or iPad itself.
Post here if you have any further doubts.

In app auto-renewable subscriptions

Sorry for the millionth question about iTunes subscriptions, but I still have a few doubts.
Basically I'm implementing auto-renewable subscriptions in my app and I want to make sure I got it right. Here's a list of steps to take that I came up with:
whenever an user buys a subscription, send the receipt to the server to validate it
if the receipt is valid, save it on the database
on application load, ask the server if a receipt for this UDID exists (this is to figure out if the user has a valid subscription)
if so, check if a new item has been added on the store in a date range from the subscription start date to the expire date
if any, notify the user about those items in some way and mark them as freely downloadable
Are these steps correct? And if so, why does the Apple doc say:
In most cases, your iOS client application should not need to change. In fact, your client application is now made simpler, as you can use the same code to recover auto-renewable subscriptions as you do to recover nonconsumable products. This is described in “Restoring Transactions.”Your application receives a separate transaction for each period of time where the subscription was renewed; your application should verify each receipt separately.
To me it looks like this needs some code to handle all the various cases I mentioned, instead. Or I'm totally wrong about it. Am I?
Plus, how do I know about the subscription expiration date? I can't find a way to get this information anywhere. Am I supposed to save this on my own database?
Update:
I've figured out a few things since I posted this question. Feel free to correct me if I'm wrong.
First of all I guess I'm supposed to store the length of the subscription somewhere on my own database, because as stated on Apple's docs, you cannot retrieve it in any way through Apple's web services. In fact, each subscription length has a different product identifier, so you should have a way to convert a product identifier to a subscription length.
Also, Sylvian has posted details about his implementation of auto-renewable subscriptions, so at least I know my thinking wasn't too much flawed.
Now the only problem is this: how do I know that an user has a valid subscription? I could store this information on my server, yeah, but how do I associate an user with a completed transaction? Should I save the device's UDID?
Here is how we implemented In App Purchases and specifically the new auto-renewable products at my company.
The application transmits the transaction receipt to our webservice, we return OK to the application if we handled it correctly and Apple could verify it. In that case we updated the user account (i.e. the database) to say "yes he has paid and his subscription is valid till the receipt expiration date".
After the OK for this webservice, the application reloads the account info through another webservice, and see there is a valid subscription. That was it... Until auto-renewable products appeared.
We now had to implement some CRON jobs which runs every day: every day we make a list of passes which are supposed to expire, and we ask Apple if the original receipt is still valid: the magic thing is that in their answer, there is a field latest-receipt which embeds the latest receipt. If it is not the same as the one we have, we understand that the subscription has been renewed automatically, we store the latest receipt for the next cron check, and we update the user account to extend the expiration date.
Hope it helps.
I think I found a solution. It doesn't require an additional username/password and it seems to be working.
Note: If you think this is inappropriate, please explain why in the comments. Thanks.
Basically, whenever an user buys a subscription, I validate the receipt against my server and store the receipt data in the user defaults. Then, when the app is opened, or whenever I need to check if the subscription is still valid, I retrieve the previously saved receipt data from the user defaults and validate it against the server.
My webservice just returns whether the subscription is still valid or has expired, plus some other related information such as the subscription length. To do this, it just queries the iTunes server as usual, and checks if the status response is nonzero. 21006 means that the subscription has expired.
If your app has some user management i.e. you use username/password to use the app, then you have to maintain a server to record the purchase/validity of the currently logged in user. This is applicable for normal subscription and non-consumable purchase. But... if you use the new auto-renewable subscription, then it's NOT possible to maintain multiple user in that app, because : this kind of purchase can not be done multiple times within the subscription period using the same Apple ID from the same application and I found it really annoying and finding a better solution for this case i.e where I have multiple child account in the app but I want to use the same Apple-Id to purchase a auto-renewable subscription for each account. And I think I have to use the old subscription model. Any new thoughts ?
as far as I have understand it the apple server will contact you (or the customer with his iPhone) and tell "look here I have a valid purchase for you". Inside your App you read this message and unlock the regarding content for use. The next step is to tell the apple server that you have responded to the receipt and the apple server will not show the message again.
So with a renewable subscription you get for each period a new message. Correct me if I'm wrong, please.