代码之家  ›  专栏  ›  技术社区  ›  Gianluca Ghettini

Android InApp购买验证

  •  1
  • Gianluca Ghettini  · 技术社区  · 7 年前

    我有一个手机应用程序,里面有一些inapp项目,用户可以购买。一旦用户购买了一些inapp产品,应用程序就会将JSON收据发送到我的服务器,根据我的谷歌开发者公钥(存储在服务器中)进行在线验证。

    应用程序将签名和数据(也称为收据)发送到服务器:

    $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方面,这是相同的数据,但从加密签名验证的角度来看,这是非常不同的。有人能解释一下怎么做吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Gianluca Ghettini    7 年前

    解决了问题:

    • 这个 data 必须是没有缩进或换行的普通字符串

    因此,与此相反:

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

    我必须这样做:

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