iOS:為 App 添加內購買項目

思維導圖

前言

在 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 里填寫的本地化信息自動選擇,因此我們只需要直接使用 localizedPricelocalizedTitlelocalizedDescription

二、購買商品(當用戶點擊購買后):

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

有任何疑問的話,歡迎在下方評論區討論。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,643評論 25 708
  • 原文地址:http://blog.csdn.net/xiaominghimi/article/details/69...
    LuxDark閱讀 6,005評論 2 4
  • 在我們應用開發中我們經常在自己的項目中使用到支付,下面我們來談談iOS這塊的支付;iOS支付主要分為兩類,第三方支...
    Hither閱讀 8,307評論 9 42
  • 現實真的很殘酷,身邊沒有一個真心朋友,經歷多了,就很難再把自己的心交出去。 “你以為別人都和你想的一樣嗎,真心...
    DYdream閱讀 261評論 0 0
  • 如果次元允許,我想活在動漫里! 我向黨和人民保證,我有了特異功能一定不會干違法亂紀的事。 (胸前的紅領巾更鮮艷了呢...
    小酒官兒閱讀 362評論 0 1