消耗型
消耗性的用户购买之后会生成一个 receipt,这个 receipt 会一直保存到用户下一次购买,用户再次购买,该凭证被刷新,之前购买的凭证无法找到了
非消耗型
自动续订
非自动续订
消耗性的用户购买之后会生成一个 receipt,这个 receipt 会一直保存到用户下一次购买,用户再次购买,该凭证被刷新,之前购买的凭证无法找到了。
消耗性的用户退款之后没有 cancellation_date 字段,也就是说无法知道用户是否退款
自动续订的购买方式可以把 支付凭证想象成一个 token,如果用户退款(refund),服务器拿这个凭证去苹果校验的时候,苹果通过设置 cancellation_date 的方式告诉服务器用户取消订阅了。
非消耗性和不自动续订的订阅如果用户退款,服务器拿这个凭证去苹果校验,苹果不会设置 cancellation_date 告诉你用户退款了。
这种情况如果想知道用户是否退款,需要 app 本地使用 SKReceiptRefreshRequest 或者 restoreCompletedTransactions 来刷新凭证,然后将凭证传给后台,后台拿着新的凭证找苹果校验,此时退款的用户会返回带 cancellation_date 的解码凭证。
上述刷新凭证的方式最大的问题是每次刷新都会触发 iOS 系统弹出它自己的一个登录框,要求用户输入 Apple ID 的帐号密码。所以苹果建议不要自动刷新凭证,在界面上放一个 restore 按钮,用户点击之后再去触发。
想通过刷新凭证来知道用户是否退款比较难,因为系统弹出的 Apple ID 登录框用户可以点击取消不登录,这时,无论如何也不可能刷新凭证了。当然下次购买或者卸载重新从 AppStroe 安装是否会刷新这个凭证存疑。
iOS7 及以后的系统下载 app 会带有 appStoreReceiptURL 文件,但是 Xcode 开发 cmd+r 跑起来的以及其他途径安装的 app 很可能没有这个文件,需要刷新。
更正:iOS7 以上的系统下载 app 在没有购买过的情况下不会有这个文件。
不自动续订这种方式无法在苹果的 itunesconnect 网站上设置过期时间,提醒用户购买有效时间可以在购买项的名字里面写上去,所以设置过期时间需要开发者自己维护。通常来说设备上的时间戳是无法信任的,所以最好搞一个服务器来维护。
内购无法设置任意金额,只能设置网站上给的那几项。
测试没有通过审核的内购的时候,如果通过非沙盒用户的方式,每次测试都会失败,说连接不上 iTunesStore,这时,你需要去申请沙盒用户,用这个用户来测试。
非消耗性的沙盒测试,如果你买过了,下次测试的时候直接就付款成功了,没法再次测整个购买流程,所以需要重新搞一个沙盒测试帐号。
有些邮箱可以提供别名的功能,如果要建一个沙盒测试帐号,可以使用别名而不是每次都真的去创建一个新的帐号。
越狱设备就不要考虑 IAP 了,因为现在越狱设备很少了。
内购的 restore 只支持非消耗品和自动续订,另外两个,消耗性和非自动续订不支持,其中非自动续订的 restore 可以依靠开发者自己来维护。
SwiftStoreKit 这个库的 completeTransactions 方法针对的是 pending transtraction,使用 purchase 相关的 api 不会触发这个 completeTransactions 的回调。
如果觉得 IAP 难用,是的,没错,之所以难用是因为苹果为了保护用户隐私和苹果自己的数据。我们能做的就是信任它。
applicationUsername 这个东西无法给你想要的。但是苹果在文档里面说这个可以防止欺诈等行为,所以能用就用,传入用户ID 的 hash 就行。
在添加了 observer 之后,如果有未完成的 transaction,那么 paymentQueue:updatedTransactions: 会被调用,但是如果在这个方法里没有 finishTransaction 的话,这个函数会一直等到下次启动添加 observer 的时候才会被调用。所以为了避免等待下次启动才去 finishTransaction,可以通过不断的观察 SKPaymentQueue.default().transactions 的值来按需 finish。
如果一笔交易没有调用 finishTransaction 这个函数,那么对于同一个 product id 的购买,iOS 系统会提示已经购买过,并为用户免费恢复。同时,不会再次回调 delegate (存疑,我用的是 SwiftyStore,回调闭包没有执行)。这种情况需要在 app 发起购买之前判断是否当前有同样的一个 product id 的未完成订单,并在必要情况下给予 finish,不需要再重复发起购买了。
用户购买 app 以后(无论是付费购买还是免费的),iOS 就会生成一个凭证放在 appStoreReceiptURL 路径中。
app 发起了购买,然后 kill 掉 app,此时用户完成付款,那么虽然你可以拿到苹果告诉你的未完成的交易,但是在这笔交易发生的时候产生的其他公司业务相关的信息就找不到了。所以,最好在购买发起之前存储这些信息。