To be clear on my question, I am in the process of implementing a iOS IAP receipt validation (consumables) and I was not expecting more then just the item(s) the user 'currently' purchased in the 'current' transaction.
So lets say the user purchases one (1) $0.99USD item that gets them 100 coins I am expecting to see in the receipt using my validation code the one (1) transation detailing the one (1) product they purchased not an array of items from previous purchases which I found out that:
With iOS 7, Apple started using something they call the “Grand Unified Receipt”. Apps retain one receipt that contains information about the purchase of the app itself, as well as IAPs.
So my question is if anyone else has an issue with the receipt format and how have everyone been validating the purchases for consumables when the entire user purchase history is always present?
Related
My problem is, the users cannot get the non-consumable item by redeeming the code.
I can confirm the non-consumable items can be bought correctly.
I used the app receipt to check whether the user owns it. I'll find through all the products to see if there's one the product id is matching.
I cannot find any useful docs to debug the redeeming process. I don't even know if there should be a callback when the app starts. Like the transactions are not completed.
How is redeeming handled behind the scene?
If the app is open after I redeemed a code, how should the app know the user 'bought' the item? How should I know when to send them the contents?
If the users try to buy the item they redeemed, they are told they can get it for free, and I see the purchase succeed callback. But then I check app receipt, the product still not exists. I got these logs from the users.
By the way I'm using in_app_purchase plugin from Flutter. And for checking the app receipt I'm using https://github.com/robotmedia/RMStore.
Products redeemed with a promo code will appear on the receipt just as a purchased product would - you won't be able to differentiate from the receipt a purchase vs promo code.
There isn't a callback on the device for promos specifically, if you refresh the receipt or the user restores transactions you should see the product in the receipt.
I read so far online that the only way to detect if a user cancelled an in app purchase is by using the receipt data that I get from the user's iPhone and check if the cancellation_date exists in there for that item, but as far as I know, this field is only to be found on auto-renewable subscription items.
(At least to what I read online on every post I found that talks about in app purchase, no mention to consumables at all.)
Because they are always stored in the receipt data, while consumable items, are stored in the receipt data until the app itself finishes the transaction, once thats done, the purchase transaction for that item is gone forever from the receipt data after the finish process on the iPhone.
So my question is, if a user requested to cancel an in app purchase from Apple, which is a consumable item, do I also get back that same item transaction in the receipt data WITH the cancellation_date field in it?
I've never seen anyone confirm this.
It would be nice if someone can provide a receipt-data base64 string with cancellation_date example in it (if that's legal to do tho).
https://developer.apple.com/documentation/storekit/in-app_purchase/handling_refund_notifications
Apple has provided a solution finally in 2020!!
A year ago I had the same question as you and I have found this thread where author said that Apple has not added a way to detect canceled purchases. I'm still living with that as it is.
The best way to know it is contacting Apple technical support, each account has 2 request/year, so I recommend you to write there.
Hope you will find the answer and tell us about the result.
I'm trying to add purchases to my application. But I don't know how to check if purchase is already bought. As far as I understand when somebody bought purchase I need to store this into UserDefaults or KeyChain and then check if it is already there (it mean that this purchase is already bought). But what about when user bought this purchase prom another device?
I have code that give me information about all purchases in iTunes.
func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) {
}
Response object have two variables: "products" and "invalidProductIdentifiers". But as I understand products contain all products from iTunes and invalidProductIdentifiers contain all identifiers that I was asking to check for but Apple can't recognise them. So where I can check if purchase was already bought or not.
Assuming iOS 7+, you should be validating the receipt, ala A complete solution to LOCALLY validate an in-app receipts and bundle receipts on iOS 7 to determine what's purchased, what's valid (in the case of subscriptions or consumables), and as noted in the other comment, offer a "Restore Purchases" UI element which allows users to cleanly propagate sharable purchases to a newly restored/acquired device.
AFA the response object, that is catalog (purchasable items) information, not info on what has been purchased. In order to have IAP work correctly, assets are to be approved by Apple similarly to the app itself as well as being under "ready for sale" control of your own in iTunes Connect. For that pass, you send Apple a complete list of the times you want to offer and Apple returns to you the list split into the "if your user tries to buy this, they will succeed" (the products) and "if your user tries to buy this, they will fail" (the invalidProductIdentifiers).
When you're testing with sandbox/iTunes Connect Test users, your products do not need to be approved by Apple, but for production code they do.
I've set up a non-consumable in app purchase for may app, it all works well except i haven't yet decided on the correct RestoreTransaction procedure.
Apple suggest storing a list of completed transactions in NSUserDefaults, but why?
If the customer resets the device then surely this list is lost so its a non starter?
Can anyone tell me from their experience, if I do need to list completed items and if I need to validate the receipt with apple for non-consumable purchase.
I can't see why either of these should be done for non-consumable products.
Doesn't Apple verify the purchase from OriginalTransaction when restoreCompletedTransactions is called?
I have an iPhone app with an in-app purchase and I want to be able to release the app independently from it (the in-app purchase). In other words, there could be times where the in-app purchase is "waiting for review" state and shouldn't be displayed by the app.
If I understand correctly, in this situation, the SKProductsResponse object (returned by the Apple App Store in response to a request for information about a list of products) will have the particular product listed under the invalidProductIdentifiers array. Thus, before displaying the in-app purchase, I could inspect the array to check for the existence of the product. This should still allow Apple to test the in-app purchase with the released version of my app since I assume their testing is done in a sandbox where all the in-app purchases are valid.
Is this correct? Should I follow a different approach?
You describe the proper workflow for displaying IAP content to the user. Put up a modal dialog or a UIActivityIndicator telling the customer that IAP content is being downloaded. Use the productIdentifiers that are returned to populate your store gui.
I discourage you from hard coding in a specific view for a specific in app purchase, and then attempting to populate that view. You can do that if you're smart about it and check for valid content ahead of time, but checking after the customer is already expecting to see something can end with both Apple review and your customer thinking your app is broken.
The least pretty implementation would be a tableView displaying the returned productIdentifiers and their respective prices, allowing the customer to pick from a familiar list.