內(nèi)購接入的坑與核心流程 - Swift

通過蘋果開發(fā)文檔、搜索與掙扎摸索,我已經(jīng)在App上實現(xiàn)了【消耗型商品】的內(nèi)購。總結(jié)流程如下:

  1. 完成必須的準備工作
  2. 用有效的商品id創(chuàng)建SKProductRequest請求蘋果服務器返回商品(SKProduct)。
  3. 用返回的有效的商品創(chuàng)建payment,并將payment加入蘋果的支付隊列。
  4. 監(jiān)聽隊列,并根據(jù)監(jiān)聽到的交易狀態(tài)進行適當?shù)奶幚恚绕湫枰诮灰淄戤厱r關閉交易。

這方面的文檔,我覺得蘋果官方的Programming Guide就寫的很好??梢宰屑氉x一下。

我實際遇到的坑

  1. 必須先簽署協(xié)議才能進行內(nèi)購開發(fā),否則無法返回商品。
  2. 創(chuàng)建沙箱測試員時,密碼必須是強密碼,即同時包含大寫字母、小寫字母和數(shù)字。否則,會報錯:Unknown Errors while creating Sandbox Tester, Please check Error Log, email=xxx。
  3. 請求商品的SKProductRequest實例的delegate必須在離開頁面時viewDidDisappear設置為nil,因為即使你已經(jīng)離開了頁面,蘋果依然會嘗試向SKProductRequest的代理發(fā)送消息,然后App就崩潰了。
  4. 必須在AppDelegate中聲明遵守SKPaymentTransactionObserver協(xié)議、實現(xiàn)協(xié)議方法updatedTransactions、并在didFinishLaunching方法中加入如下代碼SKPaymentQueue.default().add(self)

這一行代碼是將AppDelegate作為內(nèi)購隊列的監(jiān)聽者。這樣,即使你離開了內(nèi)購頁面、即使上次支付未完成等情況,都能夠在這里得到及時的處理。

如果不在這里這么做,可能的報錯有:
This In-App purchase has already been bought. It will be restored for free.

如果需要在內(nèi)購頁面上實現(xiàn)交互,可以也在內(nèi)購界面上添加監(jiān)聽,并進行交互上面適當?shù)奶幚怼5珶o路如何,不能省掉AppDelegate中的那部分。

內(nèi)購接入核心流程

以下是我實際接入中使用的代碼。

請求商品

獲取商品id

獲取商品id,這個可以請求服務器,也可以保存在App上。我的App是用的后者。

首先創(chuàng)建一個名為ProductIDplist文件。文件內(nèi)容是一個Array,里面是保存的商品id字符串。

這里需要說明的是,商品id,即product identifier,就是你在iTunes Connect 內(nèi)購列表頁面上看到的商品id,不需要再拼接包名bundle identifier。

// Get product id from plist.
func predefinedProductIdentifiers() -> [String]? {
    guard let url = Bundle.main.url(forResource: "ProductID", withExtension: "plist") else { return nil }
    guard let productIdentifiers = NSArray(contentsOf: url) as? [String] else { return nil }
    return productIdentifiers
}

驗證商品id

請求蘋果服務器驗證我們提供的商品id是否有效。不過記得要把內(nèi)購Controller設置為遵循SKProductsRequestDelegate協(xié)議,否則無法收到通知。

func validateProductIdentifers(with productIdentifiers: [String]) {
    guard let set = NSSet(array: productIdentifiers) as? Set<String> else { return }
    let productRequest = SKProductsRequest(productIdentifiers: set)
    request = productRequest    // 將request強引用,避免在完成前被提前釋放;不過也務必在離開頁面后,將request.delegate設置為nil
    productRequest.delegate = self
    productRequest.start()
    SVProgressHUD.setDefaultStyle(.dark)
}

在協(xié)議中處理商品

func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
    print("received product response")
    products = response.products    // 將獲取到的商品存儲在界面實例變量,再次購買時不需要重復請求商品

  // 下面是繼續(xù)進行支付請求

請求支付

在獲取了有效商品后,就可以用商品創(chuàng)建SKPayment,并將payment實例加入蘋果支付隊列中。

func requestPayment(with product: SKProduct) {
    let payment = SKPayment(product: product)
    SKPaymentQueue.default().add(payment)
}

處理支付

這個步驟核心的點就是創(chuàng)建并添加SKPaymentTransactionObserver。

AppDelegate添加observer

  1. 在AppDelegate聲明遵循SKPaymentTransactionObserver協(xié)議。
  2. 實現(xiàn)協(xié)議方法,實現(xiàn)后實現(xiàn)者就可以作為observer。
*// MARK: - SK Product Request Delegate*
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
        switch transaction.transactionState {
        case .purchasing:
            DispatchQueue.main.async {
                SVProgressHUD.show(withStatus: NSLocalizedString("訂單處理中", comment: "請求支付提示" ))
            }
        case .deferred:
            SVProgressHUD.show(withStatus: NSLocalizedString("訂單處理中", comment: "請求支付提示" ))
        case .purchased:
        // 購買成功,此處需要發(fā)送玩家道具、保存憑證等動作。    

        // 當然交易完畢后,一定要手動關閉            
        SKPaymentQueue.default().finishTransaction(transaction)

        case .failed:
        // 交易失敗,也要關閉交易         
        SKPaymentQueue.default().finishTransaction(transaction)

        case .restored:
        // 恢復訂單
        SKPaymentQueue.default().finishTransaction(transaction)
        default:
            print("other situation")
        SKPaymentQueue.default().finishTransaction(transaction)
        }
    }
}

  1. didFinishLaunchingWithOptions方法中添加觀察者:
    SKPaymentQueue.default().add(self)

其他界面添加observer

假如用戶一直呆在內(nèi)購界面等待結(jié)束,我們很可能需要在內(nèi)購界面也要一套前端的展示機制。跟AppDelegate的流程一樣,我們將內(nèi)購界面也作為SKPaymentTransactionObserver添加到隊列中。這樣,內(nèi)購界面也能收到通知了。

當內(nèi)購界面可用的時候,就可以讓內(nèi)購界面去處理一些前端交互,比如彈出窗口,關閉當前界面等。

本人初學,有不當或錯漏之處,感謝斧正!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 一 基礎篇 1.1 Java基礎 面向?qū)ο蟮奶卣鞒橄?將一類對象的共同特征總結(jié)出來構(gòu)建類的過程。繼承:對已有類的一...
    essential_note閱讀 765評論 0 0
  • 康英資產(chǎn)管理系統(tǒng)接口文檔 [TOC] 文檔查看地址 請求URL:http://172.16.1.135:8181/...
    云蛋風卿閱讀 576評論 0 0
  • 費 詳情 房地產(chǎn)合作開發(fā)協(xié)議 最高人民法院關于審理涉及國有土地使用權(quán)合同糾紛案件適用法律問題的解釋(法釋20055...
    品位出擊閱讀 117評論 0 0
  • 時間的價值不一樣,什么意思? 不同人的時間價值當然不一樣。馬云爸爸的一小時,和你的肯定不一樣。 然而,我說的不是這...
    劍心折手閱讀 773評論 0 5
  • 我碰到過很多次被借錢的情況,有關系很熟的人,有一般交情的人,還有很多是見過幾面,聊過幾句,卻一點也不熟悉的人。小的...
    錢鋒閱讀 643評論 0 2

友情鏈接更多精彩內(nèi)容