苹果应用内购买(IAP)—从入门到放弃

勿忘初心2018-09-04 09:59
作者:李振煜
文本总结了大量IAP相关的规则、设计开发要点和实践经验, 适合产品需要做IAP和所有对IAP知识感兴趣的策划、交互、开发、测试。因为 信息量太大 ,先放个目录:
1 IAP规则详解
  1.1 适用范围
  1.2 IAP类型
  1.3 定价
  1.4 分成
  1.5 结算
2 IAP设计开发要点
  2.1 创建和提交IAP项目
  2.2 IAP支付流程
  2.3 不能忽视的坑
3 更多IAP实践经验总结
  3.1 匿名购买
  3.2 跨平台同步
  3.3 虚拟币
  3.4 退款问题
  3.5 支付成功率
  3.6 作弊行为

1 IAP规则详解
本文所述IAP(In-App Purchase),特指苹果App Store的应用内购买,是苹果为App内购买虚拟商品或服务提供的一套交易系统。
首先来讨论一下IAP的基本规则以及其中的一些要点:
1.1 适用范围
App内需要付费使用产品功能或虚拟商品/服务,如游戏道具、电子书、音乐、视频、订阅会员、App的高级功能等。
App内购买实体商品(如淘宝买衣服)不适用IAP,不在App内使用的虚拟商品(如充话费)或服务(如滴滴叫车)也不适用IAP。
那么问题来了,假如在App内购买一个音乐专辑,既能在App里面听数字专辑,同时也能获得实体商品cd,适不适用IAP呢?
答案是适用的。因为App内的数字专辑和实体商品cd在使用上是可以分离的,数字专辑符合IAP的适用范围,购买就要用IAP。否则各种游戏里面卖648的道具,都声称商品不仅包含游戏道具,购买后还能获得一个5毛钱的实体纪念品(举例),就直接绕过IAP,苹果岂不玩蛋?
苹果规定,适用范围内的虚拟商品或服务,必须使用IAP购买支付,不允许使用支付宝、微信支付等其它支付方式(包括Apple Pay),也不允许以任何方式(包括跳出App、提示文案等)引导用户通过应用外部渠道购买。
原则上苹果也不允许通过外部兑换码等方式在应用内解锁虚拟商品或服务,但实际上兑换码的限制是有些模糊的,因为有些App可以在应用内获得兑换码(比如活动发放优惠券或签到奖励),很难严格界定是一个外部兑换码还是内容兑换码。因此,在IAP购买中使用优惠券抵扣一般情况下是允许的,但如果很明显地引导用户在App外购买兑换码,再在App内兑换成虚拟商品或服务,是会被苹果Reject的。
另外在App Store Review Guidelines 3.1.4 里面还有这样一条特殊规则:
App features that work in combination with an approved physical product (such as a toy) on an  optional  basis may unlock functionality without using IAP, provided that an IAP option is available as well.
意思就是说,用户在App内购买一个功能,而这个功能需要和一个实体商品结合起来使用,这种情况下,允许使用IAP之外的方式来解锁功能,但前提是仍然需要提供IAP购买的选项。
比如用户在一个健康管理App内购买一个高级计步器功能,但这个计步器功能需要跟手环配合使用,要和手环打包购买。这个情况下,App可以在IAP购买的选项基础上,再提供其它的购买方式。
但现实中好像并见过没有这样的案例。因为App完全可以把计步器变成免费功能,只是没有手环不起实际作用,然后把手环当成是一个在App外使用的实体商品,这样跟IAP就没有半毛钱关系了。谁没事找事还把这个东西做成IAP还要给苹果分成啊~
另外还有一些跨平台同步的复杂案例,在本文的第三部分再进一步介绍。

1.2 IAP类型
如前面说的,IAP是一套商品交易系统,而非简单的支付系统。每一个购买项目都需要在App的itunes connect后台创建一个商品,提交给苹果审核,审核通过后,购买项目才会生效。
在创建IAP商品时,主要有4种类型可供选择:
1.2.1 Consumable products
该类型适用于可多次购买的消耗型项目,如游戏道具、虚拟币等。
1.2.2 Non-consumable products
该类型适用于一次购买永久有效的项目,如电子书、游戏关卡等。
该类型项目支持跨设备同步和本地restore,比如说,用户在某个App中购买了一本书,可在所有相同Apple ID设备的App中免费获取这本书,而不要需要借助App本身的帐号体系,即使在App中删除了这本书,也可免费重新获取。
1.2.3 Auto-renewable subscriptions
该类型适用于自动续费的订阅项目,如Apple Music的按月订阅,用户购买后会每月自动续费,直到用户手动取消或者开发者下架IAP项目。
类似Non-consumable products,该类型也支持跨设备同步和本地restore机制。
之前这种类型只支持newsstand类别(报刊杂志)的App,从2016年6月开始支持所有类型的App,但除了newsstand类别之外,国内的App很少使用这种类型的内购。
1.2.4 Non-renewable subscriptions
该类型适用于固定有效期的非自动续费项目,如云音乐的会员和一些视频App的会员。没有跨设备同步和本地restore机制,用户可以多次购买。
1.2.5 Free subscriptions
该类型是Auto-renewable subscriptions的一个特例,适用于免费的订阅项目,仅支持newsstand类别的App,同样支持跨设备同步和本地restore机制。
《In-App Purchase Programming Guide》详细说明了各种类型的适用范围和特性:
其中需要特别注意的是:
1 针对Non-consumable products类型的IAP项目,苹果会要求App提供一个“恢复购买”的功能,以支持跨设备同步和本地restore。同时,如果App本身有用户帐号系统,那么用户只要付费一次,就可以通过restore机制将IAP项目无限复制到多个用户帐号下,坑爹~
因此,对于类似电子书之类的一次购买永久有效的项目,如果希望使用App本身的用户帐号系统,避开跨设备同步和本地restore机制,可以考虑选择Non-renewable subscriptions类型。同时,考虑到Non-renewable subscriptions一般是有固定有效期的,可以加一个无限长的有效期(比如9999天),以应对苹果审核。
2 Consumable products和Non-renewable subscriptions都是可以重复购买的IAP项目,前者更偏向消耗品,后者更偏向订阅品。另外还有一个区别是,针对Non-renewable subscriptions的IAP项目,用户如果之前已经买过一次,过期后再次购买或者切换App帐号后购买,支付流程中会出现一个系统弹窗提示用户之前已经购买过该项目,是否要再次购买,如果用户不小心点了取消,支付流程就会终止。
苹果设计这个弹窗的本意更多是根据Apple ID识别用户身份,避免用户重复购买相同项目。但对于有用户帐号体系的App,这个提示是有点多余的,虽然影响不大。因此,如果一个IAP项目既适用于Consumable products也适用于Non-renewable subscriptions,比较建议选择Consumable products。

1.3 定价
在创建IAP项目的时候,需要设定价格,这个价格只能从苹果预设的价格等级中选择,比如等级1对应1美元、6元人民币,等级2对应2美元、12元人民币……最高等级87对应999.99美元、6498元人民币。另外可能是为了照顾某些货币区的开发者和用户,还有一些特殊的等级,比如备用等级A对应1美元、1元人民币,备用等级B对应1美元、3元人民币这样。除此之外,IAP项目不能定一个9.9元人民币这样不符合任何等级的价格。详细价格等级表可以看苹果的官方文档:
苹果的价格等级表通常是不会调整的,但也不排除在某些货币汇率发生巨大变化的情况下,对该货币的定价进行调整,调整前苹果会发邮件通知开发者。
另外,价格等级表中不同货币的汇率关系与实际汇率存在差异,淘宝上有部分低价的iOS游戏内购代充就是利用了某些货币的汇率差来做生意。
对于开发者来说,如果App在中国区以外发布,可能需要注意一下汇率的问题。某些地区的内购结算成人民币后收入会低于相应价格等级的人民币收入,所以在一些需要严格计算实际收入的情况下(比如财务统计营收,或内购收入需要进一步与平台CP方进行分成),可能需要根据内购的实际支付货币及金额和还有相应汇率来计算收入,或者也可以用一些办法来限制某些地区的内购(在本文2.2部分会讲)。
补充说明一下,IAP项目的价格在商品发布以后是可以在itunes connect后台修改的,也可以设置限时优惠价。但是大部分联网App的内购项目价格是从自己的服务端获取的,如果要修改价格或设置限时优惠,需要两边一起处理,还是挺麻烦的。
1.4 分成
很多人都知道,App Store上的付费App和App内购,苹果与开发者默认是3/7分成。
但实际上,在某些地区苹果与开发者分成之前需要先扣除交易税,开发者的实际分成不一定是70%。从2015年10月开始,苹果对中国地区的App Store购买扣除了2%的交易税,对于中国区帐号购买的IAP,开发者的实际分成在68%~69%之间。而且中国以外不同地区的交易税标准也存在差异,如1.3中所述,如果需要严格计算实际收入,可能需要把这个部分也考虑进来。
针对不同地区的内购,内购价格和对应的开发者实际收入在苹果的价格等级表(1.3中的链接)中有详细列举。
另外,根据苹果在2016年6月的新规则,针对Auto-Renewable Subscription类型的IAP,如果用户购买的订阅时间超过1年,那么从第二年开始,开发者可以获得85%的分成。详情可查看:

1.5 结算
针对IAP的交易收入,苹果一般以5周(每年1/4/7/10月)或4周(其余月份)作为一个结算周期,并在每个结算周期结束后第33天向开发者付账。

2 IAP设计开发要点
2.1 创建和提交IAP项目
开发IAP之前需要先在itunes connect后台创建IAP商品,并按规范填写product id、商品名称、价格、截图等信息。
如果App当前版本支持新增的IAP项目,可不用发版直接提交IAP审核。如果需要App新功能配合,则需要和App版本一起提交。
《In-App Purchase Configuration Guide for iTunes Connect》详细介绍了IAP的创建和提交流程:
其中需要特别注意的是:
2.1.1 尽量不要删除已创建的IAP
已创建的IAP除了product id之外的所有信息都可以修改,如果删除了一个IAP,将无法再创建一个相同product id的IAP,也意味着该product id永久失效。而product id一般有特定的命名规则,用来标示App内的购买项目,如果命名规则下有某个product id永久失效,可能会导致整个product id命名规则都要修改,掉进坑里~
2.1.2 注意区分reference name和display name
reference name是给开发者自己看的,display name会在IAP支付流程的确认购买系统弹窗中展示给用户,而且不能随意修改(修改需要重新提交IAP审核),所以命名的时候要弄清楚。
2.1.3 当App审核被拒时
如果IAP随App版本一起提交审核,有问题时所有新提交的IAP项目和App版本会同时被拒,再次提交App审核时,一定要记得重新提交所有IAP项目(每个IAP还得要手动编辑一下才能重新提交真麻烦),否则苹果是无法继续审核的,不要傻傻的等上半个月发现苹果一点反应都没有~

2.2 IAP支付流程
这部分内容属于功能实现的逻辑,同样在《In-App Purchase Programming Guide》中有详细说明:
个人觉得产品的策划或交互也非常有必要了解一下其中的业务逻辑,才能和开发一起设计出用户体验比较好的功能方案。
具体来说,IAP的支付模式分为客户端校验和服务端校验2种模式,客户端校验模式因为容易伪造支付凭据,安全性比较低,一般只有非常简单的单机App才会使用,大部分App都会采用服务端校验模式。
另外不同类型的IAP支付流程也会有一些小差异(主要是restore机制),下面就以最常用的Consumable products和Non-renewable subscriptions类型为例,来说明一下IAP的支付流程:
  1. 用户准备购买某个项目时,App客户端通过product id向苹果API请求支付信息
  2. 手机系统弹窗验证用户的Apple ID(可能需要输入Apple ID密码或验证touch ID)
  3. Apple ID验证完成后,苹果API向App客户端返回用户将要支付的价格和货币单位
  4. App客户端再次验证product id对应的支付价格和货币单位无误(可跳过),继续请求支付
  5. 手机系统弹窗提示用户确认将要购买的内容和价格,用户点击确认购买
  6. App客户端获得苹果API返回的支付成功通知以及支付凭据,向App服务端请求校验支付凭据
  7. App服务端拿到客户端的支付凭据,再向苹果服务器请求校验支付凭据(避免一些越狱插件伪造客户端支付凭据)
  8. App服务端校验支付凭据成功,通知App客户端
  9. App收到支付凭据校验成功通知,代表用户付费成功,再处理后续业务逻辑
以上就是一个标准的IAP支付流程,看上去顺理成章,但实际上有很多坑,下面重点来讲一下需要注意的问题。

2.3 不能忽视的坑
2.3.1 延迟返回支付结果
在上述流程的步骤6,由于网络问题等种种原因,即使用户已经付款成功,客户端也可能一时半会收不到苹果API的支付成功通知,也无法主动向苹果API请求查询支付状态,只能被动等待通知。
因此有些情况下,客户端会延迟收到支付成功的通知(可能是过了几分钟,也有可能是下次打开App的时候),针对这种情况,需要做好两件事:
1 客户端本地保存所有支付结果未确认的交易信息,并设置一个监听进程,在收到支付成功的信息后,继续处理这笔交易的后续流程。极端情况下,用户在交易结果未确认的情况下删除App,保存在App本地数据库中的交易信息也会丢失,因此,更好的方案是把交易信息存到iOS系统的keychain里面
2 当本地存在支付结果未确认的交易信息时,在交互上提示用户可能需要等待支付结果,避免用户重复付款
2.3.2 服务端校验延迟
在上述流程6~8的支付凭据校验过程中,因为网络问题等各种原因,客户端可能无法及时收到服务端的校验成功通知,类似的,这种情况需要:
1 客户端本地保存支付凭据,并持续向服务端轮询校验结果,直到返回明确的校验成功或校验无效的结果。支付凭据最好也保存在keychain里面
2 在客户端向服务端轮询结果时,为了避免用户在支付结果页面等待过久,交互层面上可以先结束支付流程(经过一定超时时间),同时提示用户需要等待支付结果,避免用户重复付款
2.3.3 非官方渠道包支付失败问题
在上述流程步骤1中,如果用户安装的App不是App Store官方渠道包(从PP助手、同步推等第三方应用商店下载),苹果API会直接返回product id不存在并结束支付流程,在交互层面上表现为用户点击购买后直接提示支付失败。这个问题曾经困扰我们很长一段时间,并且网上查不到任何相似问题的信息,用尽了日志埋点和用户调研等一系列手段,最后才定位出来。
类似的,越狱设备在安装某些内购破解插件后,也会导致无法进行内购(返回product id不存在)。不过现在iOS设备的越狱比例已经非常低了,基本可以忽略。
因此,针对这个问题的解决办法是:当返回product id不存在时,提示用户安装的可能是非官方渠道包,引导用户到App Store下载官方渠道包。
2.3.4 货币校验
如本文1.3部分所述,如果App在中国区以外发布,但由于某些原因又希望限制某些地区帐号的内购,可以在上述流程的步骤4校验用户支付的货币单位,并禁止某些货币的购买。同时在交互上也要给用户相应的提示,类似不支持特殊地区帐号购买的弹窗说明。
2.3.5 未绑定App Store支付方式的用户支付流程
这是一个巨大的坑!
如果用户在内购前未绑定App Store的支付方式,在上述流程的步骤5,点击系统弹窗(第1次)的确认购买后,会自动跳转到App Store的绑定支付方式界面。接着如果顺利完成支付方式的绑定,会再自动跳转跳回App,再次出现系统弹窗(第2次)让用户确认购买。
但是,当用户点击系统弹窗(第1次)的确认购买后,苹果API会立即向客户端返回 支付失败...支付失败...失败......一般情况下,客户端收到支付失败的返回,理所应当认为支付已经取消了,而丢弃本地的交易信息。但万万没想到后面用户绑定支付方式完成后会继续确认购买,这简直就是苹果IAP系统设计的一个大bug!
如果知道了这个坑,解决方案也很简单,就是在苹果API返回支付失败时,用类似2.3.1的方式处理,保留待确认的交易信息并持续监听支付结果返回。

3 更多IAP实践经验总结
3.1 匿名购买
很多App在第一次提交IAP时都会因为不支持匿名购买被拒,原因是App Store Review Guidelines要求App在非必要的情况下,不允许强制用户注册/登录后才能使用某些功能。
一般情况下,对于没有IAP的App,强制用户注册/登录才能使用是不会被拒的(除非遇到很苛刻的审核人员),但是对于IAP,一般都会要求支持匿名购买。当然你也可以尝试编一堆原因说明为什么强制用户注册/登录是必要的(比如提供的商品或服务需要获取用户手机号或邮箱之类的理由),但也不能保证说服审核人员。
支持匿名购买,通常需要在用户未登录App帐号的情况下,临时保存用户的购买记录,并在用户登录后合并到App帐号数据。

3.2 跨平台同步
虽然在原则上,苹果不允许通过外部渠道解锁App内需要付费才能使用的功能或虚拟商品,比如在web端购买一个课程,在App内观看,但实际在某些条件下是可以做跨平台同步用户购买的内容:
1 在iOS App内也提供相应商品IAP购买的前提下,通过App帐号同步用户在不同平台上购买的内容。这条规则适用到大部分游戏上可能会比较苛刻,但是一般的内容类App都是行的通的。
2 针对电子书、音乐、视频等项目,App只提供单纯的内容阅读/观看功能,而不提供任何发现和订阅内容的功能(比如Kindle iOS版),可支持用户在外部渠道购买内容后在App中使用(具体可参考App Store Review Guidelines 3.1.3)。但实际上是否允许可能也要取决于审核人员的判断,比如云课堂曾经提交过一个版本,不能购买付费课程,但是允许用户在web端购买付费课程后在iOS端观看,就被拒了,理由是付费课程不属于上述条件的内容范畴。

3.3 虚拟币
由于IAP的价格等级机制,无法支持灵活的商品定价(如9.9元人民币)和营销功能(如优惠券抵扣等),很多App会引入虚拟币,先通过IAP内购充值特定价格的虚拟币(如6、12、18、648等),再使用虚拟币购买具体的商品。
类似IAP跨平台同步问题,iOS平台充值的虚拟币不允许和其他平台(Android、web)流通,外部平台充值的虚拟币不能在iOS平台使用,同时iOS平台充值的虚拟币也不能在外部平台使用。
但实际中,我们会发现有些App,比如喜马拉雅和得到,支持用户在微信公众号中充值虚拟币(虽然微信充值也区分了iOS平台和其他平台),再在App内使用,并且在App内的充值界面,隐晦的提示用户如果充值遇到问题,可以关注微信公众号获取客服帮助(实际上就是引导用户用微信充值)。这种做法严格意义上是不合规的,但如果苹果审核不严也能通过,算是打擦边球,估计这招效果还不错~

3.4 退款问题
根据苹果政策,用户在购买IAP后90天内,能以各种原因申请退款(扣款后购买失败、买错了、不喜欢等等),但实际能不能退成功苹果说了算。
如果一个用户申请退款成功,苹果会在与开发者结算时记一笔退款订单(当然原来购买成功的订单也在),钱就不给了,而且苹果也不会告诉你是哪个用户退款的,而且用户购买的东西还在,简直就是霸王条件~
订单数据可以在itunes connect后台的“付款和财务报告”中查看,但没有详细时间信息和用户信息,很难定位到相应的平台订单。
对于游戏或者一些自营平台来说,可能就是少点收入。而对于需要与平台CP方一一分成的产品来说,可能就要亏钱。为了解决这个问题,我们尝试设计过一套复杂的退款订单分配规则,根据IAP订单的时间周期、金额,结合平台订单的一些信息,将IAP退款订单分配到平台订单,由平台和CP方共同承担退款。但是由于开发排期原因,这个方案放了一年多至今都没做……退款都由平台承担了→_→
从历史数据来看,一般不遇到大量恶意退款的情况下,IAP的退款率可能在1~3%之间(取决于App内容质量、用户心情,还有苹果的心情)。对于IAP营收额很大的App,可能需要考虑一下退款的问题。

3.5 支付成功率
云课堂曾经对比过iPhone端使用支付宝/微信支付(注意:绕过IAP使用第三方支付属于违规行为,可能导致应用下架或开发者被封号,切勿模仿!)和IAP的支付数据,发现第三方支付的用户支付成功率大概是IAP的2~3倍,反映在营收上也差了2倍多。
不难理解,国内App Store的用户支付习惯肯定不如第三方支付成熟。而经过进一步的用户问卷调研,发现影响IAP支付成功率的因素有很多方面:
1 用户安装的App来自第三方应用商店或使用越狱设备,无法使用IAP支付(约5%用户)
2 用户未绑定App Store支付方式(约75%用户,数据很惊人)
3 用户在IAP支付过程绑定支付方式遇到问题,放弃了(约50%用户)
以上数据仅代表云课堂iPhone端的用户群,某种意义上也说明云课堂的用户比较小白(产品本身的目标用户很大一部分就是小白),没接触过IAP这种支付方式。不同产品的目标用户群的App Store内购使用习惯肯定也存在差异。
不过,随着App Store内购的普及(一方面是游戏内购带动,另一方面也得益于苹果的推广,比如经常搞一些App一元购活动,还有从2016年11月开始支持绑定支付宝),用户的内购习惯也在持续养成,从数据上也能看出IAP支付成功率的上升趋势,对于接入IAP的产品是利好的。


网易云大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者李振煜授权发布