是否可以查询 Google Play 服务器以了解用户是否购买了商品?

Posted

技术标签:

【中文标题】是否可以查询 Google Play 服务器以了解用户是否购买了商品?【英文标题】:Can Google Play Server be queried to find out if an item was purchased by user? 【发布时间】:2018-01-12 15:58:21 【问题描述】:

我正在学习如何处理来自 android 应用的应用内购买。我正在阅读this document

基本上,本文档描述的流程如下:

我的 Android 应用(又名:客户端)与收集用户付款信息的 Google Play 应用通信,然后与 Google Play 服务器通信。 Google Play 服务器依次将商品分配给用户并响应 Google Play 应用程序,然后通知我的客户购买成功。之后,客户端交付商品,然后向 Google Play 应用报告该商品已被消费,这反过来又导致 Google Play 服务器将商品标记为已消费。

这引发了一个安全问题:我的客户通过告诉我的服务器该项目已被购买来交付该项目。我的服务器是交付该项目的服务器。我的客户端应用程序是一个多人游戏。因此,我的服务器是 来提供此项目的服务器。仅客户端应用程序无法做到这一点。

但是,上述流程要求我的服务器信任客户端。如果客户端被黑客入侵或被恶意程序替换,它可以告诉我的服务器多次交付任何项目。我的服务器现在可以验证这些购买是否有效。这是一个安全风险。

相反,我希望我的服务器询问 Google Play 服务器:此用户是否真正拥有此项目? Google Play 服务器报告的答案是可信的。但是有 API 可以做到这一点吗?如果是这样,该文档在哪里?如果没有这样的API,那么多人游戏如何保证购买的安全??

【问题讨论】:

【参考方案1】:

这个Querying for purchased items 主题可能会有所帮助:

查询购买的物品

检索有关用户从以下网站进行的购买的信息 您的应用,请在应用内结算服务上调用 getPurchases 方法。 传递 In-app Billing API 版本,你调用的包名 应用程序,以及方法中的购买类型(“inapp”或“subs”)。这里 是一个例子:

Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);

Google Play 服务仅返回用户进行的购买 当前登录到设备的帐户。如果请求是 成功,返回的Bundle的响应码为0。响应 Bundle 还包含产品 ID 列表、订单列表 每次购买的详细信息,以及每次购买的签名。

为提高性能,应用内结算服务最多只能返回 getPurchase 优先时用户拥有的 700 个产品 叫。如果用户拥有大量产品,Google Play 包括一个映射到键的字符串标记 响应 Bundle 中的 INAPP_CONTINUATION_TOKEN 表示更多 可以检索产品。然后,您的应用程序可以进行后续 getPurchases 调用并传入此令牌作为参数。谷歌播放 继续在响应包中返回一个延续令牌,直到 用户拥有的所有产品都会发送到您的应用。

有关 getPurchases 返回的数据的更多信息, 请参阅应用内计费参考。下面的例子展示了你可以如何 从响应中检索此数据:

int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) 
   ArrayList<String> ownedSkus =
      ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
   ArrayList<String>  purchaseDataList =
      ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
   ArrayList<String>  signatureList =
      ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
   String continuationToken =
      ownedItems.getString("INAPP_CONTINUATION_TOKEN");

   for (int i = 0; i < purchaseDataList.size(); ++i) 
      String purchaseData = purchaseDataList.get(i);
      String signature = signatureList.get(i);
      String sku = ownedSkus.get(i);

      // do something with this purchase information
      // e.g. display the updated list of products owned by user
   

   // if continuationToken != null, call getPurchases again
   // and pass in the token to retrieve more items

【讨论】:

这似乎必须从设备上的应用程序调用 - 而不是我的服务器。 "The Google Play service returns only the purchases made by the user account that is currently logged in to the device."我需要知道我的服务器如何从 Google Play(不信任应用程序)中找到已购买但尚未消费的物品。 我没有像您那样在应用计费中对 Google Play 进行过多试验,所以我只能引用官方文档。不确定您正在做的事情是否受支持。【参考方案2】:

理想情况下,您不应该相信在客户端上进行的购买,因为我们已经看到可以在越狱的 Android 手机上使用的第三方应用程序模仿与 Google Play 商店的交互。

你应该做以下事情

    列表项 使用服务器上生成的购买令牌在应用程序上完成购买流程。 在客户端接收购买信息 将购买信息发送到服务器 - 确保购买令牌、产品、订单信息有效 让服务器与 Google 联系以验证购买 - 请参阅 https://developer.android.com/google/play/billing/api.html 验证后,将响应返回给客户端 让客户将响应返回给 Google,然后 Google 会将购买标记为已消费。

【讨论】:

以上是关于是否可以查询 Google Play 服务器以了解用户是否购买了商品?的主要内容,如果未能解决你的问题,请参考以下文章

检测当前订阅是否在Google Play商店试用版中?

Google Play:从 Beta 版到正式版

Google play billing API:如何了解用户是不是订阅?

查询 Google Play Developer API 时出现意外错误。请检查您是不是使用了正确的服务帐号

是否可以使用服务帐户访问 Google Play 游戏服务 API?

Google Play 更新一览