Unacceptable behavior change with developerPayload from Unity IAP v1.19

@nicholasr
Hi there,

From Unity IAP v1.19, there was a big behavior change with developerPayload of GooglePlay, that developerPayload field is encoded by Unity IAP to JSON form.

This behavior change is not acceptable for our payment system, because we embed original transaction ID to developerPayload and check the receipt at the server. This system is shared for other games not using Unity IAP, so we can not change to parse JSON form specified by Unity IAP.

Please provide option not to encode developerPayload. We can not update SDK anymore.

@iyc

I apologize for the inconvenience this change has caused.

As a workaround, you could add some code to manually deconstruct the receipt and decode the developerPayload. Then you could reconstruct the receipt in the format your server accepts. This isn’t ideal, but hopefully it will get you to a place where you are able to continue using Unity IAP.

If you have a project that has upgraded to v1.19 and you need to return it to the previous behavior, you can find previous versions available for download here:

I will pass your feedback along to the IAP team.

@ap-unity
Thanks for your help!
The problem is that if you manually falsified the receipt, it will fail validating receipt at server, because of inconsistency of provided signature. We need a option not to change given developerPayload.

Since our project decided to stay at v1.18, we are not hurrying for new updates, but maybe we there is a point that we need to update Unity IAP because of store changes, we hopefully new option is provided at future releases.

@iyc I don’t quite follow. You are not manually falsifying the receipt (only decoding it), can you elaborate?

1 Like

@JeffDUnity3D Our server program that verify the receipt and signature are checking below conditions.

  • Provided receipt and signature pair are valid
  • developerPayload is in specified format

As server program is shared by many services, I can’t customize these conditions. So if I don’t falsified the receipt, it will return an error with invalid format of developerPayload. But if I falsified the receipt, it will return an error with invalid receipt and signature pair.

In conclusion, I need developerPayload in our format without falsifying, to pass validator of server program.

Sorry I’m not clear on what you mean by falsifying? You are only decoding, not falsifying. As ap-unity mentioned previously, you could add some code to manually deconstruct the receipt and decode the developerPayload. Then you could reconstruct the receipt in the format your server accepts. This would be done on the client, not the server, so your server would also work with other services.

@JeffDUnity3D Yes, I can decode the receipt, modify developerPayload and reconstruct the receipt again. But if I do that, than server doesn’t accept the modified receipt because the signature I get with the receipt doesn’t match. The signature of the receipt will guarantee that receipt is not modified by anyone. For security reason, server must check the signature, so that client can’t modify the receipt.

Document guide of checking signature on the server: Google Play's billing system  |  Android Developers

I don’t believe that is correct. WE (Unity) are encoding it. When you decode it, you should be putting it back into the original format that a receipt service would expect. I will confirm with the IAP team here.

It’s not a problem of either I can reconstruct the receipt or not. It’s a problem of modifying the receipt will break the signature provided by Google Play. Do you mean that Unity IAP is modifying the developerPayload after getting the receipt and signature from Google Play?

Two possible options - If we are modifying the payload, simply decode it and your server will be happy. If Google is encoding it, then we have no control over it. Your receipt service should accept the receipt in the same format as Google returns it. Have you tried decoding it and passing it?

Oh, It seem that you are misunderstanding the issue. I have an issue with the format of developerPayload itself, not the whole receipt.

Our server expect like kind of this format. Just to simplify, only developerPayload and orderId are shown.

{
    "developerPayload": "SOME_SPECIAL_ID",
    "orderId": "ORDER_ID"
}

But Unity IAP is encoding value of developerPayload to other format like this.

{
    "developerPayload": "{\"developerPayload\":\"BASE64_ENCODED_SOME_SPECIAL_ID\",\"is_free_trial\":false,\"has_introductory_price_trial\":false}",
    "orderId": "ORDER_ID"
}

Yes I tried decoding later format receipt and encoded to former format receipt, but failed to verify signature on the server, since I modified the receipt. For this behavior, I am thinking of Unity IAP is modifying developerPayload before passing to Google Play, is it correct? Google Play will generate signature with passed developerPayload, so you can not modify the receipt returned by Google Play.

I meant to simply decode BASE64_ENCODED_SOME_SPECIAL_ID from your second example, and use it as SOME_SPECIAL_ID in the first example. Perhaps this is what you’ve tried?

I heard from the IAP team regarding this issue, apologies on the confusion. Unfortunately there is no work around at this time. We may include an update for this behavior with developerPayload in a future release, but it has not been decided at this time.

Yes I tried it on client app, sending the modified receipt to the server, but rejected for invalid signature. Only workaround is to add support of Unity IAP to server program, but the server is shared with various services and seems to be hard.

I am glad to hear that. Since I am not hurrying for updates now, I will wait for updates. But in future we maybe need to update for external factor, I hope it will be fixed at some point.