How to Get iOS Appstorereceipturl into Base 64 Encoded String

How to get iOS appStoreReceiptURL into Base 64 Encoded String?

I figured out the trick is to read the receipt as data then base 64 encode it from the data. Here's what worked for me if it helps anyone else. Also thanks to this thread for the base 64 encoding: Converting NSData to base64

// this returns an NSDictionary of the app's store receipt, status=0 for good, -1 for bad
- (NSDictionary *) getStoreReceipt:(BOOL)sandbox {

NSArray *objects;
NSArray *keys;
NSDictionary *dictionary;

BOOL gotreceipt = false;

@try {

NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];

if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptUrl path]]) {

NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];

NSString *receiptString = [self base64forData:receiptData];

if (receiptString != nil) {

objects = [[NSArray alloc] initWithObjects:receiptString, nil];
keys = [[NSArray alloc] initWithObjects:@"receipt-data", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];

NSString *postData = [self getJsonStringFromDictionary:dictionary];

NSString *urlSting = @"https://buy.itunes.apple.com/verifyReceipt";
if (sandbox) urlSting = @"https://sandbox.itunes.apple.com/verifyReceipt";

dictionary = [self getJsonDictionaryWithPostFromUrlString:urlSting andDataString:postData];

if ([dictionary objectForKey:@"status"] != nil) {

if ([[dictionary objectForKey:@"status"] intValue] == 0) {

gotreceipt = true;

}
}

}

}

} @catch (NSException * e) {
gotreceipt = false;
}

if (!gotreceipt) {
objects = [[NSArray alloc] initWithObjects:@"-1", nil];
keys = [[NSArray alloc] initWithObjects:@"status", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
}

return dictionary;
}

- (NSDictionary *) getJsonDictionaryWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *jsonString = [self getStringWithPostFromUrlString:urlString andDataString:dataString];
NSLog(@"%@", jsonString); // see what the response looks like
return [self getDictionaryFromJsonString:jsonString];
}

- (NSDictionary *) getDictionaryFromJsonString:(NSString *)jsonstring {
NSError *jsonError;
NSDictionary *dictionary = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:[jsonstring dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonError];
if (jsonError) {
dictionary = [[NSDictionary alloc] init];
}
return dictionary;
}

- (NSString *) getStringWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *s = @"";
@try {
NSData *postdata = [dataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postlength = [NSString stringWithFormat:@"%d", [postdata length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setTimeoutInterval:60];
[request setHTTPMethod:@"POST"];
[request setValue:postlength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postdata];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (data != nil) {
s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
@catch (NSException *exception) {
s = @"";
}
return s;
}

// from https://stackoverflow.com/questions/2197362/converting-nsdata-to-base64
- (NSString*)base64forData:(NSData*)theData {
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;

if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4;
output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}

Converting NSData to base64

EDIT

As of OS X 10.9 / iOS 7, this is built into the frameworks.

See -[NSData base64EncodedDataWithOptions:]


Prior to iOS7/OS X 10.9:

Matt Gallagher wrote an article on this very topic. At the bottom he gives a link to his embeddable code for iPhone.

On the mac you can use the OpenSSL library, on the iPhone he writes his own impl.

In app purchase Receipt data to base64 becoming null in iOS 9 beta?

looks like its fixed in iOS 9 beta 4 (came out yesterday) https://developer.apple.com/ios/download/

How to encode on client `transaction.transactionReceipt` with base64?

Since iOS7 there is another way to get the receipt data. Here is what I do:

NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];

NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];

NSString *receiptBase64 = [receiptData base64EncodedStringWithOptions:0];

Then you send receiptBase64 to your server :)

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];


Related Topics



Leave a reply



Submit