Search code examples
objective-cin-app-purchaseios9afnetworkingxcode7.2

In-app purchase receipt verification for auto renewal using AFNetworking objective-c


I am writing below code using AFNetworking for receipt verification and it gives me status=210002 While it gives me status=0 in NSMutableURLRequest

please help me by getting solution

 NSString *strurl = @"https://sandbox.itunes.apple.com/verifyReceipt";   
 NSData *receipt = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];

 NSDictionary *parameter=@{
                          @"receipt-data" : [receipt base64EncodedStringWithOptions:0],
                          @"password" : @"xxxxxxxxxxxxxxxxxxxx",
                         };


 NSData *jsonParam = [NSJSONSerialization dataWithJSONObject:parameter options:NSJSONWritingPrettyPrinted error:nil];

 AFHTTPRequestOperationManager *manager =  [AFHTTPRequestOperationManager manager];
 manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/plain"];
 [manager POST:strurl parameters:jsonParam success:^(AFHTTPRequestOperation *oprtation, id responseObject){
    NSLog(@"JSON: %@", responseObject);

 }failure:^(AFHTTPRequestOperation *operation, NSError *error){
    NSLog(@"Error: %@", error);

 }];

Thank you


Solution

  • Here is the Receipt validation code which i use in my application, but i have implementation in swift.

    I am also using NSMutableURLRequest for Web Service call to iTunes Server.

        func verifyPaymentReceipt(){
    
        let mainBundle = NSBundle.mainBundle() as NSBundle;
        let receiptUrl = mainBundle.appStoreReceiptURL;
        let isPresent = receiptUrl?.checkResourceIsReachableAndReturnError(NSErrorPointer());
    
        if(isPresent == true){
    
            let data = NSData(contentsOfURL: receiptUrl! );
    
            // Create the JSON object that describes the request
    
            let requestContents  = NSMutableDictionary();
            //            let encodeddata = data!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions());
            let encodeddata = data!.base64EncodedString();
    
            print("encodeddata = \(encodeddata)");
    
            requestContents.setObject(encodeddata, forKey: "receipt-data");
            requestContents.setObject("xxxxxxxxxxxxxxxxxxxxxxx", forKey: "password");
            var requestData : NSData?
            do{
                requestData = try NSJSONSerialization.dataWithJSONObject(requestContents, options: NSJSONWritingOptions());
            }catch{
                NSLog("Error in json data creation at verifyPaymentReceipt");
            }
    
            let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
            let file = "\(documentsPath)/requestData"
    
            if(NSFileManager.defaultManager().createFileAtPath(file, contents: data, attributes: nil)){
                NSLog("File %@ ",file);
            }
            else{
                NSLog("error File %@ ",file);
            }
    
    
    
            if(requestData != nil){
    
                let strRequestData = NSString(data: requestData!, encoding: NSUTF8StringEncoding);
                print(" strRequestData = \(strRequestData)");
                // Create a POST request with the receipt data.
    
                let storeURL = NSURL(string: "https://sandbox.itunes.apple.com/verifyReceipt");
                let storeRequest = NSMutableURLRequest(URL: storeURL!);
                storeRequest.HTTPMethod = "POST";
                storeRequest.HTTPBody = requestData;
    
                // Make a connection to the iTunes Store on a background queue.
    
                let queue = NSOperationQueue();
                NSURLConnection.sendAsynchronousRequest(storeRequest, queue: queue, completionHandler: { (response : NSURLResponse?, data : NSData?, error : NSError?) -> Void in
    
                    if(error != nil){
                        //Handle Error
                    }
                    else{
                        let d = NSString(data: data!, encoding: NSUTF8StringEncoding);
                        NSLog("DATA:%@", d!);
    
                        var jsonResponse: NSMutableDictionary?
                        do{
                            jsonResponse = try NSJSONSerialization.JSONObjectWithData(data!,
                                options: NSJSONReadingOptions.AllowFragments) as? NSMutableDictionary;
                            print(jsonResponse);
    
                        }catch{
                            NSLog("Parsing issue : verifyPaymentReceipt");
                        }
    
                        if(jsonResponse != nil){
    
                            let expirationDate: NSDate? = self.expirationDateFromResponse(jsonResponse!);
                            NSLog("Expiration Date: %@", expirationDate!);
    
                        }
                    }
                });
    
            }
    
        }
    
    }
    
    As you mention that your code works fine with NSMutableURLRequest but it returns 21002 with AFNetworking.
    

    21002 - The data in the receipt-data property was malformed or missing.

    It means that your encoding receipt data is malformed while using AFNetworking. So i think it is issue of encoding with AFNetworking.

    In the iOS 7 , Apple introduced new base64 methods on NSData that make it unnecessary to use a 3rd party base 64 decoding library , but i still suggest you to try to use Base64 encoding for receipt encoding. I hope this will solve your problem with AFNetworkig. As i also face same issue of 21002 when I verify receipt from server side and this encoding library works in this case. Don't know How , but it solved my issue at server side for receipt validation call. Hope it will work for you also.