Bläddra i källkod

Merge pull request #281 from bizz84/feature/verifyReceipt-receiptVerificator-remove-password

Remove `password` from `ReceiptValidator` protocol as this is specific to `AppleReceiptValidator`
Andrea Bizzotto 7 år sedan
förälder
incheckning
90bb5516d9

+ 3 - 1
CHANGELOG.md

@@ -2,9 +2,11 @@
 
 All notable changes to this project will be documented in this file.
 
-## [0.10.9](https://github.com/bizz84/SwiftyStoreKit/releases/tag/0.10.9) Add `fetchReceipt` method
+## [0.11.0](https://github.com/bizz84/SwiftyStoreKit/releases/tag/0.11.0) Add `fetchReceipt` method + update `verifyReceipt` and `ReceiptValidator` protocol
 
 * Add `fetchReceipt` method. Update `verifyReceipt` to use it ([#278](https://github.com/bizz84/SwiftyStoreKit/pull/278), related issues: [#272](https://github.com/bizz84/SwiftyStoreKit/issues/272), [#223](https://github.com/bizz84/SwiftyStoreKit/issues/223)).
+* Remove `password` from `ReceiptValidator` protocol as this is specific to `AppleReceiptValidator` ([#281](https://github.com/bizz84/SwiftyStoreKit/pull/281/)). **Note**: This is an API breaking change.
+
 
 ## [0.10.8](https://github.com/bizz84/SwiftyStoreKit/releases/tag/0.10.8) Update to swiftlint 0.22.0
 

+ 8 - 8
README.md

@@ -320,8 +320,8 @@ If `fetchReceipt` is successful, it will return the **encrypted** receipt as a s
 Use this method to (optionally) refresh the receipt and perform validation in one step.
 
 ```swift
-let appleValidator = AppleReceiptValidator(service: .production)
-SwiftyStoreKit.verifyReceipt(using: appleValidator, password: "your-shared-secret", forceRefresh: false) { result in
+let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
+SwiftyStoreKit.verifyReceipt(using: appleValidator, forceRefresh: false) { result in
     switch result {
     case .success(let receipt):
         print("Verify receipt Success: \(receipt)")
@@ -353,8 +353,8 @@ If you need to verify multiple purchases / subscriptions, you can either:
 ### Verify Purchase
 
 ```swift
-let appleValidator = AppleReceiptValidator(service: .production)
-SwiftyStoreKit.verifyReceipt(using: appleValidator, password: "your-shared-secret") { result in
+let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
+SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
     switch result {
     case .success(let receipt):
         // Verify the purchase of Consumable or NonConsumable
@@ -387,8 +387,8 @@ From [Apple - Working with Subscriptions](https://developer.apple.com/library/co
 When one or more subscriptions are found for a given product id, they are returned as a `ReceiptItem` array ordered by `expiryDate`, with the first one being the newest.
 
 ```swift
-let appleValidator = AppleReceiptValidator(service: .production)
-SwiftyStoreKit.verifyReceipt(using: appleValidator, password: "your-shared-secret") { result in
+let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
+SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
     switch result {
     case .success(let receipt):
         // Verify the purchase of a Subscription
@@ -448,8 +448,8 @@ SwiftyStoreKit.purchaseProduct(productId, atomically: true) { result in
             SwiftyStoreKit.finishTransaction(purchase.transaction)
         }
         
-        let appleValidator = AppleReceiptValidator(service: .production)
-        SwiftyStoreKit.verifyReceipt(using: appleValidator, password: "your-shared-secret") { result in
+        let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
+        SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
             
             if case .success(let receipt) = result {
                 let purchaseResult = SwiftyStoreKit.verifySubscription(

+ 2 - 3
SwiftyStoreKit-iOS-Demo/ViewController.swift

@@ -116,9 +116,8 @@ class ViewController: UIViewController {
     
     func verifyReceipt(completion: @escaping (VerifyReceiptResult) -> Void) {
         
-        let appleValidator = AppleReceiptValidator(service: .production)
-        let password = "your-shared-secret"
-        SwiftyStoreKit.verifyReceipt(using: appleValidator, password: password, completion: completion)
+        let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
+        SwiftyStoreKit.verifyReceipt(using: appleValidator, completion: completion)
     }
 
     func verifyPurchase(_ purchase: RegisteredPurchase) {

+ 2 - 3
SwiftyStoreKit-macOS-Demo/ViewController.swift

@@ -112,9 +112,8 @@ class ViewController: NSViewController {
     
     func verifyReceipt(completion: @escaping (VerifyReceiptResult) -> Void) {
         
-        let appleValidator = AppleReceiptValidator(service: .production)
-        let password = "your-shared-secret"
-        SwiftyStoreKit.verifyReceipt(using: appleValidator, password: password, completion: completion)
+        let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
+        SwiftyStoreKit.verifyReceipt(using: appleValidator, completion: completion)
     }
 
     func verifyPurchase(_ purchase: RegisteredPurchase) {

+ 14 - 10
SwiftyStoreKit/AppleReceiptValidator.swift

@@ -34,16 +34,20 @@ public struct AppleReceiptValidator: ReceiptValidator {
 		case sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
 	}
 
-	public init(service: VerifyReceiptURLType = .production) {
+    private let service: VerifyReceiptURLType
+    private let sharedSecret: String?
+
+    /**
+     * Reference Apple Receipt Validator
+     *  - Parameter service: Either .production or .sandbox
+     *  - Parameter sharedSecret: Only used for receipts that contain auto-renewable subscriptions. Your app’s shared secret (a hexadecimal string).
+     */
+    public init(service: VerifyReceiptURLType = .production, sharedSecret: String? = nil) {
 		self.service = service
+        self.sharedSecret = sharedSecret
 	}
 
-	private let service: VerifyReceiptURLType
-
-	public func validate(
-		receipt: String,
-		password autoRenewPassword: String? = nil,
-		completion: @escaping (VerifyReceiptResult) -> Void) {
+	public func validate(receipt: String, completion: @escaping (VerifyReceiptResult) -> Void) {
 
 		let storeURL = URL(string: service.rawValue)! // safe (until no more)
 		let storeRequest = NSMutableURLRequest(url: storeURL)
@@ -51,7 +55,7 @@ public struct AppleReceiptValidator: ReceiptValidator {
 
 		let requestContents: NSMutableDictionary = [ "receipt-data": receipt ]
 		// password if defined
-		if let password = autoRenewPassword {
+		if let password = sharedSecret {
 			requestContents.setValue(password, forKey: "password")
 		}
 
@@ -101,8 +105,8 @@ public struct AppleReceiptValidator: ReceiptValidator {
 				*/
 				let receiptStatus = ReceiptStatus(rawValue: status) ?? ReceiptStatus.unknown
 				if case .testReceipt = receiptStatus {
-					let sandboxValidator = AppleReceiptValidator(service: .sandbox)
-					sandboxValidator.validate(receipt: receipt, password: autoRenewPassword, completion: completion)
+                    let sandboxValidator = AppleReceiptValidator(service: .sandbox, sharedSecret: self.sharedSecret)
+					sandboxValidator.validate(receipt: receipt, completion: completion)
 				} else {
 					if receiptStatus.isValid {
 						completion(.success(receipt: receiptInfo))

+ 4 - 9
SwiftyStoreKit/InAppReceiptVerificator.swift

@@ -45,13 +45,11 @@ class InAppReceiptVerificator: NSObject {
     /**
      *  Verify application receipt.
      *  - Parameter validator: Validator to check the encrypted receipt and return the receipt in readable format
-     *  - Parameter password: Your app’s shared secret (a hexadecimal string). Only used for receipts that contain auto-renewable subscriptions.
      *  - Parameter forceRefresh: If true, refreshes the receipt even if one already exists.
      *  - Parameter refresh: closure to perform receipt refresh (this is made explicit for testability)
      *  - Parameter completion: handler for result
      */
     public func verifyReceipt(using validator: ReceiptValidator,
-                              password: String? = nil,
                               forceRefresh: Bool,
                               refresh: InAppReceiptRefreshRequest.ReceiptRefresh = InAppReceiptRefreshRequest.refresh,
                               completion: @escaping (VerifyReceiptResult) -> Void) {
@@ -59,7 +57,7 @@ class InAppReceiptVerificator: NSObject {
         fetchReceipt(forceRefresh: forceRefresh, refresh: refresh) { result in
             switch result {
             case .success(let encryptedReceipt):
-                self.verify(receipt: encryptedReceipt, using: validator, password: password, completion: completion)
+                self.verify(receipt: encryptedReceipt, using: validator, completion: completion)
             case .error(let error):
                 completion(.error(error: error))
             }
@@ -79,9 +77,7 @@ class InAppReceiptVerificator: NSObject {
                              completion: @escaping (FetchReceiptResult) -> Void) {
 
         if let receiptData = appStoreReceiptData, forceRefresh == false {
-
             fetchReceiptSuccessHandler(receiptData: receiptData, completion: completion)
-
         } else {
             
             receiptRefreshRequest = refresh(nil) { result in
@@ -111,12 +107,11 @@ class InAppReceiptVerificator: NSObject {
     /**
      *  - Parameter receiptData: encrypted receipt data
      *  - Parameter validator: Validator to check the encrypted receipt and return the receipt in readable format
-     *  - Parameter password: Your app’s shared secret (a hexadecimal string). Only used for receipts that contain auto-renewable subscriptions.
      *  - Parameter completion: handler for result
      */
-    private func verify(receipt: String, using validator: ReceiptValidator, password: String? = nil, completion: @escaping (VerifyReceiptResult) -> Void) {
-
-        validator.validate(receipt: receipt, password: password) { result in
+    private func verify(receipt: String, using validator: ReceiptValidator, completion: @escaping (VerifyReceiptResult) -> Void) {
+     
+        validator.validate(receipt: receipt) { result in
             
             DispatchQueue.main.async {
                 completion(result)

+ 1 - 1
SwiftyStoreKit/SwiftyStoreKit+Types.swift

@@ -45,7 +45,7 @@ public struct PurchaseDetails {
 
 //Conform to this protocol to provide custom receipt validator
 public protocol ReceiptValidator {
-	func validate(receipt: String, password autoRenewPassword: String?, completion: @escaping (VerifyReceiptResult) -> Void)
+	func validate(receipt: String, completion: @escaping (VerifyReceiptResult) -> Void)
 }
 
 // Payment transaction

+ 2 - 3
SwiftyStoreKit/SwiftyStoreKit.swift

@@ -229,13 +229,12 @@ extension SwiftyStoreKit {
     /**
      *  Verify application receipt
      *  - Parameter validator: receipt validator to use
-     *  - Parameter password: Only used for receipts that contain auto-renewable subscriptions. Your app’s shared secret (a hexadecimal string).
      *  - Parameter forceRefresh: If true, refreshes the receipt even if one already exists.
      *  - Parameter completion: handler for result
      */
-    public class func verifyReceipt(using validator: ReceiptValidator, password: String? = nil, forceRefresh: Bool = false, completion: @escaping (VerifyReceiptResult) -> Void) {
+    public class func verifyReceipt(using validator: ReceiptValidator, forceRefresh: Bool = false, completion: @escaping (VerifyReceiptResult) -> Void) {
 
-        sharedInstance.receiptVerificator.verifyReceipt(using: validator, password: password, forceRefresh: forceRefresh, completion: completion)
+        sharedInstance.receiptVerificator.verifyReceipt(using: validator, forceRefresh: forceRefresh, completion: completion)
     }
 
     /**

+ 9 - 9
SwiftyStoreKitTests/InAppReceiptVerificatorTests.swift

@@ -28,7 +28,7 @@ import XCTest
 
 class TestReceiptValidator: ReceiptValidator {
     var validateCalled = false
-    func validate(receipt: String, password autoRenewPassword: String?, completion: @escaping (VerifyReceiptResult) -> Void) {
+    func validate(receipt: String, completion: @escaping (VerifyReceiptResult) -> Void) {
         validateCalled = true
         completion(.success(receipt: [:]))
     }
@@ -76,7 +76,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: nil)
         
         var refreshCalled = false
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             refreshCalled = true
             return TestInAppReceiptRefreshRequest(receiptProperties: properties, callback: callback)
@@ -95,7 +95,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: testReceiptURL)
         
         var refreshCalled = false
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             refreshCalled = true
             return TestInAppReceiptRefreshRequest(receiptProperties: properties, callback: callback)
@@ -115,7 +115,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: testReceiptURL)
         
         var refreshCalled = false
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: true, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: true, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             refreshCalled = true
             return TestInAppReceiptRefreshRequest(receiptProperties: properties, callback: callback)
@@ -132,7 +132,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: nil)
         let refreshError = NSError(domain: "", code: 0, userInfo: nil)
         
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             callback(.error(e: refreshError))
             return TestInAppReceiptRefreshRequest(receiptProperties: properties, callback: callback)
@@ -148,7 +148,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let validator = TestReceiptValidator()
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: nil)
         
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             callback(.success)
             return TestInAppReceiptRefreshRequest(receiptProperties: properties, callback: callback)
@@ -167,7 +167,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let validator = TestReceiptValidator()
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: nil)
         
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             writeReceiptData(to: testReceiptURL)
             callback(.success)
@@ -188,7 +188,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let validator = TestReceiptValidator()
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: testReceiptURL)
         
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             writeReceiptData(to: testReceiptURL)
             callback(.success)
@@ -210,7 +210,7 @@ class InAppReceiptVerificatorTests: XCTestCase {
         let validator = TestReceiptValidator()
         let verificator = InAppReceiptVerificator(appStoreReceiptURL: testReceiptURL)
         
-        verificator.verifyReceipt(using: validator, password: nil, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
+        verificator.verifyReceipt(using: validator, forceRefresh: false, refresh: { (properties, callback) -> InAppReceiptRefreshRequest in
             
             XCTFail("refresh should not be called if we already have a receipt")
             return TestInAppReceiptRefreshRequest(receiptProperties: properties, callback: callback)