Non-renew subscription and receipt?

I am perplexed.


According to Apple's documenation here:


https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1


Receipts for in-app purchases of non-renewing subscriptions are retained in the receipt permanently. It says so in the above link as:


In-App Purchase Receipt

The receipt for an in-app purchase.

ASN.1 Field Type 17

ASN.1 Field Value SET of in-app purchase receipt attributes

JSON Field Name in_app

JSON Field Value array of in-app purchase receipts

In the JSON file, the value of this key is an array containing all in-app purchase receipts. In the ASN.1 file, there are multiple fields that all have type 17, each of which contains a single in-app purchase receipt.

The in-app purchase receipt for a consumable product is added to the receipt when the purchase is made. It is kept in the receipt until your app finishes that transaction. After that point, it is removed from the receipt the next time the receipt is updated—for example, when the user makes another purchase or if your app explicitly refreshes the receipt.

The in-app purchase receipt for a non-consumable product, auto-renewable subscription, non-renewing subscription, or free subscription remains in the receipt indefinitely.


Over the past few months of testing my app, this has indeed been the case. But now, the Sandbox environment is providing a the receipt only in the receipt resulting from the purchase transaction. Refreshing the app receipt no longer shows the in-app purchases.


What gives? Has there been a reversal of this policy or else what am I doing wrong?


The purchase process works fine; I finish the transaction and check the receipt. The recepit has the in-app purchase. However, if I issue a StoreKit request to refresh the receipt, the refreshed receipt doesn't show ANY of the non-renewable subscription purchases.


Any clues?

Thanks

Stu

Answered by K6TU in 74788022

I filed a Developer Tech Support request to request an explanation about which of the two referenced documents were correct and whether there had been a change of poilcy regarding which one was correct.


The initial response was that the first document was correct - non-renewing subscriptions were persisted in the app receipt. The person handling my reqest asked for some validation that dumped out all fields in the receipt which I provided. Again, showing that the purchases of non-renewing subsctiptions were not persisted in the receipt from the Sandbox.


First thing today I was asked to file a bug report as the developer handing my DTS confirmed what i was seeing.


Several hours later I got a follow up response that the change I was seeing was the result of a "bug fix" to the store logic and that now the SECOND document is considered the right answer. Developers are responsible for persisting non-renewing subscription status themselves and that the app receipt does not provide (as it did) a persisted record of the purchase of a non-renewing subscription.


The developer handling the case expressed surprise at this change but had confirmed the change with the AppStore development team.


So at least I now know what I have to do... although for the last three months of development after adding in-app purchases for this app using non-renewing subscriptions, the receipt information persisted all purchases.


No fuss, no muss and no annoucement of the change.


I am thankful that I learnt this BEFORE my app got approved for production and then had to deal with a bunch of unhappy customers.


Hopefully this thread saves others from the same headache.


Perhaps the App Store development team has a change of heart and reinstates this behavior but clearly there is still (without clarity across all doucment sources) a risk that the "bug" gets "fixed" again.


Stu

And I think you can also use:


if([[NSUbiquitousKeyValueStore defaultStore] synchronize]){

// get the expiration date

}else{

//alert - you need to log into iCloud to copy your subscription from one device to another

}

Thanks for the idea but alas it seems synchronize returns true if the sync from DISK works.


I tried this with the iPad in airplane mode and then also with the iPad logged out of iCloud - it always returns TRUE.


Oh well...

Appreciate the thought indeed.

Stu

Use the ubiquityIdentityToken by adding the iCloud documents capability.

I was debating doing that but it adds another layer of complexity support wise.


It's possible for the user (via the iCloud tab in Settings) to disable iCloud document storage on a per app basis. If they turn off access for my app, the appearance is the same as if they are not logged in - the ubiquityIdentityToken is then nil. I could provide an alert that says "You must be logged in to iCloud and have the app enabled in Settings etc" - I'll think about this approach.


In the meantime I'm going to handle this as follows:

  • Store the data I need in the iCloud key/value store (KVS) - if the user is logged into iCloud (and from polling my test users, it seems at this will be the typical case) then I'm done and data will automatically get propagated to the user's other devices the moment they run the app. No app receipt refresh etc required.
  • On the first purchase, remind the user that they must be logged into iCloud to access the subscription on their other device(s)
  • On my support web pages for the app, include an FAQ about accessing a current subscription on other devices


For the case where the user has purchased a subscription but on a device not logged into iCloud, once they login, then the data will be synced with the cloud version of the KVS.


I debated adding a receipt refresh if the app runs on a device AND the key for the required data is not present in the KVS. This would be in a situation where the user purchased a NRS on another device that is logged into iTunes (otherwise no purchase) but not into iCloud, then runs the app on a second device. Refreshing the receipt could result in an un-expected dialog for the user to login to iTunes. Something which in the past I suspect would have caused the app review team to reject the app.


Perhaps the best of both solutions (iCloud versus receipt persistence) would be for the big A to add a way of detecting that the KVS has been sync'ed with the cloud - and if not, then refresh the receipt with the persisted records of past NRS purchases?


It's a complex set of cases to handle given the conflicting requirements in the StoreKit documentation.


Hopefully the documentation will get updated, be consistent and then there is a single recipe to follow.

Stu

I actually think that the [[NSUbiquitousKeyValueStore defaultStore] synchronize] call returning YES is a bug and if that were fixed then you can simply detect that it returns NO and alert the user that to copy a subscription they need to log in to their iCloud Account for the app.


That said, there is a security issue you should consider. A user can 'share' their subscription with 100's of people if they create an iCloud Account that is a group iCloud Account - for example, one iCloud Account for all members of the XYZ Corporation. It is unclear to me whether this can actually be done but here's another feature that I do - in my key-value file I record a device identifier for each device that copies one of the subscriptions. For any subscription, when that number gets to 5 I tell the user to contact me to get additional subscriptions. This limit is not unreasonable because 1) over a one month period few people have more than 5 active iOS devices owned by them and 2) Apple limits the number of devices that can synch to iTunes to 5 and 3) I have a back door means of pushing any needed subscription to any person who contacts me. App Review has not objected to my limit of 5, although that doesn't mean they won't.

Why do I have deja vu all over again? I'm in a maze of twisty little passages all alike...


Argh!


Ok, I believe the only way that a corporate account can be created is via the Volume Purchase Program ) see http://www.apple.com/business/vpp/and one of the pages I found in searching (http://www.apple.com/ipad/business/it/deployment.html suggest that each deployed device has to be activated with the users personal Apple ID.


I couldn't find a way to create a shared iCloud account for a business - that's not to say it can't be done, simply that I haven't found it.


Given that the "Find my iPad" function is tied to the iCloud login, I suspect that the problem of sharing an id across a large number of devices is pretty unlikely.


There is no perfect security model as far as I can see. A truly (motivated and unscrupulous) user could **** break their device and then hack my app. Given that my app requires a (not inexpensive) piece of hardware to be operational, I guess that will help limit theivery.


Stu

We do need Apple to include purchase history of non-renewable subscriptions in App Store receipt, to handle the case where user requests App Store for refund. Currently there is no API or StoreKit notifications to allow us to be informed when a purchase is canceled. If I'm not wrong, there is a cancellation field in the App Store receipt. So if you care about purchase cancellation, the only way is to rely on the history of non-renewable subscription purchases embedded inside the receipt.

Rich,

Do you mean that changes has been reverted back and now non-renewing receipts are getting purchase history?

My users started facing this issue since yesterday (Nov 19th 2015). Receipts do not contain purchase history, even in sandbox as well.

I just checked in the sandbox and I got a receipt for all past purchases (many) for a non-renewing subscription after making a single new purchase.

Could you please check this thread Non-renewable in-app purchase in Hybrid app(Ionic)
Non-renew subscription and receipt?
 
 
Q