In App Purchase Receipt Verification - iphone

I'm having troubles getting a response from my receipt validation for my in-app purchase. Can you please take a look at the code below and tell me why I'm not getting anything in return? Also, if there are any suggestions on good ways to test receipt verification, please do tell!
Many thanks in advance!
Xcode:
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction {
NSString *jsonObjectString = [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length];
NSString *completeString = [NSString stringWithFormat:#"http://www.myURL.com/vReceipt.php?receipt=%#", jsonObjectString];
NSURL *urlForValidation = [NSURL URLWithString:completeString];
NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];
[validationRequest setHTTPMethod:#"GET"];
NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding: NSUTF8StringEncoding];
NSInteger response = [responseString intValue];
NSLog(#"Response String: %#", jsonObjectString);
NSLog(#"Response Integer: %#", response);
return (response = 0);}
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
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];}
PHP Code:
<?php
$myreceipt = json_encode(array('receipt-data' => $_GET['receipt']));
$url = "https://sandbox.itunes.apple.com/verifyReceipt";
//create cURL Request
$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, $myreceipt);
//execute cURL Request
$response = curl_exec($ch);
$errno = curl_errno($ch);
$errmsg = curl_error($ch);
curl_close($ch);
$response_json = json_decode($response);
print $response_json->{'status'};
?>

This string always returns 0:
return (response = 0);}
Corrected one:
return (response == 0);}

You should do stripslashes() on the data you get from the iphone perhaps

Related

how to access Salesforce Attachment Body (base64 binary data) in ios?

I am working on iOS native app for getting attachments from salesforce.
I have to show the salesforce attachments in my iPhone app for particular object like Leads,Contacts etc. For that i am using Rest Api and got response body. But in response body there is url but i want binary data of attachment body.
Here is my code:
My rest api request
NSString *attachments=[NSString stringWithFormat:#"select Name,Body, ContentType from Attachment"];
SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:attachments];
[[SFRestAPI sharedInstance] send:request delegate:self];
I get response in body in following format:
{
Body = "/services/data/v23.0/sobjects/Attachment/00P90000004SRFlEAO/Body";
ContentType = "application/video";
Name = "Video.MOV";
attributes = {
type = Attachment;
url = "/services/data/v23.0/sobjects/Attachment/00P90000004SRFlEAO";
};
}
Using this code to download after get body url:
SFRestRequest* downloadRequest = [self requestForFileContents:#"/services/data/v23.0/sobjects/Attachment/00P90000004SRFlEAO/Body"];
- (SFRestRequest *) requestForFileContents:(NSString *) path {
NSMutableDictionary *params = [NSMutableDictionary dictionary];
SFRestRequest *request = [SFRestRequest requestWithMethod:SFRestMethodGET path:path queryParams:params];
request.parseResponse = NO;
return request;}
You have to make a GET request to the URL returned in the Body field to fetch the actual binary content.
Check this code:
id url = #"http://blogs.independent.co.uk/wp-content/uploads/2012/12/google-zip.jpg";
[self getImageBase64:url];
-( NSString *) AFBase64EncodedStringFromString: (NSData*) data
{
NSUInteger length = [data length];
NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *input = (uint8_t *)[data bytes];
uint8_t *output = (uint8_t *)[mutableData mutableBytes];
for (NSUInteger i = 0; i < length; i += 3) {
NSUInteger value = 0;
for (NSUInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
NSUInteger idx = (i / 3) * 4;
output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
}
-(NSString *) getImageBase64:(NSString *) url
{
NSURLRequest * imageUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLResponse * response=nil;
NSError * error =nil;
NSData * data = [NSURLConnection sendSynchronousRequest:imageUrlRequest returningResponse:&response error:&error];
if(error == nil)
{
return [self AFBase64EncodedStringFromString:data];
}
return nil;
}

How to print raw data of ASIHTTPRequest

I want to send an image to a web server running .Net which is not Restful .
I have tried a lot of things to convert the image into string and then sending it.Like using initWithData:encoding: and also tried it with converting the image data into base64encodedstring by the method given in this question
iPhone to MS SQL Image Data Type Conversion Question
But no luck.
Then I thought of looking on facebook api for uploading images on facebook wall.Using this tutorial the image can be uploaded to facebook
http://www.raywenderlich.com/1626/how-to-post-to-a-users-wall-upload-photos-and-add-a-like-button-from-your-iphone-app
But the problem is, it is using asihttprequest to send the data on the facebook wall and I cannot see the raw data in the request will uploading the image . Can anyone help me out.
I tried it at my end. First I converted to base64encoding like this:
NSString *str64;
if(Image){
NSData *imageData = UIImageJPEGRepresentation(Image,0.75);
str64 = [imageData base64Encoding];
}
Then I added into a dictionary and then added that dictionary into an array so that I can pass it as a JSON string in request's body.
NSMutableArray *ParaArray =[[NSMutableArray alloc]init];
NSDictionary *ParaDictionary=[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:#"%#",Userid], #"userid",
[NSString stringWithFormat:#"%#",[Imagename URLEncodedString]], #"imagename",
[NSString stringWithFormat:#"%#",DateNTime], #"datetime",
[NSString stringWithFormat:#"%#",ImageLocation], #"imagelocation",
str64,#"image",
nil]; // set the parameter
[ParaArray addObject:ParaDictionary];
There after using ASIFormDataRequest I sent the image to server using this snippet:
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setPostValue:[ParaArray JSONRepresentation] forKey:#"bulk_data"];
//[ParaDictionary release];
[ParaArray release];
[request setTimeOutSeconds:20];
[request startSynchronous];
It worked fine for me. I hope it helps you as well.
Data is passed in form of a string and we can directly use the base64Encoding methods by copy pasting them. Though you might know them still here they are:
- (NSString *) base64Encoding {
return [self base64EncodingWithLineLength:0];
}
- (NSString *) base64EncodingWithLineLength:(NSUInteger) lineLength {
const unsigned char *bytes = [self bytes];
NSMutableString *result = [NSMutableString stringWithCapacity:[self length]];
unsigned long ixtext = 0;
unsigned long lentext = [self length];
long ctremaining = 0;
unsigned char inbuf[3], outbuf[4];
unsigned short i = 0;
unsigned short charsonline = 0, ctcopy = 0;
unsigned long ix = 0;
while( YES ) {
ctremaining = lentext - ixtext;
if( ctremaining <= 0 ) break;
for( i = 0; i < 3; i++ ) {
ix = ixtext + i;
if( ix < lentext ) inbuf[i] = bytes[ix];
else inbuf [i] = 0;
}
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
outbuf [3] = inbuf [2] & 0x3F;
ctcopy = 4;
switch( ctremaining ) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for( i = 0; i < ctcopy; i++ )
[result appendFormat:#"%c", encodingTable[outbuf[i]]];
for( i = ctcopy; i < 4; i++ )
[result appendString:#"="];
ixtext += 3;
charsonline += 4;
if( lineLength > 0 ) {
if( charsonline >= lineLength ) {
charsonline = 0;
[result appendString:#"\n"];
}
}
}
return [NSString stringWithString:result];
}

(iphone) KERN_PROTECTION_FAILURE at ob_msgSend()

I'm fairly certain KER_PROTECTION_FAILURE is happening due to the following code.
(I don't get the error when I skip calling this function)
What I suspect is that the following code is wrong? (data can be gone before string object is released or something like that)
NSMutableData* data = [NSMutableData dataWithLength: dataLength];
// populate data
return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
Register $r0 shows the address of the returning NSString object.
and $r1 shows "release".
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
int dataLength = ((length+2)/3)*4;
int remainder = dataLength % 16;
dataLength = dataLength + (16- remainder);
NSMutableData *data = [NSMutableData dataWithLength:
dataLength];
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]; }

Verifying a Receipt with the App Store

Retrieve the receipt data from the transaction’s transactionReceipt property and encode it using base64 encoding.
How can I encode NSData using base64 encoding? Please give the code for that.
EDIT
I did it. but now the response is
{exception = "java.lang.NullPointerException"; status = 21002;}
my recipt verification method is this
-(BOOL)verifyReceipt:(SKPaymentTransaction *)transaction
{
NSString *recieptString = [transaction.transactionReceipt base64EncodingWithLineLength:0];
NSLog(#"%#",recieptString);
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://buy.itunes.apple.com/verifyReceipt"]]];
[request setPostValue:recieptString forKey:#"receipt-data"];
[request setPostValue:#"95140bdac98d47a2b15e8e5555f55d41" forKey:#"password"];
[request start];
NSDictionary* subsInfo = [[request responseString] JSONValue];
NSLog(#"%#",subsInfo);
return subscriptionEnabled;
}
Where
NSString *recieptString = [transaction.transactionReceipt base64EncodingWithLineLength:0];
returns me base64 encoded string.
I also tried
NSString *recieptString = [transaction.transactionReceipt base64EncodingWithLineLength:[transaction.transactionReceipt length]];
but response is same.
can any one of you let me know where I could be wrong.
Thanks-
+ (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] autorelease];
}
You need to post your receipt to "https://sandbox.itunes.apple.com/verifyReceipt" while testing in the sandbox environment.

iphone SDK : How Can I Convert a string to SHA-1 And SHA-1 to Base64? (for WSSecurity)

my convert code is all i have, but it converts a string to sha-1 to hex format. how can i convert sha-1 to base64 ?
-(NSString *)digest:(NSString*)input
int i;
const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
length:CC_SHA1_DIGEST_LENGTH];
for(i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
{
[output appendFormat:#"%02x", digest[i]];
}
return output;
}
There's no built-in hashing or Base64 in iOS. You'll have to roll your own. Find a C implementation of SHA1 in Google; as for Base64, I've got one for you:
NSString *ToBase64(NSData *d)
{
static const char ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const NSString *PAD1 = #"=", *PAD2 = #"==";
int l = [d length];
unsigned char *p = (unsigned char*)[d bytes];
unichar Chunk[4];
NSMutableString *s = [NSMutableString stringWithCapacity:(l+3)*4/3];
int i;
int mod = l % 3;
int ll = l - mod;
unsigned int triad;
NSString *sChunk;
for(i=0;i<ll;i+=3)
{
triad = (p[i]<<16) | (p[i+1]<<8) | p[i+2];
Chunk[0] = ALPHABET[(triad >> 18) & 0x3f];
Chunk[1] = ALPHABET[(triad >> 12) & 0x3f];
Chunk[2] = ALPHABET[(triad >> 6) & 0x3f];
Chunk[3] = ALPHABET[triad & 0x3f];
sChunk = [[NSString alloc] initWithCharacters:Chunk length:4];
[s appendString:sChunk];
[sChunk release];
}
if(mod == 1)
{
Chunk[0] = ALPHABET[(p[i] >> 2) & 0x3f];
Chunk[1] = ALPHABET[(p[i] << 4) & 0x3f];
sChunk = [[NSString alloc] initWithCharacters:Chunk length:2];
[s appendString:sChunk];
[sChunk release];
[s appendString: PAD2];
}
if(mod == 2)
{
triad = (p[i]<<8) | p[i+1];
Chunk[0] = ALPHABET[(triad >> 10) & 0x3f];
Chunk[1] = ALPHABET[(triad >> 4) & 0x3f];
Chunk[2] = ALPHABET[(triad << 2) & 0x3f];
sChunk = [[NSString alloc] initWithCharacters:Chunk length:3];
[s appendString:sChunk];
[sChunk release];
[s appendString: PAD1];
}
return s;
}