Receipt Validation Swift

Finalizing Receipt Validation in Swift – Computing a GUID Hash

The purpose of this information is that will help you finalize the receipt validation course of by computing the GUID hash on your app, and evaluating it to the hash that’s stored inside your receipt itself.

This is a continuation of my receipt validation collection. I’m assuming that…

After finishing this information, you’ll merely need to make use of the parsed receipt knowledge to perform any app-specific enabling/disabling of features based mostly on the info within a legitimate receipt. If the receipt is invalid, you’ll have to deal with that as nicely. But all the comparatively troublesome work of working with the Open SSL crypto library shall be DONE after this information.

Just want the code? Right here you go!

Ready? Let’s do this thing!

For this last step, I’ve imagined a single further perform inside the ReceiptValidator struct referred to as validateHash(receipt:).

It’ll take in a ParsedReceipt (assessment what it appears like), and will to the computation and comparability necessary to verify that the computed hash matches the hash stored in the receipt.

A ReceiptValidationError can be thrown if things go mistaken within this perform. No ReceiptValidationError being thrown signifies a profitable hash computation and comparison.

Right here’s the skeleton of the perform:

Before I get into the implementation of the validateHash(receipt:) perform, let’s define another ReceiptValidationError case to explain a dangerous hash comparability end result:

I’ll put the code in entrance of you, and then do my greatest to elucidate my thought course of.

Walking via validateHash

First up, I’ve positioned three guard statements:

These assist guarantee that the rest of the perform may have all the required items of knowledge that it needs to completely compute a hash and examine it with what’s in the receipt.

The hash on your app is computed with the following three items of data:
1) The app purchaser’s gadget identifier
2) A bit of “opaque data” found inside the receipt
3) Your app’s bundle identifier found inside the receipt

The app purchaser’s gadget identifier is represented as a uuid_t from the Basis library. Nevertheless, to make use of it with the Open SSL library, we’ll must be working with an NSData instance. The next code goes from the uuid_t occasion, to a uncooked pointer, to an NSData occasion:

The final chunk of code inside the perform truly computes the hash knowledge.

The hash is a SHA1 hash, so what we do right here is initialize a SHA1 context, after which update it with all the elements (system identifier, opaque knowledge, and bundle identifier). The hash is finalized, and transformed to an instance of NSData.

The final guard takes the computedHashData occasion, and compares it to the receipt’s hash knowledge. If it’s equivalent, validation passes! In any other case, ReceiptValidationError.incorrectHash is thrown.

Let’s put it all together into the final ReceiptValidator struct. Additions are highlighted under:

So what now?

Nicely, at this stage, if no errors have been thrown, you’ve obtained a valid receipt.

The validateReceipt perform returns an occasion of ParsedReceipt so as to inspect individual Swift-Typed values from the receipt payload to determine what options you must enable or disable, relying on what your wants are.

If a ReceiptValidationError is thrown at any level along the best way, you’ll have to handle them.
Listed here are a few concepts:

  • Implement a grace period, simply in case the receipt validation failure occurred for a cause that the consumer can’t control (e.g. perhaps we couldn’t locate the receipt, and requesting a new one failed as a result of Apple was having points…)
  • Disable a function in your app as a result of receipt validation failed too many occasions
  • Perhaps you just want to use the info inside the ParsedReceipt because you’re altering the best way you monetize your app. Now, as an alternative of creating customers pay $zero.99 for the app, you’re going to offer it away totally free, but let individuals purchase an in-app buy to allow “pro” options, or take away advertisements…no matter. In this case, you could examine the ParsedReceipt to see the unique version of the app that your consumer downloaded. Perhaps you need to require users who download your app after model 2.0 to buy an in-app buy for [Feature X], but you need to give it to everyone who already has the app since they could have already paid $0.99 for it, and it’d make them feel ripped off if that they had to purchase the in-app buy.

How you handle the parsed receipt knowledge or a receipt validation error is absolutely customizable and specific to your specific app.

The underside line is that from this level on, you not want Open SSL or any further cryptic, low-level, unsafe pointer-type stuff to finish things out.

I hope this collection has been useful in setting you as much as validate receipts regionally on a consumer’s gadget!