Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Online receipt validation for Mac App Store In-App Purchases

For in-app purchases for iOS we can use an online API for validation, meaning that we can validate the purchase on our own server.

Is there any way (API) for such validation of in app purchases for OS X?

I've found only this snippet about in-app validation for Mac and it seems that Apple doesn't provide any API for online validation.

Or maybe there is some plan from Apple to support online validation for OS X?

like image 902
Distdev Avatar asked Sep 29 '11 13:09

Distdev


People also ask

How do I get a receipt for App Store purchase on Mac?

Go to ReportaProblem.apple.com from your favorite browser on your MAC or Windows PC. Login using your registered Apple email ID and password. In the scroll down list find the order you want a receipt for. Select the order you want the receipt and then click on “View Invoice”.

Does Apple send receipts for in-app purchases?

Apple is the only one who can provide a receipt for any purchases made in-app. Apple emails receipts to customers for all purchases, so a receipt for your ForeFlight purchase may be sitting in your email inbox or junk/spam folder.

How do I verify In-app purchases Apple?

Use the production URL https://buy.itunes.apple.com/verifyReceipt when your app is live in the App Store. For more information on these endpoints, see verifyReceipt. Verify your receipt first with the production URL; then verify with the sandbox URL if you receive a 21007 status code.


1 Answers

My app EasyBooks provides an online component that users pay yearly for. It wouldn't make sense to provide this as a non-consumable type as it only really works as a consumable (however it's really a non-repeating subscription in iOS). I would like to offer this in-app and I think I have a solution finally...

I used one of my Apple DTS tickets to query a statement made in the StoreKitGuide document. It says ...

"OS X supports both the server validation method described in this chapter and the local validation method..."

I got a reply from Apple saying ...

"The steps for verifying your In-App Purchase products for Mac applications are the same used for iOS applications. The difference is that you will be assigning your base 64 encoded app receipt (rather than the content of the transactionReceipt property) to the receipt-data field. Retrieve the full Mac App Store receipt for your application, then encode it using base64 encoding. Create a JSON object with a single key named receipt-data and assign your encoded receipt to it. Proceed as outlined in the Verifying a Receipt with the App Store section of the In-App Purchase Programming Guide.

Note: In App Purchases receipt are included in the associated Mac app's receipt. You must check the receipt associated with your app to verify the validity of the In-App Purchase receipts that it contains. Doing so also allows you to enable the appropriate functionality in your app."

So after some failed attempts, I did manage to get this working with the caveat that the receipt data returned by Apple's servers does not contain the 'hash of the GUID' and therefore does not tie the receipt data to any particular hardware.

This can be tested on your Mac quite easily using these steps:

  1. Find the Mac app receipt file (it's in your app's bundle once you've run the app and entered your (test) Apple ID and password.

  2. At the command line, base64 -i receipt will base64 encode the receipt with no line breaks (that's important)

  3. Again at the command line, curl -d '{ "receipt-data": "<your b64 string here>" }' https://sandbox.itunes.apple.com/verifyReceipt

This returns JSON data in the format

{"status":0, 
 "environment":"Sandbox", 
 "receipt":{"adam_id":"0", 
            "bundle_id":"uk.co.geode.easybooks", 
            "application_version":"2.2.7", 
            "download_id":"0", 
            "in_app":[ {"quantity":"1", 
                        "product_id":"uk.co.geode.easybooks.syncing",
                        "transaction_id":"1000000034508678",
                        "purchase_date":"2012-09-05 12:00:17 Etc/GMT",
                        "original_transaction_id":"1000000034508678",
                        "original_purchase_date":"2012-01-24 10:16:17 Etc/GMT"} ]}}

I have not confirmed it yet, but apparently (according to the Apple engineer) any consumable types of in-app purchase will be added to the receipt when first purchased, but removed after any further purchases or restore operations. I wonder whether it might be a good idea to make the code running in the app make a copy of the receipt file after each purchase just in case our own servers are down at the time the app tries to validate the receipt. Users may otherwise try to restore purchases, not realising this will remove any consumable product receipts.

I hope that helps.

(ORIGINAL COMMENTS FOLLOW)

I have the same issue. I have an iOS app in the store that has a mix of consumable and non-consumable products that can be purchased in-app. The consumable product is a service, which is fulfilled by my webserver. In the StoreKit delegate method paymentQueue:updatedTransactions:, I use the transactionReceipt property, which is an NSData object. I encode this to base64 and send it to the server. Out on the server I pass the receipt to Apple's servers for validation.

But for Mac OS, there is no transactionReceipt property on the SKPaymentTransaction, so we cannot validate receipts in the same way.

We can do the non-consumable products, which may help you. When an in-app purchase is made on Mac OS, the receipt is updated in the app bundle. It is then possible to parse the receipt file looking for each in-app receipt, which are all stored in the receipt file in the main bundle. For more about that see http://developer.apple.com/library/mac/#releasenotes/General/ValidateAppStoreReceipt/_index.html

This works fine for me when I use the non-consumable product, but I have one consumable and this is not updated into the app's receipt file. Without the transactionReceipt property, I don't see any way for my server to validate that the receipt is genuine. If anyone else has any other experience please let us know!

Anyone with an Apple developer account can also read about this on the Apple developer forum: https://devforums.apple.com/message/548411#548411

like image 151
Mathew Waters Avatar answered Nov 15 '22 10:11

Mathew Waters