Forráskód Böngészése

Renamed Product to Purchase.
Added quantity to Payment, Purchase types

Andrea Bizzotto 8 éve
szülő
commit
9b4201ac4c

+ 6 - 6
SwiftyStoreKit-iOS-Demo/AppDelegate.swift

@@ -39,17 +39,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 
     func completeIAPTransactions() {
 
-        SwiftyStoreKit.completeTransactions(atomically: true) { products in
+        SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
 
-            for product in products {
+            for purchase in purchases {
                 // swiftlint:disable:next for_where
-                if product.transaction.transactionState == .purchased || product.transaction.transactionState == .restored {
+                if purchase.transaction.transactionState == .purchased || purchase.transaction.transactionState == .restored {
 
-                    if product.needsFinishTransaction {
+                    if purchase.needsFinishTransaction {
                         // Deliver content from server, then:
-                        SwiftyStoreKit.finishTransaction(product.transaction)
+                        SwiftyStoreKit.finishTransaction(purchase.transaction)
                     }
-                    print("purchased: \(product.productId)")
+                    print("purchased: \(purchase.productId)")
                 }
             }
         }

+ 12 - 12
SwiftyStoreKit-iOS-Demo/ViewController.swift

@@ -79,10 +79,10 @@ class ViewController: UIViewController {
         SwiftyStoreKit.purchaseProduct(appBundleId + "." + purchase.rawValue, atomically: true) { result in
             NetworkActivityIndicatorManager.networkOperationFinished()
 
-            if case .success(let product) = result {
+            if case .success(let purchase) = result {
                 // Deliver content from server, then:
-                if product.needsFinishTransaction {
-                    SwiftyStoreKit.finishTransaction(product.transaction)
+                if purchase.needsFinishTransaction {
+                    SwiftyStoreKit.finishTransaction(purchase.transaction)
                 }
             }
             if let alert = self.alertForPurchaseResult(result) {
@@ -97,9 +97,9 @@ class ViewController: UIViewController {
         SwiftyStoreKit.restorePurchases(atomically: true) { results in
             NetworkActivityIndicatorManager.networkOperationFinished()
 
-            for product in results.restoredProducts where product.needsFinishTransaction {
+            for purchase in results.restoredPurchases where purchase.needsFinishTransaction {
                 // Deliver content from server, then:
-                SwiftyStoreKit.finishTransaction(product.transaction)
+                SwiftyStoreKit.finishTransaction(purchase.transaction)
             }
             self.showAlert(self.alertForRestorePurchases(results))
         }
@@ -216,8 +216,8 @@ extension ViewController {
     // swiftlint:disable cyclomatic_complexity
     func alertForPurchaseResult(_ result: PurchaseResult) -> UIAlertController? {
         switch result {
-        case .success(let product):
-            print("Purchase Success: \(product.productId)")
+        case .success(let purchase):
+            print("Purchase Success: \(purchase.productId)")
             return alertWithTitle("Thank You", message: "Purchase completed")
         case .error(let error):
             print("Purchase Failed: \(error)")
@@ -238,18 +238,18 @@ extension ViewController {
             case .cloudServiceNetworkConnectionFailed: // the device could not connect to the nework
                 return alertWithTitle("Purchase failed", message: "Could not connect to the network")
             case .cloudServiceRevoked: // user has revoked permission to use this cloud service
-                return alertWithTitle("Purchase failed", message: "Could service was revoked")
+                return alertWithTitle("Purchase failed", message: "Cloud service was revoked")
             }
         }
     }
 
     func alertForRestorePurchases(_ results: RestoreResults) -> UIAlertController {
 
-        if results.restoreFailedProducts.count > 0 {
-            print("Restore Failed: \(results.restoreFailedProducts)")
+        if results.restoreFailedPurchases.count > 0 {
+            print("Restore Failed: \(results.restoreFailedPurchases)")
             return alertWithTitle("Restore failed", message: "Unknown error. Please contact support")
-        } else if results.restoredProducts.count > 0 {
-            print("Restore Success: \(results.restoredProducts)")
+        } else if results.restoredPurchases.count > 0 {
+            print("Restore Success: \(results.restoredPurchases)")
             return alertWithTitle("Purchases Restored", message: "All purchases have been restored")
         } else {
             print("Nothing to Restore")

+ 6 - 6
SwiftyStoreKit-macOS-Demo/AppDelegate.swift

@@ -35,17 +35,17 @@ class AppDelegate: NSObject, NSApplicationDelegate {
 
     func completeIAPTransactions() {
 
-        SwiftyStoreKit.completeTransactions(atomically: true) { products in
+        SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
 
-            for product in products {
+            for purchase in purchases {
                 // swiftlint:disable:next for_where
-                if product.transaction.transactionState == .purchased || product.transaction.transactionState == .restored {
+                if purchase.transaction.transactionState == .purchased || purchase.transaction.transactionState == .restored {
 
-                    if product.needsFinishTransaction {
+                    if purchase.needsFinishTransaction {
                         // Deliver content from server, then:
-                        SwiftyStoreKit.finishTransaction(product.transaction)
+                        SwiftyStoreKit.finishTransaction(purchase.transaction)
                     }
-                    print("purchased: \(product.productId)")
+                    print("purchased: \(purchase.productId)")
                 }
             }
         }

+ 10 - 10
SwiftyStoreKit-macOS-Demo/ViewController.swift

@@ -77,10 +77,10 @@ class ViewController: NSViewController {
 
         SwiftyStoreKit.purchaseProduct(appBundleId + "." + purchase.rawValue, atomically: true) { result in
 
-            if case .success(let product) = result {
+            if case .success(let purchase) = result {
                 // Deliver content from server, then:
-                if product.needsFinishTransaction {
-                    SwiftyStoreKit.finishTransaction(product.transaction)
+                if purchase.needsFinishTransaction {
+                    SwiftyStoreKit.finishTransaction(purchase.transaction)
                 }
             }
 
@@ -94,7 +94,7 @@ class ViewController: NSViewController {
 
         SwiftyStoreKit.restorePurchases(atomically: true) { results in
 
-            for product in results.restoredProducts where product.needsFinishTransaction {
+            for purchase in results.restoredPurchases where purchase.needsFinishTransaction {
                 // Deliver content from server, then:
                 SwiftyStoreKit.finishTransaction(product.transaction)
             }
@@ -206,8 +206,8 @@ extension ViewController {
 
     func alertForPurchaseResult(_ result: PurchaseResult) -> NSAlert? {
         switch result {
-        case .success(let product):
-            print("Purchase Success: \(product.productId)")
+        case .success(let purchase):
+            print("Purchase Success: \(purchase.productId)")
             return alertWithTitle("Thank You", message: "Purchase completed")
         case .error(let error):
             print("Purchase Failed: \(error)")
@@ -227,11 +227,11 @@ extension ViewController {
 
     func alertForRestorePurchases(_ results: RestoreResults) -> NSAlert {
 
-        if results.restoreFailedProducts.count > 0 {
-            print("Restore Failed: \(results.restoreFailedProducts)")
+        if results.restoreFailedPurchases.count > 0 {
+            print("Restore Failed: \(results.restoreFailedPurchases)")
             return alertWithTitle("Restore failed", message: "Unknown error. Please contact support")
-        } else if results.restoredProducts.count > 0 {
-            print("Restore Success: \(results.restoredProducts)")
+        } else if results.restoredPurchases.count > 0 {
+            print("Restore Success: \(results.restoredPurchases)")
             return alertWithTitle("Purchases Restored", message: "All purchases have been restored")
         } else {
             print("Nothing to Restore")

+ 7 - 7
SwiftyStoreKit/CompleteTransactionsController.swift

@@ -27,9 +27,9 @@ import StoreKit
 
 struct CompleteTransactions {
     let atomically: Bool
-    let callback: ([Product]) -> Void
+    let callback: ([Purchase]) -> Void
 
-    init(atomically: Bool, callback: @escaping ([Product]) -> Void) {
+    init(atomically: Bool, callback: @escaping ([Purchase]) -> Void) {
         self.atomically = atomically
         self.callback = callback
     }
@@ -47,7 +47,7 @@ class CompleteTransactionsController: TransactionController {
         }
 
         var unhandledTransactions: [SKPaymentTransaction] = []
-        var products: [Product] = []
+        var purchases: [Purchase] = []
 
         for transaction in transactions {
 
@@ -55,9 +55,9 @@ class CompleteTransactionsController: TransactionController {
 
             if transactionState != .purchasing {
 
-                let product = Product(productId: transaction.payment.productIdentifier, transaction: transaction, needsFinishTransaction: !completeTransactions.atomically)
+                let purchase = Purchase(productId: transaction.payment.productIdentifier, quantity: transaction.payment.quantity, transaction: transaction, needsFinishTransaction: !completeTransactions.atomically)
 
-                products.append(product)
+                purchases.append(purchase)
 
                 print("Finishing transaction for payment \"\(transaction.payment.productIdentifier)\" with state: \(transactionState.debugDescription)")
 
@@ -68,8 +68,8 @@ class CompleteTransactionsController: TransactionController {
                 unhandledTransactions.append(transaction)
             }
         }
-        if products.count > 0 {
-            completeTransactions.callback(products)
+        if purchases.count > 0 {
+            completeTransactions.callback(purchases)
         }
 
         return unhandledTransactions

+ 3 - 2
SwiftyStoreKit/PaymentQueueController.swift

@@ -36,8 +36,8 @@ protocol TransactionController {
 }
 
 public enum TransactionResult {
-    case purchased(product: Product)
-    case restored(product: Product)
+    case purchased(purchase: Purchase)
+    case restored(purchase: Purchase)
     case failed(error: SKError)
 }
 
@@ -108,6 +108,7 @@ class PaymentQueueController: NSObject, SKPaymentTransactionObserver {
 
         let skPayment = SKMutablePayment(product: payment.product)
         skPayment.applicationUsername = payment.applicationUsername
+        skPayment.quantity = payment.quantity
         paymentQueue.add(skPayment)
 
         paymentsController.append(payment)

+ 3 - 2
SwiftyStoreKit/PaymentsController.swift

@@ -27,6 +27,7 @@ import StoreKit
 
 struct Payment: Hashable {
     let product: SKProduct
+    let quantity: Int
     let atomically: Bool
     let applicationUsername: String
     let callback: (TransactionResult) -> Void
@@ -72,9 +73,9 @@ class PaymentsController: TransactionController {
 
         if transactionState == .purchased {
 
-            let product = Product(productId: transactionProductIdentifier, transaction: transaction, needsFinishTransaction: !payment.atomically)
+            let purchase = Purchase(productId: transactionProductIdentifier, quantity: transaction.payment.quantity, transaction: transaction, needsFinishTransaction: !payment.atomically)
 
-            payment.callback(.purchased(product: product))
+            payment.callback(.purchased(purchase: purchase))
 
             if payment.atomically {
                 paymentQueue.finishTransaction(transaction)

+ 12 - 12
SwiftyStoreKit/RestorePurchasesController.swift

@@ -41,21 +41,21 @@ class RestorePurchasesController: TransactionController {
 
     public var restorePurchases: RestorePurchases?
 
-    private var restoredProducts: [TransactionResult] = []
+    private var restoredPurchases: [TransactionResult] = []
 
-    func processTransaction(_ transaction: SKPaymentTransaction, atomically: Bool, on paymentQueue: PaymentQueue) -> Product? {
+    func processTransaction(_ transaction: SKPaymentTransaction, atomically: Bool, on paymentQueue: PaymentQueue) -> Purchase? {
 
         let transactionState = transaction.transactionState
 
         if transactionState == .restored {
 
             let transactionProductIdentifier = transaction.payment.productIdentifier
-
-            let product = Product(productId: transactionProductIdentifier, transaction: transaction, needsFinishTransaction: !atomically)
+            
+            let purchase = Purchase(productId: transactionProductIdentifier, quantity: transaction.payment.quantity, transaction: transaction, needsFinishTransaction: !atomically)
             if atomically {
                 paymentQueue.finishTransaction(transaction)
             }
-            return product
+            return purchase
         }
         return nil
     }
@@ -68,8 +68,8 @@ class RestorePurchasesController: TransactionController {
 
         var unhandledTransactions: [SKPaymentTransaction] = []
         for transaction in transactions {
-            if let restoredProduct = processTransaction(transaction, atomically: restorePurchases.atomically, on: paymentQueue) {
-                restoredProducts.append(.restored(product: restoredProduct))
+            if let restoredPurchase = processTransaction(transaction, atomically: restorePurchases.atomically, on: paymentQueue) {
+                restoredPurchases.append(.restored(purchase: restoredPurchase))
             } else {
                 unhandledTransactions.append(transaction)
             }
@@ -84,11 +84,11 @@ class RestorePurchasesController: TransactionController {
             print("Callback already called. Returning")
             return
         }
-        restoredProducts.append(.failed(error: SKError(_nsError: error as NSError)))
-        restorePurchases.callback(restoredProducts)
+        restoredPurchases.append(.failed(error: SKError(_nsError: error as NSError)))
+        restorePurchases.callback(restoredPurchases)
 
         // Reset state after error received
-        restoredProducts = []
+        restoredPurchases = []
         self.restorePurchases = nil
 
     }
@@ -99,10 +99,10 @@ class RestorePurchasesController: TransactionController {
             print("Callback already called. Returning")
             return
         }
-        restorePurchases.callback(restoredProducts)
+        restorePurchases.callback(restoredPurchases)
 
         // Reset state after error transactions finished
-        restoredProducts = []
+        restoredPurchases = []
         self.restorePurchases = nil
     }
 }

+ 5 - 4
SwiftyStoreKit/SwiftyStoreKit+Types.swift

@@ -27,8 +27,9 @@ import StoreKit
 // MARK: Purchases
 
 // Purchased or restored product
-public struct Product {
+public struct Purchase {
     public let productId: String
+    public let quantity: Int
     public let transaction: PaymentTransaction
     public let needsFinishTransaction: Bool
 }
@@ -56,14 +57,14 @@ public struct RetrieveResults {
 
 // Purchase result
 public enum PurchaseResult {
-    case success(product: Product)
+    case success(purchase: Purchase)
     case error(error: SKError)
 }
 
 // Restore purchase results
 public struct RestoreResults {
-    public let restoredProducts: [Product]
-    public let restoreFailedProducts: [(SKError, String?)]
+    public let restoredPurchases: [Purchase]
+    public let restoreFailedPurchases: [(SKError, String?)]
 }
 
 // MARK: Receipt verification

+ 23 - 22
SwiftyStoreKit/SwiftyStoreKit.swift

@@ -45,14 +45,14 @@ public class SwiftyStoreKit {
         return productsInfoController.retrieveProductsInfo(productIds, completion: completion)
     }
 
-    func purchaseProduct(_ productId: String, atomically: Bool = true, applicationUsername: String = "", completion: @escaping ( PurchaseResult) -> Void) {
+    func purchaseProduct(_ productId: String, quantity: Int = 1, atomically: Bool = true, applicationUsername: String = "", completion: @escaping ( PurchaseResult) -> Void) {
 
         if let product = productsInfoController.products[productId] {
-            purchase(product: product, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
+            purchase(product: product, quantity: quantity, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
         } else {
             retrieveProductsInfo(Set([productId])) { result -> Void in
                 if let product = result.retrievedProducts.first {
-                    self.purchase(product: product, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
+                    self.purchase(product: product, quantity: quantity, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
                 } else if let error = result.error {
                     completion(.error(error: SKError(_nsError: error as NSError)))
                 } else if let invalidProductId = result.invalidProductIDs.first {
@@ -73,7 +73,7 @@ public class SwiftyStoreKit {
         })
     }
 
-    func completeTransactions(atomically: Bool = true, completion: @escaping ([Product]) -> Void) {
+    func completeTransactions(atomically: Bool = true, completion: @escaping ([Purchase]) -> Void) {
 
         paymentQueueController.completeTransactions(CompleteTransactions(atomically: atomically, callback: completion))
     }
@@ -102,14 +102,14 @@ public class SwiftyStoreKit {
     }
 
     // MARK: private methods
-    private func purchase(product: SKProduct, atomically: Bool, applicationUsername: String = "", completion: @escaping (PurchaseResult) -> Void) {
+    private func purchase(product: SKProduct, quantity: Int, atomically: Bool, applicationUsername: String = "", completion: @escaping (PurchaseResult) -> Void) {
         guard SwiftyStoreKit.canMakePayments else {
             let error = NSError(domain: SKErrorDomain, code: SKError.paymentNotAllowed.rawValue, userInfo: nil)
             completion(.error(error: SKError(_nsError: error)))
             return
         }
 
-        paymentQueueController.startPayment(Payment(product: product, atomically: atomically, applicationUsername: applicationUsername) { result in
+        paymentQueueController.startPayment(Payment(product: product, quantity: quantity, atomically: atomically, applicationUsername: applicationUsername) { result in
 
             completion(self.processPurchaseResult(result))
         })
@@ -117,30 +117,30 @@ public class SwiftyStoreKit {
 
     private func processPurchaseResult(_ result: TransactionResult) -> PurchaseResult {
         switch result {
-        case .purchased(let product):
-            return .success(product: product)
+        case .purchased(let purchase):
+            return .success(purchase: purchase)
         case .failed(let error):
             return .error(error: error)
-        case .restored(let product):
-            return .error(error: storeInternalError(description: "Cannot restore product \(product.productId) from purchase path"))
+        case .restored(let purchase):
+            return .error(error: storeInternalError(description: "Cannot restore product \(purchase.productId) from purchase path"))
         }
     }
 
     private func processRestoreResults(_ results: [TransactionResult]) -> RestoreResults {
-        var restoredProducts: [Product] = []
-        var restoreFailedProducts: [(SKError, String?)] = []
+        var restoredPurchases: [Purchase] = []
+        var restoreFailedPurchases: [(SKError, String?)] = []
         for result in results {
             switch result {
-            case .purchased(let product):
-                let error = storeInternalError(description: "Cannot purchase product \(product.productId) from restore purchases path")
-                restoreFailedProducts.append((error, product.productId))
+            case .purchased(let purchase):
+                let error = storeInternalError(description: "Cannot purchase product \(purchase.productId) from restore purchases path")
+                restoreFailedPurchases.append((error, purchase.productId))
             case .failed(let error):
-                restoreFailedProducts.append((error, nil))
-            case .restored(let product):
-                restoredProducts.append(product)
+                restoreFailedPurchases.append((error, nil))
+            case .restored(let purchase):
+                restoredPurchases.append(purchase)
             }
         }
-        return RestoreResults(restoredProducts: restoredProducts, restoreFailedProducts: restoreFailedProducts)
+        return RestoreResults(restoredPurchases: restoredPurchases, restoreFailedPurchases: restoreFailedPurchases)
     }
 
     private func storeInternalError(code: SKError.Code = SKError.unknown, description: String = "") -> SKError {
@@ -167,13 +167,14 @@ extension SwiftyStoreKit {
     /**
      *  Purchase a product
      *  - Parameter productId: productId as specified in iTunes Connect
+     *  - Parameter quantity: quantity of the product to be purchased
      *  - Parameter atomically: whether the product is purchased atomically (e.g. finishTransaction is called immediately)
      *  - Parameter applicationUsername: an opaque identifier for the user’s account on your system
      *  - Parameter completion: handler for result
      */
-    public class func purchaseProduct(_ productId: String, atomically: Bool = true, applicationUsername: String = "", completion: @escaping ( PurchaseResult) -> Void) {
+    public class func purchaseProduct(_ productId: String, quantity: Int = 1, atomically: Bool = true, applicationUsername: String = "", completion: @escaping ( PurchaseResult) -> Void) {
 
-        sharedInstance.purchaseProduct(productId, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
+        sharedInstance.purchaseProduct(productId, quantity: quantity, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
     }
 
     public class func restorePurchases(atomically: Bool = true, applicationUsername: String = "", completion: @escaping (RestoreResults) -> Void) {
@@ -181,7 +182,7 @@ extension SwiftyStoreKit {
         sharedInstance.restorePurchases(atomically: atomically, applicationUsername: applicationUsername, completion: completion)
     }
 
-    public class func completeTransactions(atomically: Bool = true, completion: @escaping ([Product]) -> Void) {
+    public class func completeTransactions(atomically: Bool = true, completion: @escaping ([Purchase]) -> Void) {
 
         sharedInstance.completeTransactions(atomically: atomically, completion: completion)
     }

+ 7 - 7
SwiftyStoreKitTests/CompleteTransactionsControllerTests.swift

@@ -36,11 +36,11 @@ class CompleteTransactionsControllerTests: XCTestCase {
         let transaction = TestPaymentTransaction(payment: SKPayment(product: testProduct), transactionState: .restored)
 
         var callbackCalled = false
-        let completeTransactions = CompleteTransactions(atomically: true) { products in
+        let completeTransactions = CompleteTransactions(atomically: true) { purchases in
             callbackCalled = true
-            XCTAssertEqual(products.count, 1)
-            let product = products.first!
-            XCTAssertEqual(product.productId, productIdentifier)
+            XCTAssertEqual(purchases.count, 1)
+            let purchase = purchases.first!
+            XCTAssertEqual(purchase.productId, productIdentifier)
         }
 
         let completeTransactionsController = makeCompleteTransactionsController(completeTransactions: completeTransactions)
@@ -67,12 +67,12 @@ class CompleteTransactionsControllerTests: XCTestCase {
         ]
 
         var callbackCalled = false
-        let completeTransactions = CompleteTransactions(atomically: true) { products in
+        let completeTransactions = CompleteTransactions(atomically: true) { purchases in
             callbackCalled = true
-            XCTAssertEqual(products.count, 4)
+            XCTAssertEqual(purchases.count, 4)
 
             for i in 0..<4 {
-                XCTAssertEqual(products[i].productId, transactions[i].payment.productIdentifier)
+                XCTAssertEqual(purchases[i].productId, transactions[i].payment.productIdentifier)
             }
         }
 

+ 24 - 23
SwiftyStoreKitTests/PaymentQueueControllerTests.swift

@@ -29,8 +29,9 @@ import StoreKit
 @testable import SwiftyStoreKit
 
 extension Payment {
-    init(product: SKProduct, atomically: Bool, applicationUsername: String, callback: @escaping (TransactionResult) -> Void) {
+    init(product: SKProduct, quantity: Int, atomically: Bool, applicationUsername: String, callback: @escaping (TransactionResult) -> Void) {
         self.product = product
+        self.quantity = quantity
         self.atomically = atomically
         self.applicationUsername = applicationUsername
         self.callback = callback
@@ -110,19 +111,19 @@ class PaymentQueueControllerTests: XCTestCase {
             restorePurchasesCallbackCalled = true
             XCTAssertEqual(results.count, 1)
             let first = results.first!
-            if case .restored(let restoredProduct) = first {
-                XCTAssertEqual(restoredProduct.productId, restoredProductIdentifier)
+            if case .restored(let restoredPayment) = first {
+                XCTAssertEqual(restoredPayment.productId, restoredProductIdentifier)
             } else {
                 XCTFail("expected restored callback with product")
             }
         }
 
         var completeTransactionsCallbackCalled = false
-        let completeTransactions = CompleteTransactions(atomically: true) { products in
+        let completeTransactions = CompleteTransactions(atomically: true) { purchases in
             completeTransactionsCallbackCalled = true
-            XCTAssertEqual(products.count, 2)
-            XCTAssertEqual(products[0].productId, failedProductIdentifier)
-            XCTAssertEqual(products[1].productId, deferredProductIdentifier)
+            XCTAssertEqual(purchases.count, 2)
+            XCTAssertEqual(purchases[0].productId, failedProductIdentifier)
+            XCTAssertEqual(purchases[1].productId, deferredProductIdentifier)
         }
 
         // run
@@ -165,20 +166,20 @@ class PaymentQueueControllerTests: XCTestCase {
         var paymentCallbackCalled = false
         let testPayment = makeTestPayment(productIdentifier: purchasedProductIdentifier) { result in
             paymentCallbackCalled = true
-            if case .purchased(let product) = result {
-                XCTAssertEqual(product.productId, purchasedProductIdentifier)
+            if case .purchased(let payment) = result {
+                XCTAssertEqual(payment.productId, purchasedProductIdentifier)
             } else {
                 XCTFail("expected purchased callback with product id")
             }
         }
 
         var completeTransactionsCallbackCalled = false
-        let completeTransactions = CompleteTransactions(atomically: true) { products in
+        let completeTransactions = CompleteTransactions(atomically: true) { payments in
             completeTransactionsCallbackCalled = true
-            XCTAssertEqual(products.count, 3)
-            XCTAssertEqual(products[0].productId, failedProductIdentifier)
-            XCTAssertEqual(products[1].productId, restoredProductIdentifier)
-            XCTAssertEqual(products[2].productId, deferredProductIdentifier)
+            XCTAssertEqual(payments.count, 3)
+            XCTAssertEqual(payments[0].productId, failedProductIdentifier)
+            XCTAssertEqual(payments[1].productId, restoredProductIdentifier)
+            XCTAssertEqual(payments[2].productId, deferredProductIdentifier)
         }
 
         // run
@@ -220,20 +221,20 @@ class PaymentQueueControllerTests: XCTestCase {
             restorePurchasesCallbackCalled = true
             XCTAssertEqual(results.count, 1)
             let first = results.first!
-            if case .restored(let restoredProduct) = first {
-                XCTAssertEqual(restoredProduct.productId, restoredProductIdentifier)
+            if case .restored(let restoredPayment) = first {
+                XCTAssertEqual(restoredPayment.productId, restoredProductIdentifier)
             } else {
                 XCTFail("expected restored callback with product")
             }
         }
 
         var completeTransactionsCallbackCalled = false
-        let completeTransactions = CompleteTransactions(atomically: true) { products in
+        let completeTransactions = CompleteTransactions(atomically: true) { payments in
             completeTransactionsCallbackCalled = true
-            XCTAssertEqual(products.count, 3)
-            XCTAssertEqual(products[0].productId, purchasedProductIdentifier)
-            XCTAssertEqual(products[1].productId, failedProductIdentifier)
-            XCTAssertEqual(products[2].productId, deferredProductIdentifier)
+            XCTAssertEqual(payments.count, 3)
+            XCTAssertEqual(payments[0].productId, purchasedProductIdentifier)
+            XCTAssertEqual(payments[1].productId, failedProductIdentifier)
+            XCTAssertEqual(payments[2].productId, deferredProductIdentifier)
         }
 
         // run
@@ -256,9 +257,9 @@ class PaymentQueueControllerTests: XCTestCase {
         return TestPaymentTransaction(payment: SKPayment(product: testProduct), transactionState: transactionState)
     }
 
-    func makeTestPayment(productIdentifier: String, atomically: Bool = true, callback: @escaping (TransactionResult) -> Void) -> Payment {
+    func makeTestPayment(productIdentifier: String, quantity: Int = 1, atomically: Bool = true, callback: @escaping (TransactionResult) -> Void) -> Payment {
 
         let testProduct = TestProduct(productIdentifier: productIdentifier)
-        return Payment(product: testProduct, atomically: atomically, applicationUsername: "", callback: callback)
+        return Payment(product: testProduct, quantity: quantity, atomically: atomically, applicationUsername: "", callback: callback)
     }
 }

+ 12 - 10
SwiftyStoreKitTests/PaymentsControllerTests.swift

@@ -46,8 +46,8 @@ class PaymentsControllerTests: XCTestCase {
         let payment = makeTestPayment(product: testProduct) { result in
 
             callbackCalled = true
-            if case .purchased(let product) = result {
-                XCTAssertEqual(product.productId, productIdentifier)
+            if case .purchased(let payment) = result {
+                XCTAssertEqual(payment.productId, productIdentifier)
             } else {
                 XCTFail("expected purchased callback with product id")
             }
@@ -112,8 +112,8 @@ class PaymentsControllerTests: XCTestCase {
         let payment1 = makeTestPayment(product: testProduct1) { result in
 
             callback1Called = true
-            if case .purchased(let product) = result {
-                XCTAssertEqual(product.productId, productIdentifier)
+            if case .purchased(let payment) = result {
+                XCTAssertEqual(payment.productId, productIdentifier)
             } else {
                 XCTFail("expected purchased callback with product id")
             }
@@ -160,8 +160,8 @@ class PaymentsControllerTests: XCTestCase {
         let payment1 = makeTestPayment(product: testProduct1) { result in
 
             callback1Called = true
-            if case .purchased(let product) = result {
-                XCTAssertEqual(product.productId, productIdentifier)
+            if case .purchased(let payment) = result {
+                XCTAssertEqual(payment.productId, productIdentifier)
             } else {
                 XCTFail("expected purchased callback with product id")
             }
@@ -190,6 +190,8 @@ class PaymentsControllerTests: XCTestCase {
 
         XCTAssertEqual(spy.finishTransactionCalledCount, 1)
     }
+    
+    // TODO: Test quantity > 1
 
     func makePaymentsController(appendPayments payments: [Payment]) -> PaymentsController {
 
@@ -200,15 +202,15 @@ class PaymentsControllerTests: XCTestCase {
         return paymentsController
     }
 
-    func makeTestPayment(product: SKProduct, atomically: Bool = true, callback: @escaping (TransactionResult) -> Void) -> Payment {
+    func makeTestPayment(product: SKProduct, quantity: Int = 1, atomically: Bool = true, callback: @escaping (TransactionResult) -> Void) -> Payment {
 
-        return Payment(product: product, atomically: atomically, applicationUsername: "", callback: callback)
+        return Payment(product: product, quantity: quantity, atomically: atomically, applicationUsername: "", callback: callback)
     }
 
-    func makeTestPayment(productIdentifier: String, atomically: Bool = true, callback: @escaping (TransactionResult) -> Void) -> Payment {
+    func makeTestPayment(productIdentifier: String, quantity: Int = 1, atomically: Bool = true, callback: @escaping (TransactionResult) -> Void) -> Payment {
 
         let product = TestProduct(productIdentifier: productIdentifier)
-        return makeTestPayment(product: product, atomically: atomically, callback: callback)
+        return makeTestPayment(product: product, quantity: quantity, atomically: atomically, callback: callback)
 
     }
 }

+ 6 - 6
SwiftyStoreKitTests/RestorePurchasesControllerTests.swift

@@ -40,8 +40,8 @@ class RestorePurchasesControllerTests: XCTestCase {
             callbackCalled = true
             XCTAssertEqual(results.count, 1)
             let restored = results.first!
-            if case .restored(let restoredProduct) = restored {
-                XCTAssertEqual(restoredProduct.productId, productIdentifier)
+            if case .restored(let restoredPurchase) = restored {
+                XCTAssertEqual(restoredPurchase.productId, productIdentifier)
             } else {
                 XCTFail("expected restored callback with product")
             }
@@ -86,14 +86,14 @@ class RestorePurchasesControllerTests: XCTestCase {
             callbackCalled = true
             XCTAssertEqual(results.count, 2)
             let first = results.first!
-            if case .restored(let restoredProduct) = first {
-                XCTAssertEqual(restoredProduct.productId, productIdentifier1)
+            if case .restored(let restoredPurchase) = first {
+                XCTAssertEqual(restoredPurchase.productId, productIdentifier1)
             } else {
                 XCTFail("expected restored callback with product")
             }
             let last = results.last!
-            if case .restored(let restoredProduct) = last {
-                XCTAssertEqual(restoredProduct.productId, productIdentifier2)
+            if case .restored(let restoredPurchase) = last {
+                XCTAssertEqual(restoredPurchase.productId, productIdentifier2)
             } else {
                 XCTFail("expected restored callback with product")
             }