habs93 habs93 - 5 months ago 300
iOS Question

IAP receipt validation for iOS

I am working on a client / server application which uses Apples IAP and storeKit framework to purchase a subscription.

What we would like is for the client (iPhone or iPad) to make the initial subscription purchase with apple through their iTunes account using StoreKit framework and then pass of the receipt to our server, which will validate it and then update the users account status. We'd also like the server to be responsible for managing the status of the subscription (check for auto-renew, cancellation etc..) This is all using iOS7 style appleReceipts, rather than iOS6 style transaction receipts which are deprecated currently.

Apples docs say to POST to the following URL to validate a receipt in the sandbox along with the receipt and the secret code

https://sandbox.itunes.apple.com/verifyReceipt

Up to this point .. everything works as it should.

Where things get confusing to me is in the response. Apple's docs say that the response should have upto 4 fields. If you are validating an iOS7 style app receipts then you should only expect the first 2. If its an iOS6 style subscription transaction receipt then you should expect to see all 4.

1) status (0 for valid, some error code otherwise)

2) receipt (a json representation of the receipt that was sent)

3) latest_receipt (Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions. The base-64 encoded transaction receipt for the most recent renewal.)

4) lastest_receipt_info (same as above in JSON format)

Problem 1:
I am seeing all 4 even though I am validating an iOS7 style app receipt. The docs say that shouldn't be happening.

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

Problem 2:
We'd like to have the server handle maintaining the user subscription status by polling this API with the original app receipt that the client passed after its initial purchase. The "latest_receipt_info" field does seem to contain a continually updated list of transactions, while the "receipt" field is a copy of the original with no updated transaction information.

My Question:
It seems then that the only way the server can get information about updated transaction is by looking at the "latest_receipt_info" or "latest_receipt" fields, but those fields are not supposed to be present in the response according to the documentation.

Is this an error in the Apple documentation? Or is the only way to get the latest set of transaction is to have the client send updated AppReceipts when it gets notified by the SKPayementTransactionObserver?

EDIT -- adding steps taken and some code as per comment below.



1) Making a purchase of a autoRenewSubscription product using SKPaymentQueue:

SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.applicationUsername = [self hashedValueForAccountName:[UserAccount sharedInstance].subscriberKey];
[[SKPaymentQueue defaultQueue] addPayment:payment];


2) When the payment is completed I get a call back through my SKPaymentTransactionObserver and send the file at the following URL:

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];


to my remote server.

3) I'm using the following python code to validate the receipt

import itunesiap
import base64

file = "/path/to/receipt/sandboxReceipt"
f = open(file)
encoded = base64.b64encode(f.read())

with itunesiap.env.current().clone(use_sandbox=True): # additional change for current environment.
response = itunesiap.verify(encoded,"mysecretkey")


The response contains a dictionary.
The dictionary has the following fields

"latest_receipt" = base64 encoded receipt here
"latest_receipt_info" = a JSON representation of the latest receipt
"receipt" = a JSON representation fo the receipt I sent for verification


The Docs say that the first 2 fields are


"Only returned for iOS 6 style transaction receipts for auto-renewable
subscriptions."



  1. Why are they showing up here, since I was validating an iOS7 style
    app receipt?

  2. If these fields aren't supposed to be present, how do I
    get the latest transaction information?


Answer

The wording in Apple's docs is ambiguous. Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions. This means the field is always present for iOS 7 receipts using appStoreReceiptURL but only present for deprecated transaction style receipts that are for an auto-renewing subscription. i.e. they do not show up on iOS 6 transaction receipts if the purchase isn't a subscription.

Comments