这篇文档翻译自apple,appstore的购买部分。主要介绍的是订阅功能,包括普通订阅和自动订阅。文档本身没有介绍详细的API payload,没有demo。我看的不是很明白,所以把它逐字翻译,便于理解。
提供订阅的App,需要一些考虑一些额外的行为。因为订阅涉及了时间,你的app必须能够确定订阅是否当前有效,或者订阅已经过期。你的app也必须能够相应订阅的创建,续期,以及过期,并且能够合理的处理过期订阅。
下图解释了订阅的时间线,包括你app需要处理的一些复杂东西:
计算订阅的有效期
你的app需要能够决定,某些内容只有在用户的订阅有效时才能够访问。例如,一个用户订阅了一个月的杂志,这个杂志在每月1号发布,你需要考虑下表的情况:
时间 | 事件 | 订阅状态 |
---|---|---|
2月1日 | 二月杂志发布。用户不可获得,因为他现在还没有订阅 | 未订阅 |
2月20日 | 用户订阅了杂志的阅读观看计划。二月份的杂志因为是最近的,所以用户可以立即观看 | 激活 |
3月1日 | 三月份的杂志发布了。用户可以立即获得,因为他的订阅还在有效期内 | 激活 |
3月20日 | 用户的订阅,自动更新了 | 激活 |
4月1日 | 四月份的杂志发布了。用户可以立即获得,因为他的订阅还在有效期内 | 激活 |
4月20日 | 用户取消了订阅,所以订阅周期结束了 | 过期 |
5月1日 | 五月份的杂志发布了。用户不能获取,因为他的订阅已经过期 | 过期 |
6月1日 | 六月份的杂志发布了。用户不能获取,因为他的订阅已经过期 | 过期 |
6月17日 | 用户订阅了。六月份的杂志可以立即观看 | 激活 |
7月1日 | 七月份的杂志发布了。用户可以立即获得,因为他的订阅还在有效期内 | 激活 |
想要为用户提供所有可访问内容的权限,就需要在每次内容发布的时候都记录日期。需要根据每个收据的Original Purchase Date
, Purchase Date
和Subscription Expiration Date
来确定订阅周期的开始和结束时间(关于recipe的信息,请参考这篇文档)。用户可以在订阅的开始时间到结束时间之间的时间范围内,访问所有已经发布的内容,内容需要在用户购买订阅后立即解锁。
想要确定订阅的过期,需要通过对比每个收据的Subscription Expiration Date
和Purchase Date
字段。
注意:请不要通过在购买日期后加上订阅时间的方式来计算订阅周期。这个方法,没有考虑到免费试用期,营销免费期。
例如,因为用户购买订阅后内容总是会被解锁,一个用户如果在一个月中旬购买了一个总是在月初发布的杂志,那么他在初次订阅的时候是可以访问两个月份的发布杂志的。包括他购买时那个月份的杂志,以及下个月初发布的那份杂志。
接着上面的图表来说,收据可以显示下面的日期范围:
- 2月20日 - 3月20日
- 3月20日 - 4月20日
- (过期的4月20日 - 6月17日 不会显示在收据中)
- 6月17日 - 7月17日
用户可以访问2月和6月的杂志,因为他在这些个月份完成了购买,那么就需要解锁。
用户可以访问3月,4月,6月和7月,因为这些时间段的时候订阅都处于激活状态。
(订阅)计划的升级和变更
用户可以在App Store中或者你的UI中管理他的订阅。对于每个订阅,App Store都会提供订阅提供方提供的续期选项。用户可以很简便的选择修改他的服务等级,选择升级,降级,或者跨等级修改。降级和跨级别修改,可以在下一次续期时生效。
过期和续期
订阅续期程序,会在订阅过期的前十天开始。在这些天中,App Store会检查用户不能完成自动续约的账单问题,例如:
- 用户的付款方式不在激活状态
- 商品在用户的订阅期中进行了提价
- 商品已经下架
App Store如果遇到问题,会对用户进行提示,以免影响到他们的订阅服务。
在订阅过期前的24小时,App Store会开始尝试进行续期。App Store会进行若干次续期尝试,但是如果失败太多,则会终止自动更新。
注意:对于账单相关的问题,App Store可能会在60天之前就开始进行续期尝试。你可以通过收据中的
Subscription Retry
字段来确定是否是这个情况。
App Store会在订阅过期之前,毫无痕迹的完成续期,以免用户面对订阅过期问题。不过,过期还是有可能的。例如,如果用户的支付信息无效,第一次需求尝试会失败。如果用户在订阅过期之后,更新了他的支付信息,那么在这中间的一小段时间中,用户就处于订阅过期状态。用户也可以取消自动需求,或者有意让订阅过期,之后一段时间再继续续订,那么就会有一段较长时间的过期。请确定你的App可以处理这些过期情况。
在一个订阅成功续期之后,StoreKit会将一个续期交易加入到交易队列中。你的app需要检查和处理交易队列。请注意,如果你的app在订阅更新的时候已经开始运行,那么交易observer不会被调用;app必须重新启动才行。
作为例子,下面的时间线表格展示了一个用户的账号订阅了一个app提供的月度服务计划。在这个例子中,订阅曾经因为账单问题,存在了短暂的过期。用户随后纠正了订单问题,订阅随后被续订。
日期 | 事件 | 订阅状态 |
---|---|---|
2月20日 | 用户订阅了月度订阅。服务立即可用。 | 激活 |
3月20日 | 用户的订阅成功自动续期。服务仍然可用。 | 激活 |
4月19日 | 用户的支付方式过期了。 | 激活 |
4月20日 | 因为交易失败,用户的自动续期也失败了。订阅过期了 | 过期 |
5月5日 | 用户更新了他的支付方式。App Store可以从新发起订阅续期。服务立即可用 | 激活 |
6月5日 | 用户的订阅成功自动续期。服务仍然可用。 | 激活 |
取消
因为订阅在购买的时候是全额付款。用户只有在联系Apple消费者支持的时候才能取回退款。例如,如果用户意外的买错一件商品,消费者支持可以取消这次购买,并且对用户进行完全或部分退款。消费者可能在一个订阅的途中取消了订阅,但是这个订阅已经被支付了,它必须完成之前承诺的服务直到过期。
想要检查是否一次购买交易已经由Apple消费者支持取消,可以通过检查收据中的Cancellation Date
来完成。如果这个字段包含一个日期,那么不管过期日期,这次购买都被取消了。处理被取消的购买,应该像这次购买从来没发生一样。
状态更新提醒
StatusUpdateNotification
是一个服务器-服务器的提醒服务,专门用来处理订阅的自动续订。这个提醒会在发送的时候,声明订阅的状态。
想要获得你处理事件的最新信息,你的app需要验证App Store中的最后一条收据。强烈推荐你使用状态更新提醒和收据验证功能来验证一个用户当前的订阅状态,并对他们提供服务。
想要接受状态更新提醒,你需要在Apple的后台配置订阅状态URL。App Store会通过HTTP(S) POST请求,将数据以JSON的形式发送到你的服务器。你的服务器应该负责解析,解释,以及响应所有的 statusUpdateNotification
请求。
使用服务器-服务器提醒服务不是必须的,你可以在任何时候选择使用它。
statusUpdateNotification
是一个HTTP POST请求,它的请求提包含下列元素:
Key | 描述 |
---|---|
environment | 指明这个提醒来自沙盒或者生产环境:Sandbox PROD |
notification_type | 描述这个提醒的类型。详情见下面的提醒类型表 |
password | 这个值和你验证收据是用的shared secret是一样的 |
original_transaction_id | 这个值和收据中的Original Transaction Identifier是一样的。你可以使用这个值来为单个用户订阅关联多个IOS 6风格的交易手机 |
cancellation_date | Apple消费者支持取消交易的日期。只有在notification_type 是CANCEL 的时候才会存在 |
web_order_line_item_id | 用来标示订阅购买的主键。只有在notification_type 是CANCEL 的时候才会存在 |
latest_receipt | base64编码的交易收据receipt。只有在notification_type 为RENEWAL 或者INTERACTIVE_RENEWAL 的时候才会有,并且只有在续订成功的时候才会有。 |
latest_receipt_info | 最近receipt的信息,以JSON表示。只有在续订成功的时候才会有。 |
latest_expired_receipt | base64编码的交易收据receipt。只有在订单过期的时候才会收到。 |
latest_expired_receipt_info | 最近receipt的信息,以JSON表示。只有在订单过期的时候才会收到。 |
auto_renew_status | 一个布尔值,true或者false。和receipt中的auto renew status 一样 |
auto_renew_adam_id | 自动订阅当前的续订优先级。这是商品的Apple ID。 |
auto_renew_product_id | 这个字段和receipt中的Subscription Auto Renew Perference 一样 |
expiration_intent | 这个字段和receipt中的Subscription Expiration Intent 一样。只有在notification_type 为RENEWAL 或者INTERACTIVE_RENEWAL 的时候才有. |
下面是提醒类型的列表:
提醒类型 | 描述 |
---|---|
INITIAL_BUY | 初次购买订阅。请将latest_receipt 存储在你的服务器,随时可以当作token来验证,以确定用户的订阅状态。 |
CANCEL | 订阅已经由Apple消费者支持所取消。请检查Cancellation Date 字段来确定何时订阅被取消。 |
RENEWAL | 一个已过期的订阅被成功地自动续订。请检查Subscription Expiration Date 来确定下一个续订的日期和时间。 |
INTERACTIVE_RENEWAL | 在订阅过期之后,用户手动选择了续订,可以是在你的App UI中操作,或者在Apple Store的用户设置中操作。续订后服务应该立即可用。 |
DID_CHANGE_RENEWAL_PREF | 用户修改了订阅计划,在下一个订阅周期的时候生效。当前生效的订阅计划不受影响。 |
为了确认statusUpdateNotification
请求成功被处理,你的服务器应该返回200的响应;不需要返回任何的数据。如果你的服务器返回50x或者40x的响应码,App Store会重新发送这个提醒。
安全要求
在发送提醒之前,Apple Store会使用ATS协议(App Transport Security)对你的服务器建立安全连接。如果安全连接不可建立,那么提醒就不能发送到你的服务器。
测试环境中的状态更新提醒
强烈推荐在部署到生产环境之前,将你的statusUpdateNotification
处理逻辑在测试环境经过测试。
跨平台考虑
商品标识符只关联单个app。拥有IOS和MacOS的App应该分别由单独的商品,每个平台应该有单独的商品标识。你可以让在IOS App中订阅的用户,同样可以访问MacOS的内容,但是具体的实现应该是你自己的责任。
让你的用户可以管理订阅
除了实现你自己的订阅管理UI,你的App页可以打开下面的URL:
https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions
打开这个URL,会开启iTunes或者iTunes Store,并且打开订阅页面。
测试环境
测试环境和生产环境之间,对于自动续期订阅存在不同的处理方式。
在测试环境中,订阅续期的发生速率需要提升,自动续订每天最多可以发生6次。这样可以让你充分验证一个订阅的续订,订阅的失效。。。
因为订阅的过期和续订率提速了,订阅可以在系统续订前过期,在订阅周期中留下一段失效期。请确保你的app能够正确处理这种情况。