ソースを参照

Report purchase errors as SKError

Andrea Bizzotto 8 年 前
コミット
715096a8fd

+ 20 - 5
SwiftyStoreKit-iOS-Demo/ViewController.swift

@@ -86,7 +86,9 @@ class ViewController: UIViewController {
                     SwiftyStoreKit.finishTransaction(product.transaction)
                 }
             }
-            self.showAlert(self.alertForPurchaseResult(result))
+            if let alert = self.alertForPurchaseResult(result) {
+                self.showAlert(alert)
+            }
         }
     }
     
@@ -206,7 +208,7 @@ extension ViewController {
         }
     }
 
-    func alertForPurchaseResult(_ result: PurchaseResult) -> UIAlertController {
+    func alertForPurchaseResult(_ result: PurchaseResult) -> UIAlertController? {
         switch result {
         case .success(let product):
             print("Purchase Success: \(product.productId)")
@@ -215,10 +217,23 @@ extension ViewController {
             print("Purchase Failed: \(error)")
             switch error {
                 case .failed(let error):
-                    if (error as NSError).domain == SKErrorDomain {
-                        return alertWithTitle("Purchase failed", message: "Please check your Internet connection or try again later")
+                    switch error.code {
+                    case .unknown: return alertWithTitle("Purchase failed", message: "Unknown error. Please contact support")
+                    case .clientInvalid: // client is not allowed to issue the request, etc.
+                        return alertWithTitle("Purchase failed", message: "Not allowed to make the payment")
+                    case .paymentCancelled: // user cancelled the request, etc.
+                        return nil
+                    case .paymentInvalid: // purchase identifier was invalid, etc.
+                        return alertWithTitle("Purchase failed", message: "The purchase identifier was invalid")
+                    case .paymentNotAllowed: // this device is not allowed to make the payment
+                        return alertWithTitle("Purchase failed", message: "The device is not allowed to make the payment")
+                    case .storeProductNotAvailable: // Product is not available in the current storefront
+                        return alertWithTitle("Purchase failed", message: "The product is not available in the current storefront")
+                    case .cloudServicePermissionDenied: // user has not allowed access to cloud service information
+                        return alertWithTitle("Purchase failed", message: "Access to cloud service information is not allowed")
+                    case .cloudServiceNetworkConnectionFailed: // the device could not connect to the nework
+                        return alertWithTitle("Purchase failed", message: "Could not connect to the network")
                     }
-                    return alertWithTitle("Purchase failed", message: "Unknown error. Please contact support")
                 case .invalidProductId(let productId):
                     return alertWithTitle("Purchase failed", message: "\(productId) is not a valid product identifier")
                 case .paymentNotAllowed:

+ 1 - 1
SwiftyStoreKit/PaymentQueueController.swift

@@ -38,7 +38,7 @@ protocol TransactionController {
 public enum TransactionResult {
     case purchased(product: Product)
     case restored(product: Product)
-    case failed(error: Error)
+    case failed(error: SKError)
 }
 
 public protocol PaymentQueue: class {

+ 8 - 3
SwiftyStoreKit/PaymentsController.swift

@@ -87,9 +87,7 @@ class PaymentsController: TransactionController {
         }
         if transactionState == .failed {
 
-            let message = "Transaction failed for product ID: \(transactionProductIdentifier)"
-            let altError = NSError(domain: SKErrorDomain, code: 0, userInfo: [ NSLocalizedDescriptionKey: message ])
-            payment.callback(.failed(error: transaction.error ?? altError))
+            payment.callback(.failed(error: transactionError(for: transaction.error as NSError?)))
             
             paymentQueue.finishTransaction(transaction)
             payments.remove(at: paymentIndex)
@@ -102,6 +100,13 @@ class PaymentsController: TransactionController {
         return false
     }
     
+    func transactionError(for error: NSError?) -> SKError {
+        let message = "Unknown error"
+        let altError = NSError(domain: SKErrorDomain, code: SKError.Code.unknown.rawValue, userInfo: [ NSLocalizedDescriptionKey: message ])
+        let nsError = error ?? altError
+        return SKError(_nsError: nsError)
+    }
+        
     func processTransactions(_ transactions: [SKPaymentTransaction], on paymentQueue: PaymentQueue) -> [SKPaymentTransaction] {
         
         return transactions.filter { !processTransaction($0, on: paymentQueue) }

+ 1 - 1
SwiftyStoreKit/RestorePurchasesController.swift

@@ -84,7 +84,7 @@ class RestorePurchasesController: TransactionController {
         guard let restorePurchases = restorePurchases else {
             return
         }
-        restoredProducts.append(.failed(error: error))
+        restoredProducts.append(.failed(error: SKError(_nsError: error as NSError)))
         restorePurchases.callback(restoredProducts)
         
         // Reset state after error received

+ 1 - 1
SwiftyStoreKit/SwiftyStoreKit+Types.swift

@@ -56,7 +56,7 @@ public struct RetrieveResults {
 
 // Purchase error types
 public enum PurchaseError {
-    case failed(error: Error)
+    case failed(error: SKError)
     case invalidProductId(productId: String)
     case paymentNotAllowed
 }

+ 2 - 2
SwiftyStoreKit/SwiftyStoreKit.swift

@@ -61,7 +61,7 @@ public class SwiftyStoreKit {
                     self.purchase(product: product, atomically: atomically, applicationUsername: applicationUsername, completion: completion)
                 }
                 else if let error = result.error {
-                    completion(.error(error: .failed(error: error)))
+                    completion(.error(error: .failed(error: SKError(_nsError: error as NSError))))
                 }
                 else if let invalidProductId = result.invalidProductIDs.first {
                     completion(.error(error: .invalidProductId(productId: invalidProductId)))
@@ -128,7 +128,7 @@ public class SwiftyStoreKit {
         case .failed(let error):
             return .error(error: .failed(error: error))
         case .restored(let product):
-            return .error(error: .failed(error: storeInternalError(code: InternalErrorCode.restoredPurchaseWhenPurchasing.rawValue, description: "Cannot restore product \(product.productId) from purchase path")))
+            return .error(error: .failed(error: SKError(_nsError:  storeInternalError(code: InternalErrorCode.restoredPurchaseWhenPurchasing.rawValue, description: "Cannot restore product \(product.productId) from purchase path"))))
         }
     }