UWP, IAP 1.20.1, non-consumable (durable)

I am working on an UWP version of our app. In-app purchases have generally been setup, a test app version has been published, in-app purchase details are queried for and in-app purchases can (with problems, see below) be bought. So, the setup seems fine.

When buying a non-consumable (durable), we are calling ConfirmPendingPurchase (as this also needs to be called for non-consumables according to out interpretation of the Unity docs). However, this results in an ServerError (see logs).

The transaction is then continuously processed by Unity and tried to be fulfilled. This results in another error, as Unity now somehow uses a fake transactionId when fulfilling the transaction (see logs).

Does anyone have any ideas what is going on? Is this “simply” a bug in UnityIAP?

As a side note: buying a consumable for the first time works fine. Buying it the seconds time without restarting the app lets Unity deliver this second purchase twice (by calling ProcessPurchase with the ids of the second purchase). This might be related to the non-consumable having a problem, but might be an independent bug as well.

Here is some shortened log from the non-consumable purchase:

purchase({0}): IAP_ID
UnityEngine.Purchasing.PurchasingManager:InitiatePurchase(Product, String)
UnityEngine.Purchasing.PurchasingManager:InitiatePurchase(String, String)

UnityIAPWin8: Purchase IAP_STORE_ID status:Succeeded
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

PURCHASE SUCCEEDED!:{0}: 2
UnityEngine.Purchasing.<>c__DisplayClass19_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

Just for your information. The Receipt:
{“Store”:“WinRT”,“TransactionID”:“9a1378c9-a6fd-45d8-b1a2-86d5eae20f93”,“Payload”:"

<?xml version=\"1.0\"?>

<Receipt Version="2.0" CertificateId="XXX" xmlns="http://schemas.microsoft.com/windows/2012/store/receipt\">
<ProductReceipt PurchasePrice="EUR0" PurchaseDate="2019-01-08T08:22:36.301Z" Id="9a1378c9-a6fd-45d8-b1a2-86d5eae20f93" AppId="XXXX" ProductId="IAP_STORE_ID" ProductType="Durable" PublisherUserId="XXX" MicrosoftProductId="XXX" MicrosoftAppId="XXX" ExpirationDate="2019-01-09T08:22:32.817Z" OfferId="" />
<Signature xmlns="XML-Signature Syntax and Processing}

UnityIAPWin8:Fulfilment result for IAP_STORE_ID - 9a1378c9-a6fd-45d8-b1a2-86d5eae20f93 : ServerError
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

Unity now tries to fulfil and fulfil:

UnityIAPWin8:Fake transactionID: Set transactionMap[IAP_STORE_ID] = 190501192
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

Fulfilling transaction 190501192
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

(Filename: C:\buildslave\unity\build\Runtime/Export/Debug.bindings.h Line: 45)

ProductID IAP_STORE_ID
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

(Filename: C:\buildslave\unity\build\Runtime/Export/Debug.bindings.h Line: 45)

UnityIAPWin8:Consuming: IAP_STORE_ID
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

(Filename: C:\buildslave\unity\build\Runtime/Export/Debug.bindings.h Line: 45)

UnityIAPWin8:Exception consuming IAP_STORE_ID : Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). (non-fatal)
UnityEngine.Purchasing.<>c__DisplayClass16_0:b__0()
System.Action:Invoke()
UnityEngine.Purchasing.Extension.UnityUtil:Update()

There should be no need to call ConfirmPendingPurchase in your code. You cannot re-purchase a non-consumable, as the name implies.

From my understanding of the Unity docs, ConfirmPendingPurchase finishes the transaction and must be called whenever the app finished processing/recording of the purchase. Otherwise, the transaction is delivered again and again.

Finishing is required for all Apple transactions. For Google Play, UnityIAP decides whether to consume the purchase (for consumables) or not (for non-consumables). This is the reason why UnityIAP gets the ProductType when adding products. It is working fine, as expected, and documented for Google, Amazon, and iOS.

Not sure why UWP should be any different. We can see what is happening when ConfirmPendingPurchase is not called or results in an error – the transaction is delivered to the application again and again, as it was not confirmed.

No, that is not correct. You return Complete from ProcessPurchase to finish the transaction. ConfirmPendingPurchase is optional, and only needed if you return Pending from ProcessPurchase.

Yes, that is correct. We return Pending, as we verify the purchase on our server before. Not sure why this should be triggering the issue I described.

UPDATE: I can confirm that exactly the same happens (including the log outputs) when skipping our server verification and not calling ConfirmPendingPurchase, and returning Complete instead of Pending.

So you are claiming that ALL IAP transactions on the UWP platform are failing with the error “UnityIAPWin8:Exception consuming IAP_STORE_ID : Guid should contain 32 digits with 4 dashes”? It seems we would have heard from other users as well, if this is the case. Can you share your code? Alternatively, can you test with the sample project here? Sample IAP Project

It is only durable items. Consumables are working fine.
I will try to get the sample project running and will get back then.

I have now used the sample project you provided and did not change the iap version (so it is using the older version 1.18).
The problems I have reported are still the same. I have attached the logs (having replaced the store ids). The sample is set to return Complete (not Pending). I use Unity 2018.3.0 (public version on Win10 in this case).
I have commented the log using slashes:

//Log 1: fresh app start, DURABLE1 was previously bought, DURABLE2 is now being bought

Complete = True
UnityIAPWin8:Begin PollForProducts() persistent = True, delay = 0, productsOnly = False
UnityIAPWin8:Building full product list with existing purchases
UnityIAPWin8:Fake transactionID: Set transactionMap[DURABLE1] = -1349125067
Unavailable product subscription2 -subscription2
OnInitialized: PASS
Already recorded transaction -1349125067
Fulfilling transaction -1349125067
ProductID DURABLE1
UnityIAPWin8:Consuming: DURABLE1
UnityIAPWin8:Exception DURABLE1 : Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). (non-fatal)

//start buying process DURABLE2

Purchasing product:smile:URABLE2
purchase({0}): DURABLE2
UnityIAPWin8:Purchase DURABLE2 status:Succeeded
PURCHASE SUCCEEDED!:{0}: 0
ProcessPurchase: Complete. Product:smile:URABLE2 - 91fe567c-f81d-44d0-90df-980c782e372a
Fulfilling transaction 91fe567c-f81d-44d0-90df-980c782e372a
ProductID DURABLE2
UnityIAPWin8:Consuming: DURABLE2
UnityIAPWin8:Fulfilment result for DURABLE2 - 91fe567c-f81d-44d0-90df-980c782e372a : ServerError

//Log 2: new app start, DURABLE1 and DURABLE2 previously bought durables

Complete = True
UnityIAPWin8:Begin PollForProducts() persistent = True, delay = 0, productsOnly = False
UnityIAPWin8:Fake transactionID: Set transactionMap[DURABLE1] = -1349125067
UnityIAPWin8:Fake transactionID: Set transactionMap[DURABLE2] = 190501192
Unavailable product subscription2 -subscription2
OnInitialized: PASS
Already recorded transaction 190501192
Already recorded transaction -1349125067
Fulfilling transaction 190501192
ProductID DURABLE2
UnityIAPWin8:Consuming: DURABLE2
UnityIAPWin8:Exception consuming DURABLE2 : Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). (non-fatal)
Fulfilling transaction -1349125067
ProductID DURABLE1
UnityIAPWin8:Consuming: DURABLE1
UnityIAPWin8:Exception consuming DURABLE1 : Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). (non-fatal)

//Log 3: I told in the side note that consumables are processed twice when buying them for the second time without restarting
//new app start (deleted starting logs now), CONSUMABLE is now tried to be fulfilled twice
//buying CONSUMABLE for the first time … all fine

Purchasing product:CONSUMABLE
purchase({0}): CONSUMABLE
UnityIAPWin8:Purchase CONSUMABLE status:Succeeded
PURCHASE SUCCEEDED!:{0}: 0
ProcessPurchase: Complete. CONSUMABLE - d71b2baf-5992-4c1a-9f84-6fc915798a40
Fulfilling transaction d71b2baf-5992-4c1a-9f84-6fc915798a40
ProductID CONSUMABLE
UnityIAPWin8:Consuming: CONSUMABLE
UnityIAPWin8:Fulfilment result for CONSUMABLE - d71b2baf-5992-4c1a-9f84-6fc915798a40 : Succeeded

//buying CONSUMABLE for the second time → the consumable is tried to be fulfilled twice

Purchasing product:CONSUMABLE
purchase({0}): CONSUMABLE
UnityIAPWin8:Purchase CONSUMABLE status:Succeeded
PURCHASE SUCCEEDED!:{0}: 1
ProcessPurchase: Complete. Product:CONSUMABLE - 273376c5-4e57-4285-8405-3a94bf5950e5
Fulfilling transaction 273376c5-4e57-4285-8405-3a94bf5950e5
ProductID CONSUMABLE
UnityIAPWin8:Consuming: CONSUMABLE
UnityIAPWin8:Fake transactionID: Set transactionMap[DURABLE1] = -1349125067
UnityIAPWin8:Fake transactionID: Set transactionMap[DURABLE2] = 190501192
Already recorded transaction 273376c5-4e57-4285-8405-3a94bf5950e5
Already recorded transaction 190501192
Already recorded transaction -1349125067
Fulfilling transaction 273376c5-4e57-4285-8405-3a94bf5950e5
ProductID CONSUMABLE
UnityIAPWin8:Consuming: CONSUMABLE
Fulfilling transaction 190501192
ProductID DURABLE2
UnityIAPWin8:Consuming: DURABLE2
UnityIAPWin8:Exception consuming DURABLE2 : Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). (non-fatal)
Fulfilling transaction -1349125067
ProductID DURABLE1
UnityIAPWin8:Consuming: DURABLE1
UnityIAPWin8:Exception consuming DURABLE1 : Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). (non-fatal)
UnityIAPWin8:Fulfilment result for CONSUMABLE - 273376c5-4e57-4285-8405-3a94bf5950e5 : NothingToFulfill
UnityIAPWin8:Fulfilment result for CONSUMABLE - 273376c5-4e57-4285-8405-3a94bf5950e5 : Succeeded

@seven_1 Does this also occur when using 1.20.1 ?

I just updated the test project to the latest IAP version 1.20.1.
The behaviour is still the same.

Understood, this is on my list to investigate, but unfortunately not any time soon.

Just to let you know. We are now using another simple Windows IAP integration for our app, which works without problems. We somehow start to believe that Unity seems to be working on new, shiny things for presentations but neglects the main business of keeping the engine working for basic things…

Please keep in mind that the demand for Windows Store support is low, and it’s an issue with resources vs priorities. We are focusing on Android and iOS at this time which keeps us plenty busy, and other platforms as resources allow and priorities require.

Do you mind to share what IAP integration are you using? We have same issue and unity support is useless.

We are using the Windows Store Native plugin, available in the Asset Store.

1 Like

Thank you.

Hello! I have the same exception message “UnityIAPWin8:Exception consuming IAP_STORE_ID : Guid should contain 32 digits with 4 dashes”, Unity 2019.2.19 + latest codeless IAP, durable item. The error comes automatically on app start, there are no actions from code.

As the result - IAP is not restored (but should be restored accouding to docs).

We will investigate as time and resources allow.