Chinese (Traditional) (中文(繁體)) translation by Fuhuan (you can also view the original English article)



介紹
內購是所有希望獲得更多收入並通過其應用程序提供額外內容和功能的一項服務。 例如,對於遊戲,您可以購買寶石或硬幣,對於攝影應用程序,您可以解鎖新的效果或工具。 而且你可以使用信用卡或其他付款方式完成所有操作,而無需退出應用程序。
在本教程中,我將介紹在iTunes Connect上創建消費型和非消費型IAP產品的所有必要步驟,並且你展示需要購買這兩個項目的代碼。 我已經製作了一個帶有標籤和兩個按鈕的示例Xcode中的項目,因此請下載並按照本教程了解它的工作原理。
在iTunes Connect中創建一個Sandbox測試器
我假設您已經在iTunes Connect的“我的應用程序”部分創建了一個iOS應用程序。 你應該做的第一件事就是創建一個Sandbox Tester來測試真實設備上的IAP(不需要模擬器 - 它不支持應用內購買)。
輸入用戶和角色,轉到沙盒測試器選項卡,然後單擊測試人員旁邊的(+)號。



填寫表格以添加新的沙箱測試器。 保存完信息後,請返回到我的應用程序部分,然後單擊應用程序圖標以輸入其詳細信息並創建IAP產品。
在iTunes Connect中創建IAP產品
耗材產品
點擊功能標籤,然後點擊應用內購買旁邊的(+)標誌。 你可以一次創建一個產品,因此我們先從一個消耗品開始嘗試。



一個耗材IAP,顧名思義,就是可以買多個產物。 我們將使用它在演示應用程序中收集額外的“硬幣”。
點擊創建以初始化您的IAP項目。 在下一個屏幕上,可以設置關於產品的所有信息:
- 參考名稱:此名稱將在iTunes Connect和銷售和趨勢報告中使用。 它不會顯示在App Store上,您可以鍵入任何您想要的名稱,但不能超過64個字符。
- 產品ID:由應用程序讀取的唯一字母數字標識符,用於識別您的產品。 通常開發人員對產品ID使用的Web反向語法。 在這個例子中,我們選擇了com.iaptutorial.coins。 稍後我們會將此ID作為字符串粘貼到我們的代碼中。
- 價格:從下拉菜單中選擇價格層級。 請記住,為了在App Store上銷售您的應用內購買產品,您必須在協議,稅務和銀行業務部分申請付費應用協議。
- 本地化:為了本教程的目的,我們只選擇了英文,但您可以通過點擊(+)按鈕添加更多語言。 然後輸入顯示名稱和說明。 它們都將在App Store上可見。
- 屏幕截圖:上傳截圖以供審查。 它不會顯示在App Store中,並且它必須具有適用於您的應用平台的有效大小,因此如果您的應用是Universal,您可以上傳iPad截圖。
- 複審備註:任何有關您的IAP的其他信息,這可能對審閱者有幫助。



完成後,點擊保存,你會看到這個提示:
您的第一次應用程序內購買必須提交一個新的應用程序版本。 從應用程序的“應用程序內購買”部分選擇它,然後單擊“提交”。
非消費品
現在點擊左側列表中游戲中心按鈕正上方的應用內購買按鈕,然後添加新的IAP產品。 這一次,請選擇非消耗選項:



點擊創建並重複上述步驟。 由於這將是非消費品,用戶只能購買一次,蘋果需要恢復這種購買的能力。 如果您卸載應用並重新安裝應用,或者從具有相同Apple ID的其他設備下載應用,並且需要重新購買應用而不付費兩次,則會發生這種情況。 所以稍後我們會在代碼中添加一個恢復購買功能。
我們現在創建的產品ID是com.iaptutorial.premium,價格等級為2.99美元。 我們稱之為高級解鎖版本。
完成填寫所有字段後,請保存您的產品並返回到“應用程序內購買”頁面。 現在您應該有兩個產品的列表,其名稱,類型,ID和狀態均設置為可以提交。



點擊App Store和準備提交按鈕,回到你的應用頁面。 向下滾動到應用程序內購買部分,位於通用應用程序信息下方,然後單擊(+)按鈕添加您的IAP產品。



選擇全部並單擊完成。



最後,點擊屏幕右上角的保存,即可在iTunes Connect上配置應用內購買產品。
在iOS設備上登錄到Sandbox Tester
在學習代碼之前,還有一件事要做。 在iOS設備上轉到設置> iTunes和App Store。 如果您已使用原始Apple ID登錄,請點擊它並選擇註銷。 然後只需使用您創建的沙箱測試人員的憑據登錄即可。 登錄後,您可能會收到如下警告:
只要忽略它的信息,然後點擊取消。 您的設備會在嘗試購買時再次詢問您的沙箱登錄憑據,並會識別您的測試帳戶,因此您的信用卡將不會收取任何費用。
退出設置,通過USB線將設備插入Mac上,最後開始編碼!
代碼
如果你已經下載了我們的演示項目,你會發現應用內購買的所有必要的代碼都已經寫好了,所以如果你運行它,你會得到這樣的東西:
如果你想測試應用程序,你應該將Bundle Identifier更改為你自己的ID。 否則,Xcode的將不允許您在真實設備上運行應用程序,並且該應用程序不會識別您創建的兩個IAP產品。
輸入ViewController.swift並檢查代碼。 首先,我們為StoreKit和我們需要的代理添加了一個導入聲明,以便跟踪付款交易和產品請求。
import StoreKit class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
然後我們宣布了一些有用的觀點。
/* Views */ @IBOutlet weak var coinsLabel: UILabel! @IBOutlet weak var premiumLabel: UILabel! @IBOutlet weak var consumableLabel: UILabel! @IBOutlet weak var nonConsumableLabel: UILabel!
coinsLabel和premiumLabel將用於顯示兩種產品的購買結果。 consumableLabel和nonConsumableLabel會顯示每個IAP產品,我們以前在iTunes Connect創建者的描述和價格。現在是時候添加一些變量:
現在是時候添加一些變量:
/* Variables */ let COINS_PRODUCT_ID = "com.iaptutorial.coins" let PREMIUM_PRODUCT_ID = "com.iaptutorial.premium" var productID = "" var productsRequest = SKProductsRequest() var iapProducts = [SKProduct]() var nonConsumablePurchaseMade = UserDefaults.standard.bool(forKey: "nonConsumablePurchaseMade") var coins = UserDefaults.standard.integer(forKey: "coins")
前兩行是回顧我們的產品ID。 這些字符串與iTunes Connect的應用內購買部分中註冊的字符串完全一致非常重要。
- 的productID是我們稍後將用來檢測我們將選擇購買哪種產品的字符串。
- productsRequest是SKProductsRequest的一個實例,需要從到iTC上的應用程序搜索IAP產品。
- iapProducts是一個簡單的SKProducts數組。 請注意,SK前綴表示StoreKit,即我們將用於處理購買的iOS的框架。
最後兩行加載了布爾型和整型型兩個變量,分別用於跟踪購買硬幣和高級版本,分別為易耗品和非易耗品。
viewDidLoad中中()中的以下代碼在應用程序啟動後立即執行一些操作:
// Check your In-App Purchases print("NON CONSUMABLE PURCHASE MADE: \(nonConsumablePurchaseMade)") print("COINS: \(coins)") // Set text coinsLabel.text = "COINS: \(coins)" if nonConsumablePurchaseMade { premiumLabel.text = "Premium version PURCHASED!" } else { premiumLabel.text = "Premium version LOCKED!"} // Fetch IAP Products available fetchAvailableProducts()
首先,我們將每次購買記錄到Xcode的控制台。 然後我們顯示我們用coinLabel購買的硬幣總量。 由於我們第一次運行演示應用程序,它將顯示硬幣:0。
該如果語句設置premiumLabel根據非消耗性產品是否購買的文本。 首先,它會顯示付費版本鎖定!因為我們還沒有進行高級購買。
代碼的最後一行調用我們稍後會看到的方法,它只是提取我們以前存儲在到iTC中的產品。
現在讓我們看看我們在演示應用中設置的兩個購買按鈕的功能:
// MARK: - BUY 10 COINS BUTTON @IBAction func buy10coinsButt(_ sender: Any) { purchaseMyProduct(product: iapProducts[0]) } // MARK: - UNLOCK PREMIUM BUTTON @IBAction func unlockPremiumButt(_ sender: Any) { purchaseMyProduct(product: iapProducts[1]) }
兩種方法都會調用一個函數來檢查設備是否可以進行購買,如果可以,應用程序將調用StoreKit委託方法來處理購買。
如前所述,我們需要第三個按鈕來恢復我們的非消耗品購買。 這是它的代碼:
// MARK: - RESTORE NON-CONSUMABLE PURCHASE BUTTON @IBAction func restorePurchaseButt(_ sender: Any) { SKPaymentQueue.default().add(self) SKPaymentQueue.default().restoreCompletedTransactions() } func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { nonConsumablePurchaseMade = true UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade") UIAlertView(title: "IAP Tutorial", message: "You've successfully restored your purchase!", delegate: nil, cancelButtonTitle: "OK").show() }
該IBAction為為功能連接到恢復購買的按鈕,故事板,並開始連接到蘋果的應用內購買系統如果已經已經取得恢復購買。
paymentQueueRestoreCompletedTransactionsFinished()是StoreKit框架的委託方法,可在購買成功恢復後將nonConsumablePurchaseMade變量保存為真。
我們完成了按鈕,讓我們看看fetchAvailableProducts()函數的作用:
// MARK: - FETCH AVAILABLE IAP PRODUCTS func fetchAvailableProducts() { // Put here your IAP Products ID's let productIdentifiers = NSSet(objects: COINS_PRODUCT_ID, PREMIUM_PRODUCT_ID ) productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>) productsRequest.delegate = self productsRequest.start() }
我們首先創建一個的的NSSet實例,它基本上是一個字符串數組。 我們將存儲之前在此處聲明的兩個產品ID。
然後,我們根據這些標識符開始SKProductsRequest,以便應用程序顯示有關IAP產品(描述和價格)的信息,該信息將由此委託方法處理:
// MARK: - REQUEST IAP PRODUCTS func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) { if (response.products.count > 0) { iapProducts = response.products // 1st IAP Product (Consumable) ------------------------------------ let firstProduct = response.products[0] as SKProduct // Get its price from iTunes Connect let numberFormatter = NumberFormatter() numberFormatter.formatterBehavior = .behavior10_4 numberFormatter.numberStyle = .currency numberFormatter.locale = firstProduct.priceLocale let price1Str = numberFormatter.string(from: firstProduct.price) // Show its description consumableLabel.text = firstProduct.localizedDescription + "\nfor just \(price1Str!)" // ------------------------------------------------ // 2nd IAP Product (Non-Consumable) ------------------------------ let secondProd = response.products[1] as SKProduct // Get its price from iTunes Connect numberFormatter.locale = secondProd.priceLocale let price2Str = numberFormatter.string(from: secondProd.price) // Show its description nonConsumableLabel.text = secondProd.localizedDescription + "\nfor just \(price2Str!)" // ------------------------------------ } }
在上面的功能中,我們首先必須檢查是否有任何產品在iTunes Connect中註冊並相應地設置我們的iapProducts陣列。 然後我們可以初始化兩個SKProducts並在標籤上打印它們的描述和價格。
在進入應用內購買代碼的核心之前,我們需要更多的功能:
// MARK: - MAKE PURCHASE OF A PRODUCT func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() } func purchaseMyProduct(product: SKProduct) { if self.canMakePurchases() { let payment = SKPayment(product: product) SKPaymentQueue.default().add(self) SKPaymentQueue.default().add(payment) print("PRODUCT TO PURCHASE: \(product.productIdentifier)") productID = product.productIdentifier // IAP Purchases dsabled on the Device } else { UIAlertView(title: "IAP Tutorial", message: "Purchases are disabled in your device!", delegate: nil, cancelButtonTitle: "OK").show() } }
第一個檢查我們的設備是否能夠購買。 第二個功能是我們從兩個按鈕調用的功能。 它啟動支付隊列並將我們的的productID變量轉換為選定的產品識別。
現在我們終於到達了最後一個處理付款結果的委託方法:
// MARK:- IAP PAYMENT QUEUE func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction:AnyObject in transactions { if let trans = transaction as? SKPaymentTransaction { switch trans.transactionState { case .purchased: SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) // The Consumable product (10 coins) has been purchased -> gain 10 extra coins! if productID == COINS_PRODUCT_ID { // Add 10 coins and save their total amount coins += 10 UserDefaults.standard.set(coins, forKey: "coins") coinsLabel.text = "COINS: \(coins)" UIAlertView(title: "IAP Tutorial", message: "You've successfully bought 10 extra coins!", delegate: nil, cancelButtonTitle: "OK").show() // The Non-Consumable product (Premium) has been purchased! } else if productID == PREMIUM_PRODUCT_ID { // Save your purchase locally (needed only for Non-Consumable IAP) nonConsumablePurchaseMade = true UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade") premiumLabel.text = "Premium version PURCHASED!" UIAlertView(title: "IAP Tutorial", message: "You've successfully unlocked the Premium version!", delegate: nil, cancelButtonTitle: "OK").show() } break case .failed: SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) break case .restored: SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) break default: break }}} }
該函數具有一個開關語句,用於檢查付款的每個狀態。 如果購買已成功完成並完成交易,則會調用第一個案例。
在這個塊內部,我們必須檢查我們選擇的產品ID並執行必要的操作來更新我們的應用程序 - 所以如果我們用戶購買了10個額外的硬幣,我們會將10添加到我們的硬幣變量中,使用UserDefaults保存它的值,顯示我們獲得的新硬幣數量,並發出警報。
請注意,您可以多次購買此產品,因為它是可消耗的IAP,因此無需恢復購買功能。
同樣,如果我們購買了非消費品高級產品,應用程序會將我們的nonConsumablePurchaseMade變量設置為真,保存它,更改premiumLabel的文本並觸發警報,通知您購買已成功。
其他兩種情況處理付款失敗和恢復的結果。 如果您的交易由於某種原因失敗或者您恢復了非消費品購買,該應用將自行觸發自定義提醒。
而已! 現在只需確保您使用Sandbox Tester憑據登錄並運行應用程序進行測試即可。 第一次,你會得到這樣的警報:
選擇使用現有的Apple ID並再次輸入您的Sandbox Tester的用戶名和密碼登錄。 發生這種情況是因為該應用只能從iTunes和App Store設置中識別出真正的用戶,而不是沙箱。
登錄後,您將可以購買這兩種產品。






CodeCanyon模板
如果您使用的iOS並希望深入了解斯威夫特語言和應用程序開發,請查看CodeCanyon上的一些iOS的應用程序模板。
ENVATO市場上還有數百個其他的iOS應用程序模板,可以重新製作並確保加快您的工作流程。 去查找他們! 您可能會在下一個應用程序上節省數小時的工作時間。
結論
在本教程中,我們介紹了在iTunes Connect上創建應用內購買產品所需的所有步驟,以及如何編寫代碼以在您的應用中啟用它們。 我希望你能夠把這些知識用於你的下一個iOS的應用程序!
感謝您的閱讀,我會在下次見! 請使用迅速查看我們的其他關於的iOS版的應用程序開發的課程和教程。
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weekly