Apple IAP 二三事
2020/5/1 23:02:40
本文主要是介绍Apple IAP 二三事,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、概述
1、简介
-
IAP (
In-App Purchase
)即应用内购买,是App内购买「虚拟数字产品」的支付方式;Android
和iOS
都有IAP
支付;判断APP是否需要IAP的标准:用户付费购买的商品/服务是否为「虚拟数字产品」; -
更通俗的解释:看商品/服务的实际消费场景是在 App 内,还是 App外;如果在 App内即可完成消费的,苹果要求使用 IAP,如电子书、充值类虚拟货币、游戏/直播中道具等;在App外完成消费,可以使用第三方支付;典型如线下电影票、实物电商、打车、外卖等。
-
Apple对IAP态度严苛,很大一部分原因是:Apple可以从IAP支付流水中,抽成30%;很多App不愿意使用IAP支付,通过欺骗审核方式绕开IAP支付,其实这会给App带来非常大的风险,严重可能导致App被下架。
2、IAP商品种类
-
消耗型项目:只可使用一次的产品,使用之后即失效,必须再次购买,如:游戏币、一次性虚拟道具等
-
非消耗型项目:只需购买一次,不会过期或随着使用而减少的产品。如:电子书
-
自动续期订阅:允许用户在固定时间段内购买动态内容的产品。除非用户选择取消,否则此类订阅会自动续期,如:Apple Music这类按月订阅的商品
-
非续期订阅:允许用户购买有时限性服务的产品,此 App 内购买项目的内容可以是静态的。此类订阅不会自动续期
IAP商品交易成功后,Apple收取30%的手续费,如果商品是30元,你只能得到21元;不过自动续订的商品第二年开始只成15%
3、Pre Develop
-
在
iTunes Connect
后台中填写银行账户信息、配置内购商品(包括产品ID、价格等) -
在
iTunes Connect
申请 "沙盒测试人员账号",用于IAP测试使用; -
准备iPhone真机一台,IAP只能用真机测试;
-
更多细节可参考iOS内购一条龙------账户信息填写、iOS内购一条龙------配置内购产品ID 和 iOS内购一条龙------内购测试账号
沙盒(SandBox)测试人员账号 用于testflight、adhoc包的 IAP 测试 (沙盒环境),沙盒环境IAP支付并不花费money
二、支付流程对比
1、微信/支付宝の支付流程
-
目前,微信/支付宝绝对是国内最主流的第三方支付,和IAP相比,他们都提供了非常好的技术支持;(
虽无缘于支付宝,但必须给支付宝点赞!
) -
App内,微信/支付宝的支付流程简述如下:
- App内发起支付请求;(
调起微信/支付宝支付有两种,SDK方式 和 schema方式,建议前者
) - App跳到支付宝/微信客户端,引导用户完成支付;
- 用户完成支付的同时,微信/支付宝服务器回调App的服务器,告知支付结果;App中也会收到
微信/支付宝SDK
中的支付回调结果(业务上,一般不以SDK回调结果做最终结果
); - App的服务器收到回调后,完成订单验证和发货操作;
- 从微信/支付宝返回第三方App,App去自己的服务器查询商品支付结果;
- App内发起支付请求;(
-
在整个支付流程中,如果发生用户支付成功,但是的Server回调出错了(可能是网络,也可能是App服务器异常),到账用户没有收到货物,这会对支付体验造成非常大的打击;
-
但是,微信/支付宝的服务器非常靠谱:检测回调失败后会重试,能最大程度(
错误重试机制
)保证将结果同步给第三方App服务器;
2、IAPの支付流程
-
App内,IAP的支付流程,简述如下:
- App内,通过IAP API(
StoreKit
),发起支付请求; - 用户在App内完成支付;(
获取商品信息->创建交易加入到交易队列->用户支付->支付完成
) - 用户完成支付的同时,IAP 服务器回调APP,通知购买成功,并把票据(receipt)写入到 APP 沙盒中;
- App需要将票据(receipt) 上传给App服务器;
- App服务器再将票据(receipt) 发给Apple服务器去验证;只有验证成功,App服务器才能去发货。
- App内,通过IAP API(
-
在整个支付流程中,用户在端上扣款成功,只是开始;后续的支付验证至少需要保证App上传票据成功、App服务器将票据交给Apple服务器成功、App服务器获取订单验证结果成功;否则,掉单是必然出现的事情;简单来说:用户扣款成功后,IAP支付的严峻挑战开始了;
-
Apple将每次IAP支付行为被抽象成一个事务(
SKPaymentTransaction
),只有事务被正常结束(finishTransaction:
),该次支付行为才算完成。即使支付中途被中断,但是这次事务并没有丢失。eg: 支付未完成,App Crash了,下次App重启(需addTransactionObserver:
),之前被中断的事务会接着进行。StoreKit框架主要提供三部分功能:In-App Purchase(IAP,应用程序内购买)、Recommendations and reviews(建议和评论) 和 Apple Music(苹果音乐,国内几乎不用);IAP的API在StoreKit框架。
3、总结
-
对比第三方支付和IAP支付流程发现:
- 微信/支付宝的扣款后,交易验证工作是在服务器之间通讯完成的;只要用户产生了交易,他们的服务器会回调App服务器,交易的可靠性由支付宝/微信服务保证的;
- 而IAP扣款后,交易验证是App驱动App服务器完成的;但是移动设备所处的网络环境远比服务端复杂;扣款成功后,后续的下发票据 和 App上传票据都面临严峻的考验(
网络异常、App服务器异常、Apple服务器异常等
)。
-
简单来说:Apple预期将支付流程中最重要的验证环节交给了App开发者;和国内的微信/支付宝套路完全不同;
-
此外,虽然Apple为保障交易验证完成,提供了事务机制,但是事务机制最大的问题是:如果某一个事务在当次App生命周期内未能正常结束,只能在下次App重启后,中断的事务才能恢复;这其实是对用户伤害比较大:扣了款,可能很长时间收不到货。
三、优化IAP验证
1、思路
-
完善重试机制;尽可能多的重试,保证用户扣款后能比较及时收到货物;
-
建立业务订单和IAP订单映射机制;Apple只负责告诉一个交易事务成功or失败,不关心是否映射到业务订单好;
2、完善重试机制
-
不依赖苹果事务机制重试;当Apple通知用户交易成功(
SKPaymentTransactionStatePurchased
),立刻持久化交易数据到keychain,存储成功后,finish掉交易。补充1:交易数据持久化到keychain好处有二:存储到keychain的数据被加密,安全可靠;即使App被卸载,keychain中数据也不会被删除;
补充2:扣款成功后,可能苹果没有告知交易成功,可能下次甚至下下下次启动,才告知交易成功;因此,App启动后,监听交易事务队列,当收到交易事务完成通知,立刻持久化交易数据;
-
建设交易验证队列;每笔交易数据持久化成功后,尝试订单验证,验证包含两步:上传票据 和 查询订单状态;只有两步都完成,才能算一个订单验证结束;
-
丰富交易验证的时机;
- App冷启动后x秒,
keyChain
中还有没有处理完的交易,一个个去发起校验; - 用户发生新购买,扣款成功,交易数据持久化成功后,发起验证操作;
- App从后台切换到前台x秒,无网切到有网,前台停留x分钟等情况下,如果
keyChain
中有未验证完成的交易,发起验证请求; - ...
- App冷启动后x秒,
3、订单映射
- 订单映射指:业务订单和IAP订单的映射,本质是将业务订单号
orderID
绑定到苹果的交易订单上; - 发起IAP支付后,我们给Apple的是一个
SKPayment
对象,最后监听到的是SKPaymentTransaction
对象(有SKPayment
属性对象);我们可以通过利用SKPayment
的applicationUsername
字段实现订单映射; - 创建交易对象时,将业务订单号
orderID
赋值给SKPayment
的applicationUsername
;等支付成功后,通过SKPaymentTransactiond
对象的payment
获取到业务订单号orderID
,从而实现了业务订单和IAP订单映射绑定; - 重要说明:利用
applicationUsername
透传业务订单号orderID
有失败的概率,一些情况下会导致applicationUsername
透传的值丢失(订单号丢失问题
);如果不处理的话,会发生掉单; - 总的来说,利用
applicationUsername
实现订单绑定虽然有不足,但是从ROI上评估还是可行的;订单号丢失问题可以交给服务器处理:服务端只要验证交易是正确的,且该用户的确有交易记录,自动生成订单重新发货 or 最近订单(时间、金额)匹配;即便这么做,依然有case被遗漏, 但能保证大盘基本OK。
4、票据的问题
- iOS 7后(
App几乎都是iOS 9起步
),从[[NSBundle mainBundle] appStoreReceiptURL]]
中获得的receipt(票据)数据;App上传票据信息的话,将其中的数据一起上传; - iOS 7后,
[[NSBundle mainBundle] appStoreReceiptURL]]
中的票据信息是一个receipt list
(in_app
字段),本身带有“自动修复的特性”,如果用户某次支付没有正确完成,后续也没有被成功恢复;当他产生下一次成功支付后,[[NSBundle mainBundle] appStoreReceiptURL]]
中会包含这几次支付的receipt
。 - 获取不到票据情况:如监听到交易成功了,但是从
[[NSBundle mainBundle] appStoreReceiptURL]]
中获得的数据是空,遇到此类问题,可以打标记后续重试; - 票据无效,验证失败的情况也可能遇到,这时候,让用户提供了支付信息,走补偿 or 退款吧;
5、to be continued
- 保障扣过款的IAP订单尽快得到验证,是IAP问题中首要解决的问题;本节中简单介绍了相关一些思路;我相信,做好这些能hold住大多数问题;
- 虽然IAP总体体验被微信/支付宝吊打,但是由于iOS用户被教育了这么多年,Apple在新iOS版本上也有些不为认知的优化;总体上来说,IAP支付还可以,没有早年那么糟糕;
- 做好以上这些事,不是终点;优化产品体验,做好用户教育工作,也能很好帮助实现总目标。
四、IAP周边建设
1、完善监控埋点
- 支付环节中,对关键路径埋点,包括但不限于:持久化交易数据操作、上传票据操作、查询操作,结束验单操作等;
- 监控异常的情况,包括但不限于:持久化交易数据失败、上传失败,
applicationUsername
获取订单号为空、查询失败等; - 开发阶段,尽可能多展示调试日志信息;
2、响应用户反馈
- 再好的方案,也无法hold所有的IAP问题,建立用户反馈响应机制,及时响应用户反馈;关注用户关注的;
- 例1:部分用户反馈无法支付,排查发现,是网络原因导致获取SKProduct失败;因此,尝试提前拉取SKProduct;
- 例2:部分用户反馈,iOS 13上必选Crash,排查得知:iOS13把
SKProductRequst
的回调放到了子线程;如果在这个回调中有UI操作,必然Crash。 - 将典型的,数量比较多的用户反馈集中集中起来,针对问题,尝试优化方案;同时,注意安抚用户的情绪;
3、其他
-
要加强沉淀,包括但不限于:IAP优化方案、问题排查和解决记录,用户反馈和处理记录等;
-
虽然,Apple提供了Testflight包,用户可以IAP沙盒支付;针对沙盒支付,Server要做好验证,这些非真实金钱交易,要特殊处理。
参考文章
iOS 内购(In-App Purchase)总结
谈谈苹果应用内支付(IAP)的坑
iOS IAP应用内购详细步骤和问题总结指南
苹果IAP开发中的那些坑和掉单问题
贝聊 IAP 实战之见坑填坑
贝聊 IAP 实战之订单绑定
这篇关于Apple IAP 二三事的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值