[iOS]swift版內購


//內購Demo,看代碼說話吧
class IAPTestViewController: UIViewController ,SKProductsRequestDelegate, SKPaymentTransactionObserver{

    let VERIFY_RECEIPT_URL = "https://buy.itunes.apple.com/verifyReceipt"
    let ITMS_SANDBOX_VERIFY_RECEIPT_URL = "https://sandbox.itunes.apple.com/verifyReceipt"
    
    var productDict:NSMutableDictionary!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        SKPaymentQueue.defaultQueue().addTransactionObserver(self)
        requestProducts()//請求產品列表資料
        
    }
    deinit{
        SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    // 點擊購買產品后觸發的
    func onSelectRechargePackages(productId: String){
        //先判斷是否支持內購
        if(SKPaymentQueue.canMakePayments()){
            buyProduct(productDict[productId] as! SKProduct)
        }
        else{
            println("============不支持內購功能")
        }
        
    }
    //詢問蘋果的服務器能夠銷售哪些商品
    func requestProducts(){
        var set = NSSet(array: ["你的產品id1","產品id2"。。。。更多])
        let request = SKProductsRequest(productIdentifiers: set as Set<NSObject>)
        request.delegate = self;
        request.start()
    }

    // 以上查詢的回調函數
    func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) {
        if (productDict == nil) {
            productDict = NSMutableDictionary(capacity: response.products.count)
        }
        
        for product in response.products as! [SKProduct] {
            // 激活了對應的銷售操作按鈕,相當於商店的商品上架允許銷售
            println("=======Product id=======\(product.productIdentifier)")
            println("===產品標題 ==========\(product.localizedTitle)")
            println("====產品描述信息==========\(product.localizedDescription)")
            println("=====價格: =========\(product.price)")
            
            // 填充商品字典
            productDict.setObject(product, forKey: product.productIdentifier)
            
            
        }
    }
    // 購買對應的產品
    func buyProduct(product: SKProduct){
        
        var payment = SKPayment(product: product)
        SKPaymentQueue.defaultQueue().addPayment(payment)
    }
    func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!){
        // 調試
        for transaction in transactions {
            // 如果小票狀態是購買完成
            if (SKPaymentTransactionState.Purchased == transaction.transactionState) {
                // 更新界面或者數據,把用戶購買得商品交給用戶
                println("支付成了==================")
                // 驗證購買憑據
                self.verifyPruchase()
                
                // 將交易從交易隊列中刪除
                SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
            
            }
            else if(SKPaymentTransactionState.Failed == transaction.transactionState){
                println("支付失敗==================")
                SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
            }
            else if (SKPaymentTransactionState.Restored == transaction.transactionState) {//恢復購買
                // 更新界面或者數據,把用戶購買得商品交給用戶
                // ...
                
                // 將交易從交易隊列中刪除
                SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
            }
            
        }
        
    }
    func verifyPruchase(){
        // 驗證憑據,獲取到蘋果返回的交易憑據
        // appStoreReceiptURL iOS7.0增加的,購買交易完成后,會將憑據存放在該地址
        let receiptURL = NSBundle.mainBundle().appStoreReceiptURL
        // 從沙盒中獲取到購買憑據
        let receiptData = NSData(contentsOfURL: receiptURL!)
        // 發送網絡POST請求,對購買憑據進行驗證
        let url = NSURL(string: ITMS_SANDBOX_VERIFY_RECEIPT_URL)
        // 國內訪問蘋果服務器比較慢,timeoutInterval需要長一點
        let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10.0)
        request.HTTPMethod = "POST"
        // 在網絡中傳輸數據,大多情況下是傳輸的字符串而不是二進制數據
        // 傳輸的是BASE64編碼的字符串
        /**
            BASE64 常用的編碼方案,通常用於數據傳輸,以及加密算法的基礎算法,傳輸過程中能夠保證數據傳輸的穩定性
            BASE64是可以編碼和解碼的
        */
        let encodeStr = receiptData?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithLineFeed)
        
        let payload = NSString(string: "{\"receipt-data\" : \"" + encodeStr! + "\"}")
        println(payload)
        let payloadData = payload.dataUsingEncoding(NSUTF8StringEncoding)
       
        request.HTTPBody = payloadData;
        
        // 提交驗證請求,並獲得官方的驗證JSON結果
        let result = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
        
        // 官方驗證結果為空
        if (result == nil) {
            //驗證失敗
            println("驗證失敗")
            return
        }
        var dict: AnyObject? = NSJSONSerialization.JSONObjectWithData(result!, options: NSJSONReadingOptions.AllowFragments, error: nil)
        if (dict != nil) {
            // 比對字典中以下信息基本上可以保證數據安全
            // bundle_id&application_version&product_id&transaction_id
            // 驗證成功
            println(dict)
        }
    }
    func restorePurchase(){
        SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
    }


}

 PS:過程中遇到的問題

1.點擊購買沒有彈出輸入賬戶密碼框,解決方法是 到手機設置里面iTunes Store 與 App Store 里面注銷你原本的賬號

2.每次進來添加了 SKPaymentQueue.defaultQueue().addTransactionObserver(self) 狀態監聽之后,就會調用很多次 支付失敗 ,原因是之前調試失敗之后,沒有 SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) ,所以每次系統自動幫你請求上一次失敗的操作,結果還是繼續失敗。

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM