We started getting error code 21002 from the verifyReceipt endpoint today for any receipt passed to it:
{
"status": 21002
}
I have created a new sandbox tester, and cleared and reinstalled the application before attempting the purchase. I'm seeing this response through RevenueCat's receipt validation tool (https://www.revenuecat.com/app-store-receipt-validation/) and from a direct cURL command:
curl --location --request POST 'https://sandbox.itunes.apple.com/verifyReceipt' \
--header 'content-type: application/json' \
--data-raw '{
"receipt-data":"{RECEIPT_DATA}",
"password":"{SECRET}",
"exclude-old-transactions":"false"
}'
This was working as of yesterday, but seems to be failing for anyone who has tried today. Has anyone else run into issues with this?
Post
Replies
Boosts
Views
Activity
On iOS 15 with Xcode 14.3, Product.priceFormatStyle does not appear to be populated with valid data when running unit tests and setting up an SKTestSession. If I try to access the property in the debugger (po product.priceFormatStyle) it hangs Xcode indefinitely. If I use a print statement, I get the following output.
Currency(locale: xx_XX (fixed), currencyCode: "", collection: Foundation.CurrencyFormatStyleConfiguration.Collection(scale: nil, precision: nil, group: nil, signDisplayStrategy: nil, decimalSeparatorStrategy: nil, rounding: nil, roundingIncrement: nil, presentation: Foundation.CurrencyFormatStyleConfiguration.Presentation(option: Foundation.CurrencyFormatStyleConfiguration.Presentation.Option.standard)))
The same output when running on iOS 16 is:
Currency(locale: en_US@currency=USD (fixed), currencyCode: "USD", collection: Foundation.CurrencyFormatStyleConfiguration.Collection(scale: nil, precision: nil, group: nil, signDisplayStrategy: nil, decimalSeparatorStrategy: nil, rounding: nil, roundingIncrement: nil, presentation: Foundation.CurrencyFormatStyleConfiguration.Presentation(option: Foundation.CurrencyFormatStyleConfiguration.Presentation.Option.standard)))
A simple test to replicate the issue is:
let session: SKTestSession = try! SKTestSession(configurationFileNamed: "Subscriptions")
override func setUpWithError() throws {
session.resetToDefaultState()
session.disableDialogs = true
session.clearTransactions()
session.storefront = "USA"
}
func testPriceFormat() async throws {
guard let product = try await Product.products(for: ["test.product"]).first else {
XCTFail()
return
}
XCTAssertEqual(product.priceFormatStyle.currencyCode, "USD") // Fails on iOS 15 with testPriceFormat(): XCTAssertEqual failed: ("") is not equal to ("USD")
}
It seems to be working fine when run on the live app using App Store data; I get the same output on both iOS 15 and 16.
These outputs are using the same test StoreKit configuration. Is there a trick to getting this working for iOS 15?
After completing a purchase using the StoreKit 2 APIs and receiving a successful and verified Product.PurchaseResult, the local receipt is still empty. Ideally I would not need this anymore, but our server-side implementation currently requires the encoded receipt data so for my current use-case I need to access it still.
My purchase flow looks like so:
let purchaseResult = try await product.purchase(options: purchaseOptions)
switch purchaseResult {
case .success(let verification):
let transaction = try checkVerified(verification)
...
guard let receiptPath = Bundle.main.appStoreReceiptURL?.path else {
throw Error.missingReceipt
}
let receiptData = NSData(contentsOfFile: receiptPath) // Receipt data is nil here
let receiptString = receiptData?.base64EncodedString(options: .endLineWithLineFeed) ?? ""
...
// Handle server logic
...
await transaction.finish()
case ...
...
}
My understanding was receipt data should still be generated when using StoreKit 2 APIs - is there a way to guarantee it is populated after successfully completing a purchase and during transaction handling?