思維導圖
前言
在 AppStore 里,付費應用的下載量往往比免費應用的下載量少的多。上架過應用的開發者,可能會有這樣的體會:當一個應用免費的時候,每天能有幾十上百次的下載,但是一旦設置為收費的時候,下載量立即暴跌,即使只設成了一元,可能好幾星期都沒人下載。
收費的應用不好做,與其長時間零下載,還不如設置為免費,每天看看下載量來的舒服。
但是作為一個開發者,開發免費應用的動力,顯然比不上開發收費應用。應用免費了,開發的動力也少了。因此,我們可以考慮在應用里面加入內購買項目,通過免費下載吸引用戶,再用內購買項目讓用戶按需購買,自己賺點零花錢。
本文將用一個真實的例子(已上架 AppStore:Catch - 捕捉稍縱即逝的靈感),介紹為 App 添加內購買項目的流程。
必要的準備
添加內購買項目之前,需要有一個付費的開發者賬號,并在開發者賬號的“協議、稅務和銀行業務”里完善銀行卡等信息,否則 Apple 無法將應用的收入轉給你。
你還需要準備一個已上架或者未上架的應用,應用在首次添加內購買項目時需要與新的應用版本一起提交審核。
內購買項目的用戶界面
在添加內購買項目前,你需要在你的應用里,自己設計好商品展示的界面,Apple 只負責購買的流程。這個界面在接下去新建內購買項目時也會用到。
下圖是一個實際應用的內購商品展示界面:
在 iTunesConnect 上新建內購買項目
接下來,在 iTunesConnect 上的應用頁面,選擇“功能”-“App 內購買項目“,點擊加號新建項目,如下圖:
之后會要求選擇內購買項目的類型,這里以“消費型項目”為例。在接下來的表里填寫相應的信息。產品 ID 一般以 App 的 Bundle ID 為前綴再加上自定義的產品后綴,如:com.self.purchase1。在審核信息里上傳剛剛的內購商品展示界面,供審查員審核。其他信息自行填寫即可。
新建內購買項目后,在內購買項目列表里顯示為“準備提交”狀態。現在在準備提交的 App 版本中添加剛剛新建的內購買項目。
完成內購買相關代碼
關于內購買的代碼,本文將使用一個現成的框架:SwiftyStoreKit,這樣有利于理清思路。對于直接使用 StoreKit 完成整個內購買的流程,將在下一篇文章里討論。
首先在項目里添加 SwiftyStoreKit 框架。具體添加的方法上面的鏈接里已有說明。
總共的代碼有三部分,如下:
一、獲取商品信息,用于在界面上顯示:
SwiftyStoreKit.retrieveProductsInfo([productID]) {[weak self ] result in
if let product = result.retrievedProducts.first {
let priceString = product.localizedPrice!
print("Product: \(product.localizedDescription), price: \(priceString)")
}else if let invalidProductId = result.invalidProductIDs.first {
print("Could not retrieve product info .Invalid product identifier: \(invalidProductId)")
}else {
print("Error: \(result.error)")
}
}
商品信息包括商品的價格和名稱,保存在 SKProduct
對象里。匯率的問題 Apple 已經幫我們處理好,商品的名稱會根據我們在 iTunesConect 里填寫的本地化信息自動選擇,因此我們只需要直接使用 localizedPrice
和 localizedTitle
或 localizedDescription
。
二、購買商品(當用戶點擊購買后):
func purchase(_ productID: String) {
SwiftyStoreKit.purchaseProduct(productID, atomically: true) { [weak self] result in
if case .success(let product) = result {
// Deliver content from server, then:
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
}
if let alert = self?.alertForPurchaseResult(result) {
self?.showAlert(alert)
}
}
}
productID
就是內購買項目的 ID,如:com.self.appname.purchase1。productID
可以事先在程序中定義,如果想從網絡上獲取 productID
的話,只能從自己的服務器中獲取,iTunesConnect 并不提供獲取內購買商品列表的 API。
三、完成購買事務:
func completeIAPTransactions() {
SwiftyStoreKit.completeTransactions(atomically: true) { products in
for product in products {
if product.transaction.transactionState == .purchased || product.transaction.transactionState == .restored {
if product.needsFinishTransaction {
// Deliver content from server, then:
SwiftyStoreKit.finishTransaction(product.transaction)
}
print("purchased: \(product.productId)")
}
}
}
}
在 application:didFinishLaunchingWithOptions 里調用上述的函數。因為 Apple 建議在 app 載入的時候為購買事務添加一個觀察者:
Adding your app's observer at launch ensures that it will persist during all launches of your app, thus allowing your app to receive all the payment queue notifications.
SwiftyStoreKit 用 completeTransactions 函數實現了這個功能。這樣,如果在載入的時候有任何進行中的事務,就可以對它們進行處理,更新 app 的狀態和 UI。
內購買測試
完成內購買的代碼后,在提交審核之前,還應該對它進行測試。Apple 為應用內購買項目提供了沙箱(sandbox)測試,讓你使用虛擬的貨幣模擬內購過程。
a) 在 iTunesConnect 的“用戶與職能”里添加沙箱技術測試員。
b) 在 iPhone 設置里的 “iTunes Store 與 App Store” 將原來的賬號注銷。但是不要登陸測試員的賬號。
c) 打開待測試內購買的 app,點擊內購買的項目進行購買。這時候,會提示登錄 App Store,使用沙箱測試員的賬號登錄。
d) 之后會彈出購買信息確認窗口,注意窗口內的提示信息 “Environment: Sandbox“,表示是在沙箱中測試,購買的貨幣是虛擬的。如果沒有這一行的話,則是在真實的環境中進行交易,使用的就是真實的貨幣了。
結語
測試完成后就可以提交審核了。如果是首次添加內購買項目,記得在 app 審核頁添加內購項目一起提交審核。當再次添加內購買項目,就可以獨立審核內購買項目,而無需提交新的 app 版本。當然,這樣做的前提是 app 能夠從自己的服務器上獲取內購買項目的 productID,否則 app 無法獲取新內購買項目的信息。
本文是以消費性內購買項目為例,對于其他類型的內購買項目,方法大同小異,更多的信息請參考官方文檔。
歡迎訪問我的Github:LinShiwei (Lin Shiwei) · GitHub
有任何疑問的話,歡迎在下方評論區討論。