Проверка на покупката в приложение за Android

Имам мобилно приложение с някои елементи в приложението, които потребителите могат да закупят. След като потребителите закупят някакъв продукт в приложението, приложението изпраща JSON разписката до сървъра ми за онлайн проверка спрямо публичния ми ключ за разработчици на Google (съхранен в сървъра).

Приложението изпраща подпис и данни (известни още като разписка) до сървъра:

$signature = 'E2dxlmSe0d45eJpN4FKSUxNPYXM5A1zohpVL60Hd+5jd43j4YMhBlVRLwFeDaBKZnkJ39rYYesWoOu8Z5ysczAIiQO7Myko7UJYVYKvB5GqM8a0iEDjCdCpSRSqLUmaEHKwUJFfjcgw1K5L2gM/m3u8l7Jy25IB+HFVIikO50jiy8SMRh7S+s6PgEAXqG6K6vTpuTC5ECweuQ45VTdb0jNyWOzEW/I1nA5fAB/mmp5j3B6k7nN81NMh/3oUJHba/wWGlbkWtItmDU6/jMdpd1CVViNBhKe0ktwnSRz3XF607/AfZM6JteOKhC6TquWhVNuWpKJWdJbP7Q+RVS0YKog==';

$data = '{"orderId":"GPA.xxxx-xxxx-xxxx-xxxxx","packageName":"xxx.xxx.xxx","productId":"xxx","purchaseTime":1508881024560,"purchaseState":0,"purchaseToken":"didpmjkaldaddakgfabdohdj.AO-J1Ozqb8hZAa-_FLd-sQJgXhwruU3tVEYU0sqhlgXHb8I9wI35xDeQFgFI0Zpoaurw4Ry7zahymvge1U0WlEqqvvAKvwAo0Wk1MtawzAiqVdy2RTvwFGo"}';

Ето PHP кода, който използвам за проверка на подписа:

$pkey = "...";
$apkey = "-----BEGIN PUBLIC KEY-----\n".chunk_split($pkey, 64, "\n")."-----END PUBLIC KEY-----";
$pubkeyid = openssl_get_publickey($apkey);
$ok = openssl_verify($data, $signature, $pubkeyid);
openssl_free_key($pubkeyid);
echo $ok;

и разбира се не работи. Функцията OpenSSL връща 0 (вместо 1 за OK). Според онлайн документацията https://developer.android.com/google/play/billing/billing_integrate.html това, което трябва да проверя е INAPP_PURCHASE_DATA, което е receipt. Ето един пример от документа:

'{
   "orderId":"GPA.1234-5678-9012-34567",
   "packageName":"com.example.app",
   "productId":"exampleSku",
   "purchaseTime":1345678900000,
   "purchaseState":0,
   "developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
   "purchaseToken":"opaque-token-up-to-1000-characters"
 }'

Което е точно това, което моето приложение изпраща. Сега, тъй като проверката на подписа изисква битови перфектни данни, как трябва да "изпратя" такъв низ към функцията OpenSSL? В документа данните имат прекъсвания на редове и отстъпи, моите са със същата JSON структура, но записани като обикновен низ без прекъсвания на редове или отстъпи. Това са същите данни по отношение на JSON, но много различни от гледна точка на проверка на криптографски подпис. Може ли някой да обясни как да го направя?


person Gianluca Ghettini    schedule 24.10.2017    source източник


Отговори (1)


Решен проблемът:

  • data трябва да бъде обикновен низ без отстъпи или прекъсвания на редове
  • подписът трябва да бъде декодиран base64, преди да бъде предаден на функцията OpenSSL

Така че вместо това:

$ok = openssl_verify($data, $signature, $pubkeyid);

трябва да направя това:

$ok = openssl_verify($data, base64_decode($signature), $pubkeyid);
person Gianluca Ghettini    schedule 25.10.2017