12

アプリを iOS6 から iOS7 に変換しています。非推奨の方法を使用する前にtransactionReceipt、レシートを取得するために推奨される方法を試してから、base 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];

上記は、コードの唯一の変更です。以下は私がそれを検証する方法です、変更はありません:

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
    }

サーバー側では、これはレシートを確認するために使用する PHP コードです。エラーがないかサンドボックスを試す以外に変更はありません。

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

これはエラー ログ出力です。

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

Apple にあらゆる種類の例外を投げかけているようです!

繰り返しますが、唯一の違いは、領収書を取得してエンコードする方法です。誰かがこの問題に遭遇して修正しましたか?

読んでくれてありがとう。

/年

要求に応じて、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;
}

いくつかの実験の後の新しい詳細は、既存のデータを Base 64 エンコードとして送信すると、何らかの内部制限に侵入する可能性が高いと判断しました。内部制限を超えると、データは送信されず、デバイスでローカルに失敗し、それを下回ると送信されます。列は次のとおりです: データ形式、エンコードされたデータのサイズ、サーバーに到達したかどうか:

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

正常に送信された場合と送信されなかった場合の差は 100 バイト未満であることに注意してください。

4

4 に答える 4

3

自分のサーバーからの io7 スタイルのレシートの検証中に、エラー 21002 (java.lang.IllegalArgumentException) という同じ症状が発生しました。

次の 2 つの問題があることが判明しました。

  1. 領収書データが不良でした。どういうわけか、データをサーバーに渡すときに、base64 でエンコードされた領収書データに「\r\n」文字がたくさん含まれてしまいました。(検索と置換のコードでこれらを取り除きました)。

  2. 自動更新サブスクリプションを使用している場合は、JSON ペイロードで次の 2 つのパラメーターを verifyReceipt に渡す必要があります: "receipt-data" と、itunes connect からの共有シークレットである "password" です。

これら 2 つのことを修正すると、verifyReceipt http リクエストが期待どおりに機能しました。

于 2015-01-10T23:54:28.593 に答える
0

Appleは、最後の 2 文字として -_ を持つRFC 4648の URL とファイル名に安全な base64 を使用します。+/ は、多くの実装の典型です。

OP のコードは 10.9+ または 7.0+ でのみ機能します。4.0+ および 10.6+ のサポートを可能にする以前のプライベート API は次のとおりです。

[NSData base64Encoding]
于 2014-04-17T02:58:45.707 に答える