登录所需的环境沙箱问题

Posted

技术标签:

【中文标题】登录所需的环境沙箱问题【英文标题】:sign in required environment sandbox issue 【发布时间】:2017-10-10 06:55:14 【问题描述】:

每次我构建一个临时构建并在 ios 11 上运行它时,它都会不断弹出消息“需要登录 - 输入 ***** [Environment:Sandbox] 的密码”。因此,这会像循环一样持续激活并且不会消失。也尝试从 iCloud 退出,但没有成功。我的 inAppPurchase 代码如下。

class InAppPurchase: NSObject,SKProductsRequestDelegate, 

SKPaymentTransactionObserver 


    ///Singleton
    private static var inappPurChase:InAppPurchase?;

    public static var shared:InAppPurchase 
        if inappPurChase == nil
            inappPurChase = InAppPurchase()
        
        return inappPurChase!
    
    override private init() 
        //Singleton complete
    
    ////////////

    var productsList = [SKProduct]()
    var productToPurchase = SKProduct()
    var productID = ""
    let PURCHASE_ID_PREFIX = ""//"com.purelightbeta."
    var onInAppPurchaseSuccess: (()->Void )? = nil
    var onInAppPurchaseError: (()->Void )? = nil
    var onNoProductsIDs: (()->Void )? = nil
    var appEnvironment: ((String,Bool)->Void )? = nil
    var onReceiptVarificationError: (()->Void )? = nil
    var onRestorePurchaseError: ((String)->Void )? = nil
    var onRestoreProductsIDs: ((NSMutableArray)->Void )? = nil


    public func initPayment (productID: String) 
        self.productID = PURCHASE_ID_PREFIX + productID
        print("Initializing Purchase Product ID: \(self.productID)")
        if SKPaymentQueue.canMakePayments() 
            let productID: NSSet = NSSet(objects: self.productID)
            let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
            request.delegate = self
            request.start()
        else 
            print("In App Purchases not enabled")
        
    

    func buyProduct() 
        let payment = SKPayment(product: productToPurchase)
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().add(payment as SKPayment)
    


    public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) 
        let myProducts = response.products
        print(myProducts)
        productsList = []
        if myProducts.count == 0 
            print("No products")
            if(onNoProductsIDs != nil)
            onNoProductsIDs!()
            
        
        for product in myProducts 
            print("Prod Details :\(product.productIdentifier) \(product.price) \(product.localizedDescription)")
            productsList.append(product)
        


        for product in productsList 
            let productID = product.productIdentifier
            if productID == self.productID 
                productToPurchase = product
                buyProduct()
            
        

    

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) 
        let productIDs: NSMutableArray = []
        for trasacton in queue.transactions 
            if trasacton.transactionState == SKPaymentTransactionState.restored
            
                let t: SKPaymentTransaction = trasacton as SKPaymentTransaction
                let prodID = t.payment.productIdentifier as String
                print("prodID:",prodID)

                //let appStoreId = prodID.components(separatedBy: "com.purelightbeta.")

                productIDs.add(prodID)
                SKPaymentQueue .default().finishTransaction(trasacton)

            

        
        if onRestoreProductsIDs != nil 
            print(productIDs)
            onRestoreProductsIDs! (productIDs)
        

    

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) 
        for transaction: AnyObject in transactions 
            let trans = transaction as! SKPaymentTransaction
            print(trans.error ?? "No in app error")
            switch trans.transactionState 
            case .purchased:
                print("buy ok, AIP unlocked for item :", productToPurchase.productIdentifier)
                let productID =  productToPurchase.productIdentifier

                switch productID 
                case self.productID:
                    print("Item found")
                   //  startValidatingReceipt()
                default:
                    print("Item not found")
                
                queue.finishTransaction(trans)
                if self.onInAppPurchaseSuccess != nil 
                   self.onInAppPurchaseSuccess! ()
                    self.startValidatingReceipt()
                
            case .failed:
                print("buy error")
                if self.onInAppPurchaseError != nil 
                    self.onInAppPurchaseError! ()

                
                queue.finishTransaction(trans)
                break

            case .restored:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
               // break

            default:
                print("default")
                break
            

        
    
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) 
         print("ERROR: \(error.localizedDescription)")
        if onRestorePurchaseError != nil 
           onRestorePurchaseError! (error.localizedDescription)
        
    

    func restorePurchase() 
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()

    



    func startValidatingReceipt() 
        if let isExists = try? self.getReceiptURL()?.checkResourceIsReachable(), isExists == true 
            do 
            let data = try Data(contentsOf: self.getReceiptURL()!)
               // self.startValidatingData(data: data)
                self.sendReceiptToLocalServer(data: data)
            catch 
                let appReceiptRefreshRequest = SKReceiptRefreshRequest(receiptProperties: nil)
                appReceiptRefreshRequest.delegate = self
                appReceiptRefreshRequest.start()
            
        else 
        print("No receipt for this purchase")
        
    
    func getReceiptURL() -> URL? 
        return Bundle.main.appStoreReceiptURL
    


    enum receiptValidationURLs:String 
        case sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
        case production = "https://buy.itunes.apple.com/verifyReceipt"

        static var url:URL
            if isDebug 
            return URL.init(string: self.sandbox.rawValue)!
            else
            return URL.init(string: self.production.rawValue)!
            
        
    
    func sendReceiptToLocalServer(data:Data) 
        let base64encodedReceipt = data.base64EncodedString()

        if self.appEnvironment != nil 
            self.appEnvironment! (base64encodedReceipt,isDebug)
        
    
    func startValidatingData(data:Data)


        let base64encodedReceipt = data.base64EncodedString()
        print(base64encodedReceipt)
        let requestDictionary = ["receipt-data":base64encodedReceipt]
        guard JSONSerialization.isValidJSONObject(requestDictionary) else   print("requestDictionary is not valid JSON");  return 
        do 
            let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
       //     let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt"  // this works but as noted above it's best to use your own trusted server
            NSLog("The Environment is: %@", receiptValidationURLs.url.absoluteString)
            guard let validationURL = URL(string: receiptValidationURLs.url.absoluteString) else  print("the validation url could not be created, unlikely error"); return 
            let session = URLSession(configuration: URLSessionConfiguration.default)
            var request = URLRequest(url: validationURL)
            request.httpMethod = "POST"
            request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
            let task = session.uploadTask(with: request, from: requestData)  (data, response, error) in
                if let data = data , error == nil 
                    do 
                       let appReceiptJSON = try JSONSerialization.jsonObject(with: data)
                         print((appReceiptJSON as AnyObject).count)
                         print("success. here is the json representation of the app receipt: \(appReceiptJSON)")
                         NSLog("Receipt is: %@", appReceiptJSON as! NSDictionary)
                         if let environment = (appReceiptJSON as? NSDictionary)?["environment"]

                         if self.appEnvironment != nil 
                            self.appEnvironment! (environment as? String ?? "No value",isDebug)
                         
                        
                     catch let error as NSError 
                        print("json serialization failed with error: \(error)")
                    
                 else 
                    print("the upload task returned an error: \(error)")
                
            
            task.resume()
         catch let error as NSError 
            print("json serialization failed with error: \(error)")
        
    

//    func requestDidFinish(_ request: SKRequest) 
//        // a fresh receipt should now be present at the url
//        do 
//
//            
//
//         catch 
//            // still no receipt, possible but unlikely to occur since this is the "success" delegate method
//        
//    

    func request(_ request: SKRequest, didFailWithError error: Error) 
        print("app receipt refresh request did fail with error: \(error)")
        // for some clues see here: https://samritchie.net/2015/01/29/the-operation-couldnt-be-completed-sserrordomain-error-100/
        if self.onReceiptVarificationError != nil 
            self.onReceiptVarificationError! ()
        

    



【问题讨论】:

您能否在此处发布您的 IAP 代码...我认为您的观察者处理有问题 代码已更新并已发布 【参考方案1】:

这可能不是答案,但会是一种解决方法。最好是创建一个新的沙盒用户,退出旧用户并放入新用户。

【讨论】:

以上是关于登录所需的环境沙箱问题的主要内容,如果未能解决你的问题,请参考以下文章

Sitecore 登录所需的最低角色和访问权限

在App Purchase中:需要登录[环境:沙箱]

尝试访问受保护页面时尝试获取登录所需的工作

如何在 Flask 中实现登录所需的装饰器

使用 django 和 AngularJS 使用 JWT 登录所需的装饰器

如何在 PHP 中登录页面后将用户重定向回所需的 URL?