I now really messed up to understanding the concept and reason for need, and even don't know how to implement by coding.
So, I made mobile game using unity, c#. Used php, mysql for highscore and store user's in app purchased item info.
I released my game a week ago at google play, my google wallet shows nobody until now purchased any items in that game.
But, when I checked my game server (mysql database), some users has enormous numbers of item that should be purchased.
This means some users used hacking tool and bypass google play check process and deceive my game and made fake purchase.
So I didn't implement developerPayload, nor validation of google play purchase receipt.
So now I deleted whole malicious user's item at my DB,(this will set 0 to that user's client's item), and want to implement server side verification of google play purchase receipt.
I searched many posts by googling, but there is no perfect solution from the first to end.
Anyway, I implemented so far like this.
First, after user ended google checkout process(whether this is real or fake), my unity client's OnPurchaseSucceded function called, there I implemented to start communicate my php script on my server.
private void OnPurchaseSucceded(Purchase purchase)
{
/*
// Optional verification of the payload. Can be moved to a custom server
if (!VerifyDeveloperPayload(purchase.DeveloperPayload)) {
return;
}*/
StartCoroutine(VerifyReceiptCo(purchase));
}
IEnumerator VerifyReceiptCo(Purchase purchase)
{
WWWForm hsFm = new WWWForm();
hsFm.AddField("data", purchase.OriginalJson);
hsFm.AddField("signature", purchase.Signature);
WWW hs = new WWW(verifyURL, hsFm);
yield return hs;
Debug.Log("verify result is " + hs.text);
// if result is true(validated), give item to user.
}
and here questions,
1. [Did I do right above code? for 'data' field, I used purchase.OriginalJson, but is this right? if not, what should I use?]
and after receive these info from php (verifyURL of above code),
$base64EncodedPublicKey = "MY game's public key from google play console";
$signedData = $_POST['data'];
$signature = $_POST['signature'];
$key = openssl_pkey_get_public($base64EncodedPublicKey);
$verified = (openssl_verify($signedData, base64_decode($signature), $key, OPENSSL_ALGO_SHA1) > 0);
$result = openssl_verify($signedData, base64_decode($signature), $key, OPENSSL_ALGO_SHA1);
if ($verified) {
echo 'verified : result is'.$result;
} else {
echo 'fail : result is'.$result;
}
another questions,
2. [Do I need paid SSL services to use openssl_ method like above php code?] I am using hostgator.com 's web hosting, there my plan already have 'Shared SSL' service, then is this enough? or should I buy another private SSL service plan?]
3. Are there no way to verify this without using openssl(for not using SSL services) method?
4. Overall am I doing right direction to deal with hacking user? Thanks much.
here's my code for verify google order. it works fine with all products of my company. Very simple code.
function verifyGoogleOrderLocal($packageName, $jsonData, $sig)
{
$public_keys = array(
'package1' => 'key1',
'package2' => 'key2',
);
if(!$public_keys[$packageName]) {
return array("success"=>0,"reason"=>'no public key defined');
}
$key = get_openssl_key($public_keys[$packageName]);
if(!$key) {
return array("success"=>0,"reason"=>'invalid public key');
}
$result = openssl_verify($jsonData, base64_decode($sig), $key, OPENSSL_ALGO_SHA1);
$resp = array('success'=>$result);
if($result==0) $resp['reason'] = 'invalid signature';
return $resp;
}
function get_openssl_key($publicKey)
{
$key = "-----BEGIN PUBLIC KEY-----\n" . chunk_split($publicKey, 64, "\n") . '-----END PUBLIC KEY-----';
$key = openssl_get_publickey($key);
return $key;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With