[译] 正确实现 linkedPurchaseToken 以免重复订阅

你是否在使用 Google Play 的订阅功能?要确保你的后端服务实现的方式是正确的。前端

订阅 REST APIs 是管理用户订阅的真实可信来源。Purchases.subscriptions API 的返回包括一个很是重要的字段叫作 linkedPurchaseToken。 恰当的处理这个字段,对于保证正确的用户可以访问你的内容是很是重要的。android

它是如何工做的?

就像 订阅文档 里指出的, 每一笔新的 Google Play 的购买流程 —— 初始化购买、升级和降级还有 从新注册¹ —— 都会产生一个新的购买令牌。而 linkedPurchaseToken 字段则能够用来识别属于同一个订阅的多个购买令牌。ios

打个比方,一个用户购买了一个订阅而且收到一个购买令牌 A。linkedPurchaseToken 字段(灰色圆圈)在 API 的返回里没有值,由于这个购买令牌属于一个全新的订阅。git

若是用户升级了他们的订阅,一个新的购买令牌 B 产生了。既然这个升级替代了购买令牌 A 表明的订阅,令牌 B 的 linkedPurchaseToken 字段(灰色圆圈显示的)将会指向令牌 A。注意它按照时间的逆序指向原始的购买令牌。github

购买令牌 B 将会是惟一被更新的令牌。购买令牌 A 不该该用来受权用户获取你的内容。算法

注意: 更新订阅时,若是你查询 Google Play 的订单服务器,购买令牌 A 和 B 都会是激活的。咱们会在 下一节 里讨论这个问题。数据库

如今,让咱们假设一个另外一个用户执行了如下操做:订阅、升级和降级。原始的订阅会建立购买令牌 C,升级操做会建立购买令牌 D,降级操做会建立购买令牌 E。每个令牌都会按照时间的逆序指向前一个令牌。apache

让咱们在这个例子里加上第三个用户。这个用户一直在改变主意。在初始化订阅以后,用户又一连三次取消了订阅而后从新订阅(从新订阅)。初始化订阅建立了购买令牌 F,从新订阅建立了 G、H 和 I。购买令牌 I 是最近的令牌。后端

最近的令牌 B、E 和 I 分别表明了用户 一、二、3 的最终受权和付帐的订阅。只有这些最近的令牌才有相应的权利。然而对于 Google Play 来说,若是初始的过时时间还没到,全部的令牌都是“有效的”。api

也就是说,若是你经过 获取订阅 API 来查询这些令牌,包括上面的图表内的 A, D, F, G和H,你会获得 订阅资源响应 ,响应里代表订阅尚未过时而且付款已经收到,即使如此你也只应该根据最近的令牌来受权。

第一眼看上去很奇怪:为何最初的令牌仍是在被更新后仍是有效的?简单来讲是这样实现能让开发者更灵活地提供内容和服务,也让 Google 更好的保护用户隐私。然而这也确实须要你在后端服务器上进行重点记录

操做 linkedPurchaseToken

每次当你确认一个订阅,你的后台服务都应该检查 linkedPurchaseToken 字段有没有被设定。若是已经被设定,该字段的值就表明着前一个被替换的令牌。你应该马上把前一个令牌标记为失效,这样用户就不能使用这个令牌访问你的内容。

咱们再来看看上面例子里的用户 1, 当后端服务器收到了表明初始购买的凭证 A,该凭证 A 的 linkedPurchaseToken 字段为空,这时应根据凭证进行受权。接下来,当后端服务器接收到更新后新的购买凭证 B,服务器会检查 linkedPurchaseToken 字段,发现它被设置为令牌 A,因而就禁掉令牌 A 的受权。

这样的话,后端数据库老是保存有效权限的购买凭证。以用户 3 的例子来讲,数据库的状态变化应该以下图:

检查 linkedPurchaseToken 的伪代码:

你能够在一个开源的,端对端订阅的应用 优雅出租车 的后台 Firebase 上看一些例子,特别是看 disableReplacedSubscription 方法,它在 PurchasesManager.ts 里。

清理现有的数据库

如今你的后端应该和最新的,接连到来的购买令牌保持同步,你会检查每个购买的 linkedPurchaseToken 字段,而且每个对应着被替换订阅的令牌,都被正确的禁用了。这太棒了!

可是若是你有一个已有的订阅数据的数据库,而且没有根据 linkedPurchaseToken 字段来调整?你须要在这个数据库上跑一个一次性的清理算法。

在不少状况下清理数据库中最重要的工做就是,一个令牌是否被可以受权相应的内容和服务。也就是说:并不须要对每个订阅从新建立升级/降级/从新订阅的购买历史,而只须要肯定每一个令牌正确的受权状况。一次性的数据库清理任务就能够把订阅状态整理清楚。接下来,新到来的订阅就须要像上一节中描述的那样处理。

想象一下上面三个用户的购买凭证都存在数据库里。这些购买可能出如今任什么时候间,顺序也不同。若是清理功能正确处理的话,令牌 B、E 和 I 最终会被标记为有效受权,而其余的令牌则会被禁用。

对数据库进行一次遍历,并检查每一项。若是 linkedPurchaseToken 字段被设置,就把这个字段包括的字段禁用。根据下面的图表,咱们从上到下移动:

元素 A:linkedPurchaseToken 没有被设定,移至下一项 元素 D:linkedPurchaseToken == C,禁用 C 元素 G:linkedPurchaseToken == F,禁用 F 元素 E:linkedPurchaseToken == D,禁用 D 元素 F:linkedPurchaseToken 没有被设定,移至下一项 等等。

清理现有数据库的伪代码:

执行完一次性的清理以后,全部的旧令牌都会被禁用,你的数据库也就准备好了。

简单可是重要的事

如今你已经理解 linkedPurchaseToken 字段是怎么工做的,确保在你的后端正确的处理它。每个有订阅功能的应用都应该检查这个字段。正确的追踪受权对于保证正确的用户,在正确的时间,被授予了正确的权利这一点来讲,很是关键。

参考资料

¹从新注册 是指当一个用户订阅,而后取消订阅,接着又在初始的订阅过时以前从新订阅。尽管用户不会丢失受权,新的订阅也和以前的同样,他们仍是会经历另外一个付款流程,由于他们承诺了将来的付款。他们会收到新的购买令牌而且 linkedPurchaseToken 字段会在升级或者降级的时候被设置。

本文全部的代码都遵循 Apache 2.0 许可。本文不包括 Google 正式产品任何部分,而且只是为了参考使用。

文章开始的令牌图片是从 该连接 复制的。归属:便携式古物计划/大英博物馆基金会。知识共享归属共享 2.0 许可。

感谢 Cartland Cartland

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索