不订阅更新_订阅更新制开发详解

b3119c15bc9ba9e2693902f9eb7169e8.png

订阅更新制

在 Apple 的生态里面,越来越多的应用采用订阅制作为其盈利模式。相比于买断和普通的 IAP,订阅制提供了一种周期性付费的机制,让开发者有动力持续地维护一个产品。

但这种方式也一直被用户诟病,它最大的问题在于,很多订阅制停止订阅后,正在使用的功能会被限制。尤其是对于工具类的产品,很多人觉得没有使用订阅制的道理。

JSBox 2.0 最近上线了,采用的付费方式是:

  • 通过一次付费来解锁当前和接下来一年的更新
  • 解锁过的功能永久保留
  • 只对后续感兴趣的更新付费,完全可选

关于付费方式优劣的讨论,我之前写过一篇文章,可以在这里找到。本文要讨论的,是实现订阅更新的一些技术细节。

Receipt Validation

整个方案的核心是解析应用产生的 Receipt,首先要把 Apple 提供的 Receipt Validation Programming Guide 仔仔细细地读一遍,我这里只会讲最关键的几个内容。

不管是付费下载还是应用内购买,都会通过 receipt 记录。对于订阅制而言,续订也一样会产生相应的数据。我们通过 appStoreReceiptURL 获取到 receipt 之后,再通过 Apple 提供的 verifyReceipt 获取到该用户全部的数据,通过分析这个数据我们可以得到用户的订阅状况。

这里值得注意的第一个点是,不要在客户端调用 verifyReceipt 接口。取而代之的是,通过自己的服务器调用,并做好防止中间人攻击的措施。

在 receipt 里面,in_app 字段和 latest_receipt_info 里面记录了每一次内购产生的记录,我们需要在里面找到最大的 expires_date_ms,它就是用来获取用户可用功能的一个时间戳。

Feature Timeline

在 JSBox 里面,实现了一个功能更新的时间线,可以给用户看到每次重要更新,以及该功能是否解锁:

aa681bc8a40622767755dc324de2b0c9.png

这同样也是我们在后端唯一要记录的内容,发布一个新的 PRO 功能,有两个部分:

  • 在应用内埋好该功能是否可用的逻辑(例如使用 FeatureID 来判断)
  • 发布应用同时发布在后端 Feature Timeline 里面增加记录,包括 ID, Name 以及发布时间等

用户在打开应用之后,通过后端提供的接口以及上述获取 expire date 的逻辑,获取到所有可用 ID 的列表,使得客户端写好的逻辑生效。

值得注意的是,由于 App Store 的问题,发布新版本不会立刻生效,所以在计算时间时,可以留有一定的余地(例如多算一天)。

老用户迁移

JSBox 在 2.0 之前是一个付费应用,这代表对于付费下载的用户而言,我们要在后台逻辑里面将他们等同于做过一次订阅。这涉及到两个问题:

  • 识别老用户
  • 计算老用户的 expire date

第一个问题很简单,我们通过 receipt 里面的 original_purchase_date_msoriginal_application_version 来做到,它们分别代表用户第一次下载应用时的时间戳,以及当时应用的版本号。如果他们小于某个值,我们就可以认为是老用户。这里有个坑是,你在沙盒环境测试的时候,original_application_version 会永远返回 1.0,但在正式环境这个字段返回的是应用的 Build Number。其实上述的文档写了,但测试过程中还是容易产生误导。

第二个问题,original_purchase_date_ms 加上一年就是老用户的第一个 expire date。如果老用户有订阅的话,则会变得有点复杂。

为了更好地照顾老用户的权益,我们提供了一个 6.8 折的订阅价格。但很多老用户可能距离过期还有很长的时间,所以我们提供了一个补全老用户剩余时间的设计。

也既,老用户发生第一次订阅时,我们需要看一下他距离第一次 original_purchase_date_ms 产生的 expire date 还剩多少时间,把这个时间追加到他第一次订阅产生的 expire date 后面。然后,时间继续往前走,老用户可能会发生多次订阅。所以我们还需要在这个时间戳和上述逻辑中的最大 expire date 中取最大值。

这一段有点难消化,但如果你的产品不存在老用户迁移问题,则可以忽略。

优惠价格的提供

上述的 6.8 折是如何只提供给老用户的?首先我们已经知道如何识别老用户了,那么我们要做的就是对这部分用户提供一个特殊的内购项目,然后对这个项目使用 Introductory Offer。所以 IAP 项目一定是通过服务器下发的,客户端通过 StoreKit 获取具体的信息。

然后我们会对老用户和新用户展示不同的界面:

bf4a70269975db429058cc06e1f1335c.png

这个地方需要注意的是,在提交审核的时候,要提供各自的截图,以及对两个 IAP 项目的详细说明(其实 Apple 在审核时是看不到老用户的 IAP 的,这是一个潜在的被拒风险)。

与此同时,需要在订阅的页面提供“隐私政策”以及“使用条款”,另外我们还提供了一个常见问题的页面。

刷新 Receipt

在 appStoreReceiptURL 获取不到 receipt 的时候,或是恢复购买的时候,你都可以使用 SKReceiptRefreshRequest 来刷新 receipt(恢复购买还可以使用 restoreCompletedTransactions)。这个接口它最大的问题就是慢,如果你每次都刷新的话,会严重影响用户等待的心情,进而降低支付成功的概率。但如果你不每次都刷新的话,这里有另一个坑:很多用户有两个 Apple ID

假设他用美区账号付费下载了 JSBox,然后把 Apple ID 换成了中区账号,而中区账号可能没有下载过 JSBox,所以会被判定为新用户。

但是,Apple 会允许该用户完成订阅操作,也既下载时和订阅时用的 Apple ID 是不同的。如果你的应用有这种情况的话,这会增加你的客服成本。

沙盒测试和异常处理

在整个和 IAP 相关的开发中,沙盒测试是很重要的一环。即便你做足准备,还是有可能会出错,所以一定要进行充分的测试。关于如何进行沙盒测试,这里不再赘述,Google 一下应该会得到很多答案。值得一提的是,沙盒环境会将实际订阅时长缩短很多(比如一年会变成一小时),方便你测试。另外,TestFlight 环境不能实现收费。

异常处理也同样重要,在最近一个月的时间里,Apple 与支付相关的接口出现过两次严重地线上问题,直接影响了开发者的收入:

  • verifyReceipt 不返回 JSON
  • Receipt 丢失引起的 21199

开发者对于 Apple 服务器引起的问题没有什么好办法,只能尽可能地在服务端检测到这些异常,同时给与客户端良好的提示。实际上结合上述的种种逻辑,你应该发现了客户端永远只是服务端状态的一个 UI,它并不承载任何逻辑。

识别单次购买行为

在有些时候,你需要对单次购买行为进行鉴别,比如防止通过共享的 Apple ID 薅羊毛。如果你的应用没有 IAP,那么你可以使用 original_purchase_date_ms 进行粗略的判断,有一定的重复的风险。有 IAP 的情况有更好的办法,Apple 在 WWDC 课程里面推荐的是使用 original_transaction_id 这个字段,它是具有唯一性的。

最后

开发和 IAP 相关的内容属于比较复杂的操作,需要谨慎。另外,希望这种付费模式可以给一些开发者启发,得到一定程度的推广。

祝大家赚更多钱,再见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值