Я попытался рассмотреть все другие вопросы, и ничто не могло решить эту проблему. Я сузил его, так что ответ от https://sandbox.itunes.apple.com/verifyReceipt просто {"status":21002}
. Любая помощь будет принята с благодарностью, я скопировал соответствующий код ниже.
NSString *completeString = @"http://www.mysite.com/verify.php"; NSURL *urlForValidation = [NSURL URLWithString:completeString]; NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation]; [validationRequest setHTTPMethod:@"POST"]; NSString *strTest = [NSString stringWithFormat:@"receipt=%@", [self createEncodedString:transaction.transactionReceipt]]; [validationRequest setHTTPBody:[NSData dataFromBase64String:strTest]]; NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil]; NSString *response = [[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding]; NSLog(@"%@", response); - (NSString*) createEncodedString:(NSData*)data { static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; const int size = ((data.length + 2)/3)*4; uint8_t output[size]; const uint8_t* input = (const uint8_t*)[data bytes]; for (int i = 0; i < data.length; i += 3) { int value = 0; for (int j = i; j < (i + 3); j++) { value <<= 8; if (j < data.length) value |= (0xFF & input[j]); } const int index = (i / 3) * 4; output[index + 0] = table[(value >> 18) & 0x3F]; output[index + 1] = table[(value >> 12) & 0x3F]; output[index + 2] = (i + 1) < data.length ? table[(value >> 6) & 0x3F] : '='; output[index + 3] = (i + 2) < data.length ? table[(value >> 0) & 0x3F] : '='; } return [[NSString alloc] initWithBytes:output length:size encoding:NSASCIIStringEncoding]; }
Наконец, это используемый код PHP:
$url = 'https://sandbox.itunes.apple.com/verifyReceipt'; $receipt = "{%s}" % $_POST["receipt"]; $purchase_encoded = base64_encode( $receipt ); $encodedData = json_encode( Array( 'receipt-data' => $purchase_encoded ) ); //Open a Connection using POST method, as it is required to use POST method. $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 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. echo $encodedResponse; $response = json_decode( $encodedResponse ); echo $response;
После многих попыток я смог понять это. Я считаю, что самая большая ошибка заключалась в том, как я настраивал тело HTTP. Окончательный код ниже, надеюсь, это может помочь кому-то другому!
Objective-C:
NSString *completeString = @"http://www.mysite.com/verify.php"; NSURL *urlForValidation = [NSURL URLWithString:completeString]; NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation]; [validationRequest setHTTPMethod:@"POST"]; NSString *strTest = [NSString stringWithFormat:@"receipt=%@", [self base64forData:transaction.transactionReceipt]]; [validationRequest setHTTPBody:[strTest dataUsingEncoding:NSUTF8StringEncoding]]; NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil]; NSString *response = [[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding]; NSLog(@"%@", response);
PHP:
$url = 'https://sandbox.itunes.apple.com/verifyReceipt'; $encodedData = json_encode( Array( 'receipt-data' => $_POST["receipt"] ) ); //Open a Connection using POST method, as it is required to use POST method. $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 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); $response = json_decode( $encodedResponse ); /* echo "Status Code:"; echo $response->{'status'}; */ if ($response->{'status'} != 0) { echo "FAIL"; } else { echo "SUCCESS"; }
Ответ nlutterman правильный! Это очень помогло мне. В случае, если кто-то пытается заставить свое решение работать, он будет работать, только если вы используете следующий метод для кодирования данных квитанции base64 (in-app).
- (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]; }
Обычный base64EncodedStringWithOptions:
не работает.