iOS7 - Quittungen werden in der Sandbox nicht überprüft - Fehler 21002 (java.lang.IllegalArgumentException)

Ich konvertiere eine App von iOS6 nach iOS7. Vorher habe ich das veraltete benutzttransactionReceipt So, jetzt versuche ich, die empfohlenen Methoden zum Abrufen der Quittung und dann in Basis 64 zu codieren:

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

Das Obige ist die einzige Änderung im Code. Unten ist, wie ich es validiere, keine Änderungen:

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
    }

Auf der Serverseite ist dies der PHP-Code, mit dem ich die Quittung verifiziere, keine Änderung, außer die Sandbox auf Fehler zu prüfen:

// 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));

Dies ist die Ausgabe des Fehlerprotokolls:

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

Es sieht so aus, als würde ich alle möglichen Ausnahmen auf Apple werfen!

Auch hier besteht der einzige Unterschied darin, wie der Beleg abgerufen und verschlüsselt wird. Hat jemand dieses Problem festgestellt und behoben?

Danke fürs Lesen.

/ YR

Code für PostJSONToURL wie gewünscht:

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

Neue Details haben nach einigen Experimenten festgestellt, dass das Senden der vorhandenen Daten als codierte Basis 64 wahrscheinlich eine interne Grenze überschreitet. Wenn es eine interne Grenze überschreitet, werden die Daten nicht einmal gesendet, es schlägt lokal auf dem Gerät fehl, darunter wird es gesendet. Spalten sind: Datenformat, Größe der verschlüsselten Daten, ob sie den Server erreicht haben:

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

Beachten Sie, dass der Unterschied zwischen erfolgreichem und nicht erfolgreichem Senden weniger als 100 Byte beträgt.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage