AppStore error: 707 - Receipt hash failed

Thanks Rick. You’re right. I’ll do that.

1 Like

My apologies for hijacking this thread. This is a major shift in logic because requesting the receipt is asynchronous so receipt verification can no longer just return a boolean. The open event needs to hand off to the verifier and then exit instead of handling a result. On success, the verifier needs to call some method in the app to continue instead of returning a boolean. On failure, it needs to quit. So I’ve implemented the asynchronous receipt request as follows:

  • MAS_VerifyReceipt - looks for the receipt in the bundle, if it doesn’t find it, uses StoreKit to find it using a URL path, if that fails, launches a request which proceeds asynchronously, unless that request has already been launched, in which case it gives up and quits (since there is no longer an exit(173)???).

  • MAS_ReceiptRequester - sends a request to get the receipt. A request may fail, in which case it cancels and tries again, up to a given limit. On any success or after multiple failure, it passes the result back to the verifier.

In terms of the logical flow this is doing what it’s supposed to do, but it doesn’t work. The receipt file isn’t found, then the requester fails with an error code 0 = unknown error (?), and the app quits. I’m waiting for advice from Apple.

Can you post your code?

I’ll be glad to share once I know it works correctly.

Here’s the verifying method so you can see the logic anyway. It’s called in the App.Open event, the app’s bundle ID is passed. The MAS_ReceiptRequester object is a bit too much to post here, it will be a download.

Public Sub MAS_VerifyReceipt(bundleID as string)
  // get the MAS receipt from the app bundle
  dim r as AppReceiptMBS = AppReceiptMBS.bundleReceipt
  
  // if it wasn't found, try using StoreKit to find it
  if r = Nil then
    Dim URLPath As String = StoreKitMBS.appStoreReceiptURL
    If URLPath.Len > 0 Then
      Dim theReceiptFile As New FolderItem( URLPath, FolderItem.PathModes.URL )
      If theReceiptFile <> Nil and theReceiptFile.Exists then
        r = AppReceiptMBS.receiptForFile( theReceiptFile )
      End If
    End If
  end if
  
  // if it's still not there, request it asynchronously from Apple
  ' NOTE: this method (MAS_VerifyReceipt) will get called again 
  ' from the requester regardless of the outcome.
  if r = Nil and MAS_ReceiptRequest = Nil then
    MAS_ReceiptRequest = New MAS_ReceiptRequester( bundleID, 3, true )
    exit
  end if
  
  if r <> Nil then
    // we have a receipt, so verify it
    r.setAppleRootCertificate AppleIncRootCertificate
    dim a as new AppReceiptVerificatorMBS
    a.bundleIdentifier = bundleID
    if a.verifyReceipt( r ) then
      // use a timer to return from the App.Open event as quickly as possible
      Xojo.Core.Timer.CallLater( 1, AddressOf App.SetupApp )
    else
      msgbox "MAS Receipt verification failed: " + a.FailReason
      quit
    end if
  else
    // file not found
    dim m as string = "The MAS Receipt could not be verified because the file was not found."
    if MAS_ReceiptRequest <> Nil then
      m = m + " Requesting the receipt using the appropriate API also failed."
    end if
    msgbox m
    quit
  end if
End Sub

In this line …

MAS_ReceiptRequest = New MAS_ReceiptRequester( bundleID, 3, true )

… 3 = try three times to request the receipt, true = show error messages, bundleID gets passed so it can be passed back to this method on success or after all attempts have failed.

I should have looked this up earlier, but all this can’t be right, because SKReceiptRefreshRequest is deprecated:

The absence of Exit(173) in a beta version of macOS sounds like a bug to me. I’ll report back if Apple supplies any useful information.

" Receipts are deprecated …"

I think that the non-deprecated/non-broken way of doing things should be pursued reading from here on:

ObjC version:

That all seems to be about In-App Purchases …

It seems Apple has changed the way receipts work in general. They say a receipt will not exist unless the user has made at least one in-app purchase. I don’t see how that makes any sense at all.

I’ve submitted a version of my app which displays error messages during each step of the receipt validation:

  • receipt not found via URL (that remains Apple’s recommended way to get the receipt)
  • receipt requested using StoreKit API and not delivered (deprecated, but Apple is still pointing developers to it)
  • validation can’t take place because the receipt doesn’t exist
  • launch the app anyway to show them I’ve done nothing wrong

This will work and the app doesn’t give the “damaged” message, but it can’t be right. The user will be prompted to login every time the app opens, they can dismiss that and the app will open. And this could be done on any computer because there is no receipt. No way that can be right.

All the verbiage about In-App Purchases doesn’t appear to apply to verifying the purchase of the app. As the name says, it’s about purchases made from within the app.

The “All StoreKit” options to navigate are here:

App Transaction

Thank you. I saw that too, but I think that is the low level part already implemented in the MBS plugin. I could be wrong about that – maybe Christian Schmitz will tell us …

Otherwise, as I look at it again, it’s about the transaction information, which may be useful for determining certain things about in-app purchases, but it doesn’t appear to be about receipt verifiaction, the comparatively simple step to do when launching the app (or what used to be “simple”, or what seems like it should be “simple”).

Why Apple has to make all this so incredibly unclear is anyone’s guess.

The understanding of what I’ve read is “receipts are dead, those new APIs cover your needs”.

That may be true going forward, but it’s not clear …

My app just got approved using the method I described above. This, after 7 attempts (meaning seven times sending Apple my app to test, getting rejected, sending again). Until the last two versions, the problem was that the receipt was not there at all. Why that was the case remains a mystery. My guess is that it was a technical failure on Apple’s side, but who knows … I kept tweaking the verification code, and finally got it to work. The last problem was that the bundle version of the app did not agree with that of the receipt, but that only happened because I had to upload the app to Apple more than once (they require changing the bundle version each time, though the displayed bundle version string doesn’t need to match).

Anyway, it works, and I’ve exported everything needed as a Xojo project. Anyone can download it here:

MAS_Receipt_Verification_2024.zip

The main difference between this and any other code for receipt validation that you may find through the forum is that this method is asynchronous. It also does not use hard-coded paths, it uses the StoreKit URL path, which is the correct way to do it according to Apple.

A caveat: when you try to test your installer after building and codesigning, it will fail. Apparently it only works when Apple uses it. I don’t know why this is. Transporter reports that a Test Flight Provisioning Profile is missing. Apparently that is the “right way” to test your apps now. But it does not appear to be necessary (yet).

If you have any comments or improvements, please let me know.

I’ll also post this in a new thread, since I unintentionally hijacked this one (sorry).

1 Like