Hi @vd_unity,
Thanks again for discussing the previous issue with me here:
https://discussions.unity.com/t/destructive-changes-discovered-when-upgrading-from-unity-iap-4-12-to-5-0-0pre5-feedback-and-questions/1616761
I just hit what looks like the same symptom described here:
https://discussions.unity.com/t/missing-receipt-signaturejws-when-making-purchase-on-ios-with-iap-5-0-0-pre-4/1606642.
I’m still evaluating an upgrade from Unity IAP 4.12.0 → 5.0.x.
As you can expect from our previous discussion, my project isn’t Codeless and still uses some APIs that are now obsolete in 5.x, but the workflow and catalogue (all consumable products) are otherwise unchanged, so I’m trying to keep the client code identical as much as possible.
Repro steps
-
Add a fresh Sandbox tester in App Store Connect.
-
On an iPhone logged in with that tester, install the 4.12.0 build and buy Product A.
ProcessPurchase fires, I call ConfirmPendingPurchase, everything OK.
-
Delete the 4.12.0 build.
-
Install the same project rebuilt with 5.0.0‑pre.5.
-
Buy Product A again.
-
Immediately buy Product B.
-
ProcessPurchase fires again
-
If I buy a third product, tr2 and second product appear inside the receipt and new transactionID(tr3) also appears, and the pattern repeats.
The first half with the 4.12.0 build may not be strictly required, but I reproduced the behaviour on two different Sandbox Apple IDs using exactly those steps, so I kept the full sequence.
Test environment
- Sandbox store
- Unity 2022.3.23f1
- Unity IAP 5.0.0‑pre.5
- iOS 15.0 / iOS 16.0.2 devices
- Built on Unity Cloud Build (Xcode 16.0.0)
iOS log (for the empty‑payload case)
No obvious errors—just lines like:
storekitd AMSPaymentSheetTask: [XXXXXXXX_SK2] Completed successfully
storekitd [XXXXXXXX][LoadInAppReceiptsTask] Starting receipt request from revision
storekitd [XXXXXXXX][LoadInAppReceiptsTask] Finished receipt request
So StoreKit 2 seems to successfully finish the purchase and fetch a receipt before Unity’s callback fires, yet the payload that reaches C# is still empty on the first purchase.
Let me know if I can supply additional logs or builds.
Thanks!
Sorry I edited few points (please check edit histories)
Hello @b3lypscfcon
This is something I’m currently investigating as we have noticed the same issue on our end.
I’ll keep you updated on this when I have more details.
This issue only occurs if you’re still using the 4.12.2 implementation. With StoreKit2, the receipt is deprecated and no longer the recommended way to validate purchases from Apple.
StoreKit 2 already does it’s own validation before passing it over to Unity IAP and you can also use the jwsRepresentation to validate the purchase with Apple.
We’ll have a detailed guide on how to migrate from the 4.12.2 implementation to 5.0.0 with the official release of 5.0.0.
Hi @Yannick_D,
Thank you for your quick reply and for clarifying the longer-term direction toward using jwsRepresentationinstead of the classic PKCS-7 app receipt.
I fully agree that migrating to JWS is the correct end-state. However, many developers—myself included—still need a transition period during which the existing /verifyReceipt workflow remains available. Project timelines and legacy back-end systems often make an immediate switch to the App Store Server API impractical, so having an up-to-date local receipt is still important.
Regarding the “empty receipt after the first purchase” issue in IAP 5.0-pre.5, you may already have seen the following reports, which appear to describe the same behavior:
If this receipt issue cannot be resolved in IAP 5.x, developers upgrading from 4.12 will effectively be required to adopt the JWS workflow. In that case, could you confirm whether any significant workflow changes are expected on the Unity side? My current understanding is:
- The client flow remains largely the same (Purchase → success callback → receipt verification on our trusted server → ConfirmPendingPurchase).
- The only difference is that we send the transaction’s
jwsRepresentationto our trusted server instead of the Base-64 app receipt.
Is that assumption accurate, or should we plan for additional changes such as new error cases or retry logic?
I would appreciate any update you can share on the status of the receipt issue and on the recommended migration path.
Thanks again for your help.
Best regards
Thank you for sharing all your findings on this. I was able to validate the solution of calling SKReceiptRefreshRequest after a purchase succeeds to keep the receipt up-to-date.
This solution will make it work the same way as in 4.12.2 with no changes required on your end.
We plan to release this as part of our 5.0.0-pre.6 release.
Hi @Yannick_D,
I’m glad to hear that calling SKReceiptRefreshRequest right after a successful purchase works, and that the existing 4.12-style receipt-verification flow will still be available in 5.0.0.
Looking forward to trying 5.0.0-pre.6 as soon as it drops!
Thanks again for the quick turnaround.
Hi @Yannick_D,
I retested the first-purchase receipt issue with IAP 5.0.0-pre.6, and unfortunately the problem persists:
- On the very first purchase after a fresh install,
IStoreListener.ProcessPurchase still receives a Product whose receipt field is empty.
- A quick look at the pre.6 source shows that a receipt refresh is triggered immediately after a successful purchase.
- In
AppleStoreImpl::OnPurchaseSucceeded the code calls RefreshAppReceipt. Because this call is asynchronous, execution appears to continue straight to PurchasingManager::OnPurchasePendingAction without waiting, and that method then tries to read the receipt.
- If I’m following the flow correctly, this timing gap could explain why the receipt remains empty on the first purchase.
Could you please confirm whether this interpretation is correct?
Thanks again for your help!
Best regards
Hi @Yannick_D,
I did some additional testing (on iOS 15) and it confirms my earlier hunch:
ProcessPurchase is indeed firing before the app-receipt refresh completes.
- A few frames later the refresh callback arrives and the correct receipt becomes available.
So the empty receipt on the very first purchase looks like a simple ordering issue: ProcessPurchase happens first, the refresh callback a moment later.
Thanks again for looking into this!
Hi @b3lypscfcon,
Thank you for investigating this further and for the 5.0.0-pre.6 feedback.
We will be looking into this and come back to you with an update !
@ArthurCarriere
Thanks for looking into this issue.
Because it touches the core purchase flow, we’re really hoping it can be addressed in an upcoming release.
Thank you for the report, we have made changes to await for the receipt to be refreshed before invoking the ProcessPurchase to make sure it’s been updated.
This will be part of IAP 5.0.0-pre.8