Ios7 - Receipts Not Validating at Sandbox - Error 21002 (Java.Lang.Illegalargumentexception)

iOS7 - receipts not validating at sandbox - error 21002 (java.lang.IllegalArgumentException)

I've had this problem and looked everywhere, including on Apple's development forums. Apple will give a couple of stock replies, and that's it. I think it's a bug on Apple's side. Validation locally on the device will work, so try to convert to that. If you absolutely must use server side validation, only transactionReceipt seems to work right now.

The function is just deprecated, not banned, so I would just use it and hope Apple approves of the app. In fact, it's what I just did, fingers crossed, waiting for approval.

You can turn off the warning in Xcode by bracketing your code like this:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// code using transactionReceipt
#pragma clang diagnostic pop

Validating in-app purchase via jquery -- 21002 errors

For posterity,

When you use jQuery's post method, the string it forms from the second argument JavaScript object is not a JSON literal. Instead, it probably is doing something like this:

{
"receipt-data" : "< receipt data here >"
}

becomes

"receipt-data=< receipt data here >"

almost like a GET request.

However, when you use JSON.stringify(), you get a JSON literal from a JavaScript object.

In this respect, Apple's validation server is a bit non-standard, since it expects POST data to be formatted as JSON instead of the older GET-style string.

iOS 7 receipt validation issue on PHP server

Here is the code I use to send the receipt directly to the Apple servers.

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
[self checkTransactionWithAppleUseProduction:productionWebsite andData:receiptData];
NSString *string64=[receiptData base64EncodedStringWithOptions:kNilOptions];
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}",string64];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
NSString *serverURL;
if(productionWebsite)serverURL= @"https://buy.itunes.apple.com/verifyReceipt";
if(!productionWebsite)serverURL=@"https://sandbox.itunes.apple.com/verifyReceipt";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverURL]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:payloadData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];

equivalent to transaction.transactionReceipt.bytes

iOS6 and iOS7 receipts are different. Apple changed the receipt format when going to iOS7 in an effort to improve security. Take a look at: Can Purely On-Device In-App Purchase Receipt Validation Be Done With iOS6? and iOS7 - receipts not validating at sandbox - error 21002 (java.lang.IllegalArgumentException).

If you are talking about using these two methods on iOS7, in my tests, both return iOS7 style receipts. I'm not sure if the receipts are byte by byte identical, however.

Note that transactionReceipt is deprecated in iOS7.

Keep getting {status:21002} while verifying Apple In-App Purchase receipt

Two problems exist in your code:

  1. You need to use base64EncodedStringWithOptions instead of base64EncodedDataWithOptions. The former as you can see returns a data hash, not a base64 encoded string which Apple requires.
  2. Since you're posting JSON to Apple you need to set the Content-type to application/json instead of application/x-www-form-urlencoded;charset=UTF-8.

In App Purchase Receipt verification within app

After number of tries, I decided to do the receipt verification from server side. Actually this is the recommended way.

Here is my code,

-(void)recordTransaction:(SKPaymentTransaction *)transaction {   

NSString* receiptString = [[[NSString alloc] initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding] autorelease];

// POST this string to your server

// I used ASIFormDataRequest

}

// server side

$url = 'https://sandbox.itunes.apple.com/verifyReceipt';

// encode the receipt data received from application

$purchase_encoded = base64_encode( $purchase_receipt );

//Create JSON

$encodedData = json_encode( Array(
'receipt-data' => $purchase_encoded
) );

// POST data

//Open a Connection using POST method, as it is required to use POST method.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedData);
$encodedResponse = curl_exec($ch);
curl_close($ch);

//Decode response data using json_decode method to get an object.

$response = json_decode( $encodedResponse );

// check response

if ($response->{'status'} != 0)

// Invalid receipt

else

// valid reciept

I found help form,

http://gamesfromwithin.com/in-app-purchases-part-3

iOS InApp Purchase Receipt Validation iOS 7

In what I've seen, iOS7 doesn't change the need for whether or not you should do receipt validation, just how receipt validation is possible. iOS7 has enabled receipt validation on the device (e.g., see link from https://stackoverflow.com/users/1226963/rmaddy above, and see A complete solution to LOCALLY validate an in-app receipts and bundle receipts on iOS 7).

Does on-device receipt validation add extra security? It seems to me that it does. It gives you one more tool with which to secure your purchases. In my app (yet to be released), I want to support iOS6 and iOS7 so I decided to have a back-end server to do receipt validation for the iOS6 case. And since I have that server in place, for iOS7 receipts, I do on-device validation first and if that succeeds, I do server validation as a second check.

Whether or not you do receipt validation (in iOS5, iOS6, iOS7 etc) really depends on how much your security means to you. If you don't have much in the way of security needs, then why spend much time on security. If you do, then do more.

What if Apple changes the format of the receipts? Well, of course, this can and likely will happen. Given that the iOS6 to iOS7 change restructured receipts and in-app purchases considerably, it seems we should expect iOS8 to do so again. That's the future. Deal with what we have now.



Related Topics



Leave a reply



Submit