應用程序內購買教程:入門

通過允許用戶購買或解鎖內容或功能,了解如何在此應用內購買教程中增加應用收益。

image

Pietro Rea中級·文章·30分鐘

更新說明:Pietro Rea為Xcode 10,Swift 4.2和iOS 11/12更新了本教程。Ray Wenderlich寫了原文。

構建iOS應用程序的一個好處是,您在應用程序貨幣化方面有很多選擇:普通的vanilla付費應用程序,廣告支持的免費應用程序,甚至支持應用程序內購買的應用程序。

一個應用程序內購買(或IAP),允許開發(fā)人員在使用一個應用程序來收取特定功能或內容的用戶。由于以下幾個原因,實施IAP尤其引人注目:

  • 這是一種額外的賺錢方式,除了簡單地預先付費購買應用程序。一些用戶愿意在額外的內容或功能上花費更多。
  • 一個應用程序可以免費提供,這使其成為大多數(shù)人的簡單下載。免費的應用程序通常會得到很多比付費應用下載量。如果用戶喜歡該應用,那么他們可以在以后購買更多內容或功能。
  • 您可以在免費應用程序中向用戶顯示廣告,并可選擇通過購買IAP刪除它們。
  • 在首次發(fā)布應用后,新的付費內容可以添加到同一個應用中,而不必開發(fā)全新的應用以賺取更多收益。

在此應用內購買教程中,您將利用IAP解鎖應用中嵌入的額外內容。您需要熟悉基本的Swift和iOS編程概念。如果這些是不熟悉的主題,那么 在開始之前查看我們的Swift教程范圍。您還需要一個付費開發(fā)者帳戶,可以訪問iOS開發(fā)人員中心App Store Connect

入門

在這個應用程序內購買教程中,您將構建一個名為“RazeFaces”的小應用程序,它允許用戶購買“RazeFace”,這是本網站常用的書籍和視頻的簡潔插圖。

典型的“RazeFace”

使用頂部的鏈接下載材料,然后在Xcode中打開入門項目。構建并運行以查看它到目前為止的功能。答案是:不是很多!您將看到一個空表視圖,導航欄中有一個“恢復”按鈕,稍后將連接該按鈕以恢復購買。

完成本教程后,將會在表格視圖中列出一個您可以購買的RazeFaces列表。如果您刪除并重新安裝該應用程序,“ 還原”按鈕將恢復以前購買的任何RazeFaces。

前往Xcode快速查看代碼。主視圖控制器位于MasterViewController.swift中。此類顯示表視圖,其中包含可用IAP列表。購買存儲為SKProduct對象數(shù)組。

請注意,MasterViewController正在使用一個名為RazeFaceProducts.storetype 的對象IAPHelper來執(zhí)行繁重的操作。看看他們各自的代碼文件RazeFaceProducts.swiftIAPHelper.swift

RazeFaceProducts是一個簡單的結構,包含有關應用程序中產品的一些信息,并IAPHelper完成與StoreKit交談的所有重要工作。這些方法目前都已被刪除,但您將在本教程中填寫它們以向應用程序添加IAP功能。

在編寫任何代碼以合并IAP之前,您首先需要在iOS開發(fā)人員中心和App Store Connect中進行一些設置。

創(chuàng)建應用程序ID

首先,您需要創(chuàng)建一個App ID。這會將您的應用與您的應用內購買產品相關聯(lián)。登錄Apple開發(fā)人員中心,然后選擇證書,ID和配置文件

接下來,選擇標識符>應用程序ID,然后單擊右上角的+以創(chuàng)建新的應用程序ID。

填寫新App ID的信息。輸入RazeFace IAP教程應用程序名稱。選擇顯式應用程序ID并輸入唯一的捆綁ID。通常的做法是反向使用您的域名(例如,com.razeware.razefaces)。記下Bundle ID,因為在接下來的步驟中將需要它。

向下滾動到“ 應用服務”部分。請注意, 默認情況下啟用應用程序內購買GameCenter。單擊繼續(xù),然后單擊注冊完成

恭喜!您有一個新的App ID!接下來,您將在App Store Connect中創(chuàng)建匹配的應用程序。

檢查您的協(xié)議

在將iTunes添加到iTunes Connect中的應用程序之前,您必須執(zhí)行以下兩項操作:

  • 確保您已在developer.apple.com上接受最新的Apple開發(fā)計劃許可協(xié)議。
  • 確保您已在App Store Connect的“協(xié)議,稅金和結算”部分中接受了最新的付費應用程序協(xié)議。

如果您還沒有這樣做,通常iTunes Connect會給您一個警告,如下所示:

如果您看到類似上述內容,請按照步驟接受相應的協(xié)議。

在iTunes Connect中仔細檢查協(xié)議,稅和銀行部分也是很好的:

如果您看到標題為“ 包含付費應用程序行的請求合同”的部分,請單擊“ 請求”按鈕。填寫所有必要信息并提交。您的申請可能需要一段時間才能獲得批準。穩(wěn)坐!

否則,如果您看到有效合同中列出的付費應用程序,那么您似乎已經完成了此步驟!不錯的工作!

注意:提交后,Apple可能需要數(shù)天才能批準這些與IAP相關的協(xié)議。在此期間,即使您在代碼中正確實現(xiàn)了所有內容,也無法在應用中顯示IAP產品。對于首次實施應用內購買的人來說,這是令人沮喪的常見原因。在那里掛!

在iTunes Connect中創(chuàng)建應用程序

現(xiàn)在要創(chuàng)建應用程序記錄本身,單擊 頁面左上角的App Store Connect,然后單擊 我的應用程序

接下來,單擊頁面左上角的+,然后選擇新建應用程序 以添加新的應用程序記錄。填寫如下所示的信息:

您將無法使用您在此處看到的完全相同的應用程序名稱,因為應用程序名稱在App Store中必須是唯一的。也許在上面屏幕截圖中顯示的示例標題之后添加您自己的首字母。

注意:如果您快速完成此步驟,則可能未在下拉列表中顯示Bundle ID。這有時需要一段時間才能通過Apple的系統(tǒng)傳播。

單擊“ 創(chuàng)建”,您就完成了!

創(chuàng)建應用內購買產品

提供IAP時,您必須首先在App Store Connect中為每個單獨的購買添加條目。如果您曾在商店中列出待售的應用程序,那么這是一個類似的過程,包括選擇購買的定價等級。當用戶進行購買時,App Store處理向用戶收費的復雜過程并回復有關此類操作的數(shù)據。

您可以添加一大堆不同類型的IAP:

  • 消耗品:這些可以多次購買,可以用完。這些非常適合額外的生活,游戲內貨幣,臨時加電等。
  • 非消耗品:您購買一次的東西,并期望具有永久性,如額外的水平和可解鎖的內容。本教程中的RazeFace插圖屬于此類別。
  • 非續(xù)訂訂閱:在固定時間段內可用的內容。
  • 自動續(xù)訂訂閱:重復訂閱,例如每月raywenderlich.com訂閱

您只能為數(shù)字商品提供應用內購買,而不能為實體商品或服務提供應用內購買。有關所有這些的更多信息,請查看Apple關于創(chuàng)建應用程序內購買產品的完整文檔。

現(xiàn)在,在App Store Connect中查看應用程序的條目時,單擊“ 功能” 選項卡,然后選擇“ 應用程序內購買”。要添加新的IAP產品,請單擊應用內購買右側的+

您將看到以下對話框:

當用戶在您的應用中購買RazeFace時,您會希望他們始終可以訪問它,因此請選擇“ 非耗材”,然后單擊“ 創(chuàng)建”

接下來,填寫IAP的詳細信息如下:

  • 參考名稱:標識iTunes Connect中IAP的昵稱。此名稱不會出現(xiàn)在應用中的任何位置。您將通過此次購買解鎖的RazeFace的標題是Swift Shopping,因此請在此處輸入。
  • 產品ID:這是標識IAP的唯一字符串。通常最好從Bundle ID開始,然后附加一個特定于此可購買項目的唯一名稱。對于本教程,請確保添加swiftshopping,因為稍后將在應用程序中使用它來查找RazeFace以解鎖。例如,您可以使用:com.theNameYouPickedEarlier.razefaces.swiftshopping
  • 清算待售:啟用或禁用IAP的銷售。你想啟用它!
  • 價格層:IAP的成本。選擇第1層

現(xiàn)在向下滾動到“ 本地化”部分,并注意英語(美國)有一個默認條目。為顯示名稱描述輸入“Swift Shopping” 。單擊保存。大!您已經創(chuàng)建了第一個IAP產品。

注意:App Store Connect可能會抱怨您缺少IAP的元數(shù)據。在您提交應用以供審核之前,您需要在此頁面底部添加IAP的屏幕截圖。該屏幕截圖用于Apple的評論,不會出現(xiàn)在App Store列表中。

在深入研究一些代碼之前還需要一個步驟。在應用程序的開發(fā)版本中測試應用程序內購買時,Apple提供了一個測試環(huán)境,允許您“購買”您的IAP產品,而無需創(chuàng)建財務交易。

這些特殊測試購買只能通過App Store Connect中的特殊“Sandbox Tester”用戶帳戶進行。我保證,你幾乎都在代碼中!

創(chuàng)建沙盒用戶

在App Store Connect中,單擊窗口左上角的App Store Connect以返回主菜單。選擇“ 用戶和角色”,然后單擊“ 沙箱測試器”選項卡。單擊“Tester”標題旁邊的+

填寫信息,完成后單擊“ 保存”。您可以為測試用戶組成名字和姓氏,但必須使用真實的電子郵件地址,因為Apple會向該地址發(fā)送驗證電子郵件。收到該電子郵件后,請務必點擊其中的鏈接以驗證您的地址。

您輸入的電子郵件地址也不應與Apple ID帳戶相關聯(lián)。提示:如果您有一個Gmail帳戶,您只需使用地址別名,而不必創(chuàng)建一個全新的帳戶。

注意:不幸的是,測試新購買的非耗材 IAP需要每次都有一個新的沙箱測試儀(和電子郵件地址)。使用相同沙盒測試器的重復購買將被視為恢復已購買的項目,因此不會執(zhí)行特定于新購買的任何代碼。

如果需要通過新的購買代碼進行多次測試并且您的電子郵件提供商不支持限定符,那么請考慮設置可消耗的IAP僅用于測試目的。每次測試后刪除設備上的應用程序,購買耗材IAP將被視為新購買。

您可以采用的一種策略是在測試成功案例之前盡可能多次測試失敗案例。這樣你就需要創(chuàng)建更少的沙盒測試器。一般情況下,請記住,一旦用戶(甚至是沙盒)購買了非消耗性IAP,他就不能再次購買,只能恢復它。

太棒了 - 你現(xiàn)在有一個測試用戶。您最終可以在您的應用中實施IAP!

項目配置

為了使一切正常工作,應用程序中的包標識符和產品標識符與您在開發(fā)人員中心和App Store Connect中創(chuàng)建的標識符和產品標識符相匹配非常重要。

轉到Xcode的初學者項目。在Project導航器中選擇RazeFaces項目,然后在Targets下再次選擇它。選擇常規(guī)選項卡,將您的團隊切換到正確的團隊,然后輸入您之前使用的捆綁ID。

接下來選擇Capabilities 選項卡。向下滾動到In-App Purchase并將開關切換到ON

注意:如果IAP未顯示在列表中,請確保在Xcode首選項的“帳戶”部分中使用您用于創(chuàng)建應用程序ID的Apple ID登錄。

打開RazeFaceProducts.swift。請注意,您創(chuàng)建的IAP產品有一個占位符引用:SwiftShopping。將其替換為您在App Store Connect中配置的完整產品ID - 例如:

public static let SwiftShopping = "com.theNameYouPickedEarlier.razefaces.swiftshopping"

注意:可以從Web服務器中提取產品標識符列表,以便可以動態(tài)添加新的IAP,而不需要更新應用程序。本教程簡單易用,使用硬編碼的產品標識符。

列出應用內購買

store物業(yè)RazeFaceProducts是一個實例IAPHelper。如前所述,此對象與StoreKitAPI 交互以列出和執(zhí)行購買。您的第一個任務是更新IAPHelper以檢索IAP列表 - 目前只有一個 - 來自Apple的服務器。

打開IAPHelper.swift。在該類的頂部,添加以下私有屬性:

private let productIdentifiers: Set<ProductIdentifier>

接下來,init(productIds:)在調用之前添加以下內容super.init()

productIdentifiers = productIds 

一個IAPHelper實例是通過將一組產品標識的創(chuàng)建。這是RazeFaceProducts創(chuàng)建其store實例的方式。

接下來,在剛才添加的那個下添加其他私有屬性:

private var purchasedProductIdentifiers: Set<ProductIdentifier> = []
private var productsRequest: SKProductsRequest?
private var productsRequestCompletionHandler: ProductsRequestCompletionHandler?

purchasedProductIdentifiers跟蹤已購買的商品。SKProductsRequest委托使用其他兩個屬性來執(zhí)行對Apple服務器的請求。

接下來,仍然在IAPHelper.swift中替換以下的實現(xiàn)requestProducts(_:)

public func requestProducts(completionHandler: @escaping ProductsRequestCompletionHandler) {
  productsRequest?.cancel()
  productsRequestCompletionHandler = completionHandler

  productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
  productsRequest!.delegate = self
  productsRequest!.start()
}

此代碼保存用戶的完成處理程序以供將來執(zhí)行。然后,它通過SKProductsRequest對象創(chuàng)建并向Apple發(fā)起請求。有一個問題:代碼聲明IAPHelper為請求的委托,但它還不符合SKProductsRequestDelegate協(xié)議。

要解決此問題,請在最后一個大括號之后將以下擴展名添加到IAPHelper.swift的最后:

// MARK: - SKProductsRequestDelegate

extension IAPHelper: SKProductsRequestDelegate {

  public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
    print("Loaded list of products...")
    let products = response.products
    productsRequestCompletionHandler?(true, products)
    clearRequestAndHandler()

    for p in products {
      print("Found product: \(p.productIdentifier) \(p.localizedTitle) \(p.price.floatValue)")
    }
  }
  
  public func request(_ request: SKRequest, didFailWithError error: Error) {
    print("Failed to load list of products.")
    print("Error: \(error.localizedDescription)")
    productsRequestCompletionHandler?(false, nil)
    clearRequestAndHandler()
  }

  private func clearRequestAndHandler() {
    productsRequest = nil
    productsRequestCompletionHandler = nil
  }
}

此擴展用于通過實現(xiàn)SKProductsRequestDelegate協(xié)議所需的兩種方法從Apple服務器獲取產品列表,標題,描述和價格。

productsRequest(_:didReceive:)在成功檢索列表時調用。它接收一個SKProduct對象數(shù)組并將它們傳遞給先前保存的完成處理程序。處理程序使用新數(shù)據重新加載表。如果出現(xiàn)問題,request(_:didFailWithError:)則調用。在任何一種情況下,當請求完成時,請求和完成處理程序都將被清除clearRequestAndHandler()

建立并運行。萬歲!表格視圖中顯示了產品列表(目前只有一個)!這需要一些工作,但最終你到了那里。

注意:您可以在iOS模擬器和物理iOS設備上顯示IAP產品,但如果您要測試購買或恢復購買,則只能在物理設備上執(zhí)行此操作。更多相關信息,請參閱下面的采購部分。

注意:如果運行不成功且您沒有看到任何產品,那么有很多事情需要檢查。此列表由本帖的早期版本的論壇中的itsme.manishabgtan提供,以及隨著時間的推移添加的更多提示。

  • 項目的Bundle ID是否與iOS開發(fā)中心的App ID相匹配?
  • 制作時是否使用完整的產品ID SKProductRequest?(檢查productIdentifiers屬性RazeFaceProducts。)
  • 付費應用程序合同是否對iTunes Connect有效?他們提交申請的時間可能需要數(shù)小時到數(shù)天才能從待定到接受。
  • 自從將產品添加到App Store Connect后,您有幾個小時的時間嗎?產品添加可能會立即生效或可能需要一些時間。
  • 檢查Apple Developer System狀態(tài)。或者,嘗試此鏈接。如果它沒有響應狀態(tài)值,則iTunes沙箱可能已關閉。Apple的Validating Receipts與App Store文檔中說明了狀態(tài)代碼。
  • 是否為App ID啟用了IAP?(你之前選擇過清倉嗎?)
  • 您是否嘗試從設備中刪除該應用并重新安裝?

仍然卡住?正如您所看到的,IAP需要做很多工作。嘗試本教程的評論與其他讀者討論。

購買物品

您希望能夠確定已購買的商品。為此,您將使用purchasedProductIdentifiers之前添加的 屬性。如果此集中包含產品標識符,則用戶已購買該項目。檢查這個的方法很簡單。

IAPHelper.swift中,將return語句 替換isProductPurchased(_:) 為以下內容:

return purchasedProductIdentifiers.contains(productIdentifier)

在本地保存購買狀態(tài)可以減少每次應用啟動時向Apple服務器請求此類數(shù)據的需求。purchasedProductIdentifiers 使用保存UserDefaults

仍在IAPHelper.swift中,替換init(productIds:)為以下內容:

public init(productIds: Set<ProductIdentifier>) {
  productIdentifiers = productIds
  for productIdentifier in productIds {
    let purchased = UserDefaults.standard.bool(forKey: productIdentifier)
    if purchased {
      purchasedProductIdentifiers.insert(productIdentifier)
      print("Previously purchased: \(productIdentifier)")
    } else {
      print("Not purchased: \(productIdentifier)")
    }
  }
  super.init()
}

對于每個產品標識符,檢查是否存儲該值UserDefaults。如果是,則將標識符插入到purchasedProductIdentifiers集合中。之后,您將在購買后向集合中添加標識符。

注意:用戶默認值可能不是在實際應用程序中存儲有關已購買產品的信息的最佳位置。越獄設備的所有者可以輕松訪問您的應用程序的UserDefaultsplist,并將其修改為“解鎖”購買。如果這種事情與您有關,那么值得查看Apple關于驗證App Store收據的文檔- 這可以讓您驗證用戶是否進行了特定購買。

購物(給我看錢!)

了解用戶購買的產品很棒,但您仍然需要首先進行購買!實施購買能力是合乎邏輯的下一步。

仍在IAPHelper.swift中,替換buyProduct(_:)為以下內容:

public func buyProduct(_ product: SKProduct) {
  print("Buying \(product.productIdentifier)...")
  let payment = SKPayment(product: product)
  SKPaymentQueue.default().add(payment)
}

這將使用SKProduct(從Apple服務器檢索)創(chuàng)建支付對象以添加到支付隊列。該代碼使用一個SKPaymentQueue名為的單例對象default()。繁榮!錢在銀行里。或者是嗎?你怎么知道付款是否通過?

付款驗證是通過IAPHelper觀察交易發(fā)生的SKPaymentQueue。在設置IAPHelperSKPaymentQueue事務觀察器之前,該類必須符合SKPaymentTransactionObserver協(xié)議。

轉到IAPHelper.swift的最底部(在最后一個大括號之后)并添加以下擴展名:

// MARK: - SKPaymentTransactionObserver
 
extension IAPHelper: SKPaymentTransactionObserver {
 
  public func paymentQueue(_ queue: SKPaymentQueue, 
                           updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
      switch transaction.transactionState {
      case .purchased:
        complete(transaction: transaction)
        break
      case .failed:
        fail(transaction: transaction)
        break
      case .restored:
        restore(transaction: transaction)
        break
      case .deferred:
        break
      case .purchasing:
        break
      }
    }
  }
 
  private func complete(transaction: SKPaymentTransaction) {
    print("complete...")
    deliverPurchaseNotificationFor(identifier: transaction.payment.productIdentifier)
    SKPaymentQueue.default().finishTransaction(transaction)
  }
 
  private func restore(transaction: SKPaymentTransaction) {
    guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }
 
    print("restore... \(productIdentifier)")
    deliverPurchaseNotificationFor(identifier: productIdentifier)
    SKPaymentQueue.default().finishTransaction(transaction)
  }
 
  private func fail(transaction: SKPaymentTransaction) {
    print("fail...")
    if let transactionError = transaction.error as NSError?,
      let localizedDescription = transaction.error?.localizedDescription,
        transactionError.code != SKError.paymentCancelled.rawValue {
        print("Transaction Error: \(localizedDescription)")
      }

    SKPaymentQueue.default().finishTransaction(transaction)
  }
 
  private func deliverPurchaseNotificationFor(identifier: String?) {
    guard let identifier = identifier else { return }
 
    purchasedProductIdentifiers.insert(identifier)
    UserDefaults.standard.set(true, forKey: identifier)
    NotificationCenter.default.post(name: .IAPHelperPurchaseNotification, object: identifier)
  }
}

這是很多代碼!詳細的審查是有序的。幸運的是,每種方法都很短。

paymentQueue(_:updatedTransactions:)是協(xié)議實際需要的唯一方法。當一個或多個事務狀態(tài)發(fā)生變化時,它會被調用。此方法評估更新事務數(shù)組中每個事務的狀態(tài),并調用相關的幫助方法:complete(transaction:)restore(transaction:)fail(transaction:)

如果交易已完成或已恢復,則會將其添加到購買集并將標識符保存在其中UserDefaults。它還會在該事務中發(fā)布通知,以便應用程序中的任何感興趣的對象都可以監(jiān)聽它以執(zhí)行更新用戶界面等操作。最后,在成功失敗的情況下,它將交易標記為已完成。

剩下的就是IAPHelper作為支付交易觀察員。仍然在IAPHelper.swift,回去init(productIds:)和右側添加以下行之后 super.init()

SKPaymentQueue.default().add(self)

購買沙箱

構建并運行應用程序 - 但要測試購買,您必須在設備上運行它。之前創(chuàng)建的沙箱測試儀可用于執(zhí)行購買而無需收費。如果只有我可以讓沙箱測試人員去購買我的雜貨店:]以下是如何使用測試人員帳戶:

轉到您的iPhone并確保您已退出正常的App Store帳戶。要執(zhí)行此操作,請轉到“ 設置”應用,然后點按“ iTunes和App Store”

點按您的iCloud帳戶名稱,然后點按退出。此時,實際上并未使用沙箱用戶登錄。一旦您嘗試在示例應用程序中購買IAP,系統(tǒng)將提示您執(zhí)行此操作。

連接您的設備,構建并運行!您會在應用中看到您的產品。要開始購買,請點按“ 購買”按鈕。

將出現(xiàn)一個提示您登錄的警報。點擊使用現(xiàn)有Apple ID,然后輸入您之前創(chuàng)建的沙箱測試人員帳戶的登錄詳細信息。

點按“購買”確認購買。警報視圖顯示正在沙盒中進行購買,以提醒您不會向您收取費用。

最后,將出現(xiàn)一個警報視圖,確認購買成功。購買過程完成后,購買項目旁邊會出現(xiàn)一個復選標記。點擊購買的商品即可享受新的RazeFace。

最后你會看到這個“Swift Shopping”RazeFace,你一直聽到這么多!

恢復購買

如果用戶刪除并重新安裝應用程序或將其安裝在其他設備上,則他們需要能夠訪問以前購買的項目。事實上,如果蘋果無法恢復非消費品購買,Apple可能會拒絕該應用。

作為購買交易觀察員,IAPHelper在購買恢復時已經收到通知。下一步是通過恢復購買來對此通知做出反應。

打開IAPHelper.swift并滾動到文件的底部。在StoreKit API擴展中,替換restorePurchases()為以下內容:

public func restorePurchases() {
  SKPaymentQueue.default().restoreCompletedTransactions()
}

那太簡單了!您已經設置了事務觀察器并實現(xiàn)了方法來處理上一步中的恢復事務。

要對此進行測試,請在上一步中完成購買后,從設備中刪除該應用。再次構建并運行,然后點擊右上角的“恢復”。您應該會在先前購買的產品旁邊看到復選標記。

付款權限

某些設備和帳戶可能不允許進行應用內購買。例如,如果將父級控件設置為禁止它,則會發(fā)生這種情況。Apple要求優(yōu)雅地處理這種情況。不這樣做可能會導致應用拒絕。

再次打開IAPHelper.swift。在StoreKit API擴展中,使用以下行替換return語句canMakePayments()

return SKPaymentQueue.canMakePayments()

產品單元格的行為應根據返回的值而有所不同canMakePayments()。例如,如果canMakePayments()退貨false,則不應顯示“ 購買”按鈕,并且應將價格替換為“不可用”。

要完成此任務,請打開ProductCell.swift并使用以下內容替換product屬性didSet處理程序的整個實現(xiàn):

didSet {
  guard let product = product else { return }
 
  textLabel?.text = product.localizedTitle
 
  if RazeFaceProducts.store.isProductPurchased(product.productIdentifier) {
    accessoryType = .checkmark
    accessoryView = nil
    detailTextLabel?.text = ""
  } else if IAPHelper.canMakePayments() {
    ProductCell.priceFormatter.locale = product.priceLocale
    detailTextLabel?.text = ProductCell.priceFormatter.string(from: product.price)
 
    accessoryType = .none
    accessoryView = self.newBuyButton()
  } else {
    detailTextLabel?.text = "Not available"
  }
}

當無法使用設備付款時,此實施將顯示更合適的信息。而且你有它 - 一個應用程序內購買的應用程序!

然后去哪兒?

您可以使用本教程頂部或底部的“ 下載材料”按鈕下載項目的完整版本。您可以在自己的項目中重復使用IAP幫助程序類!

應用程序內購買視頻教程系列 由山姆·戴維斯涵蓋了所有的介紹到這里的主題,但進入到一個新的水平在他談到驗證收據3部分。

示例應用程序的一個缺點是,它不會向用戶表明何時與Apple通信。可能的改進是在適當?shù)臅r間顯示旋轉器或HUD控制。但是,此UI增強超出了本教程的范圍。有關HUD控件的更多信息,請查看iOS Apprentice的第3部分。

Apple有一個很棒的登錄頁面可供應用內購買:面向開發(fā)人員的應用內購買。它匯集了所有相關文檔和WWDC視頻的鏈接。

IAP可以成為您業(yè)務模式的重要組成部分。明智地使用它們并確保遵循有關恢復購買和優(yōu)雅失敗的指導方針,您將走向成功的道路!

如果您對此應用內購買教程有任何疑問或意見,請加入以下論壇討論!

原文: https://www.raywenderlich.com/5456-in-app-purchase-tutorial-getting-started

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

推薦閱讀更多精彩內容