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 專題目錄