10

I'm trying to verify receipts with Xcode 12 and a StoreKit config file, but keep getting a 21002 error. According to the docs, I need to use a different cert. I generated the cert but it's not clear what to do with it?

#if DEBUG
        let certificate = “StoreKitTestCertificate” 
#else
        let certificate = “AppleIncRootCertificate” 
#endif

That's great, but what uses certificate?

John Scalo
  • 3,194
  • 1
  • 27
  • 35

2 Answers2

2

The following code has been adapted from the Ray Wenderlich tutorial on Receipt Validation:

Note; You'll need to first statically link OpenSSL into your project, after that follow the tutorial in its entirety. This is only to show the context of where Apple's code sample is used.

  private func validateSigning(_ receipt: UnsafeMutablePointer<PKCS7>?) -> Bool {
    #if DEBUG
    let certificateName = "StoreKitTestCertificate"
    #else
    let certificateName = "AppleIncRootCertificate"
    #endif
    
    guard let rootCertURL = Bundle.main.url(forResource: certificateName, withExtension: "cer"),
          let rootCertData = try? Data(contentsOf: rootCertURL) else {
      receiptStatus = .invalidAppleRootCertificate
      return false
    }
    let rootCertBio = BIO_new(BIO_s_mem())
    let rootCertBytes: [UInt8] = .init(rootCertData)
    BIO_write(rootCertBio, rootCertBytes, Int32(rootCertData.count))
    let rootCertX509 = d2i_X509_bio(rootCertBio, nil)
    BIO_free(rootCertBio)
    let store = X509_STORE_new()
    X509_STORE_add_cert(store, rootCertX509)
    
    OPENSSL_init_crypto(UInt64(OPENSSL_INIT_ADD_ALL_DIGESTS), nil)
    
    #if DEBUG
    let verificationResult = PKCS7_verify(receipt, nil, store, nil, nil, PKCS7_NOCHAIN)
    #else
    let verificationResult = PKCS7_verify(receipt, nil, store, nil, nil, nil)
    #endif
    
    guard verificationResult == 1 else {
      receiptStatus = .failedAppleSignature
      return false
    }
    return true
  }
Joey Slomowitz
  • 179
  • 1
  • 12
1

You need to specify StoreKitTestCertificate.crt for local receipt validation via OpenSSL. You can't verify xcode-generated receipts via Apple's /verifyReceipt endpoint.

andron
  • 307
  • 1
  • 11
  • Hello, a team of us are currently trying to implement apple pay for our ios app. We are successfully able to generate receipt from xcode using sandbox environment, but we are not able to verify the receipt using /verifyReceipt endpoint (using Ruby on rails BE). Is it due to same issue? Also, FE is implemented using react-native and we have no idea of swift programming language. How to specify storekit certificate in this case? – Debanjan Dey Apr 20 '23 at 09:37
  • @andron the problem is "verify xcode-generated receipts via Apple's /verifyReceipt endpoint" doesn't work – Gargo Aug 24 '23 at 09:19