bizz84 / SwiftyStoreKit

Lightweight In App Purchases Swift framework for iOS 8.0+, tvOS 9.0+ and macOS 10.10+ ⛺

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Implement Local Receipt Validation as recommended by Apple

bizz84 opened this issue · comments

As recommended by Apple, local receipt validation can be performed with a number of steps:

To validate the receipt, perform the following tests, in order:

  1. Locate the receipt.
    If no receipt is present, validation fails.

  2. Verify that the receipt is properly signed by Apple.
    If it is not signed by Apple, validation fails.

  3. Verify that the bundle identifier in the receipt matches a hard-coded constant containing the CFBundleIdentifier value you expect in the Info.plist file.
    If they do not match, validation fails.

  4. Verify that the version identifier string in the receipt matches a hard-coded constant containing the CFBundleShortVersionString value you expect in the Info.plist file.
    If they do not match, validation fails.

  5. Compute the hash of the GUID as described in Compute the Hash of the GUID.
    If the result does not match the hash in the receipt, validation fails.

If all of the tests pass, validation passes.

A discussion on how this has been implemented by RMStore is here:
http://stackoverflow.com/questions/19943183/a-complete-solution-to-locally-validate-an-in-app-receipts-and-bundle-receipts-o

Also this series was recently published with some guidelines on how to implement local receipt validation. This links to the SwiftyLocalReceiptValidator project on GitHub, which you can already use independently of SwiftyStoreKit.

Ongoing discussion about how SwiftyStoreKit and SwiftyLocalReceiptValidator may fit together:
andrewcbancroft/SwiftyLocalReceiptValidator#1

commented

Have there been any developments in regards to this issue? I was planning on writing a gist / small library for doing local receipt validation myself. I might contribute if there is still a need for this.

I don't expect to have time to implement this unfortunately.

Recently we have introduced a ReceiptValidator protocol and an AppleReceiptValidator class to implement validation with the Apple server.

@Kymer If you are planning to write this yourself, I would advise to create a new class that conforms to the ReceiptValidator protocol. This way the new code can be used directly in SwiftyStoreKit without changing existing interfaces.

Closed linked issue as duplicate: #75

Hello, is there a way to clear all data associated with the in app purchase on a device? In particular, can we erase the "localReceiptData"? I see this is a read only property.

Yes, can you please make SwiftyStoreKit.localReceiptData swappable?

I'm experiencing issues with testing my receipt when running my macOS from Xcode because it doesn't have a receipt. I have to read Contents/_MASReceipt/receipt from the copy installed from the App Store.

I need the receipt to be able to read original_application_version.

Thanks!

@hanming223 But the author said he has no time to implement local receipt validation.

Hey,
first of all: thank you @bizz84 for maintaining this awesome project! It makes it so much easier to implement StoreKit functionality in any app.
I just found the MerchantKit framework from @benjaminmayo who skipped the OpenSSL implementation by writing a seperate ASN1 parser in Swift. This might be a great starting point, when adding a LocalReceiptValidator ( which implements the ReceiptValidator protocol).
I just wanted to save this thought for later, since I am quite busy in the next few weeks. But I definitely will have a look at it later on. 🙂

Hi,
A while ago I wrote a library to read and verify in app receipt locally. It has been decoding pkcs7 (and asn1 objects) into a sweet swift structure, validating hash and signature using OpenSSL.
A week ago I decided to substitute openssl with own decoder and validator. So far, all functionality, but signature validation work well.

Here is the lib: https://github.com/tikhop/TPInAppReceipt

Personally, I use SwiftyStoreKit for every project where I need to make in app purchase and I use my lib to validate and read receipt. (thank you @bizz84 for simplifying our lives)

If it's really an issue, we can try to combine both projects.

P.

Hi @tikhop, is there a demo available using your TPInAppReceipt lib with SwiftyStoreKit?

@teologov they are kind of independent. That's how I check a subscription:

public static func isSubscribed() -> Bool {
        do {
            let receipt = try InAppReceipt.localReceipt()
            if let _ = receipt.activeAutoRenewableSubscriptionPurchases(ofProductIdentifier: subscriptionProductID, forDate: Date()){
                return true
            }
        } catch {
            print(error)
        }
        return false
    }

What's missing here is the logic to load from the Apple server if expired.

@nuthinking I tried to conform to ReceiptValidator protocol first, but it's not that convenient. So I just did the same way as you proposed. Thanks!

@bizz84 it is not enhancement. It is a bug