소스 검색

Merge pull request #24 from bizz84/hotfix/transactionQueue-mismatch-fix

Each InAppProductPurchaseRequest to handle only its own transactions
Andrea Bizzotto 9 년 전
부모
커밋
a5333f3344
2개의 변경된 파일26개의 추가작업 그리고 14개의 파일을 삭제
  1. 24 11
      SwiftyStoreKit/InAppProductPurchaseRequest.swift
  2. 2 3
      SwiftyStoreKit/SwiftyStoreKit.swift

+ 24 - 11
SwiftyStoreKit/InAppProductPurchaseRequest.swift

@@ -70,6 +70,8 @@ class InAppProductPurchaseRequest: NSObject, SKPaymentTransactionObserver {
     // MARK: Private methods
     private func startPayment(product: SKProduct) {
         guard let _ = product._productIdentifier else {
+            let error = NSError(domain: SKErrorDomain, code: 0, userInfo: [ NSLocalizedDescriptionKey: "Missing product identifier" ])
+            callback(results: [ TransactionResult.Failed(error: error) ])
             return
         }
         let payment = SKMutablePayment(product: product)
@@ -83,13 +85,23 @@ class InAppProductPurchaseRequest: NSObject, SKPaymentTransactionObserver {
             self.paymentQueue.restoreCompletedTransactions()
         }
     }
-    
+        
     // MARK: SKPaymentTransactionObserver
     func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
         
         var transactionResults: [TransactionResult] = []
         
         for transaction in transactions {
+            
+            let transactionProductIdentifier = transaction.payment.productIdentifier
+            
+            var isPurchaseRequest = false
+            if let productIdentifier = product?._productIdentifier {
+                if transactionProductIdentifier != productIdentifier {
+                    continue
+                }
+                isPurchaseRequest = true
+            }
 
             #if os(iOS)
                 let transactionState = transaction.transactionState
@@ -99,17 +111,22 @@ class InAppProductPurchaseRequest: NSObject, SKPaymentTransactionObserver {
 
             switch transactionState {
             case .Purchased:
-                transactionResults.append(.Purchased(productId: transaction.payment.productIdentifier))
-                paymentQueue.finishTransaction(transaction)
+                if isPurchaseRequest {
+                    transactionResults.append(.Purchased(productId: transactionProductIdentifier))
+                    paymentQueue.finishTransaction(transaction)
+                }
             case .Failed:
+                // TODO: How to discriminate between purchase and restore?
                 // It appears that in some edge cases transaction.error is nil here. Since returning an associated error is
                 // mandatory, return a default one if needed
                 let altError = NSError(domain: SKErrorDomain, code: 0, userInfo: [ NSLocalizedDescriptionKey: "Unknown error" ])
                 transactionResults.append(.Failed(error: transaction.error ?? altError))
                 paymentQueue.finishTransaction(transaction)
             case .Restored:
-                transactionResults.append(.Restored(productId: transaction.payment.productIdentifier))
-                paymentQueue.finishTransaction(transaction)
+                if !isPurchaseRequest {
+                    transactionResults.append(.Restored(productId: transactionProductIdentifier))
+                    paymentQueue.finishTransaction(transaction)
+                }
             case .Purchasing:
                 // In progress: do nothing
                 break
@@ -118,10 +135,10 @@ class InAppProductPurchaseRequest: NSObject, SKPaymentTransactionObserver {
             }
             // Keep track of payments
             if let _ = purchases[transactionState] {
-                purchases[transactionState]?.append(transaction.payment.productIdentifier)
+                purchases[transactionState]?.append(transactionProductIdentifier)
             }
             else {
-                purchases[transactionState] = [ transaction.payment.productIdentifier ]
+                purchases[transactionState] = [ transactionProductIdentifier ]
             }
         }
         if transactionResults.count > 0 {
@@ -143,10 +160,6 @@ class InAppProductPurchaseRequest: NSObject, SKPaymentTransactionObserver {
     }
 
     func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
-        if let product = self.product, productIdentifier = product._productIdentifier {
-            self.callback(results: [.Restored(productId: productIdentifier)])
-            return
-        }
         // This method will be called after all purchases have been restored (includes the case of no purchases)
         guard let restored = purchases[.Restored] where restored.count > 0 else {
             

+ 2 - 3
SwiftyStoreKit/SwiftyStoreKit.swift

@@ -186,9 +186,8 @@ public class SwiftyStoreKit {
 
         inflightPurchases[productIdentifier] = InAppProductPurchaseRequest.startPayment(product) { results in
 
-            if let productIdentifier = product._productIdentifier {
-                self.inflightPurchases[productIdentifier] = nil
-            }
+            self.inflightPurchases[productIdentifier] = nil
+            
             if let purchasedProductTransaction = results.first {
                 let returnValue = self.processPurchaseResult(purchasedProductTransaction)
                 completion(result: returnValue)