Different Hash In App Store Receipt

I'm trying to create a Mac application, and be gentle on me as this is my first attempt! Essentially transferring what I've done on iOS to the Mac and it's almost ready to go with one part remaining - App Store verification to prevent people from being able to copy it.


I have receipt verification code running in a couple of my iOS apps and they work find for me (for in-app purchase). With the Mac I simply want to verify the receipt and hope that's enough. Here is the basis of the code I have created:


char buf[512] = "";
get_platform_uuid(buf, sizeof(buf));

NSString *uuidString = [NSString stringWithUTF8String:buf];
NSUUID *myUUID = [[NSUUID UUID] initWithUUIDString:uuidString];

unsigned char uuidBytes[16];
[myUUID getUUIDBytes:uuidBytes];

NSMutableData *input = [NSMutableData data];
[input appendBytes:uuidBytes length:16];
[input appendData:[receipt objectForKey:kReceiptOpaqueValue]];
[input appendData:[receipt objectForKey:kReceiptBundleIdentifierData]];

NSMutableData *hash = [NSMutableData dataWithLength:SHA_DIGEST_LENGTH];
SHA1([input bytes], [input length], [hash mutableBytes]);

NSLog(@"kReceiptHash: %@", [receipt objectForKey:kReceiptHash]);
NSLog(@"hash: %@", hash);


The last two NSLog commands are just so that I can log this during debug, but the hash values would be compared. This is where I know the two are incorrect. "get_platform_uuid" is a function I've found for getting the UUID for the Mac and it seems to work fine.


I've taken the entire "input" variable and plugged the information from it and ran it on iOS, and I've done the same from the iOS device and run it on the Mac. In both cases the calculated Hash is the same; I think the calculation is fine. When I do the iOS the calculated hash for its own app matches that in the receipt as you'd expect.


But on the Mac, even though the calculated hash seems correct (as verifed putting it in to iOS) the receipt hash is different. The iOS calculation and receipt hash matches for that app perfectly. It seems that on iOS the code is working fine, so I assume that it is therefore working on the Mac too. There must be another problem that I can't detect.


I've set up the App on App Store Connect, it seems to pick up the right bundle identifier. Following the instructions on how to test receipts on the Mac I have logged out of the App Store on the Mac App Store application. I copy the App out from where Xcode builds the app to a different directory to run it. It then asks me to log in, which I do with a test account. Then repeatedly tries to rerun the app and exits (I copy it back to the debug folder and this breaks that rerunning cycle).


I've got the certificates set up for development and distribution for Mac set up in the Apple Developer site but I'm sure it's something that I've not got right with App permissions or how I'm running the app. But what I just can't figure out (and I have looked - for a long time!).


Most recently I've reregistered on App Store Connect and I run it from the Debug directory where it has been built. This runs fine, it prompts for a user and password where I put in my sandbox test ID, and then it tells me to down load again. I can then run through on XCode with breakpoints to pick up where the NSLogs are and get information out. This where I can see that the calculated hash is different from the one being produced by the receipt.


I think I'm doing everything right but I'm sure it's something silly, but as a lone developer my only hope is to ask you what am I doing wrong? I've really spent way too long chasing my tail on this one that I really don't know where to look next.


Is there a way that I can check that I've got the permissions set correctly for my account and app to ensure that the receipts are being correctly generated?


Thanks.

Accepted Reply

Found another method to do the building, creation and comparison of the hash that seems to work. Although it's strange that the original code works ok on the iOS devices but not on the Mac. I'm not a good enough programmer to delve deep in to why.


The other code needs modification as it doesn't work fully on the Mac, so I've got a hybrid between the two now. Bit messy, but working.

Replies

Found another method to do the building, creation and comparison of the hash that seems to work. Although it's strange that the original code works ok on the iOS devices but not on the Mac. I'm not a good enough programmer to delve deep in to why.


The other code needs modification as it doesn't work fully on the Mac, so I've got a hybrid between the two now. Bit messy, but working.

I'm glad you got it to work. Your original post made reference to a "receipt" which, in your case, responds to 'objectForKey'. That means you left out lots of your code that decodes the receipt binary file and turns it into a dictionary-like object so you can extract various values from it. Perhaps that code was wrong or perhaps your get_platform_uuid was wrong.