question

Tommy Li avatar image
Tommy Li asked

Windows Store receipt with only one product info is deemed invalid by PlayFab

I was using ValidateWindowsStoreReceipt to verify purchases made in Windows Store apps.

(API Link: https://docs.microsoft.com/en-us/rest/api/playfab/client/platform-specific-methods/ValidateWindowsStoreReceipt?view=playfab-rest)

When I submit the app receipt (XML that contains the AppReceipt node), it is accepted:

<?xml version="1.0" encoding="UTF-8"?>

<Receipt xmlns="http://schemas.microsoft.com/windows/2012/store/receipt" Version="1.0" CertificateId="A656B9B1B3AA509EEA30222E6D5E7DBDA9822DCD" ReceiptDate="2020-04-30T05:10:01.008Z" ReceiptDeviceId="6755410917373333">

   <AppReceipt Id="f93e4f86-1908-4e3a-ae82-ec63c0f08f6e" AppId="ImpactInteractiveLimited.polytone_wvp253gvbgfsy" LicenseType="Purchase" PurchaseDate="2018-03-10T03:41:27.172Z" />

   <ProductReceipt PurchasePrice="USD0" PurchaseDate="2018-03-21T06:16:13.846Z" Id="d3da96c0-e08d-477c-81b0-b3518b190cd8" AppId="ImpactInteractiveLimited.polytone_wvp253gvbgfsy" ProductId="PB_ALLTRACKS100" ProductType="Durable" PublisherUserId="Grx+uRKMgiLPje7sVgk0kTDA6Ul+BeKwf6oZKOXa9W8=" MicrosoftProductId="4f73b749-b363-45f0-8072-0814ce8f6c21" MicrosoftAppId="4f73b749-b363-45f0-8072-0814ce8f6c21" ExpirationDate="9999-12-31T23:59:59.999Z" />

   <ProductReceipt PurchasePrice="USD1.09" PurchaseDate="2018-03-21T06:10:33.017Z" Id="ebf0694b-e315-42b5-95e3-9db6a82e2251" AppId="ImpactInteractiveLimited.polytone_wvp253gvbgfsy" ProductId="PD_EVERYTHING" ProductType="Durable" PublisherUserId="Grx+uRKMgiLPje7sVgk0kTDA6Ul+BeKwf6oZKOXa9W8=" MicrosoftProductId="4f73b749-b363-45f0-8072-0814ce8f6c21" MicrosoftAppId="4f73b749-b363-45f0-8072-0814ce8f6c21" ExpirationDate="9999-12-31T23:59:59.999Z" OfferId="" />

   <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

      <SignedInfo>

         <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />

         <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />

         <Reference URI="">

            <Transforms>

               <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />

            </Transforms>

            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />

            <DigestValue>OYe3+fP32C8+ogH/3EhffaEyfXGRHO6XTZTpqQobTAI=</DigestValue>

         </Reference>

      </SignedInfo>

      <SignatureValue>gdi4P4NDqHTTABoVDX3zfzPe+zqYb6ykrLVH47YfPdPpU+Ts86WSvdo5eRzFD/ttWW3UTjlzm9qBajhXG/FgeaFrox7kYHRn6vzQcJJeYxBwJMKZp/5eS3+z/45+JcAqKdKzzlRYImblhzENkUH3AuHky179+96OzcO3bIzuMPmX4GUmCbxXnZgAg0emkOOhuo5wZOLWMVWtRJgf4hPC/8QdqaQFzJki3BiwmVvcixzxGpccgX+TFX7+wXLRJMFpjuCZ35P1mAMIWo6Jcq3qy/zXcvE3xN7KcZ7nWbaX/NM1PvYLiDIOgxD136RBk1ow2hOx6PiIRqE1VHFL8+TmmA==</SignatureValue>

   </Signature>

</Receipt>

However, after a purchase is made and I submit the newly generated receipt with a single ProductReceipt node, the API returns error 1021 (InvalidReceipt):

<?xml version="1.0" encoding="UTF-8"?>

<Receipt xmlns="http://schemas.microsoft.com/windows/2012/store/receipt" Version="2.0" CertificateId="A656B9B1B3AA509EEA30222E6D5E7DBDA9822DCD">

   <ProductReceipt PurchasePrice="USD1.09" PurchaseDate="2020-04-30T05:10:52.649Z" Id="90f42ec3-8fe3-44b0-8f93-2bc905c6f963" AppId="ImpactInteractiveLimited.polytone_wvp253gvbgfsy" ProductId="PD_TERMINALSHORE" ProductType="Durable" PublisherUserId="8vJdTcFZbTO/zDbtCkEqF3lX7p04dnZlHMSICYfmvyk=" MicrosoftProductId="4f73b749-b363-45f0-8072-0814ce8f6c21" MicrosoftAppId="4f73b749-b363-45f0-8072-0814ce8f6c21" ExpirationDate="9999-12-31T23:59:59.999Z" OfferId="" />

   <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

      <SignedInfo>

         <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />

         <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />

         <Reference URI="">

            <Transforms>

               <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />

            </Transforms>

            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />

            <DigestValue>GMt83R8JHiHRwAK9HsiCnAe7/74x+pSMmvrCSmz/7e8=</DigestValue>

         </Reference>

      </SignedInfo>

      <SignatureValue>gzvhODN5nHpPaLGwrgnFuwvHLLPbZfwfCUb2Bwk2oZtDFnrPGETHwOxZW0FwTGd+8tL9fqD2sVc7qpq3HnEyP6xtH0ppG7DgZGIRe1eQ5ZWpzVDSnEKNbabh1XnlipKuz7EBQEiSNDyFEn3KyQaAXNTolPtp+rIuWCMadtvxduwe5fH8tfBAtqwvJFtzTZcT1dQjhj0mSJjfsFnZZ1qCFSz0TZfNLRgkWzyrjmR1/1qd5ekEfKQb3GWIhsIxc4D1gdx+rnBnYZFMa82EFEWlt+fGOiySD9eIkVSqf9lvLwTWGXe4HHLs4ZKXGc+pblvX8FTeb3llcECGDJ2k/c1SNw==</SignatureValue>

   </Signature>

</Receipt>
apiswindows
3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sarah Zhang avatar image Sarah Zhang commented ·

Could you please provide the detailed "errorMessage"?

0 Likes 0 ·
Tommy Li avatar image Tommy Li Sarah Zhang commented ·

I don't have a detailed Error message as the situation is gone until I make another real-money purchase, but I can provide the event data logged under the affecting account:

{
  "PlayFabEnvironment": {
    "Application": "mainserver",
    "Vertical": "master",
    "Commit": "9ec7f25",
    "Cloud": "main"
  },
  "EventNamespace": "com.playfab",
  "EntityType": "player",
  "SourceType": "BackEnd",
  "Timestamp": "2020-04-30T05:11:05.6543502Z",
  "EventName": "player_receipt_validation",
  "EntityId": "[REDACTED]",
  "TitleId": "[REDACTED]",
  "EventId": "[REDACTED]",
  "Source": "PlayFab",
  "PaymentProvider": "Windows Store",
  "ReceiptContent": "[SAME AS THE PRODUCT RECEIPT POSTED ABOVE]",
  "PaymentType": "ReceiptValidation",
  "Valid": false,
  "Error": "Invalid receipt"
}
0 Likes 0 ·
Tommy Li avatar image Tommy Li Sarah Zhang commented ·

Hello, was the provided info enough for your team to reproduce the errors?

0 Likes 0 ·
Tommy Li avatar image
Tommy Li answered

@Sarah Zhang

Here is a code snippet that showed exactly how I called the API:

// In a class called PlayFabUtility I defined this function...

public static async Task<PlayFabErrorCode> ValidateWindowsStoreReceipt(string xmlReceipt, string paymentCurrencyCode, uint paymentAmountInCentesimal, string catalogVersion = null)
{
        var verificationResponse = await PlayFabClientAPI.ValidateWindowsStoreReceiptAsync(
                new ValidateWindowsReceiptRequest()
                {
                        Receipt = xmlReceipt,
                        CatalogVersion = catalogVersion,
                        CurrencyCode = paymentCurrencyCode,
                        PurchasePrice = paymentAmountInCentesimal
                }
        );

        PlayFabError error = boxedResult.Error;
        T result = boxedResult.Result;

        if(error != null)
        {
                return error.Error;
        }
        else if(result != null)
        {
                return PlayFabErrorCode.Success;
        }

        return PlayFabErrorCode.Unknown;
}

// Somewhere else in my project, I call the function like this. 
// The receipt is retrieved by Unity IAP. I did verify the content against Microsoft documentation and they are both valid. 

string payload = <xml string posted in the original question>;
decimal price = <price of the item>;
string isoCurrencyCode = "USD";

PlayFabErrorCode error = PlayFabUtility.ValidateWindowsStoreReceipt(payload, isoCurrencyCode, decimal.ToUInt32(price * 100));

Debug.Log($"Result: {error}"); // Prints "InvalidReceipt" in Unity console
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sarah Zhang avatar image Sarah Zhang commented ·

The code looks fine, we checked your receipts again, then find there is a similar thread that mentioned the receipt that misses ReceiptDate and ReceiptDeviceId would be not valid and cannot be processed. The second receipt you provide seems lack these two attributes. You can navigate to this thread for more info.

0 Likes 0 ·
Sarah Zhang avatar image
Sarah Zhang answered

The info you provide maybe not enough to reproduce the issue, if your studio is a paid tier, you can contact us in the https://developer.playfab.com/en-US/r/t/[YouTitleId]/support to submit a ticket for support and provide your sample code there. If not, could you please provide the sample project as the reference here? Please take care of hiding your private info and other logic code not related to this problem.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Tommy Li avatar image Tommy Li commented ·

I have provided my code below. I think this is suffice to recreate the issue, but if you need a VS project, I can make one too.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.