I know there have been quite a few posts on this but none seem to address the issues we\'re running into. So far I think I have everything setup correctly as specified in th
For anyone else in the future getting the 21002 error. It took a few hours to figure what was going wrong. It generally means that the base 64 encoded string within the JSON you send to Apple's servers is incorrect. This probably means that you're not Base-64 encoding or that your encoding routine is buggy. These are the steps you should use:
1) Base-64 encode all the NSData you receive from the transactionReceipt property of your SKPaymentTransaction object into a NSString object. You can use the method below.
2) Insert that into a JSON string. In objective-C code it would be:
NSString* json = [NSString stringWithFormat:@"{ 'receipt-data' : '%@' }", base64String];
3) HTTP POST that
4) You will get a JSON string back - extract the value for 'status'. If it is 0 your receipt has been confirmed - otherwise it is an unverified purchase.
Below is the code I use to convert the NSData to a Base-64 encoded string:
@interface NSData (Base64Encoding)
- (NSString*)base64Encode;
@end
@implementation NSData (Base64Encoding)
- (NSString*)base64Encode
{
static char table [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSInteger length = [self length];
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* input = (uint8_t*)[self bytes];
uint8_t* output = (uint8_t*)data.mutableBytes;
for (NSInteger i = 0; i < length; i += 3)
{
NSInteger value = 0;
for (NSInteger j = i; j < (i + 3); ++j)
{
value <<= 8;
if (j < length)
{
value |= (0xff & input[j]);
}
}
NSInteger index = (i / 3) * 4;
output[index + 0] = table[(value >> 18) & 0x3f];
output[index + 1] = table[(value >> 12) & 0x3f];
output[index + 2] = (i + 1) < length ? table[(value >> 6) & 0x3f] : '=';
output[index + 3] = (i + 2) < length ? table[(value >> 0) & 0x3f] : '=';
}
return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
}
@end
To use it just do something like:
NSString* base64string = [transaction.transactionReceipt base64Encode];