WWDC 2018:IAP最佳實踐並加強活動營銷功能

Session: WWDC2018 Best Practices and What’s New with In-App Purchaseshtml

對於一個標準的 IAP 流程,大體以下圖所示前端

標準的IAP流程

翻譯成中文就是ios

  1. 設置商品 ID(跟 ITC 上面的 ID 一致)
  2. 根據商品 ID 去蘋果後臺獲取商品信息,這時會得到商品名字、價格等信息
  3. 把 IAP 的購買界面展現給用戶,用戶能夠贊成購買並點擊購買按鈕。
  4. 用戶受權購買,客戶端向服務器發送購買請求。
  5. 此時購買流程狀態變動,客戶端根據蘋果規定的狀態機流程處理回調
  6. 若是購買請求驗證經過,客戶端此時解鎖內容或者提供金幣。
  7. 至此,整個交易流程結束。

以上是蘋果文檔上的流程,應用到 App 的實際操做中,咱們還應該包含如下流程git

  1. 營銷活動配置
  2. 試用功能控制
  3. 沙箱聯調流程
  4. 安全性校驗

本次 WWDC 議題很好地描述了上述的細節github

App 訂價策略

通常的 App 營銷活動有以下的類型算法

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 內購買項目的每一個訂閱設置和管理推介促銷價,並能夠針對每一個地區設置一個當前價格和一個將來推介促銷價。若是建立的新價格出現重疊日期,則最新一次操做將覆蓋現有的推介促銷價。操做流程以下安全

  1. 在首頁上,點按「個人 App 」,而後選擇與該 App 內購買項目相關聯的 App。
  2. 在工具欄中,點按「功能」,而後在左列中點按「App 內購買項目」。
  3. 點按自動續期訂閱,前往「訂閱價格」部分,而後點按「添加」按鈕(+)。
  4. 選擇「設置推介促銷價」。
    Set_an_introductory_price_for_an_auto-renewable_subscription_iOS-tvOS-macOS_Create_an_introductory_price_Step4
  5. 選擇想要提供折扣價格的地區,而後再點按「下一步」。
    Set_an_introductory_price_for_an_auto-renewable_subscription_iOS-tvOS-macOS_Create_an_introductory_price_Step5
  6. 選擇開始和結束日期。若是想讓推介促銷價無限期使用,能夠選擇「無結束日期」。而後點按「下一步」。
  7. 選擇「隨用隨付」、「提早支付」或者「免費試用」,而後選擇合適的時限、貨幣和價格。點按「下一步」。
    Set_an_introductory_price_for_an_auto-renewable_subscription_iOS-tvOS-macOS_Create_an_introductory_price_Step7
  8. 蘋果會根據您選擇的價格點自動爲全部地區計算價格,但您能夠爲特定地區設定不一樣的價格。在此處選擇地區價格,而後點按「完成」。
    Set_an_introductory_price_for_an_auto-renewable_subscription_iOS-tvOS-macOS_Create_an_introductory_price_Step8

推介促銷價有三種類型,分別以下服務器

  1. 隨用隨付
    用戶將按選定時限的每一個結算週期支付推介促銷價(例如,訂閱的標準價格爲 9.99 美圓,推介促銷價爲前 3 個月每個月 1.99 美圓)。
    結算週期可設定如下時限:
  • 1 周訂閱,1 至 12 周
  • 1 個月訂閱,1 至 12 個月
  • 2 個月訂閱,二、四、六、八、10 和 12 個月
  • 3 個月訂閱,三、六、9 和 12 個月
  • 6 個月訂閱,6 和 12 個月
  • 1 年訂閱,1 年
  1. 提早支付
    用戶將一次性支付選定時限的推介促銷價(例如,訂閱的標準價格爲 9.99 美圓,推介促銷價爲前 2 個月 1.99 美圓)。可設定如下時限:1 個月、2 個月、3 個月、6 個月或 1 年。

  2. 免費試用
    用戶在選定的時限內免費訪問訂閱。時限能夠是 3 天、1 周、2 周、1 個月、2 個月、3 個月、6 個月或 1 年。

符合促銷訂價的用戶

促銷價的展現依賴於用戶的購買狀態,對於未購買的用戶,確定符合促銷價的條件。若是用戶已經付費,經過用戶本地的付費收據,能夠判斷用戶是否符合促銷訂價的條件。若是能夠的話,經過App的業務後臺進行一次預判斷會更好。若是用戶已付費,具體流程以下

  1. 讀取用戶本地存儲的付費票據信息
  2. 判斷票據信息中Subscription Trial Period字段和Subscription Introductory Price Period字段
  3. 若是這兩個字段中有一個爲true,表示用戶已經正在享受促銷訂價週期,因爲每一個訂閱羣組的新顧客和從新訂閱的顧客只可享受一次折扣價或免費試用,所以這個時候用戶並不符合促銷訂價的條件

總結一下,符合促銷訂價的用戶,只有如下兩種類型

  1. 新的購買者
  2. 續期訂閱的購買者而且以前沒有享受過促銷訂價

相關代碼

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審覈的時候,必須注意如下三點避免被拒風險

  1. App 在醒目的位置聲明瞭試用期的剩餘時間
  2. 給用戶展現解鎖功能的費用
  3. 明確說明,當試用期結束時,有哪些產品特性或本地內容將會丟失

如何使用

此功能是App Store Connect新增的功能,只須要前端配合展現相關內容信息便可

應用內評價

應用內評價是iOS10.3新增的功能,該功能使用了私有方法來分析當前是不是向用戶詢問評分的好時機,因此蘋果強烈建議開發者不要在響應用戶行爲時調用此方法。例如,若是你把請求評分放在按鈕觸摸的回調函數裏,但此時 iOS 可能決定不顯示評分,因此用戶就會認爲 App 的功能出現了問題。另外一方面,也不要太早讓用戶評分,最好等 App 運行幾回以後再詢問評分。儘管咱們並不瞭解蘋果的算法,但咱們知道此方法的行爲模式,因此最好在肯定用戶處於合適的時間時再進行調用。

注意

在本地調試代碼的時候,也就是說每次進行請求調用,評分對話框都會顯示,但沒法提交評分。在Testflight中,請求都不會被經過,因此若是Testflight測試時評分對話框沒有正確顯示,不要慌張。App 上架後,就會在合適的時間顯示對話框了。本次會議,蘋果的工程師還特別強調了兩種限制場景

  1. 對於一個應用而言,該函數的調用次數在同一設備上,365天內是有限制的。根據蘋果人機交互文檔中的說明,The system automatically limits the display of the prompt to three occurrences per app within a 365-day period,也就是說一年以內最多隻會出現三次
  2. 用戶能夠在設置中關閉應用內彈窗功能

相關代碼

if(canShowReview()/*通常是App業務的判斷,如是否知足活躍用戶等條件*/){
	SKStoreReviewController.requestReview() /*這個調用將會異步出現對話框,因此不會阻塞當前流程*/
	recordShowTimes()/*應該有節操地調用評分彈窗的接口*/
	/* * 爲何這裏須要增長showtime這個維度呢?考慮一下這個場景 * 已經判斷是活躍分子,調用蘋果api,這個時候蘋果的算法判斷須要出現彈窗 * 用戶點取消 * 第二次App啓動後,用戶又觸發了彈窗的知足條件,這個時候依然知足蘋果的算法 * 彈窗再次出現 * 此時已構成騷擾,用戶給差評的機率大大上升,所以showtime的這個維度仍是很是值得加入到產品邏輯中去的 */
}

func canShowReview() -> Bool 
{
	// Local business rules
}
複製代碼

One more thing

應用內評價彈窗確實有次數限制,可是蘋果仍是給開發者留了一手,如今只須要給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已經有詳細討論過了,推薦閱讀這篇文章,此次會議討論了一些代碼上的使用細節

Transaction Observer

對於SKPaymentTransactionObserver的回調處理,應該註冊在 App 啓動的時候,這樣咱們能第一時間知道用戶是否完成購買流程

class AppDelegate: UIResponder, UIApplicationDelegate, SKPaymentTransactionObserver {
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    SKPaymentQueue.default().add(self)
    return true
}
複製代碼

這是由於用戶的購買流程跟 App 生命週期不掛鉤致使的,典型的有如下幾個場景

  • 用戶殺死了 App
  • 用戶須要更新賬號中的付費信息(此時已跳出 App )
  • App 閃退
  • 用戶進行了訂閱續期
  • 用戶進入了推介促銷價的流程
  • 用戶跳出 App 輸入推廣碼

Transaction State

正確理解購買流程中的各狀態表明的意義,是很是關鍵的

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,有一個對應的過時時間以下圖所示

過時時間

Finishing Transactions

對於購買完成的這個流程咱們須要當心處理,否則一不當心就成爲一個 App 漏洞形成較大損失(對於遊戲項目而言確實是很可怕的事情)

  • 確保付費內容都已從蘋果後臺下載,而後才調用finishTransaction方法,否則該方法會阻止全部的下載流程,而且沒法從新下載
  • 必定要經過業務後臺去校驗票據,不要在前端直接校驗

用戶票據的處理

這已是一個很老的話題了,此次會議從新再整理幾個要點

  • 票據驗證必定是經過Server-to-Server的方式去驗證,前端環境是不可信任的
  • 票據的失效日期比對,不要經過用戶的本地時間(能夠人爲變動),而應該根據票據中的購買時間(已固化沒法變動)去比對
  • 本地票據由一個通過簽名的 PKCS #7 容器組成,開發者能夠實現本身獨有的的收據驗證代碼
  • 經過SKReceiptRefreshRequest的接口,能夠向蘋果後臺從新請求用戶的付費票據,這個流程是異步的
  • 經過遍歷票據內容,能夠判斷用戶是否繼續處於試用版的流程中,默認認爲用戶處於試用版
  • 若是在App Store Connect後臺中更新了收費類型,理應對用戶已付費過的功能進行保持而不是從新收費

總結

蘋果此次會議中介紹的新功能,有很多是針對自動訂閱付費場景,自動訂閱是指用戶能夠購買指定時間期限內的更新和動態內容,除非用戶取消選擇,不然訂閱(例如雜誌訂閱等)會自動續訂。而對於中國區的開發者而言,更常見的場景是一次性付費,如王者榮耀中的充值功能,微信讀書中的買書功能等。所以暫時而言,蘋果的一些關於 IAP 的新功能,在中國開發者的眼裏並非太有用。對比一下國內的一些 IAP 管理後臺,如騰訊的米大師等,在功能的便利性和普適性上還有很大的差距,但願蘋果後面能對IAP的相關功能投入更大的精力去開發和升級,爲開發者提供更好用的應用管理平臺。


參考資料

蘋果文檔 In-App Purchase Best Practices

Offering Introductory Pricing in Your App

爲自動續期訂閱設定推介促銷價

Validating Receipts With the App Store

App Store Guidelines最新版

基於Swift最流行的StoreKit封裝庫

騰訊米大師文檔

查看更多 WWDC 18 相關文章請前往老司機x知識小集xSwiftGG WWDC 18 專題目錄

相關文章
相關標籤/搜索