Session: WWDC2018 Best Practices and What’s New with In-App Purchaseshtml
对于一个标准的 IAP 流程,大体以下图所示前端
翻译成中文就是ios
以上是苹果文档上的流程,应用到 App 的实际操做中,咱们还应该包含如下流程git
本次 WWDC 议题很好地描述了上述的细节github
通常的 App 营销活动有以下的类型算法
在iOS11.2
的时候,苹果增长了以下类和接口便于开发者实现上述业务流程(只针对自动续期订阅的场景)swift
@available(iOS 11.2, *)
open class SKProductDiscount : NSObject {
@available(iOS 11.2, *)
open var price: NSDecimalNumber { get }
@available(iOS 11.2, *)
open var priceLocale: Locale { get }
@available(iOS 11.2, *)
open var subscriptionPeriod: SKProductSubscriptionPeriod { get }
@available(iOS 11.2, *)
open var numberOfPeriods: Int { get }
@available(iOS 11.2, *)
open var paymentMode: SKProductDiscount.PaymentMode { get }
}
复制代码
以上的 api 对应于App Store Connect
后台中设定的推介促销价,能够设置为折扣价格或免费试用,根据适当的条件,App 能够为符合条件的用户显示促销价。接下来咱们先了解一些基本概念,而后再看看如何经过以上的 api 来完成对应的业务流程。api
在App Store Connect
中能够为 App 内购买项目的每一个订阅设置和管理推介促销价,并能够针对每一个地区设置一个当前价格和一个将来推介促销价。若是建立的新价格出现重叠日期,则最新一次操做将覆盖现有的推介促销价。操做流程以下安全
推介促销价有三种类型,分别以下服务器
提早支付
用户将一次性支付选定时限的推介促销价(例如,订阅的标准价格为 9.99 美圆,推介促销价为前 2 个月 1.99 美圆)。可设定如下时限:1 个月、2 个月、3 个月、6 个月或 1 年。
免费试用
用户在选定的时限内免费访问订阅。时限能够是 3 天、1 周、2 周、1 个月、2 个月、3 个月、6 个月或 1 年。
促销价的展现依赖于用户的购买状态,对于未购买的用户,确定符合促销价的条件。若是用户已经付费,经过用户本地的付费收据,能够判断用户是否符合促销订价的条件。若是能够的话,经过App的业务后台进行一次预判断会更好。若是用户已付费,具体流程以下
Subscription Trial Period
字段和Subscription Introductory Price Period
字段总结一下,符合促销订价的用户,只有如下两种类型
if SKPaymentQueue.canMakePayments() {
let request = SKProductsRequest(productIdentifiers:
self.productIdentifiers as Set<NSObject>)
request.delegate = self
request.start()
}
public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse)
{
let products = Set<SKProduct>(response.products)
if (products.count != 0) {
for var i = 0; i < products.count; i++
{
let product = products[i] as? SKProduct
let introductoryPrice: SKProductDiscount = product.introductoryPrice //这里获取促销订价的对象
//假设咱们设定了一个付费周期为3个月,头两个月以促销价结算的商品,而且付费方式后台设定是随用随付,它的值展开以下所示
/* * introductoryPrice.price = 1.99 * introductoryPrice.priceLocale.localizedString = "1.99" //本地化货币价格 * introductoryPrice.subscriptionPeriod.unit = .month //以月为周期 * introductoryPrice.subscriptionPeriod.numberOfUnits = 3 //1个周期为3个月 * introductoryPrice.numberOfPeriods = 2 * introductoryPrice.paymentMode = .payAsYouGo //随用随付 */
}
} else {
println("No products found")
}
let invalidproducts = response.invalidProductIdentifiers
for product in invalidproducts
{
println("Product not found: \(product)")
}
}
复制代码
咱们一样能够为普通 App 设置试用体验,等用户付费之后再解锁相关功能,这是iOS12
发布之后,App Store Review Guidelines
中新增的功能(6月4日更新的版本)
3.1.1 In-App Purchase: Non-subscription apps may offer a free time-based trial period before presenting a full unlock option by setting up a Non-Consumable IAP item at Price Tier 0 that follows the naming convention: “14-day Trial.” Prior to the start of the trial, your app must clearly identify its duration, the content or services that will no longer be accessible when the trial ends, and any downstream charges the user would need to pay for full functionality. Learn more about managing content access and the duration of the trial period using Receipts and Device Check.
意思是你能够对你的付费 App 设置一个14天
的免费试用期(此时用户实际上已发起了付费信息,安装 App 后在 bundle 里面含有票据),当试用期满之后,内容或服务再也不容许访问,用户须要付费才能够继续使用。
若是使用了该特性的 App ,在提交AppStore
审核的时候,必须注意如下三点避免被拒风险
此功能是App Store Connect
新增的功能,只须要前端配合展现相关内容信息便可
应用内评价是iOS10.3
新增的功能,该功能使用了私有方法来分析当前是不是向用户询问评分的好时机,因此苹果强烈建议开发者不要在响应用户行为时调用此方法。例如,若是你把请求评分放在按钮触摸的回调函数里,但此时 iOS 可能决定不显示评分,因此用户就会认为 App 的功能出现了问题。另外一方面,也不要太早让用户评分,最好等 App 运行几回以后再询问评分。尽管咱们并不了解苹果的算法,但咱们知道此方法的行为模式,因此最好在肯定用户处于合适的时间时再进行调用。
在本地调试代码的时候,也就是说每次进行请求调用,评分对话框都会显示,但没法提交评分。在Testflight
中,请求都不会被经过,因此若是Testflight
测试时评分对话框没有正确显示,不要慌张。App 上架后,就会在合适的时间显示对话框了。本次会议,苹果的工程师还特别强调了两种限制场景
365
天内是有限制的。根据苹果人机交互文档中的说明,The system automatically limits the display of the prompt to three occurrences per app within a 365-day period
,也就是说一年以内最多只会出现三次。if(canShowReview()/*通常是App业务的判断,如是否知足活跃用户等条件*/){
SKStoreReviewController.requestReview() /*这个调用将会异步出现对话框,因此不会阻塞当前流程*/
recordShowTimes()/*应该有节操地调用评分弹窗的接口*/
/* * 为何这里须要增长showtime这个维度呢?考虑一下这个场景 * 已经判断是活跃分子,调用苹果api,这个时候苹果的算法判断须要出现弹窗 * 用户点取消 * 第二次App启动后,用户又触发了弹窗的知足条件,这个时候依然知足苹果的算法 * 弹窗再次出现 * 此时已构成骚扰,用户给差评的几率大大上升,所以showtime的这个维度仍是很是值得加入到产品逻辑中去的 */
}
func canShowReview() -> Bool
{
// Local business rules
}
复制代码
应用内评价弹窗确实有次数限制,可是苹果仍是给开发者留了一手,如今只须要给AppStore
商店连接加上?action=write-review
便可,如https://itunes.apple.com/us/app/itunes-u/id490217893?action=write-review
,这样用户就能够跳转页面并弹起评价弹框。因此对于上述的流程,咱们能够再扩展一下
if(canShowReview()/*通常是App业务的判断,如是否知足活跃用户等条件*/){
if(isLimited()/*应用内评价窗口不能弹起*/){
//感谢苹果爸爸的接口
UIApplication.shared.openURL(myAppStoreLink()+"?action=write-review")/*跳转并提示用户进行评分*/
}else{
SKStoreReviewController.requestReview() /*这个调用将会异步出现对话框,因此不会阻塞当前流程*/
recordShowTimes()/*应该有节操地调用评分弹窗的接口*/
}
}
复制代码
因为付费功能如此重要,通常咱们在上线前都但愿先在测试环境下进行调试,苹果对于 IAP 也相应地给开发者配套了沙盒环境。
SKMutablePayment
对象的
simulatesAskToBuyInSandbox
设置为
YES
才会连到苹果的沙箱环境。 测试自动更新类 IAP 时,有一个不一样之处:该购买是有周期的。订阅会于5次更新后做废。看到这里你确定会想:"等等,要是我设置了每个月的订阅,要测试过时得等到5个月后?" 实际上,自动更新的 IAP 在沙箱环境下,周期是会加速的,更新是按分钟或小时计算。对应的时间表以下所示
关于付费票据的处理过程,去年的WWDC2017
已经有详细讨论过了,推荐阅读这篇文章,此次会议讨论了一些代码上的使用细节
对于SKPaymentTransactionObserver
的回调处理,应该注册在 App 启动的时候,这样咱们能第一时间知道用户是否完成购买流程
class AppDelegate: UIResponder, UIApplicationDelegate, SKPaymentTransactionObserver {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
SKPaymentQueue.default().add(self)
return true
}
复制代码
这是由于用户的购买流程跟 App 生命周期不挂钩致使的,典型的有如下几个场景
正确理解购买流程中的各状态表明的意义,是很是关键的
public enum SKPaymentTransactionState : Int {
case purchasing // Transaction is being added to the server queue.
case purchased // Transaction is in queue, user has been charged. Client should complete the transaction.
case failed // Transaction was cancelled or failed before being added to the server queue.
case restored // Transaction was restored from user's purchase history. Client should complete the transaction.
@available(iOS 8.0, *)
case deferred // The transaction is in the queue, but its final status is pending external action.
}
复制代码
结合上述代码,咱们看一下下面的这个对应表
Transaction State | Action Needed |
---|---|
.purchasing |
不须要作什么,继续等待SKPaymentTransactionState 的状态流转 |
.purchased |
用户已完成付费,处理付费后的流程并调用finishTransaction 方法 |
.failed |
用户付费失败,处理付费失败的流程并调用finishTransaction 方法 |
.restored |
用户已完成付费,处理付费后的流程并调用finishTransaction 方法 |
.deferred |
不须要作什么,继续等待SKPaymentTransactionState 的状态流转 |
deferred
这个状态比较特殊,通常是家长控制致使的,即该购买请求会发送到孩子的家长账号上,若是家长赞成付费,该付费流程才能完成。可是deferred
不会永远是deferred
,有一个对应的过时时间以下图所示
对于购买完成的这个流程咱们须要当心处理,否则一不当心就成为一个 App 漏洞形成较大损失(对于游戏项目而言确实是很可怕的事情)
finishTransaction
方法,否则该方法会阻止全部的下载流程,而且没法从新下载这已是一个很老的话题了,此次会议从新再整理几个要点
Server-to-Server
的方式去验证,前端环境是不可信任的SKReceiptRefreshRequest
的接口,能够向苹果后台从新请求用户的付费票据,这个流程是异步的App Store Connect
后台中更新了收费类型,理应对用户已付费过的功能进行保持而不是从新收费苹果此次会议中介绍的新功能,有很多是针对自动订阅付费场景,自动订阅是指用户能够购买指定时间期限内的更新和动态内容,除非用户取消选择,不然订阅(例如杂志订阅等)会自动续订。而对于中国区的开发者而言,更常见的场景是一次性付费,如王者荣耀中的充值功能,微信读书中的买书功能等。所以暂时而言,苹果的一些关于 IAP 的新功能,在中国开发者的眼里并非太有用。对比一下国内的一些 IAP 管理后台,如腾讯的米大师等,在功能的便利性和普适性上还有很大的差距,但愿苹果后面能对IAP的相关功能投入更大的精力去开发和升级,为开发者提供更好用的应用管理平台。
参考资料
苹果文档 In-App Purchase Best Practices
Offering Introductory Pricing in Your App
Validating Receipts With the App Store
查看更多 WWDC 18 相关文章请前往老司机x知识小集xSwiftGG WWDC 18 专题目录