Validating Mac App Store purchase with StoreKit

For years I've been using Receigen for receipt verification for the Mac App Store build of my application. However, with the deprecation of exit code 173, I am moving to StoreKit-based verification and have a couple of questions.

I have followed the instructions from https://developer.apple.com/documentation/storekit/apptransaction/shared and have something like this (simplified):

Swift:

@objc class ValidateReceipt: NSObject {
	@objc func validate() async -> Bool {
		do {
			let verificationResult = try await AppTransaction.shared
			
			switch verificationResult {
				case .verified(_ /*let appTransaction*/):
					// StoreKit verified that the user purchased this app and
					// the properties in the AppTransaction instance
					return true;
					
				default:
					// The app transaction didn't pass StoreKit's verification
					return false;
			}
		}
		catch {
			// Handle errors
			return false;
		}
	}
}

Objective-C:

		ValidateReceipt *validateReceipt = [[ValidateReceipt alloc] init];
		[validateReceipt validateWithCompletionHandler:^(BOOL result) {
			if (result)
			{
				// Successful app purchase validation
			}
			else
			{
				// App purchase validation failure
			}
		}];

Thing is, I always get a valid result, i.e., in ValidReceipt.validate(), the case .verified block always runs. Even when exporting a new release build of my app and running it (without any _MASReceipt).

When using exit code 173, an .app without a _MASReceipt would prompt for app store login. Nothing of the sort happens now.

Am I misunderstanding the documentation / doing something wrong / missing something obvious?

I'm in the same boat, but a couple of days behind you.

From what I understand, you don't get a receipt during development anymore. See this post.

I've seen many posts about problems with StoreKit2. Most people seem to just switch to StoreKit1. However, it can be difficult to learn anything from the internet anymore. I should know more in a few days.

I should emphasize that all I really want to do is verify that the MAS-downloaded application is running as a valid purchase.

I tried Quinn's example app from https://developer.apple.com/forums/thread/764537?page=2 (which, as it turns out, is pretty much exactly what I did).

In that case, with the simple example app, I get an error response:

Received error that does not have a corresponding StoreKit Error: Error Domain=AMSErrorDomain Code=301 "Invalid Status Code The response has an invalid status code" UserInfo={AMSFailureReason=The response has an invalid status code, AMSURL=https://mzstorekit-sb.itunes.apple.com/inApps/v1/receipts/createAppReceipt?REDACTED, AMSStatusCode=500, AMSServerPayload={ errorCode = 500318; }, AMSDescription=Invalid Status Code, NSDebugDescription=Invalid Status Code The response has an invalid status code}

which I'm going to assume has to do with the fact that there is no matching app/configuration on the App Store? Maybe? (Guessing, because there's no documentation on that, either.)

So I can produce an error with the example code, or (always) a success/purchased result in my own app, but so far I've been unable to produce a not-purchased/validated result, which is kind of the whole thing I want to check for.

[@K T](https://developer.apple.com/forums/profile/K T)

Thing is, I always get a valid result, i.e., in ValidReceipt.validate(), the case .verified block always runs....without a _MASReceipt

Using StoreKit 2 takes you away from the receipt concept as you found out. You now look at the app transaction information to determine which features to unlock in your app.

If you want to check your app's integrity, see Establishing your app’s integrity.

I'm not sure that's what I'm looking for. I don't necessarily need to know that a given copy of the application hasn't somehow been fiddled with. That may be beyond the scope of what I'm trying to do.

What I want to know is if User B is running a copy of Mac App Store purchased software that User A purchased legitimately and threw up on an FTP server or something for them to download.

As it is, the part of the Apple sample code, above, that says "StoreKit verified that the user purchased this app" doesn't seem to be doing that.

Or, maybe, to clarify: what is it that AppTransaction.shared is actually verifying?

Is it that the current Apple ID has a purchase for com.whatever.software on file in the Mac App Store? (Because that's really all I'm looking for.)

See, I've tried changing users, logging out of the App Store, logging in to the App Store with a different user — and I always get the .verified result. So it seems like it's allowing exactly the thing I'm trying to check for (and which the Apple example code seems to be saying it's checking for).

Also, is there any explanation as to what the error code in my implementation of Quinn's example means, above? I don't get that with my application, only when testing the example. Is it related to (not) having a record with that application with that signature on the App Store? I need to figure out how/if I'm going to handle it.

Validating Mac App Store purchase with StoreKit
 
 
Q