Same Receipt Payload for Consecutive Same-SKU Purchases in iOS (Unity IAP 5.0.0-pre.7)

Testing Environment

  • Unity IAP 5.0.0-pre.7
  • iOS build (Sandbox purchase testing)

Hi everyone,

During sandbox testing on iOS we noticed that the receipt data coming from Unity IAP is not behaving as expected.

The JSON strings shown in #1 and #2 below are the raw values we logged from pendingOrder.Info.Receipt after two consecutive sandbox purchases of the same SKU.
In our project we pass this value to our backend for receipt validation.

Issue
When the same SKU is purchased twice in a row, the second purchase’s pendingOrder.Info.Receipt contains a different TransactionID (as expected) but the Payload field is identical to that of the first purchase.
Because the payload is unchanged, our server-side receipt validation fails on the second purchase.

Is there any way to refresh or retrieve an updated pendingOrder.Info.Receipt for the second purchase?

#1
{"Payload":"MIIUUwYJKo...SE9SkwOJi8=","Store":"AppleAppStore","TransactionID":"2000000962640049"}

#2
{"Payload":"MIIUUwYJKo...SE9SkwOJi8=","Store":"AppleAppStore","TransactionID":"2000000962640616"}

Hello,

We’re making improvements to how we refresh the receipt in IAP 5.0.0-pre.8 which should solve this case.

Alsoe note that Apple has deprecated the receipt and no longer updates it automatically on StoreKit 2. We recommend eventually using the jwsRepresentation to do backend validation.

The problem persists in version 5.0.0.
Is it necessary for us to switch to jwsRepresentation?

Hi Yannick_D, does this issue of getting the same payload in consecutive purchases occur only in the sandbox environment, or does it also affect the production environment?

In IAP 5.0.0, we made a change to await the receipt refresh after a purchase is made to replicate the behaviour of StoreKit 1 where the receipt is always up-to-date. The case raised in the first post should no longer be happening, but if it is and you can reproduce, give us details on your case and we will investigate it.

There could still be an identical payload because the Apple receipt is a global one for all purchases. If purchases are coming in at the same time such as being restored, they will all have the same receipt. This was also the case on IAP 4.13.0, so there shouldn’t be any difference on this point.
If you parse the receipt, you will be able to find the latest transaction for that product inside of it.

Sandbox is also known to be quite different from Production, so we don’t exclude that possibility, but it’s not something we have observed since 5.0.0.

Hello @Yannick_D, I have implemented JWSRepresentation for Unity IAP, but I am still getting the same JWS string when purchasing the same product on an iOS device in the sandbox environment.

Hello @Frimus
I just retested this by validating the Order.Info.Apple.jwsRepresentation in OnPurchasePending after purchasing the same consumable multiple times in a row and the jwsRepresentation is always different.

Could you share more details on how you are testing this?

I’m on Unity IAP 5.0.0, testing in the Sandbox environment on an iPhone XS. I’m also validating the Order.Info.Apple.jwsRepresentation inside the OnPurchasePending function.

Few more questions:

  • What OS version are you on?
  • Is the Pending Order confirmed between each purchase attempt?
  • Could you share some logs showing the different purchases with their jwsRepresentation?

We have confirmed that this issue does not occur in the Production environment.

Test Environment

  • Unity IAP 5.0.1
  • Purchase testing on an iOS build installed via TestFlight , using an Apple ID registered in App Store Connect (not a Sandbox Apple Account )

Hi @Yannick_D, the initial issue I reported (“identical Payload values on consecutive purchases during sandbox testing”) was resolved after updating to Unity IAP 5.0.0-pre.8. Thank you (and apologies for the late follow-up). We then updated to the 5.0.1 release and, after OTA install, confirmed again that consecutive purchases succeed without issues when using a Sandbox Apple Account.

We are now testing a build uploaded to TestFlight, and we’re seeing the same problem as in the original report. Using an Apple ID registered in App Store Connect, we downloaded and tested on two devices (iPhone and iPad). On consecutive purchases, the second pendingOrder.Info.Receipt shows a new TransactionID as expected, but the Payload remains identical to the first purchase.

Could you please take a look?

#2-1
{"Payload":"MIIZ9QYJKo...Hv+3IL1Q==","Store":"AppleAppStore","TransactionID":"2000000996724959"}

#2-2
{"Payload":"MIIZ9QYJKo...Hv+3IL1Q==","Store":"AppleAppStore","TransactionID":"2000000997968577"}

Test Environment

  • Tested by downgrading package versions: Unity IAP 5.0.1 → 5.0.0 → 5.0.0-pre.8
  • Purchase testing after OTA install using a sandbox test account

Hello, @Yannick_D
I sincerely apologize. In the report I submitted two days ago, the statement that “after an OTA install, consecutive purchases succeeded without issues using a sandbox test account” was incorrect. During that purchase test, I skipped the step of checking the receipt value.

So today I ran the purchase tests again, recording and verifying the receipt value for every purchase. As noted in the test environment, I downgraded the Unity IAP version one step at a time and purchased the same SKU three times (or more) repeatedly. Occasionally, with good timing, the Payload value in pendingOrder.Info.Receipt did change; however, when I continued with back-to-back purchases afterward—just like in my original test on Unity IAP 5.0.0-pre.7—the TransactionID updated correctly, but the Payload remained identical to that of the first purchase in most cases.

Could you please take another look at this issue?

// 5.0.1
{"Payload":"MIIUcQYJKo...4VVBSOHVw=","Store":"AppleAppStore","TransactionID":"2000000999765587"}

{"Payload":"MIIUcQYJKo...4VVBSOHVw=","Store":"AppleAppStore","TransactionID":"2000000999767762"}

{"Payload":"MIIUcQYJKo...4VVBSOHVw=","Store":"AppleAppStore","TransactionID":"2000000999768595"}


// 5.0.0
{"Payload":"MIIUWAYJKo...9XOlFWrQ==","Store":"AppleAppStore","TransactionID":"2000000999795007"}

{"Payload":"MIIUWAYJKo...9XOlFWrQ==","Store":"AppleAppStore","TransactionID":"2000000999795537"}

{"Payload":"MIIUWAYJKo...9XOlFWrQ==","Store":"AppleAppStore","TransactionID":"2000000999795942"}


// 5.0.0-pre.8
{"Payload":"MIIUWAYJKo...q2ib9K1g==","Store":"AppleAppStore","TransactionID":"2000000999799262"}

{"Payload":"MIIUWAYJKo...q2ib9K1g==","Store":"AppleAppStore","TransactionID":"2000000999799624"}

{"Payload":"MIIUWAYJKo...q2ib9K1g==","Store":"AppleAppStore","TransactionID":"2000000999800915"}

Is this only happening on TestFlight or also on Sandbox?
There’s many reports saying that the receipt doesn’t update properly on TestFlight when calling SKReceiptRefreshRequest which is the workaround we have to do since StoreKit 2 no longer updates the receipt automatically (StoreKit 1 did). If that’s the case, there isn’t much we can do to improve this on TestFlight.

When testing, can you do a direct call to RefreshAppReceipt and see if there’s an error being returned?

Hello,I have same problem and I’ve tested in both Sandbox and TestFlight environments. The RefreshAppReceipt call returns success in both cases, but the receipt doesn’t get updated - it remains exactly the same as it was before the refresh.

  • Unity 2021.3.45f1
  • Unity IAP 5.0.1
  • iOS 18.5

Hi, I’m having the same issue, reproduced in Sandbox by me and in TestFlight by our testers. RefreshAppReceipt returns success, but for some reason the callback is called twice for me. The issue is easily reproducible when buying two (even different) products in quick succession. When waiting for some time between purchases, the receipt payloads are different and we can validate them properly.

Unity 2022.3.62
Unity IAP 5.0.2
I have the same issue in both sandbox and production.

Same Here.

Unity 6000.2.10f1
Unity IAP 5.0.2

If I purchase two different item in 5minutes, later one’s receipt always returns first one’s receipt.
This behaviour is reproducible on production not even sandbox.
It is a critical problem for game service.

Unfortunately, the receipt is deprecated on StoreKit 2 and it doesn’t receive updates on every purchase like it used to on StoreKit 1. We are forcing the refresh after each purchase to provide the most accurate one we can, but that receipt is not always the latest.

If you wish to do remote validation for StoreKit 2 purchases, you will need to update your backend to validate the jwsRepresentation. IAP 4.14.0 can also be used if you prefer staying on StoreKit 1 to use your existing validation.