php - iOS7 - 收据未在沙箱中验证 - 错误 21002 (java.lang.IllegalArgumentException)

标签 php objective-c in-app-purchase ios7 sandbox

我正在将一个应用程序从 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字节。

最佳答案

我遇到过这个问题并到处查看,包括 Apple 的开发论坛。 Apple 将给出几个股票回复,仅此而已。我认为这是苹果方面的一个错误。设备上的本地验证将起作用,因此请尝试转换为该验证。如果您绝对必须使用服务器端验证,那么现在似乎只有 transactionReceipt 可以工作。

该功能只是被弃用,并没有被禁止,所以我只会使用它并希望 Apple 批准该应用程序。事实上,这就是我刚刚所做的,祈祷,等待批准。

您可以像这样将代码括起来以关闭 Xcode 中的警告:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// code using transactionReceipt
#pragma clang diagnostic pop

关于php - iOS7 - 收据未在沙箱中验证 - 错误 21002 (java.lang.IllegalArgumentException),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19222845/

相关文章:

iphone - 添加 ASIHTTPRequest 时收到 apple O Linker Error

ios - 生产时应用内购买收据未发送到服务器

google-play - 如何在Apple App Store和Google Play商店中设置相同的价格?

swift - IAP 的 NSCoding 或 Userdefaults

php仅将数组中的变量返回到网页中

php - SQL 更新 id = 1 的行

php - 我的 php 文件没有以 JSON 形式返回所有值

php - 使用 psr-4 命名空间失败

objective-c - 在 ARC 下,是否仍然建议为循环创建一个 @autoreleasepool?

ios - 如果用户在应用程序处于后台时进入/退出区域,则调用 localNotification