Patel Jigar
Patel Jigar

Reputation: 2151

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

Upvotes: 1

Views: 1038

Answers (2)

JG_
JG_

Reputation: 65

Here's a snippet of the iOS receipt validation code I use in objective C in order to check for renewal on app launch. This helps me in getting the subscription renewal receipt data from App Store on app launch.

- (void)verifyPurchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction isTestServer:(BOOL)flag{
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
    [self handleActionWithType:kIAPPurchSuccess data:receipt];

    NSError *error;
    NSDictionary *requestContents = @{
                                      @"receipt-data": [receipt base64EncodedStringWithOptions:0],
                                      @"password": @"INSERT_PASSWORD_HERE",
                                      @"exclude-old-transactions": @"true"
                                      };
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                          options:0
                                                            error:&error];

    NSString *serverString = @"https://buy.itunes.apple.com/verifyReceipt";
    NSURL *storeURL = [NSURL URLWithString:serverString];
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                               if (connectionError) {
                                   [self handleActionWithType:KIAPPurchVerFailed data:nil];
                               } else {
                                   NSError *error;
                                   NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                   if (!jsonResponse) {
                                       [self handleActionWithType:KIAPPurchVerFailed data:nil];
                                   }
                                   NSString *status = [NSString stringWithFormat:@"%@",jsonResponse[@"status"]];
                                   if (status && [status isEqualToString:@"21007"]) {
                                       [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:YES];
                                   }else if(status && [status isEqualToString:@"0"]){
                                       [self handleActionWithType:KIAPPurchVerSuccess data:nil];
                                   }
#if DEBUG
                                   NSLog(@"log-IAP> jsonResults: %@",jsonResponse);
#endif
                               }
                           }];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

Hope this helps. Best if you could convert your Objective C project to swift soon, as its getting harder and harder to find tutorials on Objective C especially for newer implementation.

Upvotes: 1

technerd
technerd

Reputation: 14504

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.

Upvotes: 2

Related Questions