iOS7 - potwierdzenia niepotwierdzające w piaskownicy - błąd 21002 (java.lang.IllegalArgumentException)

Konwertuję aplikację z iOS6 na iOS7. Zanim użyłem przestarzałegotransactionReceipt metoda więc teraz próbuję zalecanych metod pobierania paragonu, a następnie kodowania w bazie 64:

NSData *working = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
// Tried 64 or 76 chars/line and LF or CR line endings
NSString *receipt = [working base64EncodedStringWithOptions:kNilOptions];

Powyższe jest jedyną zmianą w kodzie. Poniżej przedstawiam, jak to sprawdzam, bez zmian:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue,
     ^{
         NSMutableString *url = [NSMutableString string];

         [url appendFormat:@"%@", WEB_SERVICE];
         [url appendFormat:@"receipt=%@", receipt];

         NSStringEncoding encoding;
         NSError *error = [NSError new];
         NSURL *URL = [NSURL URLWithString:url];
         NSString *json = [NSString stringWithContentsOfURL:URL usedEncoding:&encoding error:&error];

         // check json and error
         // ... code omitted
    }

Po stronie serwera jest to kod PHP, którego używam do sprawdzenia potwierdzenia, bez zmian innych niż wypróbowanie piaskownicy w przypadku jakiegokolwiek błędu:

// Encode as JSON
$json = json_encode(array('receipt-data' => $receipt));
// Try production first, if it doesn't work, then try the sandbox
$working = postJSONToURL('https://buy.itunes.apple.com/verifyReceipt', $json, false);
error_log('production - '.print_r($working, true));
if (@$working['status'] !== 0) // === 21007)
    $working = postJSONToURL('https://sandbox.itunes.apple.com/verifyReceipt', $json, true);
error_log('sandbox - '.print_r($working, true));

To jest wyjście dziennika błędów:

production - Array\n(\n    [status] => 21002\n    [exception] => java.lang.IllegalArgumentException\n)\n
sandbox - Array\n(\n    [status] => 21002\n    [exception] => java.lang.IllegalArgumentException\n)\n

Wygląda na to, że w Apple rzucam wszelkiego rodzaju wyjątki!

Ponownie jedyną różnicą jest sposób pobierania i kodowania paragonu. Czy ktoś napotkał ten problem i naprawił go?

Dziękuje za przeczytanie.

/ YR

Na żądanie kod dla PostJSONToURL:

function postJSONToURL($url, $json, $disableSSLVerify = false)
{
    $resource = curl_init($url);
    curl_setopt($resource, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($resource, CURLOPT_POSTFIELDS, $json);
    curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($resource, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: '.strlen($json)));
    curl_setopt($resource, CURLOPT_HEADER, 0);
    if ($disableSSLVerify)
    {
        curl_setopt($resource, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($resource, CURLOPT_SSL_VERIFYPEER, 0);
    }
    //curl_setopt($resource, CURLOPT_VERBOSE, true);
    //curl_setopt($resource, CURLOPT_STDERR, $fp = fopen('/tmp/curl_output'.rand(1000, 9999).'.txt', 'w'));
    $contents = json_decode(curl_exec($resource), true);
    if (!$contents)
        $contents = array();
    curl_close($resource);
    //fclose($fp);
    return $contents;
}

Nowe szczegóły po kilku eksperymentach wykazały, że wysyłanie istniejących danych jako zakodowanych w bazie 64 prawdopodobnie narusza pewien wewnętrzny limit. Jeśli przekroczy jakiś wewnętrzny limit, dane nie są nawet wysyłane, a lokalnie nie działa na urządzeniu, poniżej tego jest wysyłane. Kolumny to: format danych, rozmiar zakodowanych danych, czy dotarł do serwera:

raw receipt data         5K  N/A
base64 no options     6.66K  yes
base64 76 chars/line  6.75K  no
base64 64 chars/line  6.77K  no
hex coded               10K  no

Należy zauważyć, że różnica między pomyślnym wysłaniem a nie wysłaniem jest mniejsza niż 100 bajtów.

questionAnswers(3)

yourAnswerToTheQuestion