Mar*_* A. 7 android in-app-purchase in-app-billing google-play
通过Billing API的第3版,Google消除了消费品和非消费品之间的区别.两者都被组合成一种名为"托管"的新类型,其行为有点像混合:您的应用需要主动调用方法来"消耗"这些项目.如果从未对一组skus执行此操作,那些项目基本上就像它们是非消耗品一样.
该文档描述了预期的购买流程,如下所示:
getBuyIntent电话启动购买流程.Bundle从Google Play 获取回复,表明购买是否成功完成.consumePurchase请拨打电话进行购买.我看到这种方法存在两个问题.一个是相当明显的,文档中的"bug"比API更多,但另一个是相当微妙的,我仍然没有想出如何最好地处理它.让我们从显而易见的完整性开始:
问题1:在单个设备上购买丢失:
文档说,应用程序应在getPurchases每次启动时调用"检查用户是否拥有任何未完成的耗材应用程序内产品".如果是这样,应用程序应使用这些并配置关联的项目.这包括购买流程在购买完成后但在消耗物品之前(即步骤2周围)中断的情况.
但是如果购买流程在步骤4和5之间中断怎么办?即应用程序已经成功完成了购买,但它有机会将产品配置给用户之前已经被杀死(电话进来并且没有足够的内存,电池耗尽,崩溃等等).在这种情况下,购买将不再包括在内getPurchases,基本上用户永远不会收到他所支付的费用(在这里插入愤怒的支持电子邮件和一星评价) ......
幸运的是,通过引入"日志"(如在文件系统中)将购买流程更改为更类似的内容(步骤1和2与上面相同),这个问题相当容易解决:
如果购买成功,请进入日记中说"一旦购买<order-id here>成功消费,就将硬币从300增加到400 ".
确认日记帐后,通过consumePurchase拨打电话进行购买.
然后,每次应用程序启动时,它不应该只检查getPurchases,而且还应该是日志.如果有未完成购买的条目未报告getPurchases,请继续执行步骤6.如果稍后getPurchase再将该订单ID再次归还(例如,如果消费完全失败),则只需忽略该交易journal将此订单ID列为完整.
这应该解决问题1,但如果您发现此方法存在任何缺陷,请告诉我.
问题2:涉及多个设备时的问题:
假设用户拥有两台设备(例如手机和平板电脑),两者都拥有相同的帐户.
他(或她 - 从现在开始暗示)可以尝试在他的手机上购买更多硬币,并且应用程序可能会在购买完成后被杀死,但在消费之前.现在,如果他接下来在平板电脑上打开应用程序,getPurchases则会将产品报告为已拥有.
平板电脑上的应用程序必须假定购买是在那里启动的,并且在创建日记帐分录之前就已经死亡,因此它将创建日记帐分录,使用产品并配置硬币.
如果手机应用程序在有机会进入日记帐之前就已经死亡,那么硬币将永远不会在手机上配置(在这里插入愤怒的支持电子邮件和一星评价).如果手机应用程序在创建日记帐分录后死亡,则硬币也将在手机上配置,基本上可以让用户在平板电脑上免费购买(在此处插入损失的收入).
解决此问题的一种方法是在购买时添加一些唯一的安装或设备ID作为有效负载,以检查购买是否适用于此设备.然后,平板电脑可以简单地忽略购买,只有手机才会记入硬币并消费该物品.
但是:由于此时sku仍然在用户手中,Play商店将不允许用户购买另一个副本,所以基本上,直到用户再次在他的手机上启动应用程序来完成待处理的交易,他不会能够在平板电脑上购买更多的虚拟硬币(插入愤怒的支持电子邮件,一星评价,以及这里的收入损失).
有一种优雅的方式来处理这种情况吗?我能想到的唯一解决方案是:
有没有更好的办法?或者我可能只是从根本上误解了一些东西,这里真的没有问题吗?(我意识到这个问题出现的可能性很小,但是有足够大的用户群,"不太可能"最终变成"一直都是".)
这是解决所有这些问题的最简单方法,到目前为止我已经提出了这个问题.这不是最优雅的方法,但至少它应该工作:
getBuyIntent使用购买ID作为开发人员有效负载启动购买流程.Bundle从Google Play 获取回复,表明购买是否成功完成.consumePurchase拨打电话来消费购买每次启动应用程序时,请执行以下操作:
getPurchases请求以查询用户的自有应用内商品.以下是单个设备上出现问题的方式以及随后发生的情况:
在多设备情况下,任何其他设备将简单地忽略任何非本地待处理的购买(报告为拥有的消耗品),因为购买ID不在该设备的本地列表中.
一个问题是待定购买将阻止其他设备能够为同一产品开始并行购买.因此,如果用户在他的手机上的步骤2和5之间(即在购买完成之后,但在消费完成之前)某处有不完整的交易,他将无法再在他的平板电脑上购买相同的产品,直到应用程序完成步骤5,即在手机上使用产品.
通过将每个耗材SKU的多个副本(可能是5个?)添加到Google Play并将第一个列表中的第2步更改为:可以非常轻松地解决此问题(但不是很优雅):
getBuyIntent与购买ID为开发人员负载.关于黑客行为的说明(按照黑客难度增加的顺序):
总的来说,购买的签名验证和一些相对简单但非明显的相关数据校验和签名(在内存和本地存储中)应该足以迫使黑客反编译(或以其他方式反向工程)应用程序为了窃取产品.除非应用程序非常受欢迎,否则这应该是一个足够的威慑力量.代码中的灵活逻辑与频繁更新可以打破任何已开发的补丁程序,可以使应用程序成为黑客的移动目标.
请记住,我可能会忘记其他一些黑客.如果你知道一个,请评论.
结论:
总的来说,这不是最干净的解决方案,因为需要为每个消耗品维护多个并行SKU,但到目前为止,我还没有找到一个能够解决问题的更好的SKU.
所以,请分享您可能有的任何其他想法.对于任何好的指针都保证+ 1.:)
首先我想说我同意你写的一切。问题确实存在,我会尝试以与您类似的方式解决它。我真的建议找 Google Play 关系团队的人员,让他们知道这一点。
现在回到你的解决方案。这可能是我能想到的最好的不涉及服务器的独立解决方案。这很简单,但相当不错。它可能被滥用的一个地方是攻击者伪造日志文件并“购买”他们想要的任何东西,因为getPurchases不会从被操纵的日志文件中返回任何内容。
否则,我还会尝试做的就是降低应用程序被系统杀死的可能性。为此,您可以将购买和消费逻辑提取到在单独进程中运行的较小前台服务中。这将增加服务完成其工作的可能性,即使 Android 会杀死更大的游戏应用程序。更复杂但更可靠的解决方案是在服务器上实现日志并在设备之间共享它。通过此解决方案,您可以随时检查是否有人在购买时作弊,甚至可以在涉及多个设备时解决问题。
| 归档时间: |
|
| 查看次数: |
2289 次 |
| 最近记录: |