Validating Google Play In-App Purchases In Php

(Reposting this from general Android Forum as no-one seems to be able to answer there…)

 

Hello –

 

Has anyone out there figured-out how to validate Google Play in-app purchases from Corona in PHP?  I can’t find any definitive resources, other than that you’re supposed to use openssl_verify…  I’ve been trying code like below but it isn’t working (always returns false)

 

 

\<?php $receipt &nbsp; &nbsp; &nbsp; = $\_REQUEST['receipt']; &nbsp; &nbsp;// receipt data from Corona (event.transaction.receipt) $signature &nbsp; &nbsp; = $\_REQUEST['signature']; &nbsp;// signature from Corona (event.transaction.signature) $googlePlayKey &nbsp; = "MIIBIjANB... Public key text from Google Play Developer Console ..."; $publicKey &nbsp; &nbsp; &nbsp; = "-----BEGIN PUBLIC KEY-----\n" . chunk\_split($googlePlayKey, 64, "\n") . '-----END PUBLIC KEY-----'; function isReceiptValid( $store, $receiptdata, $signature ) { &nbsp;&nbsp;&nbsp;&nbsp;global $publicKey; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;if ( $store == "google" ) { &nbsp; &nbsp; &nbsp; &nbsp; $key = openssl\_get\_publickey( $publicKey ); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ( 1 == openssl\_verify( $receiptdata, base64\_decode( $signature ), $key, OPENSSL\_ALGO\_SHA1 ) ); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return false; } ?\> &nbsp;

 

Any help would be *greatly* appreciated!

Just curious.  Why are you wanting to do this?

Validating the receipt (by checking it’s signature against your public key) is best practice per Google.  Otherwise, the receipts can be easily spoofed, especially when fulfilling a purchase requires posting to an external server (such as our case).  

BTW – the code above DOES work after all.  I was inadvertently escaping the receipt before validating, so that’s what was causing it to fail…

So do you make an HTTP request to your own server from the Corona app so you can do the php validation of the purchase?  I’m just trying to understand the flow. 

Yes – for our app, which is a slot machine app with virtual currency, balances are kept on the server.  When we receive notification in the app that a purchase has been made (from either the App Store or Google Play), the app submits the receipt information to a php script on the server, which first validates the receipt (using the code above in the case of Google Play), then pulls the product id and transaction id from the receipt to determine how much currency to add the the account, checks to make sure that the transaction id hasn’t been used before (to prevent replay hacks), then updates the balance on the account and returns a status code to the app.

If we didn’t validate the receipts from Apple or Google, anyone could use a proxy to inspect the calls to our sever, then they could simply forge the receipt information and make as many calls as they want to the server to increase their balance.

Right, it sounds very appropriate for your situation.   Thanks for the explanation.

Just curious.  Why are you wanting to do this?

Validating the receipt (by checking it’s signature against your public key) is best practice per Google.  Otherwise, the receipts can be easily spoofed, especially when fulfilling a purchase requires posting to an external server (such as our case).  

BTW – the code above DOES work after all.  I was inadvertently escaping the receipt before validating, so that’s what was causing it to fail…

So do you make an HTTP request to your own server from the Corona app so you can do the php validation of the purchase?  I’m just trying to understand the flow. 

Yes – for our app, which is a slot machine app with virtual currency, balances are kept on the server.  When we receive notification in the app that a purchase has been made (from either the App Store or Google Play), the app submits the receipt information to a php script on the server, which first validates the receipt (using the code above in the case of Google Play), then pulls the product id and transaction id from the receipt to determine how much currency to add the the account, checks to make sure that the transaction id hasn’t been used before (to prevent replay hacks), then updates the balance on the account and returns a status code to the app.

If we didn’t validate the receipts from Apple or Google, anyone could use a proxy to inspect the calls to our sever, then they could simply forge the receipt information and make as many calls as they want to the server to increase their balance.

Right, it sounds very appropriate for your situation.   Thanks for the explanation.