//內購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) ,所以每次系統自動幫你請求上一次失敗的操作,結果還是繼續失敗。